diff --git a/.github/workflows/e2e-linux.yml b/.github/workflows/e2e-linux.yml index 746ddb1795..ccdc268300 100644 --- a/.github/workflows/e2e-linux.yml +++ b/.github/workflows/e2e-linux.yml @@ -16,6 +16,7 @@ jobs: ELECTRON_CUSTOM_VERSION: 23.0.0 DISPLAY: ":99.0" TEST_MODE: true + IS_CI: true steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/.github/workflows/e2e-mac.yml b/.github/workflows/e2e-mac.yml index 97dcbdfe00..cc363591a2 100644 --- a/.github/workflows/e2e-mac.yml +++ b/.github/workflows/e2e-mac.yml @@ -9,6 +9,7 @@ jobs: ELECTRON_CUSTOM_VERSION: 23.0.0 TEST_MODE: true IS_E2E: true + IS_CI: true steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/.github/workflows/e2e-win.yml b/.github/workflows/e2e-win.yml index 98ec12837e..3c6b32f20e 100644 --- a/.github/workflows/e2e-win.yml +++ b/.github/workflows/e2e-win.yml @@ -11,6 +11,7 @@ jobs: ELECTRON_CUSTOM_VERSION: 23.0.0 TEST_MODE: true E2E: true + IS_CI: true steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/.github/workflows/utils-tests.yml b/.github/workflows/utils-tests.yml new file mode 100644 index 0000000000..15edc17f60 --- /dev/null +++ b/.github/workflows/utils-tests.yml @@ -0,0 +1,29 @@ +name: Common package tests + +on: + pull_request: + paths: + - packages/common/** + +jobs: + utils-tests: + timeout-minutes: 25 + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-20.04, macos-latest, windows-2019] + + steps: + - name: "Print OS" + run: echo ${{ matrix.os }} + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: "Setup environment" + uses: ./.github/actions/setup-env + with: + bootstrap-packages: "@quiet/eslint-config,@quiet/logger,@quiet/types,@quiet/common" + + - name: "Unit tests" + run: lerna run test --scope @quiet/common --stream diff --git a/CHANGELOG.md b/CHANGELOG.md index 930a751d04..56600bb044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,33 @@ [unreleased] +# New features: + +* Add support for new format of invitation link: `c=&t=&s=&i=` ([#2310](https://github.com/TryQuiet/quiet/issues/2310)) + +# Refactorings: + +# Fixes + +# Chores + +* Cleanup data directory at end of e2e tests + +[2.2.0] + +# New features: + +* Add utilities for emoji detection in messages and make all-emoji message larger font size ([#519](https://github.com/TryQuiet/quiet/issues/519)) + # Refactorings: * Use ack for CREATE_NETWORK and simplify -* Refactored package.json to have consistent license "GPL-3.0-or-later" +* Move Community model to the backend -# Fixes +# Fixes: -* Fixes channel name creation logic * Allow JPEG and GIF files as profile photos ([#2332](https://github.com/TryQuiet/quiet/issues/2332)) +* Fix issues with recreating general channel when deleted while offline ([#2334](https://github.com/TryQuiet/quiet/issues/2334)) +* Fix package.json license inconsistency [2.1.2] @@ -22,14 +41,14 @@ # Fixes: +* Fixes channel name creation logic * Remove duplicate introduction messages once again * Prevent channel creation with names that start with special character, then a hyphen * Choose random ports for Tor services (iOS) * Use consistent identicons for messages and profile * Add retry ability to tor-control and misc tor-control fixes -* Ship Tor binary and use custom TorHandler -# Chores: +# Other: * Upgraded React-Native to 0.73.2 diff --git a/docs/tor_mobile.md b/docs/tor_mobile.md deleted file mode 100644 index 7f82aedba4..0000000000 --- a/docs/tor_mobile.md +++ /dev/null @@ -1,30 +0,0 @@ -# Guide on Android Tor - -Tor runs within its own thread, spawned and managed by [TorHandler](https://github.com/TryQuiet/quiet/blob/8924a5573ed11980ceeadb2f8dd1ce45169f03ee/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/TorHandler.java). TorHandler is based on the Tor-Android library from the Guardian Project, specifically the [TorService](https://github.com/guardianproject/tor-android/blob/master/tor-android-binary/src/main/java/org/torproject/jni/TorService.java). - -We ship the binary [libtor.so](https://github.com/TryQuiet/quiet/blob/8924a5573ed11980ceeadb2f8dd1ce45169f03ee/packages/mobile/android/app/src/main/libs/arm64-v8a/libtor.so), which exposes certain native APIs through JNI. These are used to configure and run Tor. These JNI methods are directed to the official Guardian Project's library, forcing us to use our [wrapper](https://github.com/TryQuiet/quiet/blob/8924a5573ed11980ceeadb2f8dd1ce45169f03ee/packages/mobile/android/app/src/main/cpp/tor-wrapper.cpp) around it. It bridges C-level global namespace accessible libtor.so methods and exposes them through Quiet's app scope JNI interface, enabling its use without modifying the Tor source code itself. - -## Building the Tor Binary - -The Tor binary is designed to be a ready-made product and does not contain the SONAME property. This absence makes linking it to any other shared object, like our tor-wrapper, challenging. While building Tor, it is essential to remember to pass an extra linker flag to set the SONAME property for the compilation product. The entry point for building the Tor binary is [tor-droid-make.sh](https://github.com/guardianproject/tor-android/blob/master/tor-droid-make.sh), with a crucial step being `build_external_dependencies()`. It is advisable to modify the script and skip the `./gradlew` command build assembling, as it is not essential for acquiring the Tor binary. The script is important as it sets flags to enable the Android API in Tor. The prerequisites for building are listed [here](https://raw.githubusercontent.com/guardianproject/tor-android/master/BUILD). The output Tor binary will be located in `external/tor/lib/{ABI}/`. - -### Build Command -```bash -LDFLAGS='-Wl,-soname,libtor.so' ./tor-droid-make.sh externals -a arm64-v8a -``` - -### Verify Build -To check for the presence of the SONAME property, run: -```bash -readelf -d libtor.so -``` - -To verify the API presence, run: -```bash -nm -D libtor.so | grep "Java_org_torproject_jni_TorService_createTorConfiguration" -``` - -## Post Mortem - -#### Missing Tor Binary ([Issue #2328](https://github.com/TryQuiet/quiet/issues/2328)) -The issue was caused by the removal of the deprecated Gradle flag `enableUncompressedNativeLibs`, which resulted in the deletion of the binary from the location to which we were pointing. We had to alter the method we use the binary, as now described in the previous sections of this document. \ No newline at end of file diff --git a/external-licenses/licensing.md b/external-licenses/licensing.md deleted file mode 100644 index 78bbbe59a2..0000000000 --- a/external-licenses/licensing.md +++ /dev/null @@ -1,5 +0,0 @@ -The follow is licensing information for code and binaries from external projects: - -- [packages/mobile/android/app/libtor/bin/libtor.so](packages/mobile/android/app/libtor/bin/libtor.so) is built from https://github.com/guardianproject/tor-android and licensed under [tor-android.license.txt](tor-android.license.txt) - -- [packages/mobile/android/app/libnode/bin/libnode.so](packages/mobile/android/app/libnode/bin/libnode.so) is built from https://github.com/nodejs-mobile/nodejs-mobile and licensed under [nodejs-mobile.license.txt](nodejs-mobile.license.txt) diff --git a/external-licenses/nodejs-mobile-react-native.license.txt b/external-licenses/nodejs-mobile-react-native.license.txt deleted file mode 100644 index 58ec98df63..0000000000 --- a/external-licenses/nodejs-mobile-react-native.license.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Janea Systems, Inc. and 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. diff --git a/external-licenses/nodejs-mobile.license.txt b/external-licenses/nodejs-mobile.license.txt deleted file mode 100644 index 2cae73c275..0000000000 --- a/external-licenses/nodejs-mobile.license.txt +++ /dev/null @@ -1,2177 +0,0 @@ -Node.js is licensed for use as follows: - -""" -Copyright Node.js contributors. All rights reserved. - -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. -""" - -This license applies to parts of Node.js originating from the -https://github.com/joyent/node repository: - -""" -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -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. -""" - -The Node.js license applies to all parts of Node.js that are not externally -maintained libraries. - -The externally maintained libraries used by Node.js are: - -- Acorn, located at deps/acorn, is licensed as follows: - """ - MIT License - - Copyright (C) 2012-2022 by various contributors (see AUTHORS) - - 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. - """ - -- c-ares, located at deps/cares, is licensed as follows: - """ - Copyright (c) 2007 - 2018, Daniel Stenberg with many contributors, see AUTHORS - file. - - Copyright 1998 by the Massachusetts Institute of Technology. - - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose and without fee is hereby granted, provided that - the above copyright notice appear in all copies and that both that copyright - notice and this permission notice appear in supporting documentation, and that - the name of M.I.T. not be used in advertising or publicity pertaining to - distribution of the software without specific, written prior permission. - M.I.T. makes no representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied warranty. - """ - -- cjs-module-lexer, located at deps/cjs-module-lexer, is licensed as follows: - """ - MIT License - ----------- - - Copyright (C) 2018-2020 Guy Bedford - - 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. - """ - -- ittapi, located at deps/v8/third_party/ittapi, is licensed as follows: - """ - Copyright (c) 2019 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- ICU, located at deps/icu-small, is licensed as follows: - """ - UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE - - See Terms of Use - for definitions of Unicode Inc.’s Data Files and Software. - - NOTICE TO USER: Carefully read the following legal agreement. - BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S - DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), - YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE - TERMS AND CONDITIONS OF THIS AGREEMENT. - IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE - THE DATA FILES OR SOFTWARE. - - COPYRIGHT AND PERMISSION NOTICE - - Copyright © 1991-2023 Unicode, Inc. All rights reserved. - Distributed under the Terms of Use in https://www.unicode.org/copyright.html. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of the Unicode data files and any associated documentation - (the "Data Files") or Unicode software and any associated documentation - (the "Software") to deal in the Data Files or Software - without restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, and/or sell copies of - the Data Files or Software, and to permit persons to whom the Data Files - or Software are furnished to do so, provided that either - (a) this copyright and permission notice appear with all copies - of the Data Files or Software, or - (b) this copyright and permission notice appear in associated - Documentation. - - THE DATA FILES AND SOFTWARE ARE 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 OF THIRD PARTY RIGHTS. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS - NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 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 THE DATA FILES OR SOFTWARE. - - Except as contained in this notice, the name of a copyright holder - shall not be used in advertising or otherwise to promote the sale, - use or other dealings in these Data Files or Software without prior - written authorization of the copyright holder. - - ---------------------------------------------------------------------- - - Third-Party Software Licenses - - This section contains third-party software notices and/or additional - terms for licensed third-party software components included within ICU - libraries. - - ---------------------------------------------------------------------- - - ICU License - ICU 1.8.1 to ICU 57.1 - - COPYRIGHT AND PERMISSION NOTICE - - Copyright (c) 1995-2016 International Business Machines Corporation and others - All rights reserved. - - 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, and/or sell copies of the Software, and to permit persons - to whom the Software is furnished to do so, provided that the above - copyright notice(s) and this permission notice appear in all copies of - the Software and that both the above copyright notice(s) and this - permission notice appear in supporting documentation. - - 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 - OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY - SPECIAL 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. - - Except as contained in this notice, the name of a copyright holder - shall not be used in advertising or otherwise to promote the sale, use - or other dealings in this Software without prior written authorization - of the copyright holder. - - All trademarks and registered trademarks mentioned herein are the - property of their respective owners. - - ---------------------------------------------------------------------- - - Chinese/Japanese Word Break Dictionary Data (cjdict.txt) - - # The Google Chrome software developed by Google is licensed under - # the BSD license. Other software included in this distribution is - # provided under other licenses, as set forth below. - # - # The BSD License - # http://opensource.org/licenses/bsd-license.php - # Copyright (C) 2006-2008, Google Inc. - # - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # - # Redistributions of source code must retain the above copyright notice, - # this list of conditions and the following disclaimer. - # Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided with - # the distribution. - # Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - # - # - # The word list in cjdict.txt are generated by combining three word lists - # listed below with further processing for compound word breaking. The - # frequency is generated with an iterative training against Google web - # corpora. - # - # * Libtabe (Chinese) - # - https://sourceforge.net/project/?group_id=1519 - # - Its license terms and conditions are shown below. - # - # * IPADIC (Japanese) - # - http://chasen.aist-nara.ac.jp/chasen/distribution.html - # - Its license terms and conditions are shown below. - # - # ---------COPYING.libtabe ---- BEGIN-------------------- - # - # /* - # * Copyright (c) 1999 TaBE Project. - # * Copyright (c) 1999 Pai-Hsiang Hsiao. - # * All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the TaBE Project nor the names of its - # * contributors may be used to endorse or promote products derived - # * from this software without specific prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # /* - # * Copyright (c) 1999 Computer Systems and Communication Lab, - # * Institute of Information Science, Academia - # * Sinica. All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the Computer Systems and Communication Lab - # * nor the names of its contributors may be used to endorse or - # * promote products derived from this software without specific - # * prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, - # University of Illinois - # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 - # - # ---------------COPYING.libtabe-----END-------------------------------- - # - # - # ---------------COPYING.ipadic-----BEGIN------------------------------- - # - # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science - # and Technology. All Rights Reserved. - # - # Use, reproduction, and distribution of this software is permitted. - # Any copy of this software, whether in its original form or modified, - # must include both the above copyright notice and the following - # paragraphs. - # - # Nara Institute of Science and Technology (NAIST), - # the copyright holders, disclaims all warranties with regard to this - # software, including all implied warranties of merchantability and - # fitness, in no event shall NAIST be liable for - # any special, 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 tortuous action, arising out - # of or in connection with the use or performance of this software. - # - # A large portion of the dictionary entries - # originate from ICOT Free Software. The following conditions for ICOT - # Free Software applies to the current dictionary as well. - # - # Each User may also freely distribute the Program, whether in its - # original form or modified, to any third party or parties, PROVIDED - # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear - # on, or be attached to, the Program, which is distributed substantially - # in the same form as set out herein and that such intended - # distribution, if actually made, will neither violate or otherwise - # contravene any of the laws and regulations of the countries having - # jurisdiction over the User or the intended distribution itself. - # - # NO WARRANTY - # - # The program was produced on an experimental basis in the course of the - # research and development conducted during the project and is provided - # to users as so produced on an experimental basis. Accordingly, the - # program is provided without any warranty whatsoever, whether express, - # implied, statutory or otherwise. The term "warranty" used herein - # includes, but is not limited to, any warranty of the quality, - # performance, merchantability and fitness for a particular purpose of - # the program and the nonexistence of any infringement or violation of - # any right of any third party. - # - # Each user of the program will agree and understand, and be deemed to - # have agreed and understood, that there is no warranty whatsoever for - # the program and, accordingly, the entire risk arising from or - # otherwise connected with the program is assumed by the user. - # - # Therefore, neither ICOT, the copyright holder, or any other - # organization that participated in or was otherwise related to the - # development of the program and their respective officials, directors, - # officers and other employees shall be held liable for any and all - # damages, including, without limitation, general, special, incidental - # and consequential damages, arising out of or otherwise in connection - # with the use or inability to use the program or any product, material - # or result produced or otherwise obtained by using the program, - # regardless of whether they have been advised of, or otherwise had - # knowledge of, the possibility of such damages at any time during the - # project or thereafter. Each user will be deemed to have agreed to the - # foregoing by his or her commencement of use of the program. The term - # "use" as used herein includes, but is not limited to, the use, - # modification, copying and distribution of the program and the - # production of secondary products from the program. - # - # In the case where the program, whether in its original form or - # modified, was distributed or delivered to or received by a user from - # any person, organization or entity other than ICOT, unless it makes or - # grants independently of ICOT any specific warranty to the user in - # writing, such person, organization or entity, will also be exempted - # from and not be held liable to the user for any such damages as noted - # above as far as the program is concerned. - # - # ---------------COPYING.ipadic-----END---------------------------------- - - ---------------------------------------------------------------------- - - Lao Word Break Dictionary Data (laodict.txt) - - # Copyright (C) 2016 and later: Unicode, Inc. and others. - # License & terms of use: http://www.unicode.org/copyright.html - # Copyright (c) 2015 International Business Machines Corporation - # and others. All Rights Reserved. - # - # Project: https://github.com/rober42539/lao-dictionary - # Dictionary: https://github.com/rober42539/lao-dictionary/laodict.txt - # License: https://github.com/rober42539/lao-dictionary/LICENSE.txt - # (copied below) - # - # This file is derived from the above dictionary version of Nov 22, 2020 - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # - # Redistributions of source code must retain the above copyright notice, this - # list of conditions and the following disclaimer. Redistributions in binary - # form must reproduce the above copyright notice, this list of conditions and - # the following disclaimer in the documentation and/or other materials - # provided with the distribution. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # OF THE POSSIBILITY OF SUCH DAMAGE. - # -------------------------------------------------------------------------- - - ---------------------------------------------------------------------- - - Burmese Word Break Dictionary Data (burmesedict.txt) - - # Copyright (c) 2014 International Business Machines Corporation - # and others. All Rights Reserved. - # - # This list is part of a project hosted at: - # github.com/kanyawtech/myanmar-karen-word-lists - # - # -------------------------------------------------------------------------- - # Copyright (c) 2013, LeRoy Benjamin Sharon - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions - # are met: Redistributions of source code must retain the above - # copyright notice, this list of conditions and the following - # disclaimer. Redistributions in binary form must reproduce the - # above copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided - # with the distribution. - # - # Neither the name Myanmar Karen Word Lists, nor the names of its - # contributors may be used to endorse or promote products derived - # from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS - # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - # SUCH DAMAGE. - # -------------------------------------------------------------------------- - - ---------------------------------------------------------------------- - - Time Zone Database - - ICU uses the public domain data and code derived from Time Zone - Database for its time zone support. The ownership of the TZ database - is explained in BCP 175: Procedure for Maintaining the Time Zone - Database section 7. - - # 7. Database Ownership - # - # The TZ database itself is not an IETF Contribution or an IETF - # document. Rather it is a pre-existing and regularly updated work - # that is in the public domain, and is intended to remain in the - # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do - # not apply to the TZ Database or contributions that individuals make - # to it. Should any claims be made and substantiated against the TZ - # Database, the organization that is providing the IANA - # Considerations defined in this RFC, under the memorandum of - # understanding with the IETF, currently ICANN, may act in accordance - # with all competent court orders. No ownership claims will be made - # by ICANN or the IETF Trust on the database or the code. Any person - # making a contribution to the database or code waives all rights to - # future claims in that contribution or in the TZ Database. - - ---------------------------------------------------------------------- - - Google double-conversion - - Copyright 2006-2011, the V8 project authors. All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ---------------------------------------------------------------------- - - File: aclocal.m4 (only for ICU4C) - Section: pkg.m4 - Macros to locate and utilise pkg-config. - - - Copyright © 2004 Scott James Remnant . - Copyright © 2012-2015 Dan Nicholson - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. - - As a special exception to the GNU General Public License, if you - distribute this file as part of a program that contains a - configuration script generated by Autoconf, you may include it under - the same distribution terms that you use for the rest of that - program. - - - (The condition for the exception is fulfilled because - ICU4C includes a configuration script generated by Autoconf, - namely the `configure` script.) - - ---------------------------------------------------------------------- - - File: config.guess (only for ICU4C) - - - This file is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . - - As a special exception to the GNU General Public License, if you - distribute this file as part of a program that contains a - configuration script generated by Autoconf, you may include it under - the same distribution terms that you use for the rest of that - program. This Exception is an additional permission under section 7 - of the GNU General Public License, version 3 ("GPLv3"). - - - (The condition for the exception is fulfilled because - ICU4C includes a configuration script generated by Autoconf, - namely the `configure` script.) - - ---------------------------------------------------------------------- - - File: install-sh (only for ICU4C) - - - Copyright 1991 by the Massachusetts Institute of Technology - - Permission to use, copy, modify, distribute, and sell this software and its - documentation for any purpose is hereby granted without fee, provided that - the above copyright notice appear in all copies and that both that - copyright notice and this permission notice appear in supporting - documentation, and that the name of M.I.T. not be used in advertising or - publicity pertaining to distribution of the software without specific, - written prior permission. M.I.T. makes no representations about the - suitability of this software for any purpose. It is provided "as is" - without express or implied warranty. - """ - -- libuv, located at deps/uv, is licensed as follows: - """ - Copyright (c) 2015-present libuv project 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. - This license applies to parts of libuv originating from the - https://github.com/joyent/libuv repository: - - ==== - - Copyright Joyent, Inc. and other Node contributors. All rights reserved. - 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. - - ==== - - This license applies to all parts of libuv that are not externally - maintained libraries. - - The externally maintained libraries used by libuv are: - - - tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license. - - - inet_pton and inet_ntop implementations, contained in src/inet.c, are - copyright the Internet Systems Consortium, Inc., and licensed under the ISC - license. - """ - -- llhttp, located at deps/llhttp, is licensed as follows: - """ - This software is licensed under the MIT License. - - Copyright Fedor Indutny, 2018. - - 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. - """ - -- corepack, located at deps/corepack, is licensed as follows: - """ - **Copyright © Corepack 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. - """ - -- undici, located at deps/undici, is licensed as follows: - """ - MIT License - - Copyright (c) Matteo Collina and Undici 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. - """ - -- postject, located at test/fixtures/postject-copy, is licensed as follows: - """ - Postject is licensed for use as follows: - - """ - MIT License - - Copyright (c) 2022 Postman, Inc - - 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. - """ - - The Postject license applies to all parts of Postject that are not externally - maintained libraries. - - The externally maintained libraries used by Postject are: - - - LIEF, located at vendor/LIEF, is licensed as follows: - """ - 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 2017 - 2022 R. Thomas - Copyright 2017 - 2022 Quarkslab - - 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. - """ - """ - -- OpenSSL, located at deps/openssl, is licensed as follows: - """ - Apache License - Version 2.0, January 2004 - https://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 - """ - -- Punycode.js, located at lib/punycode.js, is licensed as follows: - """ - Copyright Mathias Bynens - - 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. - """ - -- V8, located at deps/v8, is licensed as follows: - """ - This license applies to all parts of V8 that are not externally - maintained libraries. The externally maintained libraries used by V8 - are: - - - PCRE test suite, located in - test/mjsunit/third_party/regexp-pcre/regexp-pcre.js. This is based on the - test suite from PCRE-7.3, which is copyrighted by the University - of Cambridge and Google, Inc. The copyright notice and license - are embedded in regexp-pcre.js. - - - Layout tests, located in test/mjsunit/third_party/object-keys. These are - based on layout tests from webkit.org which are copyrighted by - Apple Computer, Inc. and released under a 3-clause BSD license. - - - Strongtalk assembler, the basis of the files assembler-arm-inl.h, - assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h, - assembler-ia32.cc, assembler-ia32.h, assembler-x64-inl.h, - assembler-x64.cc, assembler-x64.h, assembler.cc and assembler.h. - This code is copyrighted by Sun Microsystems Inc. and released - under a 3-clause BSD license. - - - Valgrind client API header, located at src/third_party/valgrind/valgrind.h - This is released under the BSD license. - - - The Wasm C/C++ API headers, located at third_party/wasm-api/wasm.{h,hh} - This is released under the Apache license. The API's upstream prototype - implementation also formed the basis of V8's implementation in - src/wasm/c-api.cc. - - These libraries have their own licenses; we recommend you read them, - as their terms may differ from the terms below. - - Further license information can be found in LICENSE files located in - sub-directories. - - Copyright 2014, the V8 project authors. All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- SipHash, located at deps/v8/src/third_party/siphash, is licensed as follows: - """ - SipHash reference C implementation - - Copyright (c) 2016 Jean-Philippe Aumasson - - To the extent possible under law, the author(s) have dedicated all - copyright and related and neighboring rights to this software to the public - domain worldwide. This software is distributed without any warranty. - """ - -- zlib, located at deps/zlib, is licensed as follows: - """ - zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.13, October 13th, 2022 - - Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - """ - -- simdutf, located at deps/simdutf, is licensed as follows: - """ - Copyright 2021 The simdutf authors - - 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. - """ - -- ada, located at deps/ada, is licensed as follows: - """ - Copyright 2023 Ada authors - - 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. - """ - -- minimatch, located at deps/minimatch, is licensed as follows: - """ - The ISC License - - Copyright (c) 2011-2023 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. - """ - -- npm, located at deps/npm, is licensed as follows: - """ - The npm application - Copyright (c) npm, Inc. and Contributors - Licensed on the terms of The Artistic License 2.0 - - Node package dependencies of the npm application - Copyright (c) their respective copyright owners - Licensed on their respective license terms - - The npm public registry at https://registry.npmjs.org - and the npm website at https://www.npmjs.com - Operated by npm, Inc. - Use governed by terms published on https://www.npmjs.com - - "Node.js" - Trademark Joyent, Inc., https://joyent.com - Neither npm nor npm, Inc. are affiliated with Joyent, Inc. - - The Node.js application - Project of Node Foundation, https://nodejs.org - - The npm Logo - Copyright (c) Mathias Pettersson and Brian Hammond - - "Gubblebum Blocky" typeface - Copyright (c) Tjarda Koster, https://jelloween.deviantart.com - Used with permission - - -------- - - The Artistic License 2.0 - - Copyright (c) 2000-2006, The Perl Foundation. - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - This license establishes the terms under which a given free software - Package may be copied, modified, distributed, and/or redistributed. - The intent is that the Copyright Holder maintains some artistic - control over the development of that Package while still keeping the - Package available as open source and free software. - - You are always permitted to make arrangements wholly outside of this - license directly with the Copyright Holder of a given Package. If the - terms of this license do not permit the full use that you propose to - make of the Package, you should contact the Copyright Holder and seek - a different licensing arrangement. - - Definitions - - "Copyright Holder" means the individual(s) or organization(s) - named in the copyright notice for the entire Package. - - "Contributor" means any party that has contributed code or other - material to the Package, in accordance with the Copyright Holder's - procedures. - - "You" and "your" means any person who would like to copy, - distribute, or modify the Package. - - "Package" means the collection of files distributed by the - Copyright Holder, and derivatives of that collection and/or of - those files. A given Package may consist of either the Standard - Version, or a Modified Version. - - "Distribute" means providing a copy of the Package or making it - accessible to anyone else, or in the case of a company or - organization, to others outside of your company or organization. - - "Distributor Fee" means any fee that you charge for Distributing - this Package or providing support for this Package to another - party. It does not mean licensing fees. - - "Standard Version" refers to the Package if it has not been - modified, or has been modified only in ways explicitly requested - by the Copyright Holder. - - "Modified Version" means the Package, if it has been changed, and - such changes were not explicitly requested by the Copyright - Holder. - - "Original License" means this Artistic License as Distributed with - the Standard Version of the Package, in its current version or as - it may be modified by The Perl Foundation in the future. - - "Source" form means the source code, documentation source, and - configuration files for the Package. - - "Compiled" form means the compiled bytecode, object code, binary, - or any other form resulting from mechanical transformation or - translation of the Source form. - - Permission for Use and Modification Without Distribution - - (1) You are permitted to use the Standard Version and create and use - Modified Versions for any purpose without restriction, provided that - you do not Distribute the Modified Version. - - Permissions for Redistribution of the Standard Version - - (2) You may Distribute verbatim copies of the Source form of the - Standard Version of this Package in any medium without restriction, - either gratis or for a Distributor Fee, provided that you duplicate - all of the original copyright notices and associated disclaimers. At - your discretion, such verbatim copies may or may not include a - Compiled form of the Package. - - (3) You may apply any bug fixes, portability changes, and other - modifications made available from the Copyright Holder. The resulting - Package will still be considered the Standard Version, and as such - will be subject to the Original License. - - Distribution of Modified Versions of the Package as Source - - (4) You may Distribute your Modified Version as Source (either gratis - or for a Distributor Fee, and with or without a Compiled form of the - Modified Version) provided that you clearly document how it differs - from the Standard Version, including, but not limited to, documenting - any non-standard features, executables, or modules, and provided that - you do at least ONE of the following: - - (a) make the Modified Version available to the Copyright Holder - of the Standard Version, under the Original License, so that the - Copyright Holder may include your modifications in the Standard - Version. - - (b) ensure that installation of your Modified Version does not - prevent the user installing or running the Standard Version. In - addition, the Modified Version must bear a name that is different - from the name of the Standard Version. - - (c) allow anyone who receives a copy of the Modified Version to - make the Source form of the Modified Version available to others - under - - (i) the Original License or - - (ii) a license that permits the licensee to freely copy, - modify and redistribute the Modified Version using the same - licensing terms that apply to the copy that the licensee - received, and requires that the Source form of the Modified - Version, and of any works derived from it, be made freely - available in that license fees are prohibited but Distributor - Fees are allowed. - - Distribution of Compiled Forms of the Standard Version - or Modified Versions without the Source - - (5) You may Distribute Compiled forms of the Standard Version without - the Source, provided that you include complete instructions on how to - get the Source of the Standard Version. Such instructions must be - valid at the time of your distribution. If these instructions, at any - time while you are carrying out such distribution, become invalid, you - must provide new instructions on demand or cease further distribution. - If you provide valid instructions or cease distribution within thirty - days after you become aware that the instructions are invalid, then - you do not forfeit any of your rights under this license. - - (6) You may Distribute a Modified Version in Compiled form without - the Source, provided that you comply with Section 4 with respect to - the Source of the Modified Version. - - Aggregating or Linking the Package - - (7) You may aggregate the Package (either the Standard Version or - Modified Version) with other packages and Distribute the resulting - aggregation provided that you do not charge a licensing fee for the - Package. Distributor Fees are permitted, and licensing fees for other - components in the aggregation are permitted. The terms of this license - apply to the use and Distribution of the Standard or Modified Versions - as included in the aggregation. - - (8) You are permitted to link Modified and Standard Versions with - other works, to embed the Package in a larger work of your own, or to - build stand-alone binary or bytecode versions of applications that - include the Package, and Distribute the result without restriction, - provided the result does not expose a direct interface to the Package. - - Items That are Not Considered Part of a Modified Version - - (9) Works (including, but not limited to, modules and scripts) that - merely extend or make use of the Package, do not, by themselves, cause - the Package to be a Modified Version. In addition, such works are not - considered parts of the Package itself, and are not subject to the - terms of this license. - - General Provisions - - (10) Any use, modification, and distribution of the Standard or - Modified Versions is governed by this Artistic License. By using, - modifying or distributing the Package, you accept this license. Do not - use, modify, or distribute the Package, if you do not accept this - license. - - (11) If your Modified Version has been derived from a Modified - Version made by someone other than you, you are nevertheless required - to ensure that your Modified Version complies with the requirements of - this license. - - (12) This license does not grant you the right to use any trademark, - service mark, tradename, or logo of the Copyright Holder. - - (13) This license includes the non-exclusive, worldwide, - free-of-charge patent license to make, have made, use, offer to sell, - sell, import and otherwise transfer the Package with respect to any - patent claims licensable by the Copyright Holder that are necessarily - infringed by the Package. If you institute patent litigation - (including a cross-claim or counterclaim) against any party alleging - that the Package constitutes direct or contributory patent - infringement, then this Artistic License to you shall terminate on the - date that such litigation is filed. - - (14) Disclaimer of Warranty: - THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS - IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED - WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR - NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL - LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL - DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------- - """ - -- GYP, located at tools/gyp, is licensed as follows: - """ - Copyright (c) 2020 Node.js contributors. All rights reserved. - Copyright (c) 2009 Google Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- inspector_protocol, located at tools/inspector_protocol, is licensed as follows: - """ - // Copyright 2016 The Chromium Authors. All rights reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions are - // met: - // - // * Redistributions of source code must retain the above copyright - // notice, this list of conditions and the following disclaimer. - // * Redistributions in binary form must reproduce the above - // copyright notice, this list of conditions and the following disclaimer - // in the documentation and/or other materials provided with the - // distribution. - // * Neither the name of Google Inc. nor the names of its - // contributors may be used to endorse or promote products derived from - // this software without specific prior written permission. - // - // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- jinja2, located at tools/inspector_protocol/jinja2, is licensed as follows: - """ - Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details. - - Some rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- markupsafe, located at tools/inspector_protocol/markupsafe, is licensed as follows: - """ - Copyright (c) 2010 by Armin Ronacher and contributors. See AUTHORS - for more details. - - Some rights reserved. - - Redistribution and use in source and binary forms of the software as well - as documentation, with or without modification, are permitted provided - that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND - CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT - NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. - """ - -- cpplint.py, located at tools/cpplint.py, is licensed as follows: - """ - Copyright (c) 2009 Google Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- ESLint, located at tools/node_modules/eslint, is licensed as follows: - """ - Copyright OpenJS Foundation and other 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. - """ - -- gtest, located at deps/googletest, is licensed as follows: - """ - Copyright 2008, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- nghttp2, located at deps/nghttp2, is licensed as follows: - """ - The MIT License - - Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa - Copyright (c) 2012, 2014, 2015, 2016 nghttp2 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. - """ - -- large_pages, located at src/large_pages, is licensed as follows: - """ - Copyright (C) 2018 Intel Corporation - - 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. - """ - -- caja, located at lib/internal/freeze_intrinsics.js, is licensed as follows: - """ - Adapted from SES/Caja - Copyright (C) 2011 Google Inc. - Copyright (C) 2018 Agoric - - 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. - """ - -- brotli, located at deps/brotli, is licensed as follows: - """ - Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. - - 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. - """ - -- HdrHistogram, located at deps/histogram, is licensed as follows: - """ - The code in this repository code was Written by Gil Tene, Michael Barker, - and Matt Warren, and released to the public domain, as explained at - http://creativecommons.org/publicdomain/zero/1.0/ - - For users of this code who wish to consume it under the "BSD" license - rather than under the public domain or CC0 contribution text mentioned - above, the code found under this directory is *also* provided under the - following license (commonly referred to as the BSD 2-Clause License). This - license does not detract from the above stated release of the code into - the public domain, and simply represents an additional license granted by - the Author. - - ----------------------------------------------------------------------------- - ** Beginning of "BSD 2-Clause License" text. ** - - Copyright (c) 2012, 2013, 2014 Gil Tene - Copyright (c) 2014 Michael Barker - Copyright (c) 2014 Matt Warren - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - THE POSSIBILITY OF SUCH DAMAGE. - """ - -- highlight.js, located at doc/api_assets/highlight.pack.js, is licensed as follows: - """ - BSD 3-Clause License - - Copyright (c) 2006, Ivan Sagalaev. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ - -- node-heapdump, located at src/heap_utils.cc, is licensed as follows: - """ - ISC License - - Copyright (c) 2012, Ben Noordhuis - - 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. - - === src/compat.h src/compat-inl.h === - - ISC License - - Copyright (c) 2014, StrongLoop Inc. - - 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. - """ - -- rimraf, located at lib/internal/fs/rimraf.js, is licensed as follows: - """ - 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. - """ - -- uvwasi, located at deps/uvwasi, is licensed as follows: - """ - MIT License - - Copyright (c) 2019 Colin Ihrig and 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. - """ - -- ngtcp2, located at deps/ngtcp2/ngtcp2/, is licensed as follows: - """ - The MIT License - - Copyright (c) 2016 ngtcp2 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. - """ - -- nghttp3, located at deps/ngtcp2/nghttp3/, is licensed as follows: - """ - The MIT License - - Copyright (c) 2019 nghttp3 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. - """ - -- node-fs-extra, located at lib/internal/fs/cp, is licensed as follows: - """ - (The MIT License) - - Copyright (c) 2011-2017 JP Richardson - - 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. - """ - -- base64, located at deps/base64/base64/, is licensed as follows: - """ - Copyright (c) 2005-2007, Nick Galbreath - Copyright (c) 2013-2019, Alfred Klomp - Copyright (c) 2015-2017, Wojciech Mula - Copyright (c) 2016-2017, Matthieu Darbois - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - """ diff --git a/external-licenses/tor-android.license.txt b/external-licenses/tor-android.license.txt deleted file mode 100644 index e42a0c00ed..0000000000 --- a/external-licenses/tor-android.license.txt +++ /dev/null @@ -1,224 +0,0 @@ -This file contains the license for Orbot, a free software project to -provide anonymity on the Internet from a Google Android smartphone. - -It also lists the licenses for other components used by Orbot, including -Tor, Privoxy, and iptables. - -For more information about Orbot, see https://guardianproject.info/apps/orbot - -If you got this file as a part of a larger bundle, there may be other -license terms that you should be aware of. -=============================================================================== -Orbot is distributed under this license (aka the 3-clause BSD license) - -Copyright (c) 2009-2010, Nathan Freitas, The Guardian Project - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - - * Neither the names of the copyright owners nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -***** - -=============================================================================== -Orbot includes the Obfs4 pluggable transport: -https://gitweb.torproject.org/pluggable-transports/obfs4.git - -Copyright (c) 2014, Yawning Angel -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -=============================================================================== - - -***** - -***** -Orbot contains a binary distribution of Privoxy (http://www.privoxy.org/) -Copyright © 2001-2010 by Privoxy Developers -http://www.privoxy.org/user-manual/copyright.html - -Some source code is based on code Copyright © 1997 by Anonymous Coders and Junkbusters, Inc. -and licensed under the GNU General Public License. - -Privoxy is free software; you can redistribute it and/or modify it under the terms of the -GNU General Public License, version 2, as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for details. -http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - -****** -Orbot contains a binary distribution of Tor: - - This file contains the license for Tor, - a free software project to provide anonymity on the Internet. - - It also lists the licenses for other components used by Tor. - - For more information about Tor, see https://www.torproject.org/. - - If you got this file as a part of a larger bundle, - there may be other license terms that you should be aware of. - -=============================================================================== -Tor is distributed under this license: - -Copyright (c) 2001-2004, Roger Dingledine -Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson -Copyright (c) 2007-2009, The Tor Project, Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - - * Neither the names of the copyright owners nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== - -src/common/strlcat.c and src/common/strlcpy.c by Todd C. Miller are licensed -under the following license: - - * Copyright (c) 1998 Todd C. Miller - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=============================================================================== -If you got Tor as a static binary with OpenSSL included, then you should know: - "This product includes software developed by the OpenSSL Project - for use in the OpenSSL Toolkit (http://www.openssl.org/)" -=============================================================================== - -=============================================================================== -"This program uses the IP-to-Country Database provided by -WebHosting.Info (http://www.webhosting.info), available from -http://ip-to-country.webhosting.info." -See the src/config/geoip file in particular. -=============================================================================== - -=============================================================================== -Orbot also uses iptables from the Netfilter.org project - -netfilter/iptables is - like all of the Linux Kernel - Free Software (sometimes -referred to as Open Source Software), distributed under the terms of the GNU GPLv2 -only. Please, note that some source code files might differ, and in that case it -is explicitely stated in the header of every file. - -The GPL also contains some obligations. If you distribute netfilter/iptables code -in binary form, you have to offer the source code, too. -=============================================================================== - -=============================================================================== -Orbot also includes BadVPN tun2socks: https://github.com/ambrop72/badvpn - -Copyright (c) 2009, Ambroz Bizjak -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== diff --git a/external-licenses/tor.license.txt b/external-licenses/tor.license.txt deleted file mode 100644 index abab8e33fe..0000000000 --- a/external-licenses/tor.license.txt +++ /dev/null @@ -1,389 +0,0 @@ - This file contains the license for Tor, - a free software project to provide anonymity on the Internet. - - It also lists the licenses for other components used by Tor. - - For more information about Tor, see https://www.torproject.org/. - - If you got this file as a part of a larger bundle, - there may be other license terms that you should be aware of. - -=============================================================================== -Tor is distributed under the "3-clause BSD" license, a commonly used -software license that means Tor is both free software and open source: - -Copyright (c) 2001-2004, Roger Dingledine -Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson -Copyright (c) 2007-2019, The Tor Project, Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - - * Neither the names of the copyright owners nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== -src/ext/strlcat.c and src/ext/strlcpy.c by Todd C. Miller are licensed -under the following license: - - * Copyright (c) 1998 Todd C. Miller - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== -src/ext/tor_queue.h is licensed under the following license: - - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - -=============================================================================== -src/ext/csiphash.c is licensed under the following license: - - Copyright (c) 2013 Marek Majkowski - - 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. -=============================================================================== -Trunnel is distributed under this license: - -Copyright 2014 The Tor Project, Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - - * Neither the names of the copyright owners nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=============================================================================== -getdelim.c is distributed under this license: - - Copyright (c) 2011 The NetBSD Foundation, Inc. - All rights reserved. - - This code is derived from software contributed to The NetBSD Foundation - by Christos Zoulas. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -=============================================================================== -src/config/geoip and src/config/geoip6: - -These files are based on the IPFire Location Database. For more -information, see https://location.ipfire.org/. - -The data is distributed under a creative commons "BY-SA 4.0" license. - -Find the full license terms at: - https://creativecommons.org/licenses/by-sa/4.0/ - -=============================================================================== -m4/pc_from_ucontext.m4 is available under the following license. Note that -it is *not* built into the Tor software. - -Copyright (c) 2005, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=============================================================================== -m4/pkg.m4 is available under the following license. Note that -it is *not* built into the Tor software. - -pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -serial 1 (pkg-config-0.24) - -Copyright © 2004 Scott James Remnant . - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -As a special exception to the GNU General Public License, if you -distribute this file as part of a program that contains a -configuration script generated by Autoconf, you may include it under -the same distribution terms that you use for the rest of that program. -=============================================================================== -src/ext/readpassphrase.[ch] are distributed under this license: - - Copyright (c) 2000-2002, 2007 Todd C. Miller - - Permission to use, copy, modify, and 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. - - Sponsored in part by the Defense Advanced Research Projects - Agency (DARPA) and Air Force Research Laboratory, Air Force - Materiel Command, USAF, under agreement number F39502-99-1-0512. - -=============================================================================== -src/ext/mulodi4.c is distributed under this license: - - ========================================================================= - compiler_rt License - ========================================================================= - - The compiler_rt library is dual licensed under both the - University of Illinois "BSD-Like" license and the MIT license. - As a user of this code you may choose to use it under either - license. As a contributor, you agree to allow your code to be - used under both. - - Full text of the relevant licenses is included below. - - ========================================================================= - - University of Illinois/NCSA - Open Source License - - Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT - - All rights reserved. - - Developed by: - - LLVM Team - - University of Illinois at Urbana-Champaign - - http://llvm.org - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal with 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: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimers. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimers in the documentation and/or other materials - provided with the distribution. - - * Neither the names of the LLVM Team, University of Illinois - at Urbana-Champaign, nor the names of its contributors may - be used to endorse or promote products derived from this - Software without specific prior written permission. - - 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 CONTRIBUTORS 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 WITH THE SOFTWARE. - - ========================================================================= - - Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT - - 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. - - ========================================================================= - Copyrights and Licenses for Third Party Software Distributed with LLVM: - ========================================================================= - - The LLVM software contains code written by third parties. Such - software will have its own individual LICENSE.TXT file in the - directory in which it appears. This file will describe the - copyrights, license, and restrictions which apply to that code. - - The disclaimer of warranty in the University of Illinois Open - Source License applies to all code in the LLVM Distribution, and - nothing in any of the other licenses gives permission to use the - names of the LLVM Team or the University of Illinois to endorse - or promote products derived from this Software. - -=============================================================================== -If you got Tor as a static binary with OpenSSL included, then you should know: - "This product includes software developed by the OpenSSL Project - for use in the OpenSSL Toolkit (http://www.openssl.org/)" -=============================================================================== diff --git a/package-lock.json b/package-lock.json index a7ee97b2e4..1545f1aaba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,39 +5,16 @@ "packages": { "": { "name": "root", - "dependencies": { - "@typescript-eslint/eslint-plugin": "6.7.4", - "@typescript-eslint/parser": "6.7.4", - "eslint": "^8.50.0", - "eslint-config-prettier": "^9.0.0", - "eslint-config-standard": "^17.1.0", - "eslint-config-standard-with-typescript": "^39.1.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jest": "^27.4.2", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-react-hooks": "^4.6.0", - "prettier": "^3.0.3" - }, "devDependencies": { "husky": "^9.0.11", - "lerna": "^6.6.2" + "lerna": "^6.6.2", + "typescript": "^4.9.3" }, "engines": { "node": "18.12.1", "npm": "8.19.2" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", @@ -135,116 +112,12 @@ "node": ">=4" } }, - "node_modules/@babel/runtime": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", - "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.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==", - "dependencies": { - "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/@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==", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.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==", - "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" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, - "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==", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "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==", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "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==" - }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -606,6 +479,7 @@ "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": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -618,6 +492,7 @@ "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, "engines": { "node": ">= 8" } @@ -626,6 +501,7 @@ "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": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1472,17 +1348,6 @@ "node": ">=14" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/@sigstore/protobuf-specs": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz", @@ -1567,16 +1432,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -1601,272 +1456,6 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.4.tgz", - "integrity": "sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==", - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/type-utils": "6.7.4", - "@typescript-eslint/utils": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", - "integrity": "sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==", - "dependencies": { - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz", - "integrity": "sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==", - "dependencies": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.4.tgz", - "integrity": "sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==", - "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/utils": "6.7.4", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.4.tgz", - "integrity": "sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz", - "integrity": "sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==", - "dependencies": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.4.tgz", - "integrity": "sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.4.tgz", - "integrity": "sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==", - "dependencies": { - "@typescript-eslint/types": "6.7.4", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" - }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -1941,25 +1530,6 @@ "node": ">=6.5" } }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/add-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", @@ -2005,21 +1575,6 @@ "node": ">=8" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -2048,6 +1603,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -2056,6 +1612,7 @@ "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" }, @@ -2088,30 +1645,8 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-differ": { "version": "3.0.0", @@ -2128,123 +1663,15 @@ "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, - "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -2254,25 +1681,12 @@ "node": ">=0.10.0" } }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" - }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dependencies": { - "has-symbols": "^1.0.3" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2288,28 +1702,6 @@ "node": ">= 4.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", - "engines": { - "node": ">=4" - } - }, "node_modules/axios": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", @@ -2321,18 +1713,11 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dependencies": { - "dequal": "^2.0.3" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -2433,6 +1818,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2442,6 +1828,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -2479,22 +1866,11 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, "dependencies": { "semver": "^7.0.0" } @@ -2543,28 +1919,11 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "engines": { "node": ">=6" } @@ -2599,6 +1958,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2735,6 +2095,7 @@ "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" }, @@ -2745,7 +2106,8 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/color-support": { "version": "1.1.3", @@ -2812,7 +2174,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/concat-stream": { "version": "2.0.0", @@ -3044,6 +2407,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3057,6 +2421,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -3088,11 +2453,6 @@ "node": ">=4" } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -3115,6 +2475,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -3167,11 +2528,6 @@ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -3184,22 +2540,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -3209,22 +2549,6 @@ "node": ">=8" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/del": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", @@ -3324,14 +2648,6 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "engines": { - "node": ">=6" - } - }, "node_modules/detect-indent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", @@ -3345,6 +2661,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -3352,17 +2669,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dot-prop": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", @@ -3500,146 +2806,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.1", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", - "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", - "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3658,687 +2824,451 @@ "node": ">=0.8.0" } }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, "bin": { - "eslint": "bin/eslint.js" + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=4" } }, - "node_modules/eslint-compat-utils": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz", - "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==", - "peer": true, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": ">=6.0.0" + "node": ">=6" } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } + "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/eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0" + "node": ">=0.8.x" } }, - "node_modules/eslint-config-standard-with-typescript": { - "version": "39.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-39.1.1.tgz", - "integrity": "sha512-t6B5Ep8E4I18uuoYeYxINyqcXb2UbC0SOOTxRtBSt2JUs+EzeXbfe2oaiPs71AIdnoWhXDO2fYOHz8df3kV84A==", + "node_modules/execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, "dependencies": { - "@typescript-eslint/parser": "^6.4.0", - "eslint-config-standard": "17.1.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^6.4.0", - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0", - "typescript": "*" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, "dependencies": { - "debug": "^3.2.7" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, "engines": { "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" + "os-tmpdir": "~1.0.2" }, "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" + "node": ">=0.6.0" } }, - "node_modules/eslint-plugin-es-x": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz", - "integrity": "sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==", - "peer": true, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.6.0", - "eslint-compat-utils": "^0.1.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "eslint": ">=8" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "node": ">=8.6.0" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, "dependencies": { - "ms": "^2.1.1" + "reusify": "^1.0.4" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, "dependencies": { - "esutils": "^2.0.2" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" + "node": ">=8" }, - "bin": { - "json5": "lib/cli.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/file-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", + "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", + "dev": true, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" } }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "dependencies": { - "@typescript-eslint/utils": "^5.10.0" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } + "node": ">=8" } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=4.0" }, "peerDependenciesMeta": { - "typescript": { + "debug": { "optional": true } } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-plugin-jest/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=8.0.0" + "node": ">= 6" } }, - "node_modules/eslint-plugin-jest/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" + "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": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "node": ">=10" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/fs-minipass": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", + "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "minipass": "^5.0.0" }, "engines": { - "node": "*" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/eslint-plugin-n": { - "version": "16.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", - "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.5.0", - "get-tsconfig": "^4.7.0", - "globals": "^13.24.0", - "ignore": "^5.2.4", - "is-builtin-module": "^3.2.1", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", - "semver": "^7.5.3" - }, - "engines": { - "node": ">=16.0.0" - }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-n/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "engines": { - "node": "*" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/eslint-plugin-n/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "peer": true, + "node_modules/get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" }, "bin": { - "semver": "bin/semver.js" + "get-pkg-repo": "src/cli.js" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "node_modules/get-pkg-repo/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "node": ">=10" } }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "node_modules/get-pkg-repo/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "yallist": "^4.0.0" }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", "engines": { "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/get-pkg-repo/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": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "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/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "node_modules/get-pkg-repo/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/get-pkg-repo/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": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "safe-buffer": "~5.1.0" } }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "engines": { - "node": ">=4" + "node_modules/get-pkg-repo/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true, "engines": { "node": ">=10" }, @@ -4346,653 +3276,623 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, "dependencies": { - "is-glob": "^4.0.3" + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" + "bin": { + "git-raw-commits": "cli.js" }, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", + "dev": true, "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=4" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/git-remote-origin-url/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "node_modules/git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "dev": true, "dependencies": { - "estraverse": "^5.1.0" + "meow": "^8.0.0", + "semver": "^6.0.0" + }, + "bin": { + "git-semver-tags": "cli.js" }, "engines": { - "node": ">=0.10" + "node": ">=10" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" + "node_modules/git-semver-tags/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" + "node_modules/git-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", + "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", + "dev": true, + "dependencies": { + "is-ssh": "^1.4.0", + "parse-url": "^8.1.0" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/git-url-parse": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", + "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "git-up": "^7.0.0" } }, - "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/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", "dev": true, - "engines": { - "node": ">=0.8.x" + "dependencies": { + "ini": "^1.3.2" } }, - "node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "node_modules/glob": { + "version": "10.2.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.7.tgz", + "integrity": "sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2", + "path-scurry": "^1.7.0" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/external-editor/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" + "balanced-match": "^1.0.0" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dependencies": { - "reusify": "^1.0.4" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.5" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/file-url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", - "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "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": { - "minimatch": "^5.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/filelist/node_modules/brace-expansion": { + "node_modules/has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "lru-cache": "^7.5.1" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "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==", "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 6" } }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10.17.0" } }, - "node_modules/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "ms": "^2.0.0" } }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "dev": true, "bin": { - "rimraf": "bin.js" + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - ], + ] + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, "engines": { - "node": ">=4.0" + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", + "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { - "is-callable": "^1.1.3" + "balanced-match": "^1.0.0" } }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">=14" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/form-data": { + "node_modules/import-fresh/node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "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/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fs-minipass": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", - "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "dependencies": { - "minipass": "^5.0.0" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.8.19" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/init-package-json": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-3.0.2.tgz", + "integrity": "sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A==", "dev": true, "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" + "npm-package-arg": "^9.0.1", + "promzard": "^0.3.0", + "read": "^1.0.7", + "read-package-json": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^4.0.0" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/init-package-json/node_modules/hosted-git-info": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "node_modules/init-package-json/node_modules/npm-package-arg": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", + "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "hosted-git-info": "^5.0.0", + "proc-log": "^2.0.1", + "semver": "^7.3.5", + "validate-npm-package-name": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "node_modules/init-package-json/node_modules/proc-log": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", + "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", "dev": true, - "dependencies": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "get-pkg-repo": "src/cli.js" - }, "engines": { - "node": ">=6.9.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/get-pkg-repo/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "node_modules/inquirer": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=10" + "node": ">=12.0.0" } }, - "node_modules/get-pkg-repo/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/inquirer/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": { - "yallist": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/get-pkg-repo/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": { - "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/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true }, - "node_modules/get-pkg-repo/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==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, - "node_modules/get-pkg-repo/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/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" } }, - "node_modules/get-pkg-repo/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, + "bin": { + "is-docker": "cli.js" + }, "engines": { "node": ">=8" }, @@ -5000,1296 +3900,239 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", - "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/get-tsconfig": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", - "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", - "peer": true, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "is-extglob": "^2.1.1" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, "engines": { - "node": ">=4" + "node": ">=0.12.0" } }, - "node_modules/git-remote-origin-url/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true, - "dependencies": { - "meow": "^8.0.0", - "semver": "^6.0.0" - }, - "bin": { - "git-semver-tags": "cli.js" - }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/git-semver-tags/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=8" } }, - "node_modules/git-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", - "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, - "dependencies": { - "is-ssh": "^1.4.0", - "parse-url": "^8.1.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/git-url-parse": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", - "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, - "dependencies": { - "git-up": "^7.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", + "node_modules/is-ssh": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", + "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", "dev": true, "dependencies": { - "ini": "^1.3.2" + "protocols": "^2.0.1" } }, - "node_modules/glob": { - "version": "10.2.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.7.tgz", - "integrity": "sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==", + "node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2", - "path-scurry": "^1.7.0" - }, - "bin": { - "glob": "dist/cjs/src/bin.js" - }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "text-extensions": "^1.0.0" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node": ">=0.10.0" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "is-docker": "^2.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globals/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "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/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "node_modules/jackspeak": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", + "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", + "dev": true, "dependencies": { - "define-properties": "^1.1.3" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3" + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "*" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "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==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/husky": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", - "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", - "dev": true, - "bin": { - "husky": "bin.mjs" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-walk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", - "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", - "dev": true, - "dependencies": { - "minimatch": "^5.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/init-package-json": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-3.0.2.tgz", - "integrity": "sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A==", - "dev": true, - "dependencies": { - "npm-package-arg": "^9.0.1", - "promzard": "^0.3.0", - "read": "^1.0.7", - "read-package-json": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/init-package-json/node_modules/hosted-git-info": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", - "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", - "dev": true, - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/init-package-json/node_modules/npm-package-arg": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", - "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", - "dev": true, - "dependencies": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/init-package-json/node_modules/proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/inquirer": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/inquirer/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/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "peer": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ssh": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", - "dev": true, - "dependencies": { - "protocols": "^2.0.1" - } - }, - "node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "dev": true, - "dependencies": { - "text-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jackspeak": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", - "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", - "dev": true, - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -6297,11 +4140,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -6317,16 +4155,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, "node_modules/json-stringify-nice": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", @@ -6397,20 +4225,6 @@ "node": "*" } }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, "node_modules/just-diff": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", @@ -6423,14 +4237,6 @@ "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", "dev": true }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -6440,22 +4246,6 @@ "node": ">=0.10.0" } }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/lerna": { "version": "6.6.2", "resolved": "https://registry.npmjs.org/lerna/-/lerna-6.6.2.tgz", @@ -6546,18 +4336,6 @@ "node": "^14.17.0 || >=16.0.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/libnpmaccess": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.4.tgz", @@ -6968,6 +4746,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -6990,11 +4769,6 @@ "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -7309,6 +5083,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "engines": { "node": ">= 8" } @@ -7317,6 +5092,7 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -7368,6 +5144,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7379,6 +5156,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7604,7 +5382,8 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/multimatch": { "version": "5.0.0", @@ -7640,11 +5419,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -8279,114 +6053,25 @@ "node": ">=12" } }, - "node_modules/nx/node_modules/yargs/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", - "dependencies": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "node_modules/nx/node_modules/yargs/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -8423,22 +6108,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -8484,6 +6153,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -8498,6 +6168,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -8777,6 +6448,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -8850,6 +6522,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -8858,6 +6531,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -8866,6 +6540,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -8873,7 +6548,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/path-scurry": { "version": "1.9.2", @@ -8904,6 +6580,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -8912,6 +6589,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -8995,14 +6673,6 @@ "node": ">=8" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/postcss-selector-parser": { "version": "6.0.13", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", @@ -9016,39 +6686,6 @@ "node": ">=4" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/pretty-format": { "version": "29.4.3", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", @@ -9163,14 +6800,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -9185,6 +6814,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -9549,59 +7179,6 @@ "node": ">=8" } }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", - "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -9615,6 +7192,7 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9648,15 +7226,6 @@ "node": ">=8" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "peer": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -9683,6 +7252,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -9770,6 +7340,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -9797,28 +7368,6 @@ "tslib": "^2.1.0" } }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -9839,22 +7388,6 @@ } ] }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -9865,6 +7398,7 @@ "version": "7.5.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -9879,6 +7413,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -9892,36 +7427,6 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -9938,6 +7443,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9949,27 +7455,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -9998,6 +7488,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, "engines": { "node": ">=8" } @@ -10182,52 +7673,11 @@ "node": ">=8" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10278,17 +7728,6 @@ "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strong-log-transformer": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", @@ -10310,6 +7749,7 @@ "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" }, @@ -10321,6 +7761,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -10328,21 +7769,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", @@ -10458,11 +7884,6 @@ "node": ">=0.10" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -10541,6 +7962,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -10572,17 +7994,6 @@ "node": ">=8" } }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -10609,26 +8020,8 @@ "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true }, "node_modules/tuf-js": { "version": "1.1.7", @@ -10644,17 +8037,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -10667,75 +8049,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -10746,6 +8059,7 @@ "version": "4.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10763,22 +8077,8 @@ "bin": { "uglifyjs": "bin/uglifyjs" }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.8.0" } }, "node_modules/unique-filename": { @@ -10842,14 +8142,6 @@ "yarn": "*" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10939,86 +8231,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -11072,7 +8284,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "4.0.1", @@ -11190,7 +8403,8 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/yaml": { "version": "1.10.2", @@ -11232,6 +8446,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "engines": { "node": ">=10" }, @@ -11241,11 +8456,6 @@ } }, "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==" - }, "@babel/code-frame": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", @@ -11324,84 +8534,12 @@ } } }, - "@babel/runtime": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", - "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", - "requires": { - "regenerator-runtime": "^0.14.0" - } - }, - "@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==", - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@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==" - }, - "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "requires": { - "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" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==" - }, "@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, - "@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "requires": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" - }, - "@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" - }, "@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -11693,6 +8831,7 @@ "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, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -11701,12 +8840,14 @@ "@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==" + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true }, "@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, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -12353,11 +9494,6 @@ "dev": true, "optional": true }, - "@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==" - }, "@sigstore/protobuf-specs": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz", @@ -12423,16 +9559,6 @@ } } }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, "@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -12457,162 +9583,6 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" - }, - "@typescript-eslint/eslint-plugin": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.4.tgz", - "integrity": "sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==", - "requires": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/type-utils": "6.7.4", - "@typescript-eslint/utils": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", - "integrity": "sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==", - "requires": { - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz", - "integrity": "sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==", - "requires": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4" - } - }, - "@typescript-eslint/type-utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.4.tgz", - "integrity": "sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==", - "requires": { - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/utils": "6.7.4", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/types": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.4.tgz", - "integrity": "sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==" - }, - "@typescript-eslint/typescript-estree": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz", - "integrity": "sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==", - "requires": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.4.tgz", - "integrity": "sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==", - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "semver": "^7.5.4" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.4.tgz", - "integrity": "sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==", - "requires": { - "@typescript-eslint/types": "6.7.4", - "eslint-visitor-keys": "^3.4.1" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" - }, "@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -12674,17 +9644,6 @@ "event-target-shim": "^5.0.0" } }, - "acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==" - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "requires": {} - }, "add-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", @@ -12721,17 +9680,6 @@ "indent-string": "^4.0.0" } }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -12750,12 +9698,14 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, "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, "requires": { "color-convert": "^2.0.1" } @@ -12779,24 +9729,8 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "requires": { - "dequal": "^2.0.3" - } - }, - "array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "requires": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - } + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "array-differ": { "version": "3.0.0", @@ -12810,83 +9744,11 @@ "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, - "array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - } - }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, - "array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - } - }, - "array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", - "requires": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - } - }, - "array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "requires": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - } + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true }, "arrify": { "version": "1.0.1", @@ -12894,25 +9756,12 @@ "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true }, - "ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" - }, "async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "requires": { - "has-symbols": "^1.0.3" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -12925,19 +9774,6 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, - "available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "requires": { - "possible-typed-array-names": "^1.0.0" - } - }, - "axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==" - }, "axios": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", @@ -12949,18 +9785,11 @@ "proxy-from-env": "^1.1.0" } }, - "axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "requires": { - "dequal": "^2.0.3" - } - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "base64-js": { "version": "1.5.1", @@ -13031,6 +9860,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -13040,6 +9870,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -13060,16 +9891,11 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "peer": true - }, "builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, "requires": { "semver": "^7.0.0" } @@ -13111,22 +9937,11 @@ } } }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true }, "camelcase": { "version": "5.3.1", @@ -13149,6 +9964,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13251,6 +10067,7 @@ "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, "requires": { "color-name": "~1.1.4" } @@ -13258,7 +10075,8 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "color-support": { "version": "1.1.3", @@ -13315,7 +10133,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "concat-stream": { "version": "2.0.0", @@ -13503,6 +10322,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -13513,6 +10333,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -13531,11 +10352,6 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, - "damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, "dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -13552,6 +10368,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -13586,11 +10403,6 @@ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, "defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -13600,32 +10412,12 @@ "clone": "^1.0.2" } }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "dev": true }, - "define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "requires": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, "del": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", @@ -13700,11 +10492,6 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" - }, "detect-indent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", @@ -13715,16 +10502,9 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "requires": { - "esutils": "^2.0.2" + "path-type": "^4.0.0" } }, "dot-prop": { @@ -13773,671 +10553,80 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", - "requires": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.1", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" - } - }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-iterator-helpers": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", - "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", - "requires": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" - } - }, - "es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "requires": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - } - }, - "es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "requires": { - "hasown": "^2.0.0" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "requires": { - "is-glob": "^4.0.3" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "eslint-compat-utils": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz", - "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==", - "peer": true, - "requires": {} - }, - "eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "requires": {} - }, - "eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "requires": {} - }, - "eslint-config-standard-with-typescript": { - "version": "39.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-39.1.1.tgz", - "integrity": "sha512-t6B5Ep8E4I18uuoYeYxINyqcXb2UbC0SOOTxRtBSt2JUs+EzeXbfe2oaiPs71AIdnoWhXDO2fYOHz8df3kV84A==", - "requires": { - "@typescript-eslint/parser": "^6.4.0", - "eslint-config-standard": "17.1.0" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - } - }, - "eslint-plugin-es-x": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz", - "integrity": "sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==", - "peer": true, - "requires": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.6.0", - "eslint-compat-utils": "^0.1.2" - } - }, - "eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "requires": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "requires": { - "esutils": "^2.0.2" - } - }, - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "requires": { - "minimist": "^1.2.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" - }, - "tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - } - } - }, - "eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", - "requires": { - "@typescript-eslint/utils": "^5.10.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - } - }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==" - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - } - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", - "requires": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" - }, - "dependencies": { - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "eslint-plugin-n": { - "version": "16.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", - "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", - "peer": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.5.0", - "get-tsconfig": "^4.7.0", - "globals": "^13.24.0", - "ignore": "^5.2.4", - "is-builtin-module": "^3.2.1", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", - "semver": "^7.5.3" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "peer": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "peer": true, + "dev": true, + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, "requires": { - "lru-cache": "^6.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" } } } }, - "eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "requires": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } + "once": "^1.4.0" } }, - "eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, "requires": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "ansi-colors": "^4.1.1" } }, - "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "requires": {} + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true }, - "eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "requires": {} + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" - } + "is-arrayish": "^0.2.1" } }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true }, "esprima": { "version": "4.0.1", @@ -14445,32 +10634,6 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -14534,20 +10697,11 @@ } } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" - }, "fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -14556,20 +10710,11 @@ "micromatch": "^4.0.4" } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, "requires": { "reusify": "^1.0.4" } @@ -14583,14 +10728,6 @@ "escape-string-regexp": "^1.0.5" } }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "requires": { - "flat-cache": "^3.0.4" - } - }, "file-url": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", @@ -14630,6 +10767,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -14638,6 +10776,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -14649,66 +10788,12 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, - "flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" - }, "follow-redirects": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "dev": true }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } - }, "foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -14768,28 +10853,14 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true }, "gauge": { "version": "4.0.4", @@ -14813,18 +10884,6 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, "get-pkg-repo": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", @@ -14909,25 +10968,6 @@ "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true }, - "get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "requires": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - } - }, - "get-tsconfig": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", - "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", - "peer": true, - "requires": { - "resolve-pkg-maps": "^1.0.0" - } - }, "git-raw-commits": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", @@ -15042,37 +11082,16 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { "is-glob": "^4.0.1" } }, - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "requires": { - "type-fest": "^0.20.2" - }, - "dependencies": { - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" - } - } - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "requires": { - "define-properties": "^1.1.3" - } - }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -15082,25 +11101,12 @@ "slash": "^3.0.0" } }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } - }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" - }, "handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -15120,41 +11126,11 @@ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "requires": { - "has-symbols": "^1.0.3" - } + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "has-unicode": { "version": "2.0.1", @@ -15166,6 +11142,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, "requires": { "function-bind": "^1.1.2" } @@ -15245,7 +11222,8 @@ "ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true }, "ignore-walk": { "version": "5.0.1", @@ -15280,6 +11258,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -15288,7 +11267,8 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true } } }, @@ -15305,7 +11285,8 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true }, "indent-string": { "version": "4.0.0", @@ -15323,6 +11304,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -15331,7 +11313,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "ini": { "version": "1.3.8", @@ -15418,76 +11401,18 @@ } } }, - "internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "requires": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - } - }, "ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, - "is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, - "is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "peer": true, - "requires": { - "builtin-modules": "^3.3.0" - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" - }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -15501,18 +11426,11 @@ "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, "requires": { "hasown": "^2.0.0" } }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, "is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -15522,15 +11440,8 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "requires": { - "call-bind": "^1.0.2" - } + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -15538,18 +11449,11 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -15566,28 +11470,11 @@ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, - "is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" - }, - "is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" - }, "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "is-obj": { "version": "2.0.0", @@ -15604,7 +11491,8 @@ "is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true }, "is-plain-obj": { "version": "1.1.0", @@ -15618,28 +11506,6 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" - }, - "is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "requires": { - "call-bind": "^1.0.7" - } - }, "is-ssh": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", @@ -15655,22 +11521,6 @@ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -15680,42 +11530,12 @@ "text-extensions": "^1.0.0" } }, - "is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "requires": { - "which-typed-array": "^1.1.14" - } - }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, - "is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "requires": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - } - }, "is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -15734,7 +11554,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "isobject": { "version": "3.0.1", @@ -15742,18 +11563,6 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, - "iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "requires": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, "jackspeak": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", @@ -15797,15 +11606,11 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "requires": { "argparse": "^2.0.1" } }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -15818,16 +11623,6 @@ "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", "dev": true }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, "json-stringify-nice": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", @@ -15878,17 +11673,6 @@ "through": ">=2.2.7 <3" } }, - "jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - } - }, "just-diff": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", @@ -15901,33 +11685,12 @@ "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", "dev": true }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "requires": { - "json-buffer": "3.0.1" - } - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" - }, - "language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "requires": { - "language-subtag-registry": "^0.3.20" - } - }, "lerna": { "version": "6.6.2", "resolved": "https://registry.npmjs.org/lerna/-/lerna-6.6.2.tgz", @@ -16012,15 +11775,6 @@ "yargs-parser": "20.2.4" } }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, "libnpmaccess": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.4.tgz", @@ -16344,6 +12098,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "requires": { "p-locate": "^5.0.0" } @@ -16360,11 +12115,6 @@ "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -16604,12 +12354,14 @@ "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -16646,6 +12398,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -16653,7 +12406,8 @@ "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true }, "minimist-options": { "version": "4.1.0", @@ -16832,7 +12586,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "multimatch": { "version": "5.0.0", @@ -16861,11 +12616,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -17365,73 +13115,11 @@ } } }, - "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "requires": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", - "requires": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" - } - }, - "object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "requires": { "wrappy": "1" } @@ -17456,19 +13144,6 @@ "is-wsl": "^2.2.0" } }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, "ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -17502,6 +13177,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "requires": { "yocto-queue": "^0.1.0" } @@ -17510,6 +13186,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "requires": { "p-limit": "^3.0.2" } @@ -17712,6 +13389,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { "callsites": "^3.0.0" } @@ -17774,22 +13452,26 @@ "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "path-scurry": { "version": "1.9.2", @@ -17812,12 +13494,14 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true }, "pify": { "version": "5.0.0", @@ -17873,11 +13557,6 @@ } } }, - "possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==" - }, "postcss-selector-parser": { "version": "6.0.13", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", @@ -17888,24 +13567,6 @@ "util-deprecate": "^1.0.2" } }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" - }, - "prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==" - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "requires": { - "fast-diff": "^1.1.2" - } - }, "pretty-format": { "version": "29.4.3", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", @@ -17998,11 +13659,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -18012,7 +13668,8 @@ "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true }, "quick-lru": { "version": "4.0.1", @@ -18291,41 +13948,6 @@ "strip-indent": "^3.0.0" } }, - "reflect.getprototypeof": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", - "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", - "requires": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - } - }, - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "requires": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -18336,6 +13958,7 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, "requires": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -18357,12 +13980,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "peer": true - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -18382,7 +13999,8 @@ "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true }, "rimraf": { "version": "4.4.1", @@ -18441,6 +14059,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "requires": { "queue-microtask": "^1.2.2" } @@ -18454,40 +14073,12 @@ "tslib": "^2.1.0" } }, - "safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "requires": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - } - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, - "safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "requires": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - } - }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -18498,6 +14089,7 @@ "version": "7.5.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" }, @@ -18506,6 +14098,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "requires": { "yallist": "^4.0.0" } @@ -18518,30 +14111,6 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - } - }, - "set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - } - }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -18555,6 +14124,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -18562,18 +14132,8 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - } + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, "signal-exit": { "version": "3.0.7", @@ -18596,7 +14156,8 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, "smart-buffer": { "version": "4.2.0", @@ -18747,40 +14308,11 @@ "strip-ansi": "^6.0.1" } }, - "string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, - "string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - } - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -18815,11 +14347,6 @@ "min-indent": "^1.0.0" } }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - }, "strong-log-transformer": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", @@ -18835,6 +14362,7 @@ "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, "requires": { "has-flag": "^4.0.0" } @@ -18842,16 +14370,8 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "requires": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - } + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true }, "tar": { "version": "6.1.11", @@ -18939,11 +14459,6 @@ "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -19006,6 +14521,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -19028,12 +14544,6 @@ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, - "ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "requires": {} - }, "tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -19056,22 +14566,8 @@ "tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true }, "tuf-js": { "version": "1.1.7", @@ -19084,68 +14580,12 @@ "make-fetch-happen": "^11.1.1" } }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "requires": { - "prelude-ls": "^1.2.1" - } - }, "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 }, - "typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "requires": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "requires": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", - "requires": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - } - }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -19155,7 +14595,8 @@ "typescript": { "version": "4.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", - "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==" + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true }, "uglify-js": { "version": "3.17.4", @@ -19164,17 +14605,6 @@ "dev": true, "optional": true }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, "unique-filename": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", @@ -19220,14 +14650,6 @@ "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", "dev": true }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -19305,67 +14727,6 @@ "isexe": "^2.0.0" } }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "requires": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - } - } - }, - "which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "requires": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - } - }, - "which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "requires": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - } - }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -19406,7 +14767,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "write-file-atomic": { "version": "4.0.1", @@ -19501,7 +14863,8 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "yaml": { "version": "1.10.2", @@ -19533,7 +14896,8 @@ "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 5c2e28ce5c..c9e44e9828 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "start:desktop": "lerna run --scope @quiet/desktop start", "lint:all": "lerna run lint", "distAndRunE2ETests:mac:local": "lerna run --scope @quiet/desktop distMac:local && lerna run --scope e2e-tests test:localBinary --", + "e2e:linux:build": "lerna run --scope @quiet/backend webpack:prod && lerna run --scope @quiet/desktop distUbuntu && lerna run --scope e2e-tests linux:copy", + "e2e:linux:run": "lerna run --scope e2e-tests test --", "prepare": "husky", "lint-staged": "lerna run lint-staged" }, diff --git a/packages/backend/jestSetup.js b/packages/backend/jestSetup.js index 269624f2bd..b82077ab46 100644 --- a/packages/backend/jestSetup.js +++ b/packages/backend/jestSetup.js @@ -1,11 +1,14 @@ -import { setEngine, CryptoEngine } from'pkijs' +import { setEngine, CryptoEngine } from 'pkijs' import { Crypto } from '@peculiar/webcrypto' -const crypto = new Crypto(); -global.crypto = crypto; +const crypto = new Crypto() +global.crypto = crypto -setEngine('newEngine', new CryptoEngine({ +setEngine( + 'newEngine', + new CryptoEngine({ name: 'newEngine', // @ts-ignore crypto: crypto, - })) + }) +) diff --git a/packages/backend/package-lock.json b/packages/backend/package-lock.json index 72b65f7167..2697f66df2 100644 --- a/packages/backend/package-lock.json +++ b/packages/backend/package-lock.json @@ -26,6 +26,7 @@ "dotenv": "8.2.0", "events": "^3.2.0", "express": "^4.17.1", + "fastq": "^1.17.1", "get-port": "^5.1.1", "go-ipfs": "npm:mocked-go-ipfs@0.17.0", "http-server": "^0.12.3", @@ -10816,6 +10817,23 @@ "node": ">= 4.9.1" } }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fastq/node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/fb-watchman": { "version": "2.0.1", "license": "Apache-2.0", @@ -30783,6 +30801,21 @@ "version": "1.0.16", "dev": true }, + "fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "requires": { + "reusify": "^1.0.4" + }, + "dependencies": { + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + } + } + }, "fb-watchman": { "version": "2.0.1", "requires": { diff --git a/packages/backend/package.json b/packages/backend/package.json index 58e01cc76f..87312a5a6e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -108,6 +108,7 @@ "dotenv": "8.2.0", "events": "^3.2.0", "express": "^4.17.1", + "fastq": "^1.17.1", "get-port": "^5.1.1", "go-ipfs": "npm:mocked-go-ipfs@0.17.0", "http-server": "^0.12.3", diff --git a/packages/backend/src/nest/app.module.ts b/packages/backend/src/nest/app.module.ts index 03e987a178..01b4215930 100644 --- a/packages/backend/src/nest/app.module.ts +++ b/packages/backend/src/nest/app.module.ts @@ -105,7 +105,7 @@ export class AppModule { io.engine.use((req, res, next) => { const authHeader = req.headers['authorization'] if (!authHeader) { - console.error('No authorization header') + console.error('Backend server: No authorization header') res.writeHead(401, 'No authorization header') res.end() return @@ -113,7 +113,7 @@ export class AppModule { const token = authHeader && authHeader.split(' ')[1] if (!token) { - console.error('No auth token') + console.error('Backend server: No auth token') res.writeHead(401, 'No authorization token') res.end() return @@ -122,7 +122,7 @@ export class AppModule { if (verifyToken(options.socketIOSecret, token)) { next() } else { - console.error('Wrong basic token') + console.error('Backend server: Unauthorized') res.writeHead(401, 'Unauthorized') res.end() } diff --git a/packages/backend/src/nest/common/client-server.ts b/packages/backend/src/nest/common/client-server.ts index 71e22c4728..b94f8f0b2c 100644 --- a/packages/backend/src/nest/common/client-server.ts +++ b/packages/backend/src/nest/common/client-server.ts @@ -9,7 +9,6 @@ export const createUsersCerts = async ( nickname: 'dev99damian1', commonName: onion, peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLert', - dmPublicKey: 'dmPublicKey1', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, } diff --git a/packages/backend/src/nest/connections-manager/connections-manager.service.spec.ts b/packages/backend/src/nest/connections-manager/connections-manager.service.spec.ts index 9f4d842a1f..e66bbee048 100644 --- a/packages/backend/src/nest/connections-manager/connections-manager.service.spec.ts +++ b/packages/backend/src/nest/connections-manager/connections-manager.service.spec.ts @@ -95,21 +95,23 @@ describe('ConnectionsManagerService', () => { 'y7yczmugl2tekami7sbdz5pfaemvx7bahwthrdvcbzw5vex2crsr26qd', 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE' ) - const launchCommunityPayload: InitCommunityPayload = { + + // Using the factory includes extra properties that affect the assertion + // below + const actualCommunity = { id: community.id, + peerList: [remotePeer], + } + await localDbService.setCommunity(actualCommunity) + await localDbService.setCurrentCommunityId(community.id) + // TODO: Revisit this when we move the Identity model to the backend, since + // this network data lives in that model. + const network = { peerId: userIdentity.peerId, hiddenService: userIdentity.hiddenService, - certs: { - // @ts-expect-error - certificate: userIdentity.userCertificate, - // @ts-expect-error - key: userIdentity.userCsr?.userKey, - CA: [communityRootCa], - }, - peers: [remotePeer], } + await localDbService.setNetworkInfo(network) - await localDbService.put(LocalDBKeys.COMMUNITY, launchCommunityPayload) await connectionsManagerService.closeAllServices() const launchCommunitySpy = jest.spyOn(connectionsManagerService, 'launchCommunity').mockResolvedValue() @@ -117,7 +119,10 @@ describe('ConnectionsManagerService', () => { await connectionsManagerService.init() const localPeerAddress = createLibp2pAddress(userIdentity.hiddenService.onionAddress, userIdentity.peerId.id) - const updatedLaunchCommunityPayload = { ...launchCommunityPayload, peers: [localPeerAddress, remotePeer] } + const updatedLaunchCommunityPayload = { + community: { ...actualCommunity, peerList: [localPeerAddress, remotePeer] }, + network, + } expect(launchCommunitySpy).toHaveBeenCalledWith(updatedLaunchCommunityPayload) }) @@ -129,20 +134,13 @@ describe('ConnectionsManagerService', () => { expect(launchCommunitySpy).not.toHaveBeenCalled() }) - // At this moment, that test have to be skipped, because checking statues is called before launchCommunity method - it.skip('community is only launched once', async () => { - const launchCommunityPayload: InitCommunityPayload = { - id: community.id, - peerId: userIdentity.peerId, - hiddenService: userIdentity.hiddenService, - certs: { - // @ts-expect-error - certificate: userIdentity.userCertificate, - // @ts-expect-error - key: userIdentity.userCsr?.userKey, - CA: [communityRootCa], + it('community is only launched once', async () => { + const launchCommunityPayload = { + community: community, + network: { + peerId: userIdentity.peerId, + hiddenService: userIdentity.hiddenService, }, - peers: community.peerList, } //@ts-ignore @@ -157,22 +155,15 @@ describe('ConnectionsManagerService', () => { }) it('Bug reproduction - Error on startup - Error: TOR: Connection already established - Trigger launchCommunity from backend and state manager', async () => { - const launchCommunityPayload: InitCommunityPayload = { - id: community.id, + await localDbService.setCommunity(community) + await localDbService.setCurrentCommunityId(community.id) + // TODO: Revisit this when we move the Identity model to the backend, since + // this network data lives in that model. + const network = { peerId: userIdentity.peerId, hiddenService: userIdentity.hiddenService, - certs: { - // @ts-expect-error - certificate: userIdentity.userCertificate, - // @ts-expect-error - key: userIdentity.userCsr?.userKey, - CA: [communityRootCa], - }, - peers: community.peerList, } - - // await connectionsManager.init() - await localDbService.put(LocalDBKeys.COMMUNITY, launchCommunityPayload) + await localDbService.setNetworkInfo(network) const peerid = 'QmaEvCkpUG7GxhgvMkk8wxurfi1ehjHhSUNRksWTmXN2ix' await localDbService.put(LocalDBKeys.PEERS, { diff --git a/packages/backend/src/nest/connections-manager/connections-manager.service.tor.spec.ts b/packages/backend/src/nest/connections-manager/connections-manager.service.tor.spec.ts index f545231518..5753e3feb0 100644 --- a/packages/backend/src/nest/connections-manager/connections-manager.service.tor.spec.ts +++ b/packages/backend/src/nest/connections-manager/connections-manager.service.tor.spec.ts @@ -5,8 +5,7 @@ import { CustomEvent } from '@libp2p/interfaces/events' import { jest, beforeEach, describe, it, expect, afterEach } from '@jest/globals' import { communities, getFactory, identity, prepareStore, Store } from '@quiet/state-manager' import { createPeerId, createTmpDir, libp2pInstanceParams, removeFilesFromDir, tmpQuietDirPath } from '../common/utils' - -import { NetworkStats, type Community, type Identity, type InitCommunityPayload } from '@quiet/types' +import { NetworkStats, type Community, type Identity } from '@quiet/types' import { LazyModuleLoader } from '@nestjs/core' import { TestingModule, Test } from '@nestjs/testing' import { FactoryGirl } from 'factory-girl' @@ -31,6 +30,7 @@ import waitForExpect from 'wait-for-expect' import { Libp2pEvents } from '../libp2p/libp2p.types' import { sleep } from '../common/sleep' import { createLibp2pAddress } from '@quiet/common' +import { lib } from 'crypto-js' jest.setTimeout(100_000) @@ -113,7 +113,6 @@ beforeEach(async () => { }) afterEach(async () => { - await libp2pService?.libp2pInstance?.stop() if (connectionsManagerService) { await connectionsManagerService.closeAllServices() } @@ -122,6 +121,10 @@ afterEach(async () => { describe('Connections manager', () => { it('saves peer stats when peer has been disconnected', async () => { + // @ts-expect-error + libp2pService.processInChunksService.init = jest.fn() + // @ts-expect-error + libp2pService.processInChunksService.process = jest.fn() class RemotePeerEventDetail { peerId: string @@ -135,24 +138,12 @@ describe('Connections manager', () => { } const emitSpy = jest.spyOn(libp2pService, 'emit') - const launchCommunityPayload: InitCommunityPayload = { - id: community.id, - peerId: userIdentity.peerId, - hiddenService: userIdentity.hiddenService, - certs: { - // @ts-expect-error - certificate: userIdentity.userCertificate, - // @ts-expect-error - key: userIdentity.userCsr?.userKey, - CA: [communityRootCa], - }, - peers: community.peerList, - } - - await localDbService.put(LocalDBKeys.COMMUNITY, launchCommunityPayload) - // Peer connected await connectionsManagerService.init() + await connectionsManagerService.launchCommunity({ + community, + network: { peerId: userIdentity.peerId, hiddenService: userIdentity.hiddenService }, + }) libp2pService.connectedPeers.set(peerId.toString(), DateTime.utc().valueOf()) // Peer disconnected @@ -161,11 +152,16 @@ describe('Connections manager', () => { remotePeer: new RemotePeerEventDetail(peerId.toString()), remoteAddr: new RemotePeerEventDetail(remoteAddr), } + await waitForExpect(async () => { + expect(libp2pService.libp2pInstance).not.toBeUndefined() + }, 2_000) libp2pService.libp2pInstance?.dispatchEvent( new CustomEvent('peer:disconnect', { detail: peerDisconectEventDetail }) ) + await waitForExpect(async () => { + expect(libp2pService.connectedPeers.size).toEqual(0) + }, 2000) - expect(libp2pService.connectedPeers.size).toEqual(0) await waitForExpect(async () => { expect(await localDbService.get(LocalDBKeys.PEERS)).not.toBeNull() }, 2000) @@ -206,27 +202,23 @@ describe('Connections manager', () => { ) } - const launchCommunityPayload: InitCommunityPayload = { - id: community.id, - peerId: userIdentity.peerId, - hiddenService: userIdentity.hiddenService, - certs: { - // @ts-expect-error Identity.userCertificate can be null - certificate: userIdentity.userCertificate, - // @ts-expect-error Identity.userCertificate userCsr.userKey can be undefined - key: userIdentity.userCsr?.userKey, - // @ts-expect-error - CA: [community.rootCa], + const launchCommunityPayload = { + community: { + id: community.id, + peerList, + }, + network: { + peerId: userIdentity.peerId, + hiddenService: userIdentity.hiddenService, }, - peers: peerList, } await connectionsManagerService.init() await connectionsManagerService.launchCommunity(launchCommunityPayload) await sleep(5000) // It looks LibP2P dials peers initially when it's started and // then IPFS service dials peers again when started, thus - // peersCount * 2 - expect(spyOnDial).toHaveBeenCalledTimes(peersCount * 2) + // peersCount-1 * 2 because we don't dial ourself (the first peer in the list) + expect(spyOnDial).toHaveBeenCalledTimes((peersCount - 1) * 2) // Temporary fix for hanging test - websocketOverTor doesn't have abortController await sleep(5000) }) @@ -248,19 +240,15 @@ describe('Connections manager', () => { ) } - const launchCommunityPayload: InitCommunityPayload = { - id: community.id, - peerId: userIdentity.peerId, - hiddenService: userIdentity.hiddenService, - certs: { - // @ts-expect-error Identity.userCertificate can be null - certificate: userIdentity.userCertificate, - // @ts-expect-error - key: userIdentity.userCsr?.userKey, - // @ts-expect-error - CA: [community.rootCa], + const launchCommunityPayload = { + community: { + id: community.id, + peerList, + }, + network: { + peerId: userIdentity.peerId, + hiddenService: userIdentity.hiddenService, }, - peers: peerList, } await connectionsManagerService.launchCommunity(launchCommunityPayload) diff --git a/packages/backend/src/nest/connections-manager/connections-manager.service.ts b/packages/backend/src/nest/connections-manager/connections-manager.service.ts index be707b27b4..f52de0f6bb 100644 --- a/packages/backend/src/nest/connections-manager/connections-manager.service.ts +++ b/packages/backend/src/nest/connections-manager/connections-manager.service.ts @@ -29,6 +29,7 @@ import { NetworkDataPayload, NetworkInfo, NetworkStats, + type SavedOwnerCertificatePayload, PushNotificationPayload, RegisterOwnerCertificatePayload, RemoveDownloadStatus, @@ -61,7 +62,8 @@ import { StorageEvents } from '../storage/storage.types' import { LazyModuleLoader } from '@nestjs/core' import Logger from '../common/logger' import { emitError } from '../socket/socket.errors' -import { isPSKcodeValid } from '@quiet/common' +import { createLibp2pAddress, isPSKcodeValid } from '@quiet/common' +import { CertFieldsTypes, createRootCA, getCertFieldValue, loadCertificate } from '@quiet/identity' @Injectable() export class ConnectionsManagerService extends EventEmitter implements OnModuleInit { @@ -138,7 +140,6 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI } this.attachSocketServiceListeners() - this.attachRegistrationListeners() this.attachTorEventsListeners() this.attachStorageListeners() @@ -147,26 +148,75 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI } if (this.configOptions.torControlPort) { - console.log('launch 1') + await this.migrateLevelDb() await this.launchCommunityFromStorage() } } + /** + * Migrate LevelDB when upgrading Quiet for existing communities + * + * Move data from Redux in the frontend to LevelDB in the backend for existing + * communities when upgrading. Hopefully this will make features easier to + * test and develop. In order to do this, we need the data to be accessible on + * the backend before it's first used. Since the backend starts up + * asynchronously, independent of the frontend, we wait for the frontend to + * load migration data before launching the community. + */ + public async migrateLevelDb(): Promise { + // Empty promise used to wait on a callback below + let onDataReceived: () => void + const dataReceivedPromise = new Promise((resolve: () => void) => { + onDataReceived = resolve + }) + // This is related to a specific migration, perhaps there is a way to + // encapsulate this in LocalDbService. + const keys = [LocalDBKeys.CURRENT_COMMUNITY_ID, LocalDBKeys.COMMUNITIES] + const keysRequired: string[] = [] + + for (const key of keys) { + if (!(await this.localDbService.exists(key))) { + keysRequired.push(key) + } + } + + this.socketService.on(SocketActionTypes.LOAD_MIGRATION_DATA, async (data: Record) => { + this.logger('Migrating LevelDB') + await this.localDbService.load(data) + onDataReceived() + }) + + // Only require migration data for existing communities. We can tell because + // they are using the deprecated COMMUNITY key in LevelDB. This is related + // to a specific migration. Perhaps we want a more general purpose migration + // mechanism, like a table to hold migrations that have already been + // applied. + if ((await this.localDbService.exists(LocalDBKeys.COMMUNITY)) && keysRequired.length > 0) { + this.logger('Migration data required:', keysRequired) + this.serverIoProvider.io.emit(SocketActionTypes.MIGRATION_DATA_REQUIRED, keysRequired) + await dataReceivedPromise + } else { + this.logger('Nothing to migrate') + } + } + public async launchCommunityFromStorage() { - this.logger('launchCommunityFromStorage') + this.logger('Launching community from storage') - const community: InitCommunityPayload = await this.localDbService.get(LocalDBKeys.COMMUNITY) - this.logger('launchCommunityFromStorage - community peers', community?.peers) - if (community) { - const sortedPeers = await this.localDbService.getSortedPeers(community.peers) + const community = await this.localDbService.getCurrentCommunity() + // TODO: Revisit this when we move the Identity model to the backend, since + // this network data lives in that model. + const network = await this.localDbService.getNetworkInfo() + + if (community && network) { + const sortedPeers = await this.localDbService.getSortedPeers(community.peerList) this.logger('launchCommunityFromStorage - sorted peers', sortedPeers) if (sortedPeers.length > 0) { - community.peers = sortedPeers + community.peerList = sortedPeers } - await this.localDbService.put(LocalDBKeys.COMMUNITY, community) - if ([ServiceState.LAUNCHING, ServiceState.LAUNCHED].includes(this.communityState)) return - this.communityState = ServiceState.LAUNCHING - await this.launchCommunity(community) + await this.localDbService.setCommunity(community) + + await this.launchCommunity({ community, network }) } } @@ -233,8 +283,10 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI public async getNetwork(): Promise { const hiddenService = await this.tor.createNewHiddenService({ targetPort: this.ports.libp2pHiddenService }) - await this.tor.destroyHiddenService(hiddenService.onionAddress.split('.')[0]) + + // TODO: Do we want to create the PeerId here? It doesn't necessarily have + // anything to do with Tor. const peerId: PeerId = await PeerId.create() const peerIdJson = peerId.toJSON() this.logger(`Created network for peer ${peerId.toString()}. Address: ${hiddenService.onionAddress}`) @@ -260,106 +312,192 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI return } + // TODO: Should we save this network info in LevelDB at this point? return network } - private async generatePSK() { - const pskBase64 = Libp2pService.generateLibp2pPSK().psk - await this.localDbService.put(LocalDBKeys.PSK, pskBase64) - this.logger('Generated Libp2p PSK') - this.serverIoProvider.io.emit(SocketActionTypes.LIBP2P_PSK_STORED, { psk: pskBase64 }) - } - - public async createCommunity(payload: InitCommunityPayload) { + public async createCommunity(payload: InitCommunityPayload): Promise { this.logger('Creating community: peers:', payload.peers) - await this.generatePSK() + if (!payload.CA || !payload.rootCa) { + this.logger.error('CA and rootCa are required to create community') + return + } - await this.launchCommunity(payload) - this.logger(`Created and launched community ${payload.id}`) - this.serverIoProvider.io.emit(SocketActionTypes.COMMUNITY_CREATED, { id: payload.id }) - } + if (!payload.ownerCsr) { + this.logger.error('ownerCsr is required to create community') + return + } - public async launchCommunity(payload: InitCommunityPayload) { - this.logger('Launching community: peers:', payload.peers) - this.communityState = ServiceState.LAUNCHING + const psk = Libp2pService.generateLibp2pPSK().psk + let ownerCertResult: SavedOwnerCertificatePayload - // TODO: Move community creation to the backend so that - // launchCommunity/createCommunity return a Community object to the - // frontend. Also deprecate the COMMUNITY/PSK/OWNER_ORBIT_DB_IDENTITY - // IndexDB keys in favor of COMMUNITIES/CURRENT_COMMUNITY_ID/IDENTITIES, - // mirroring the frontend state so that we can easily move things from the - // frontend to the backend. - const communityData: InitCommunityPayload = await this.localDbService.get(LocalDBKeys.COMMUNITY) - if (!communityData) { - await this.localDbService.put(LocalDBKeys.COMMUNITY, payload) + try { + this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.REGISTERING_OWNER_CERTIFICATE) + ownerCertResult = await this.registrationService.registerOwnerCertificate({ + communityId: payload.id, + userCsr: payload.ownerCsr, + permsData: { + certificate: payload.CA.rootCertString, + privKey: payload.CA.rootKeyString, + }, + }) + } catch (e) { + this.logger.error('Failed to register owner certificate') + return } - const psk = payload.psk - if (psk) { - this.logger('Launching community: received Libp2p PSK') - if (!isPSKcodeValid(psk)) { - this.logger.error('Launching community: received Libp2p PSK is not valid') - emitError(this.serverIoProvider.io, { - type: SocketActionTypes.LAUNCH_COMMUNITY, - message: ErrorMessages.NETWORK_SETUP_FAILED, - community: payload.id, - }) - return + const localAddress = createLibp2pAddress(payload.hiddenService.onionAddress, payload.peerId.id) + + let community: Community = { + id: payload.id, + name: payload.name, + CA: payload.CA, + rootCa: payload.rootCa, + peerList: [localAddress], + ownerCertificate: ownerCertResult.network.certificate, + psk: psk, + } + + const network = { + hiddenService: payload.hiddenService, + peerId: payload.peerId, + } + + await this.localDbService.setCommunity(community) + await this.localDbService.setCurrentCommunityId(community.id) + // TODO: Revisit this when we move the Identity model to the backend, since + // this network data lives in that model. + await this.localDbService.setNetworkInfo(network) + + await this.launchCommunity({ community, network }) + + const meta = await this.storageService.updateCommunityMetadata({ + id: community.id, + rootCa: community.rootCa as string, + ownerCertificate: community.ownerCertificate as string, + }) + const currentCommunity = await this.localDbService.getCurrentCommunity() + + if (meta && currentCommunity) { + community = { + ...currentCommunity, + ownerOrbitDbIdentity: meta.ownerOrbitDbIdentity, } - await this.localDbService.put(LocalDBKeys.PSK, psk) + await this.localDbService.setCommunity(community) + } + + this.logger(`Created and launched community ${community.id}`) + + return community + } + + public async joinCommunity(payload: InitCommunityPayload): Promise { + this.logger('Joining community: peers:', payload.peers) + + if (!payload.peers || payload.peers.length === 0) { + this.logger.error('Joining community: Peers required') + return } - const ownerOrbitDbIdentity = payload.ownerOrbitDbIdentity - if (ownerOrbitDbIdentity) { - this.logger("Creating network: received owner's OrbitDB identity") - await this.localDbService.putOwnerOrbitDbIdentity(ownerOrbitDbIdentity) + if (!payload.psk || !isPSKcodeValid(payload.psk)) { + this.logger.error('Joining community: Libp2p PSK is not valid') + emitError(this.serverIoProvider.io, { + type: SocketActionTypes.LAUNCH_COMMUNITY, + message: ErrorMessages.NETWORK_SETUP_FAILED, + community: payload.id, + }) + return } + if (!payload.ownerOrbitDbIdentity) { + this.logger.error('Joining community: ownerOrbitDbIdentity is not valid') + emitError(this.serverIoProvider.io, { + type: SocketActionTypes.LAUNCH_COMMUNITY, + message: ErrorMessages.NETWORK_SETUP_FAILED, + community: payload.id, + }) + return + } + + const localAddress = createLibp2pAddress(payload.hiddenService.onionAddress, payload.peerId.id) + + const community = { + id: payload.id, + peerList: [...new Set([localAddress, ...payload.peers])], + psk: payload.psk, + ownerOrbitDbIdentity: payload.ownerOrbitDbIdentity, + } + + const network = { + hiddenService: payload.hiddenService, + peerId: payload.peerId, + } + + await this.localDbService.setCommunity(community) + await this.localDbService.setCurrentCommunityId(community.id) + // TODO: Revisit this when we move the Identity model to the backend, since + // this network data lives in that model. + await this.localDbService.setNetworkInfo(network) + + await this.launchCommunity({ community, network }) + this.logger(`Joined and launched community ${community.id}`) + + return community + } + + public async launchCommunity({ community, network }: { community: Community; network: NetworkInfo }) { + if ([ServiceState.LAUNCHING, ServiceState.LAUNCHED].includes(this.communityState)) { + this.logger.error( + 'Cannot launch community more than once.' + + ' Community has already been launched or is currently being launched.' + ) + return + } + this.communityState = ServiceState.LAUNCHING + try { - await this.launch(payload) + await this.launch({ community, network }) } catch (e) { - this.logger(`Couldn't launch community for peer ${payload.peerId.id}.`, e) + this.logger(`Couldn't launch community for peer ${network.peerId.id}.`, e) emitError(this.serverIoProvider.io, { type: SocketActionTypes.LAUNCH_COMMUNITY, message: ErrorMessages.COMMUNITY_LAUNCH_FAILED, - community: payload.id, + community: community.id, trace: e.stack, }) return } - this.logger(`Launched community ${payload.id}`) + this.logger(`Launched community ${community.id}`) this.serverIoProvider.io.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.COMMUNITY_LAUNCHED) - this.communityId = payload.id + this.communityId = community.id this.communityState = ServiceState.LAUNCHED - console.log('Hunting for heisenbug: Backend initialized community and sent event to state manager') - // Unblock websocket endpoints this.socketService.resolveReadyness() - this.serverIoProvider.io.emit(SocketActionTypes.COMMUNITY_LAUNCHED, { id: payload.id }) + this.serverIoProvider.io.emit(SocketActionTypes.COMMUNITY_LAUNCHED, { id: community.id }) } - public async spawnTorHiddenService(payload: InitCommunityPayload): Promise { - this.logger(`Spawning hidden service for community ${payload.id}, peer: ${payload.peerId.id}`) + public async spawnTorHiddenService(communityId: string, network: NetworkInfo): Promise { + this.logger(`Spawning hidden service for community ${communityId}, peer: ${network.peerId.id}`) this.serverIoProvider.io.emit( SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.SPAWNING_HIDDEN_SERVICE ) return await this.tor.spawnHiddenService({ targetPort: this.ports.libp2pHiddenService, - privKey: payload.hiddenService.privateKey, + privKey: network.hiddenService.privateKey, }) } - public async launch(payload: InitCommunityPayload) { - this.logger(`Launching community ${payload.id}: peer: ${payload.peerId.id}`) + public async launch({ community, network }: { community: Community; network: NetworkInfo }) { + this.logger(`Launching community ${community.id}: peer: ${network.peerId.id}`) - const onionAddress = await this.spawnTorHiddenService(payload) + const onionAddress = await this.spawnTorHiddenService(community.id, network) const { Libp2pModule } = await import('../libp2p/libp2p.module') const moduleRef = await this.lazyModuleLoader.load(() => Libp2pModule) @@ -367,37 +505,28 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI const lazyService = moduleRef.get(Libp2pService) this.libp2pService = lazyService - const restoredRsa = await PeerId.createFromJSON(payload.peerId) - const _peerId = await peerIdFromKeys(restoredRsa.marshalPubKey(), restoredRsa.marshalPrivKey()) + const restoredRsa = await PeerId.createFromJSON(network.peerId) + const peerId = await peerIdFromKeys(restoredRsa.marshalPubKey(), restoredRsa.marshalPrivKey()) - let peers = payload.peers - this.logger(`Launching community ${payload.id}: payload peers: ${peers}`) - if (!peers || peers.length === 0) { - peers = [this.libp2pService.createLibp2pAddress(onionAddress, _peerId.toString())] - } + const peers = community.peerList + this.logger(`Launching community ${community.id}: payload peers: ${peers}`) - const pskValue: string = await this.localDbService.get(LocalDBKeys.PSK) - if (!pskValue) { - throw new Error('No psk in local db') - } - this.logger(`Launching community ${payload.id}: retrieved Libp2p PSK`) - - const libp2pPSK = Libp2pService.generateLibp2pPSK(pskValue).fullKey const params: Libp2pNodeParams = { - peerId: _peerId, + peerId, listenAddresses: [this.libp2pService.createLibp2pListenAddress(onionAddress)], agent: this.socksProxyAgent, - localAddress: this.libp2pService.createLibp2pAddress(onionAddress, _peerId.toString()), + localAddress: this.libp2pService.createLibp2pAddress(onionAddress, peerId.toString()), targetPort: this.ports.libp2pHiddenService, - peers, - psk: libp2pPSK, + peers: peers ? peers.slice(1) : [], + psk: Libp2pService.generateLibp2pPSK(community.psk).fullKey, } - await this.libp2pService.createInstance(params) + // Libp2p event listeners this.libp2pService.on(Libp2pEvents.PEER_CONNECTED, (payload: { peers: string[] }) => { this.serverIoProvider.io.emit(SocketActionTypes.PEER_CONNECTED, payload) }) + this.libp2pService.on(Libp2pEvents.PEER_DISCONNECTED, async (payload: NetworkDataPayload) => { const peerPrevStats = await this.localDbService.find(LocalDBKeys.PEERS, payload.peer) const prev = peerPrevStats?.connectionTime || 0 @@ -414,14 +543,23 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI // BARTEK: Potentially obsolete to send this to state-manager this.serverIoProvider.io.emit(SocketActionTypes.PEER_DISCONNECTED, payload) }) - await this.storageService.init(_peerId) + + await this.storageService.init(peerId) // We can use Nest for dependency injection, but I think since the // registration service depends on the storage service being // initialized, this is helpful to manually inject the storage // service for now. Both object construction and object // initialization need to happen in order based on dependencies. await this.registrationService.init(this.storageService) - this.logger('storage initialized') + + if (community.CA) { + this.registrationService.setPermsData({ + certificate: community.CA.rootCertString, + privKey: community.CA.rootKeyString, + }) + } + + this.logger('Storage initialized') this.serverIoProvider.io.emit( SocketActionTypes.CONNECTION_PROCESS_INFO, @@ -440,21 +578,11 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI }) } - private attachRegistrationListeners() { - this.registrationService.on(SocketActionTypes.OWNER_CERTIFICATE_ISSUED, payload => { - this.serverIoProvider.io.emit(SocketActionTypes.OWNER_CERTIFICATE_ISSUED, payload) - }) - this.registrationService.on(RegistrationEvents.ERROR, payload => { - emitError(this.serverIoProvider.io, payload) - }) - } - private attachSocketServiceListeners() { // Community this.socketService.on(SocketActionTypes.CONNECTION, async () => { // Update Frontend with Initialized Communities if (this.communityId) { - console.log('Hunting for heisenbug: Backend initialized community and sent event to state manager') this.serverIoProvider.io.emit(SocketActionTypes.COMMUNITY_LAUNCHED, { id: this.communityId }) console.log('this.libp2pService.connectedPeers', this.libp2pService.connectedPeers) console.log('this.libp2pservice', this.libp2pService) @@ -470,25 +598,24 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI }) this.socketService.on( SocketActionTypes.CREATE_NETWORK, - async (communityId: string, callback: (response?: NetworkInfo) => void) => { + async (communityId: string, callback: (response: NetworkInfo | undefined) => void) => { this.logger(`socketService - ${SocketActionTypes.CREATE_NETWORK}`) callback(await this.createNetwork(communityId)) } ) - this.socketService.on(SocketActionTypes.CREATE_COMMUNITY, async (args: InitCommunityPayload) => { - await this.createCommunity(args) - }) - this.socketService.on(SocketActionTypes.LAUNCH_COMMUNITY, async (args: InitCommunityPayload) => { - this.logger(`socketService - ${SocketActionTypes.LAUNCH_COMMUNITY}`) - if ([ServiceState.LAUNCHING, ServiceState.LAUNCHED].includes(this.communityState)) return - this.communityState = ServiceState.LAUNCHING - await this.launchCommunity(args) - }) this.socketService.on( - SocketActionTypes.SET_COMMUNITY_METADATA, - async (payload: CommunityMetadata, callback: (response?: CommunityMetadata) => void) => { - const meta = await this.storageService?.updateCommunityMetadata(payload) - callback(meta) + SocketActionTypes.CREATE_COMMUNITY, + async (args: InitCommunityPayload, callback: (response: Community | undefined) => void) => { + this.logger(`socketService - ${SocketActionTypes.CREATE_COMMUNITY}`) + callback(await this.createCommunity(args)) + } + ) + // TODO: Rename to JOIN_COMMUNITY? + this.socketService.on( + SocketActionTypes.LAUNCH_COMMUNITY, + async (args: InitCommunityPayload, callback: (response: Community | undefined) => void) => { + this.logger(`socketService - ${SocketActionTypes.LAUNCH_COMMUNITY}`) + callback(await this.joinCommunity(args)) } ) this.socketService.on(SocketActionTypes.LEAVE_COMMUNITY, async () => { @@ -500,19 +627,6 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI this.logger(`socketService - ${SocketActionTypes.ADD_CSR}`) await this.storageService?.saveCSR(payload) }) - this.socketService.on( - SocketActionTypes.REGISTER_OWNER_CERTIFICATE, - async (args: RegisterOwnerCertificatePayload) => { - await this.registrationService.registerOwnerCertificate(args) - } - ) - // TODO: Save community CA data in LevelDB. Perhaps save the - // entire Community type in LevelDB. We can probably do this once - // when creating the community. - this.socketService.on(SocketActionTypes.SET_COMMUNITY_CA_DATA, async (payload: PermsData) => { - this.logger(`socketService - ${SocketActionTypes.SET_COMMUNITY_CA_DATA}`) - this.registrationService.setPermsData(payload) - }) // Public Channels this.socketService.on( @@ -609,8 +723,8 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI this.storageService.on(StorageEvents.MESSAGE_MEDIA_UPDATED, (payload: FileMetadata) => { this.serverIoProvider.io.emit(SocketActionTypes.MESSAGE_MEDIA_UPDATED, payload) }) - this.storageService.on(StorageEvents.UPDATE_PEERS_LIST, (payload: StorePeerListPayload) => { - this.serverIoProvider.io.emit(SocketActionTypes.PEER_LIST, payload) + this.storageService.on(StorageEvents.COMMUNITY_UPDATED, (payload: Community) => { + this.serverIoProvider.io.emit(SocketActionTypes.COMMUNITY_UPDATED, payload) }) this.storageService.on(StorageEvents.SEND_PUSH_NOTIFICATION, (payload: PushNotificationPayload) => { this.serverIoProvider.io.emit(SocketActionTypes.PUSH_NOTIFICATION, payload) @@ -623,7 +737,27 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI }) this.storageService.on(StorageEvents.COMMUNITY_METADATA_STORED, async (meta: CommunityMetadata) => { this.logger(`Storage - ${StorageEvents.COMMUNITY_METADATA_STORED}: ${meta}`) - this.serverIoProvider.io.emit(SocketActionTypes.COMMUNITY_METADATA_STORED, meta) + const community = await this.localDbService.getCurrentCommunity() + + if (community) { + const rootCaCert = loadCertificate(meta.rootCa) + const communityName = getCertFieldValue(rootCaCert, CertFieldsTypes.commonName) + + if (!communityName) { + this.logger.error(`Could not retrieve ${CertFieldsTypes.commonName} from CommunityMetadata.rootCa`) + } + + const updatedCommunity = { + ...community, + name: communityName ?? undefined, + rootCa: meta.rootCa, + ownerCertificate: meta.ownerCertificate, + ownerOrbitDbIdentity: meta.ownerOrbitDbIdentity, + } + await this.localDbService.setCommunity(updatedCommunity) + + this.serverIoProvider.io.emit(SocketActionTypes.COMMUNITY_UPDATED, updatedCommunity) + } }) this.storageService.on(StorageEvents.USER_PROFILES_STORED, (payload: UserProfilesStoredEvent) => { this.serverIoProvider.io.emit(SocketActionTypes.USER_PROFILES_STORED, payload) diff --git a/packages/backend/src/nest/libp2p/libp2p.service.spec.ts b/packages/backend/src/nest/libp2p/libp2p.service.spec.ts index 13ebb5f1ed..91d9d177c4 100644 --- a/packages/backend/src/nest/libp2p/libp2p.service.spec.ts +++ b/packages/backend/src/nest/libp2p/libp2p.service.spec.ts @@ -8,7 +8,7 @@ import { Libp2pEvents, Libp2pNodeParams } from './libp2p.types' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import validator from 'validator' import waitForExpect from 'wait-for-expect' -import { ProcessInChunksService } from './process-in-chunks.service' +import { DEFAULT_NUM_TRIES, ProcessInChunksService } from './process-in-chunks.service' describe('Libp2pService', () => { let module: TestingModule @@ -93,10 +93,12 @@ describe('Libp2pService', () => { await libp2pService.createInstance(params) expect(libp2pService.libp2pInstance).not.toBeNull() // @ts-expect-error processItem is private - const dialPeerSpy = jest.spyOn(processInChunks, 'processItem') + const processItemSpy = jest.spyOn(processInChunks, 'processItem') + const dialSpy = jest.spyOn(libp2pService.libp2pInstance!, 'dial') libp2pService.emit(Libp2pEvents.DIAL_PEERS, addresses) await waitForExpect(async () => { - expect(dialPeerSpy).toBeCalledTimes(1) + expect(processItemSpy).toBeCalledTimes(2 * DEFAULT_NUM_TRIES) + expect(dialSpy).toBeCalledTimes(1) }) }) }) diff --git a/packages/backend/src/nest/libp2p/libp2p.types.ts b/packages/backend/src/nest/libp2p/libp2p.types.ts index 1f9d8c9fb7..985c3a4907 100644 --- a/packages/backend/src/nest/libp2p/libp2p.types.ts +++ b/packages/backend/src/nest/libp2p/libp2p.types.ts @@ -17,12 +17,3 @@ export interface Libp2pNodeParams { peers: string[] psk: Uint8Array } - -export interface InitLibp2pParams { - peerId: any - address: string - addressPort: number - targetPort: number - bootstrapMultiaddrs: string[] - certs: Certificates -} diff --git a/packages/backend/src/nest/libp2p/process-in-chunks.service.ts b/packages/backend/src/nest/libp2p/process-in-chunks.service.ts index 2e7b30588b..e57e681227 100644 --- a/packages/backend/src/nest/libp2p/process-in-chunks.service.ts +++ b/packages/backend/src/nest/libp2p/process-in-chunks.service.ts @@ -1,12 +1,22 @@ import { EventEmitter } from 'events' +import fastq from 'fastq' +import type { queue, done } from 'fastq' + import Logger from '../common/logger' const DEFAULT_CHUNK_SIZE = 10 +export const DEFAULT_NUM_TRIES = 2 + +type ProcessTask = { + data: T + tries: number +} export class ProcessInChunksService extends EventEmitter { private isActive: boolean - private data: T[] + private data: Set = new Set() private chunkSize: number + private taskQueue: queue> private processItem: (arg: T) => Promise private readonly logger = Logger(ProcessInChunksService.name) constructor() { @@ -14,43 +24,62 @@ export class ProcessInChunksService extends EventEmitter { } public init(data: T[], processItem: (arg: T) => Promise, chunkSize: number = DEFAULT_CHUNK_SIZE) { - this.data = data + this.logger(`Initializing process-in-chunks.service with peers ${JSON.stringify(data, null, 2)}`) this.processItem = processItem this.chunkSize = chunkSize + this.taskQueue = fastq(this, this.processOneItem, this.chunkSize) + this.updateData(data) + this.addToTaskQueue() } - updateData(items: T[]) { + public updateData(items: T[]) { this.logger(`Updating data with ${items.length} items`) - this.data = [...new Set(this.data.concat(items))] + this.taskQueue.pause() + items.forEach(item => this.data.add(item)) + this.addToTaskQueue() } - public async processOneItem() { - const toProcess = this.data.shift() - if (toProcess) { - try { - await this.processItem(toProcess) - } catch (e) { - this.logger(`Processing ${toProcess} failed, message:`, e.message) - } finally { - process.nextTick(async () => { - await this.processOneItem() - }) + private addToTaskQueue() { + this.logger(`Adding ${this.data.size} items to the task queue`) + for (const item of this.data) { + if (item) { + this.logger(`Adding data ${item} to the task queue`) + this.data.delete(item) + try { + this.taskQueue.push({ data: item, tries: 0 } as ProcessTask) + } catch (e) { + this.logger.error(`Error occurred while adding new task for item ${item} to the queue`, e) + this.data.add(item) + } } } } - public async process() { - this.logger(`Processing ${this.data.length} items`) - for (let i = 0; i < this.chunkSize; i++) { - // Do not wait for this promise as items should be processed simultineously - void this.processOneItem() + public async processOneItem(task: ProcessTask) { + try { + this.logger(`Processing task with data ${task.data}`) + await this.processItem(task.data) + } catch (e) { + this.logger.error(`Processing task with data ${task.data} failed`, e) + if (task.tries + 1 < DEFAULT_NUM_TRIES) { + this.logger(`Will try to re-attempt task with data ${task.data}`) + this.taskQueue.push({ ...task, tries: task.tries + 1 }) + } + } finally { + this.logger(`Done attempting to process task with data ${task.data}`) } } + public async process() { + this.logger(`Processing ${this.taskQueue.length} items`) + this.taskQueue.resume() + } + public stop() { if (this.isActive) { this.logger('Stopping initial dial') this.isActive = false + this.taskQueue.pause() } } } diff --git a/packages/backend/src/nest/libp2p/process-in-chunks.spec.ts b/packages/backend/src/nest/libp2p/process-in-chunks.spec.ts index 38979c1cf9..ce751afdf3 100644 --- a/packages/backend/src/nest/libp2p/process-in-chunks.spec.ts +++ b/packages/backend/src/nest/libp2p/process-in-chunks.spec.ts @@ -27,7 +27,7 @@ describe('ProcessInChunks', () => { processInChunks.init(['a', 'b', 'c', 'd'], mockProcessItem) await processInChunks.process() await waitForExpect(() => { - expect(mockProcessItem).toBeCalledTimes(4) + expect(mockProcessItem).toBeCalledTimes(6) }) }) @@ -43,7 +43,7 @@ describe('ProcessInChunks', () => { processInChunks.updateData(['e', 'f']) await processInChunks.process() await waitForExpect(() => { - expect(mockProcessItem).toBeCalledTimes(4) + expect(mockProcessItem).toBeCalledTimes(5) }) }) @@ -60,7 +60,7 @@ describe('ProcessInChunks', () => { processInChunks.init(['a', 'b', 'c', 'd'], mockProcessItem, chunkSize) await processInChunks.process() await waitForExpect(() => { - expect(mockProcessItem).toBeCalledTimes(4) + expect(mockProcessItem).toBeCalledTimes(2) }) }) diff --git a/packages/backend/src/nest/local-db/local-db.service.ts b/packages/backend/src/nest/local-db/local-db.service.ts index 327a7b43f1..fd36ed80d8 100644 --- a/packages/backend/src/nest/local-db/local-db.service.ts +++ b/packages/backend/src/nest/local-db/local-db.service.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common' import { Level } from 'level' -import { InitCommunityPayload, NetworkStats } from '@quiet/types' +import { type Community, type Identity, InitCommunityPayload, type NetworkInfo, NetworkStats } from '@quiet/types' import { createLibp2pAddress, filterAndSortPeers } from '@quiet/common' import { LEVEL_DB } from '../const' import { LocalDBKeys, LocalDbStatus } from './local-db.types' @@ -42,6 +42,10 @@ export class LocalDbService { return data } + public async exists(key: string): Promise { + return Boolean(await this.get(key)) + } + public async put(key: string, value: any) { await this.db.put(key, value) } @@ -72,23 +76,100 @@ export class LocalDbService { } } - public async getSortedPeers(peers: string[] = []): Promise { + public async delete(key: string) { + await this.db.del(key) + } + + public async load(data: any) { + for (const key in data) { + if (typeof data[key] === 'object' && Object.keys(data[key]).length === 0) { + continue + } + if (typeof data[key] === 'string' && data[key].length === 0) { + continue + } + if (Array.isArray(data[key]) && data[key].length === 0) { + continue + } + await this.put(key, data[key]) + } + } + + public async getSortedPeers( + peers?: string[] | undefined, + includeLocalPeerAddress: boolean = true + ): Promise { + if (!peers) { + const currentCommunity = await this.getCurrentCommunity() + if (!currentCommunity) { + throw new Error('No peers were provided and no community was found to extract peers from') + } + peers = currentCommunity.peerList + if (!peers) { + throw new Error('No peers provided and no peers found on current stored community') + } + } + const peersStats = (await this.get(LocalDBKeys.PEERS)) || {} const stats: NetworkStats[] = Object.values(peersStats) - const community: InitCommunityPayload = await this.get(LocalDBKeys.COMMUNITY) - if (!community) { - return filterAndSortPeers(peers, stats) + const network = await this.getNetworkInfo() + + if (network) { + const localPeerAddress = createLibp2pAddress(network.hiddenService.onionAddress, network.peerId.id) + this.logger('Local peer', localPeerAddress) + return filterAndSortPeers(peers, stats, localPeerAddress, includeLocalPeerAddress) + } else { + return filterAndSortPeers(peers, stats, undefined, includeLocalPeerAddress) } - const localPeerAddress = createLibp2pAddress(community.hiddenService.onionAddress, community.peerId.id) - this.logger('Local peer', localPeerAddress) - return filterAndSortPeers(peers, stats, localPeerAddress) } - public async putOwnerOrbitDbIdentity(id: string): Promise { - this.put(LocalDBKeys.OWNER_ORBIT_DB_IDENTITY, id) + public async setCommunity(community: Community) { + let communities = await this.get(LocalDBKeys.COMMUNITIES) + if (!communities) { + communities = {} + } + communities[community.id] = community + await this.put(LocalDBKeys.COMMUNITIES, communities) } - public async getOwnerOrbitDbIdentity(): Promise { - return this.get(LocalDBKeys.OWNER_ORBIT_DB_IDENTITY) + public async setCurrentCommunityId(communityId: string) { + await this.put(LocalDBKeys.CURRENT_COMMUNITY_ID, communityId) + } + + public async getCommunities(): Promise> { + return await this.get(LocalDBKeys.COMMUNITIES) + } + + public async getCurrentCommunity(): Promise { + const currentCommunityId = await this.get(LocalDBKeys.CURRENT_COMMUNITY_ID) + const communities = await this.get(LocalDBKeys.COMMUNITIES) + + return communities?.[currentCommunityId] + } + + public async communityExists(communityId: string): Promise { + return communityId in ((await this.getCommunities()) ?? {}) + } + + // These are potentially temporary functions to help us migrate data to the + // backend. Currently this information lives under the COMMUNITY key in + // LevelDB, but on the frontend this data lives in the Identity model. So we + // may want to keep this data in the Identity model in LevelDB (when we + // migrate it from the frontend) and have getIdentity/setIdentity functions. + public async setNetworkInfo(network: NetworkInfo) { + await this.put(LocalDBKeys.COMMUNITY, network) + } + + // These are potentially temporary functions to help us migrate data to the + // backend. Currently this information lives under the COMMUNITY key in + // LevelDB, but on the frontend this data lives in the Identity model. So we + // may want to keep this data in the Identity model in LevelDB (when we + // migrate it from the frontend) and have getIdentity/setIdentity functions. + public async getNetworkInfo(): Promise { + const initCommunityPayload = await this.get(LocalDBKeys.COMMUNITY) + + return initCommunityPayload + ? { peerId: initCommunityPayload.peerId, hiddenService: initCommunityPayload.hiddenService } + : undefined } } diff --git a/packages/backend/src/nest/local-db/local-db.types.ts b/packages/backend/src/nest/local-db/local-db.types.ts index aded572cec..f3ea58ed9c 100644 --- a/packages/backend/src/nest/local-db/local-db.types.ts +++ b/packages/backend/src/nest/local-db/local-db.types.ts @@ -1,8 +1,19 @@ export enum LocalDBKeys { - COMMUNITY = 'community', - REGISTRAR = 'registrar', + // Record of Community objects + COMMUNITIES = 'communities', + // ID of current community + CURRENT_COMMUNITY_ID = 'currentCommunityId', + // Record of peer details PEERS = 'peers', + + // TODO: Deprecate this once we move the Identity data model to the backend + // (and delete the data from LevelDB). + COMMUNITY = 'community', + // TODO: Deprecate this soon (and delete the data from LevelDB). This data + // exists in the Community object. PSK = 'psk', + // TODO: Deprecate this soon (and delete the data from LevelDB). This data + // exists in the Community object. OWNER_ORBIT_DB_IDENTITY = 'ownerOrbitDbIdentity', } export type LocalDbStatus = 'opening' | 'open' | 'closing' | 'closed' diff --git a/packages/backend/src/nest/registration/registration.service.spec.ts b/packages/backend/src/nest/registration/registration.service.spec.ts index fbaa2a6191..1ccbcf4dd1 100644 --- a/packages/backend/src/nest/registration/registration.service.spec.ts +++ b/packages/backend/src/nest/registration/registration.service.spec.ts @@ -46,7 +46,6 @@ describe('RegistrationService', () => { nickname: 'userName', commonName: 'nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: 'testdmPublicKey', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, }) @@ -88,7 +87,6 @@ describe('RegistrationService', () => { nickname: 'alice', commonName: 'nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: 'testdmPublicKey', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, }) @@ -122,7 +120,6 @@ describe('RegistrationService', () => { nickname: 'userName2', commonName: 'nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: 'testdmPublicKey', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, }) @@ -136,7 +133,6 @@ describe('RegistrationService', () => { nickname: 'karol', commonName: 'nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: 'testdmPublicKey', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, }) @@ -144,7 +140,6 @@ describe('RegistrationService', () => { nickname: 'karol', commonName: 'nnnnnnc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'QmffffffqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: 'testdmPublicKey', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, }) @@ -187,7 +182,6 @@ describe('RegistrationService', () => { nickname: 'alice', commonName: 'nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: 'testdmPublicKey', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, }) @@ -196,7 +190,6 @@ describe('RegistrationService', () => { nickname: 'alice', commonName: 'nnnnnnc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'QmffffffqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: 'testdmPublicKey', signAlg: configCrypto.signAlg, hashAlg: configCrypto.hashAlg, }) diff --git a/packages/backend/src/nest/registration/registration.service.ts b/packages/backend/src/nest/registration/registration.service.ts index cb74153492..9c04e2bb56 100644 --- a/packages/backend/src/nest/registration/registration.service.ts +++ b/packages/backend/src/nest/registration/registration.service.ts @@ -1,7 +1,14 @@ import { Injectable, OnModuleInit } from '@nestjs/common' import { EventEmitter } from 'events' import { extractPendingCsrs, issueCertificate } from './registration.functions' -import { ErrorCodes, ErrorMessages, PermsData, RegisterOwnerCertificatePayload, SocketActionTypes } from '@quiet/types' +import { + ErrorCodes, + ErrorMessages, + PermsData, + RegisterOwnerCertificatePayload, + type SavedOwnerCertificatePayload, + SocketActionTypes, +} from '@quiet/types' import { RegistrationEvents } from './registration.types' import Logger from '../common/logger' import { StorageService } from '../storage/storage.service' @@ -93,21 +100,22 @@ export class RegistrationService extends EventEmitter implements OnModuleInit { ) } - public async registerOwnerCertificate(payload: RegisterOwnerCertificatePayload): Promise { + // TODO: This doesn't save the owner's certificate in OrbitDB, so perhaps we + // should rename it or look into refactoring so that it does save to OrbitDB. + // However, currently, this is called before the storage service is + // initialized. + public async registerOwnerCertificate( + payload: RegisterOwnerCertificatePayload + ): Promise { this.permsData = payload.permsData const result = await issueCertificate(payload.userCsr.userCsr, this.permsData) if (result?.cert) { - this.emit(SocketActionTypes.OWNER_CERTIFICATE_ISSUED, { + return { communityId: payload.communityId, network: { certificate: result.cert }, - }) + } } else { - this.emit(SocketActionTypes.ERROR, { - type: SocketActionTypes.REGISTER_OWNER_CERTIFICATE, - code: ErrorCodes.SERVER_ERROR, - message: ErrorMessages.REGISTRATION_FAILED, - community: payload.communityId, - }) + throw new Error('Failed to register owner certificate') } } diff --git a/packages/backend/src/nest/socket/socket.service.spec.ts b/packages/backend/src/nest/socket/socket.service.spec.ts index 79089e4410..58fe9f5d82 100644 --- a/packages/backend/src/nest/socket/socket.service.spec.ts +++ b/packages/backend/src/nest/socket/socket.service.spec.ts @@ -59,10 +59,8 @@ describe('SocketService', () => { SocketActionTypes.CREATE_NETWORK.valueOf(), SocketActionTypes.CREATE_COMMUNITY.valueOf(), SocketActionTypes.LAUNCH_COMMUNITY.valueOf(), - SocketActionTypes.REGISTER_OWNER_CERTIFICATE.valueOf(), SocketActionTypes.REGISTER_USER_CERTIFICATE.valueOf(), SocketActionTypes.ADD_CSR.valueOf(), - SocketActionTypes.SET_COMMUNITY_METADATA.valueOf(), ] fragile.forEach(event => { diff --git a/packages/backend/src/nest/socket/socket.service.ts b/packages/backend/src/nest/socket/socket.service.ts index 0057cc0e51..77364128dd 100644 --- a/packages/backend/src/nest/socket/socket.service.ts +++ b/packages/backend/src/nest/socket/socket.service.ts @@ -21,6 +21,8 @@ import { type DeleteChannelResponse, type MessagesLoadedPayload, type NetworkInfo, + CreateNetworkPayload, + CommunityOwnership, } from '@quiet/types' import EventEmitter from 'events' import { CONFIG_OPTIONS, SERVER_IO_PROVIDER } from '../const' @@ -143,33 +145,47 @@ export class SocketService extends EventEmitter implements OnModuleInit { this.emit(SocketActionTypes.ADD_CSR, payload) }) - socket.on(SocketActionTypes.REGISTER_OWNER_CERTIFICATE, async (payload: RegisterOwnerCertificatePayload) => { - this.logger(`Registering owner certificate (${payload.communityId})`) - - this.emit(SocketActionTypes.REGISTER_OWNER_CERTIFICATE, payload) - this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.REGISTERING_OWNER_CERTIFICATE) - }) - // ====== Community ====== - socket.on(SocketActionTypes.CREATE_COMMUNITY, async (payload: InitCommunityPayload) => { - this.logger(`Creating community ${payload.id}`) - this.emit(SocketActionTypes.CREATE_COMMUNITY, payload) - }) + socket.on( + SocketActionTypes.CREATE_COMMUNITY, + async (payload: InitCommunityPayload, callback: (response: Community | undefined) => void) => { + this.logger(`Creating community ${payload.id}`) + this.emit(SocketActionTypes.CREATE_COMMUNITY, payload, callback) + } + ) - socket.on(SocketActionTypes.LAUNCH_COMMUNITY, async (payload: InitCommunityPayload) => { - this.logger(`Launching community ${payload.id} for ${payload.peerId.id}`) - this.emit(SocketActionTypes.LAUNCH_COMMUNITY, payload) - this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.LAUNCHING_COMMUNITY) - }) + socket.on( + SocketActionTypes.LAUNCH_COMMUNITY, + async (payload: InitCommunityPayload, callback: (response: Community | undefined) => void) => { + this.logger(`Launching community ${payload.id} for ${payload.peerId.id}`) + this.emit(SocketActionTypes.LAUNCH_COMMUNITY, payload, callback) + this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.LAUNCHING_COMMUNITY) + } + ) socket.on( SocketActionTypes.CREATE_NETWORK, - async (communityId: string, callback: (response?: NetworkInfo) => void) => { + async (communityId: string, callback: (response: NetworkInfo | undefined) => void) => { this.logger(`Creating network for community ${communityId}`) this.emit(SocketActionTypes.CREATE_NETWORK, communityId, callback) } ) + socket.on( + SocketActionTypes.DOWNLOAD_INVITE_DATA, + async (payload: { serverAddress: string; cid: string }, callback: (response: CreateNetworkPayload) => void) => { + // this.emit(SocketActionTypes.DOWNLOAD_INVITE_DATA, payload, callback) + console.log('download invite data', payload) + // Mock it for now + callback({ + ownership: CommunityOwnership.User, + peers: [], + psk: '', + ownerOrbitDbIdentity: '', + }) + } + ) + socket.on(SocketActionTypes.LEAVE_COMMUNITY, async () => { this.logger('Leaving community') this.emit(SocketActionTypes.LEAVE_COMMUNITY) @@ -180,22 +196,17 @@ export class SocketService extends EventEmitter implements OnModuleInit { this.emit(SocketActionTypes.LIBP2P_PSK_STORED, payload) }) - socket.on( - SocketActionTypes.SET_COMMUNITY_METADATA, - (payload: CommunityMetadata, callback: (response?: CommunityMetadata) => void) => { - this.emit(SocketActionTypes.SET_COMMUNITY_METADATA, payload, callback) - } - ) - - socket.on(SocketActionTypes.SET_COMMUNITY_CA_DATA, (payload: PermsData) => { - this.emit(SocketActionTypes.SET_COMMUNITY_CA_DATA, payload) - }) - // ====== Users ====== socket.on(SocketActionTypes.SET_USER_PROFILE, (profile: UserProfile) => { this.emit(SocketActionTypes.SET_USER_PROFILE, profile) }) + + // ====== Misc ====== + + socket.on(SocketActionTypes.LOAD_MIGRATION_DATA, async (data: Record) => { + this.emit(SocketActionTypes.LOAD_MIGRATION_DATA, data) + }) }) } diff --git a/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.spec.ts b/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.spec.ts index fd7b7d568f..6c49a5604d 100644 --- a/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.spec.ts +++ b/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.spec.ts @@ -40,9 +40,13 @@ describe('CommmunityMetadataStore', () => { let community: Community const mockLocalDbService = { - putOwnerOrbitDbIdentity: jest.fn(), - // @ts-ignore - OrbitDB's type definition doesn't include identity - getOwnerOrbitDbIdentity: jest.fn(() => orbitDbService.orbitDb.identity.id), + setCommunity: jest.fn(), + getCurrentCommunity: jest.fn(() => { + return { + // @ts-ignore - OrbitDB's type definition doesn't include identity + ownerOrbitDbIdentity: orbitDbService.orbitDb.identity.id, + } + }), } beforeAll(async () => { diff --git a/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.ts b/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.ts index 65ce085150..9acbb661be 100644 --- a/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.ts +++ b/packages/backend/src/nest/storage/communityMetadata/communityMetadata.store.ts @@ -123,9 +123,14 @@ export class CommunityMetadataStore extends EventEmitter { ownerOrbitDbIdentity, } - // putOwnerOrbitDbIdentity goes before store.put because the - // store's KeyValueIndex calls getOwnerOrbitDbIdentity - this.localDbService.putOwnerOrbitDbIdentity(ownerOrbitDbIdentity) + // Updating this here before store.put because the store's KeyValueIndex + // then uses the updated Community object. + const community = await this.localDbService.getCurrentCommunity() + if (community) { + await this.localDbService.setCommunity({ ...community, ownerOrbitDbIdentity }) + } else { + throw new Error('Current community missing') + } // FIXME: I think potentially there is a subtle developer // experience bug here. Internally OrbitDB will call @@ -170,7 +175,8 @@ export class CommunityMetadataStore extends EventEmitter { return false } - const ownerOrbitDbIdentity = await localDbService.getOwnerOrbitDbIdentity() + const community = await localDbService.getCurrentCommunity() + const ownerOrbitDbIdentity = community?.ownerOrbitDbIdentity if (!ownerOrbitDbIdentity) { logger.error('Failed to verify community metadata entry:', entry.hash, 'owner identity is invalid') return false diff --git a/packages/backend/src/nest/storage/storage.service.spec.ts b/packages/backend/src/nest/storage/storage.service.spec.ts index 7c0abb0594..fa65bcd37b 100644 --- a/packages/backend/src/nest/storage/storage.service.spec.ts +++ b/packages/backend/src/nest/storage/storage.service.spec.ts @@ -164,7 +164,8 @@ describe('StorageService', () => { expect(ipfsService.ipfsInstance).not.toBeNull() expect(localDbService.getStatus()).toEqual('open') - await localDbService.put(LocalDBKeys.COMMUNITY, community) + await localDbService.setCommunity(community) + await localDbService.setCurrentCommunityId(community.id) }) afterEach(async () => { @@ -524,15 +525,11 @@ describe('StorageService', () => { { onionAddress: '6vu2bxki777it3cpayv6fq6vpl4ke3kzj7gxicfygm55dhhtphyfdvyd.onion', peerId: 'QmXRY4rhAx8Muq8dMGkr9qknJdE6UHZDdGaDRTQEbwFN5b', - dmPublicKey: - '299abdb3a1c456245fa65560624ba583a5d5e35d5945ee14d548df5d37f5a516b281f71e9c66d3e9145a80fb59ce3baae611dd621a838d1cd98676e7f1901261380133ba9cb1e52ae54a52d69134f032368de3caa9ab69dcfce6e9afcc192ce21129d1131efce0994a7f028c8c9977dd403c9509bd9e149e0081f2071ddce0b7fc217756da7deb9e16d57e3a41300c7087a96df9ee5a82d197cbeabfc4011251e2cf7d481161672d94b82df0ea7e593a4bc81919b1516806f26b32dd9774cd11237d98cd346be7a19715ae15c90998e715f095048f8227403fb8cf915ca035ca1e5ef033d990a4dc84750a7de65fc9cc928e773250cd68c625754400d2e836f3f4bb0654a56aad820c3e0e977b304eaec2e0a193c4aac8dfaaee614671ecd11a40317957b56fa8f099d1f6684c826e4984d0ebb8', username: 'o', }, { onionAddress: 'y7yczmugl2tekami7sbdz5pfaemvx7bahwthrdvcbzw5vex2crsr26qd.onion', peerId: 'QmT18UvnUBkseMc3SqnfPxpHwN8nzLrJeNSLZtc8rAFXhz', - dmPublicKey: - '050bf2be48a25c47ff3cb2a7b11d416bd02162c54ef28e7a6e77ed527a15cc19516605332c9bce4aba0f93f1266d5cfea2484cadc60d802587bf1ac0a87555ab42513fa6e2f7c06d094a2dc7a38f147a792b94022fad21a1dd6e02784aa1cc891bdb6ca0cf5a4be92b9ff93e83844206388f676e5c0bb406fd436beb0c8843c7a5061a3830a9bc88ea7b112852b19395d5feb1ae75d8082ff3c9473ce4612ec9c2f35489a0010bcf0136dd333638cd21a734b1f192f494371691f4b9c459ffa2d637aa70e8973af99dc94e417b766a8462afbc183fe6fc8b4220887de6a98d97a69cba851d0062b609439b6c6728be87cccc9f6680073d5ed8716611e2ca54f49bbc43c6aa49e02bcb1eecc79e5e491e063b95104e8e43ad09fac6d930399ff2b6c3a49c5b6117c8dc03db9300c0ca0364f29425', username: 'o', }, ]) diff --git a/packages/backend/src/nest/storage/storage.service.ts b/packages/backend/src/nest/storage/storage.service.ts index a15388082c..5f353a3119 100644 --- a/packages/backend/src/nest/storage/storage.service.ts +++ b/packages/backend/src/nest/storage/storage.service.ts @@ -317,13 +317,15 @@ export class StorageService extends EventEmitter { const peers = Array.from(new Set(users.map(peer => createLibp2pAddress(peer.onionAddress, peer.peerId)))) console.log('updatePeersList, peers count:', peers.length) - const community = await this.localDbService.get(LocalDBKeys.COMMUNITY) + const community = await this.localDbService.getCurrentCommunity() + if (!community) return + const sortedPeers = await this.localDbService.getSortedPeers(peers) if (sortedPeers.length > 0) { - community.peers = sortedPeers - await this.localDbService.put(LocalDBKeys.COMMUNITY, community) + community.peerList = sortedPeers + await this.localDbService.setCommunity(community) } - this.emit(StorageEvents.UPDATE_PEERS_LIST, { communityId: community.id, peerList: peers }) + this.emit(StorageEvents.COMMUNITY_UPDATED, community) } public async loadAllCertificates() { @@ -501,22 +503,28 @@ export class StorageService extends EventEmitter { db.events.on('replicated', async address => { this.logger('Replicated.', address) const ids = this.getAllEventLogEntries(db).map(msg => msg.id) - const community = await this.localDbService.get(LocalDBKeys.COMMUNITY) - this.emit(StorageEvents.MESSAGE_IDS_STORED, { - ids, - channelId: channelData.id, - communityId: community.id, - }) + const community = await this.localDbService.getCurrentCommunity() + + if (community) { + this.emit(StorageEvents.MESSAGE_IDS_STORED, { + ids, + channelId: channelData.id, + communityId: community.id, + }) + } }) db.events.on('ready', async () => { const ids = this.getAllEventLogEntries(db).map(msg => msg.id) - const community = await this.localDbService.get(LocalDBKeys.COMMUNITY) - this.emit(StorageEvents.MESSAGE_IDS_STORED, { - ids, - channelId: channelData.id, - communityId: community.id, - }) + const community = await this.localDbService.getCurrentCommunity() + + if (community) { + this.emit(StorageEvents.MESSAGE_IDS_STORED, { + ids, + channelId: channelData.id, + communityId: community.id, + }) + } }) await db.load() @@ -612,15 +620,15 @@ export class StorageService extends EventEmitter { } } await repo.db.load() - const allEntries = this.getAllEventLogRawEntries(repo.db) + // const allEntries = this.getAllEventLogRawEntries(repo.db) await repo.db.close() await repo.db.drop() - const hashes = allEntries.map(e => CID.parse(e.hash)) - const files = allEntries - .map(e => { - return e.payload.value.media - }) - .filter(isDefined) + // const hashes = allEntries.map(e => CID.parse(e.hash)) + // const files = allEntries + // .map(e => { + // return e.payload.value.media + // }) + // .filter(isDefined) // await this.deleteChannelFiles(files) // await this.deleteChannelMessages(hashes) this.publicChannelsRepos.delete(channelId) @@ -730,9 +738,8 @@ export class StorageService extends EventEmitter { const onionAddress = getReqFieldValue(parsedCert, CertFieldsTypes.commonName) const peerId = getReqFieldValue(parsedCert, CertFieldsTypes.peerId) const username = getReqFieldValue(parsedCert, CertFieldsTypes.nickName) - const dmPublicKey = getReqFieldValue(parsedCert, CertFieldsTypes.dmPublicKey) - if (!onionAddress || !peerId || !username || !dmPublicKey) continue - allUsers.push({ onionAddress, peerId, username, dmPublicKey }) + if (!onionAddress || !peerId || !username) continue + allUsers.push({ onionAddress, peerId, username }) } return allUsers } diff --git a/packages/backend/src/nest/storage/storage.types.ts b/packages/backend/src/nest/storage/storage.types.ts index 599739059f..40949570c6 100644 --- a/packages/backend/src/nest/storage/storage.types.ts +++ b/packages/backend/src/nest/storage/storage.types.ts @@ -1,8 +1,6 @@ import { Certificates } from '@quiet/types' export enum StorageEvents { - // Peers - UPDATE_PEERS_LIST = 'updatePeersList', // Public Channels CHANNEL_SUBSCRIBED = 'channelSubscribed', CHANNELS_STORED = 'channelsStored', @@ -22,15 +20,7 @@ export enum StorageEvents { USER_PROFILES_STORED = 'userProfilesStored', // Community COMMUNITY_METADATA_STORED = 'communityMetadataStored', -} - -export interface InitStorageParams { - communityId: string - peerId: any - onionAddress: string - targetPort: number - peers?: string[] - certs: Certificates + COMMUNITY_UPDATED = 'communityUpdated', } export interface CsrReplicatedPromiseValues { diff --git a/packages/backend/src/nest/websocketOverTor/index.ts b/packages/backend/src/nest/websocketOverTor/index.ts index 929ac78cb2..e714970e8b 100644 --- a/packages/backend/src/nest/websocketOverTor/index.ts +++ b/packages/backend/src/nest/websocketOverTor/index.ts @@ -81,6 +81,7 @@ export class WebSockets extends EventEmitter { websocket: { ...this._websocketOpts, }, + signal: options.signal, }) } catch (e) { log.error('error connecting to %s. Details: %s', ma, e.message) diff --git a/packages/mobile/src/utils/functions/areObjectsEqual/areObjectsEqual.ts b/packages/common/src/compare.ts similarity index 58% rename from packages/mobile/src/utils/functions/areObjectsEqual/areObjectsEqual.ts rename to packages/common/src/compare.ts index d2f9899e4f..10db5fdbc0 100644 --- a/packages/mobile/src/utils/functions/areObjectsEqual/areObjectsEqual.ts +++ b/packages/common/src/compare.ts @@ -1,3 +1,4 @@ export const areObjectsEqual = (obj1: any, obj2: any): boolean => { + // Using this only makes sense for small objects whose properties are in the same order return JSON.stringify(obj1) === JSON.stringify(obj2) } diff --git a/packages/common/src/dir.ts b/packages/common/src/dir.ts new file mode 100644 index 0000000000..4130a7ed4d --- /dev/null +++ b/packages/common/src/dir.ts @@ -0,0 +1,19 @@ +import path from 'path' +import { DESKTOP_DATA_DIR, DESKTOP_DEV_DATA_DIR } from './static' + +export type GetDataAppPathDefaults = { + appDataPath?: string + dataDir?: string +} + +export const getAppDataPath = (defaults: GetDataAppPathDefaults = {}): string => { + const defaultAppDataPath = defaults.appDataPath || process.env.APPDATA + const defaultDataDir = defaults.dataDir || process.env.DATA_DIR + + const dataPath = + defaultAppDataPath || + (process.platform === 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + '/.config') + const appPath = defaultDataDir || (process.env.NODE_ENV === 'development' ? DESKTOP_DEV_DATA_DIR : DESKTOP_DATA_DIR) + + return path.join(dataPath, appPath) +} diff --git a/packages/common/src/emojis.test.ts b/packages/common/src/emojis.test.ts new file mode 100644 index 0000000000..17337f8147 --- /dev/null +++ b/packages/common/src/emojis.test.ts @@ -0,0 +1,22 @@ +import { hasEmoji, isAllEmoji } from './emojis' + +describe('Emoji Utilities', () => { + it('Should detect an emoji in a string', () => { + expect(hasEmoji('❤️‍🔥')).toBeTruthy() + expect(hasEmoji('Hello ❤️‍🔥 Emoji')).toBeTruthy() + expect(hasEmoji('No emoji :-(')).toBeFalsy() + }) + + it('Should detect when a string is all emojis (or spaces)', () => { + expect(isAllEmoji('🙂🙂🙂🙂🙂🙂🙂🙂')).toBeTruthy() + expect(isAllEmoji('🐈‍⬛❤️‍🔥🏴')).toBeTruthy() + expect(isAllEmoji('🐈‍⬛ ❤️‍🔥 🏴')).toBeTruthy() + expect(isAllEmoji('❤️‍🔥')).toBeTruthy() + expect(isAllEmoji('🐈‍⬛')).toBeTruthy() + expect(isAllEmoji('❤️‍🔥 Emoji')).toBeFalsy() + expect(isAllEmoji('Hello ❤️‍🔥')).toBeFalsy() + expect(isAllEmoji('Hello ❤️‍🔥 Emoji')).toBeFalsy() + expect(isAllEmoji('🐈‍⬛ (Not emoji) 🏴')).toBeFalsy() + expect(isAllEmoji('No emoji :-(')).toBeFalsy() + }) +}) diff --git a/packages/common/src/emojis.ts b/packages/common/src/emojis.ts new file mode 100644 index 0000000000..ac5a7486da --- /dev/null +++ b/packages/common/src/emojis.ts @@ -0,0 +1,12 @@ +export const hasEmoji = (testString: string) => { + // All strings with at least one emoji character should match this + const regExp = /\p{Emoji}/gu + return regExp.test(testString) +} + +export const isAllEmoji = (testString: string) => { + // Detect whether a string is entirely emojis (and whitespace and zero-width-joins, region indicators, etc) + // This may need to be updated as Unicode's Emoji spec is a moving target + const emojiOrWhitespaceRegExp = /^(\p{Emoji}|\p{Emoji_Modifier}|\uFE0F|\u200D|\p{RI}|\uE007F|\s)+$/gu + return emojiOrWhitespaceRegExp.test(testString) +} diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index f15cd34520..90c610f716 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -11,3 +11,5 @@ export * from './libp2p' export * from './tests' export * from './auth' export * from './messages' +export * from './compare' +export * from './dir' diff --git a/packages/common/src/invitationCode.test.ts b/packages/common/src/invitationCode.test.ts index 5f18ae4378..6a48b409a2 100644 --- a/packages/common/src/invitationCode.test.ts +++ b/packages/common/src/invitationCode.test.ts @@ -1,120 +1,172 @@ -import { InvitationData } from '@quiet/types' +import { InvitationDataV1, InvitationDataVersion, InvitationPair } from '@quiet/types' import { argvInvitationCode, composeInvitationDeepUrl, - invitationShareUrl, composeInvitationShareUrl, parseInvitationCodeDeepUrl, PSK_PARAM_KEY, + OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, + p2pAddressesToPairs, + CID_PARAM_KEY, + TOKEN_PARAM_KEY, + SERVER_ADDRESS_PARAM_KEY, + INVITER_ADDRESS_PARAM_KEY, + DEEP_URL_SCHEME_WITH_SEPARATOR, } from './invitationCode' import { QUIET_JOIN_PAGE } from './static' +import { validInvitationDatav1, validInvitationDatav2 } from './tests' +import { createLibp2pAddress } from './libp2p' -describe('Invitation code helper', () => { - const peerId1 = 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSA' - const address1 = 'gloao6h5plwjy4tdlze24zzgcxll6upq2ex2fmu2ohhyu4gtys4nrjad' - const peerId2 = 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE' - const address2 = 'y7yczmugl2tekami7sbdz5pfaemvx7bahwthrdvcbzw5vex2crsr26qd' - const psk = 'BNlxfE2WBF7LrlpIX0CvECN5o1oZtA16PkAb7GYiwYw%3D' - const pskDecoded = 'BNlxfE2WBF7LrlpIX0CvECN5o1oZtA16PkAb7GYiwYw=' - const ownerOrbitDbIdentity = 'testOwnerOrbitDbIdentity' +describe(`Invitation code helper ${InvitationDataVersion.v1}`, () => { + const address = 'gloao6h5plwjy4tdlze24zzgcxll6upq2ex2fmu2ohhyu4gtys4nrjad' + const peerId = 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE' + const data: InvitationDataV1 = { + ...validInvitationDatav1[0], + pairs: [...validInvitationDatav1[0].pairs, { peerId: peerId, onionAddress: address }], + } + const urlParams = [ + [data.pairs[0].peerId, data.pairs[0].onionAddress], + [data.pairs[1].peerId, data.pairs[1].onionAddress], + [PSK_PARAM_KEY, data.psk], + [OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, data.ownerOrbitDbIdentity], + ] it('retrieves invitation code from argv', () => { - const expectedCodes: InvitationData = { - pairs: [ - { peerId: peerId1, onionAddress: address1 }, - { peerId: peerId2, onionAddress: address2 }, - ], - psk: pskDecoded, - ownerOrbitDbIdentity, - } - const result = argvInvitationCode([ - 'something', - 'quiet:/invalid', - 'zbay://invalid', - 'quiet://invalid', - 'quiet://?param=invalid', - composeInvitationDeepUrl(expectedCodes), - ]) - expect(result).toEqual(expectedCodes) + const result = argvInvitationCode(['something', 'quiet:/invalid', 'zbay://invalid', composeInvitationDeepUrl(data)]) + expect(result).toEqual(data) }) - it('returns null if argv do not contain any valid invitation code', () => { - const result = argvInvitationCode([ - 'something', - 'quiet:/invalid', - 'zbay://invalid', - 'quiet://invalid', - 'quiet://?param=invalid', - ]) + it('returns null if argv do not contain any url with proper scheme', () => { + const result = argvInvitationCode(['something', 'quiet:/invalid', 'zbay://invalid']) expect(result).toBeNull() }) + it('throws error if argv contains invalid invitation url', () => { + expect(() => { + argvInvitationCode(['something', 'quiet:/invalid', 'quiet://?param=invalid']) + }).toThrow() + }) + it('composes proper invitation deep url', () => { - expect( - composeInvitationDeepUrl({ - pairs: [ - { peerId: 'peerID1', onionAddress: 'address1' }, - { peerId: 'peerID2', onionAddress: 'address2' }, - ], - psk: pskDecoded, - ownerOrbitDbIdentity, - }) - ).toEqual(`quiet://?peerID1=address1&peerID2=address2&${PSK_PARAM_KEY}=${psk}`) + const url = new URL(DEEP_URL_SCHEME_WITH_SEPARATOR) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + expect(composeInvitationDeepUrl(data)).toEqual(url.href) }) it('creates invitation share url based on invitation data', () => { - const pairs: InvitationData = { - pairs: [ - { peerId: 'peerID1', onionAddress: 'address1' }, - { peerId: 'peerID2', onionAddress: 'address2' }, - ], - psk: pskDecoded, - ownerOrbitDbIdentity, - } - const expected = `${QUIET_JOIN_PAGE}#peerID1=address1&peerID2=address2&${PSK_PARAM_KEY}=${psk}` - expect(composeInvitationShareUrl(pairs)).toEqual(expected) + const url = new URL(QUIET_JOIN_PAGE) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + expect(composeInvitationShareUrl(data)).toEqual(url.href.replace('?', '#')) }) - it('builds proper invitation share url from peers addresses', () => { + it('converts list of p2p addresses to invitation pairs', () => { + const pair: InvitationPair = { + peerId: 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE', + onionAddress: 'gloao6h5plwjy4tdlze24zzgcxll6upq2ex2fmu2ohhyu4gtys4nrjad', + } const peerList = [ - '/dns4/gloao6h5plwjy4tdlze24zzgcxll6upq2ex2fmu2ohhyu4gtys4nrjad.onion/tcp/443/wss/p2p/QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE', + createLibp2pAddress(pair.onionAddress, pair.peerId), 'invalidAddress', - '/dns4/somethingElse.onion/tcp/443/wss/p2p/QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSA', + createLibp2pAddress('somethingElse.onion', 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSA'), ] - expect(invitationShareUrl(peerList, pskDecoded, ownerOrbitDbIdentity)).toEqual( - `${QUIET_JOIN_PAGE}#QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE=gloao6h5plwjy4tdlze24zzgcxll6upq2ex2fmu2ohhyu4gtys4nrjad&QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSA=somethingElse&${PSK_PARAM_KEY}=${psk}` - ) + expect(p2pAddressesToPairs(peerList)).toEqual([pair]) }) it('retrieves invitation codes from deep url', () => { - const codes = parseInvitationCodeDeepUrl( - `quiet://?${peerId1}=${address1}&${peerId2}=${address2}&${PSK_PARAM_KEY}=${psk}` - ) + const url = new URL(DEEP_URL_SCHEME_WITH_SEPARATOR) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + + const codes = parseInvitationCodeDeepUrl(url.href) expect(codes).toEqual({ - pairs: [ - { peerId: peerId1, onionAddress: address1 }, - { peerId: peerId2, onionAddress: address2 }, - ], - psk: pskDecoded, - ownerOrbitDbIdentity, + version: InvitationDataVersion.v1, + ...data, }) }) - it.each([['12345'], ['a2FzemE='], 'a2FycGllIHcgZ2FsYXJlY2llIGVjaWUgcGVjaWUgYWxlIGkgdGFrIHpqZWNpZQ=='])( - 'parsing invitation code throws error if psk is invalid: (%s)', - (psk: string) => { - expect(() => { - parseInvitationCodeDeepUrl(`quiet://?${peerId1}=${address1}&${peerId2}=${address2}&${PSK_PARAM_KEY}=${psk}`) - }).toThrow() - } - ) - - it('retrieves invitation codes from deep url with partly invalid codes', () => { - const peerId2 = 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLs' - const address2 = 'y7yczmugl2tekami7sbdz5pfaemvx7bahwthrdvcbzw5vex2crsr26qd' - const parsed = parseInvitationCodeDeepUrl( - `quiet://?${peerId1}=${address1}&${peerId2}=${address2}&${PSK_PARAM_KEY}=${psk}` - ) - expect(parsed).toEqual({ pairs: [{ peerId: peerId1, onionAddress: address1 }], psk: pskDecoded }) + it.each([ + [PSK_PARAM_KEY, '12345'], + [PSK_PARAM_KEY, 'a2FzemE='], + [PSK_PARAM_KEY, 'a2FycGllIHcgZ2FsYXJlY2llIGVjaWUgcGVjaWUgYWxlIGkgdGFrIHpqZWNpZQ=='], + ])('parsing deep url throws error if data is invalid: %s=%s', (paramKey: string, paramValue: string) => { + const url = new URL(DEEP_URL_SCHEME_WITH_SEPARATOR) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + + // Replace valid param value with invalid one + url.searchParams.set(paramKey, paramValue) + + expect(() => { + parseInvitationCodeDeepUrl(url.href) + }).toThrow() + }) + + it('retrieves invitation codes from deep url with partly invalid addresses', () => { + const urlParamsWithInvalidAddress = [ + [data.pairs[0].peerId, data.pairs[0].onionAddress], + [data.pairs[1].peerId, data.pairs[1].onionAddress], + ['QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wf', 'y7yczmugl2tekami7sbdz5pfaemvx7bahwthrdv'], + [PSK_PARAM_KEY, data.psk], + [OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, data.ownerOrbitDbIdentity], + ] + + const url = new URL(DEEP_URL_SCHEME_WITH_SEPARATOR) + urlParamsWithInvalidAddress.forEach(([key, value]) => url.searchParams.append(key, value)) + + const parsed = parseInvitationCodeDeepUrl(url.href) + expect(parsed).toEqual({ + version: InvitationDataVersion.v1, + ...data, + }) + }) +}) + +describe(`Invitation code helper ${InvitationDataVersion.v2}`, () => { + const data = validInvitationDatav2[0] + const urlParams = [ + [CID_PARAM_KEY, data.cid], + [TOKEN_PARAM_KEY, data.token], + [SERVER_ADDRESS_PARAM_KEY, data.serverAddress], + [INVITER_ADDRESS_PARAM_KEY, data.inviterAddress], + ] + + it('creates invitation share url based on invitation data', () => { + const url = new URL(QUIET_JOIN_PAGE) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + expect(composeInvitationShareUrl(data)).toEqual(url.href.replace('?', '#')) + }) + + it('composes proper invitation deep url', () => { + const url = new URL(DEEP_URL_SCHEME_WITH_SEPARATOR) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + expect(composeInvitationDeepUrl(data)).toEqual(url.href) + }) + + it('retrieves invitation codes from deep url v2', () => { + const url = new URL(DEEP_URL_SCHEME_WITH_SEPARATOR) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + const codes = parseInvitationCodeDeepUrl(url.href) + expect(codes).toEqual({ + version: InvitationDataVersion.v2, + cid: data.cid, + token: data.token, + serverAddress: data.serverAddress, + inviterAddress: data.inviterAddress, + }) + }) + + it.each([ + // TODO: add check for invalid token + [CID_PARAM_KEY, 'sth'], + [SERVER_ADDRESS_PARAM_KEY, 'website.com'], + [INVITER_ADDRESS_PARAM_KEY, 'abcd'], + ])('parsing deep url throws error if data is invalid: %s=%s', (paramKey: string, paramValue: string) => { + const url = new URL(DEEP_URL_SCHEME_WITH_SEPARATOR) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + + // Replace valid param value with invalid one + url.searchParams.set(paramKey, paramValue) + + expect(() => { + parseInvitationCodeDeepUrl(url.href) + }).toThrow() }) }) diff --git a/packages/common/src/invitationCode.ts b/packages/common/src/invitationCode.ts index 470fb6536e..16182ed325 100644 --- a/packages/common/src/invitationCode.ts +++ b/packages/common/src/invitationCode.ts @@ -1,12 +1,21 @@ -import { InvitationData, InvitationPair } from '@quiet/types' +import { InvitationData, InvitationDataV1, InvitationDataV2, InvitationDataVersion, InvitationPair } from '@quiet/types' import { QUIET_JOIN_PAGE } from './static' import { createLibp2pAddress, isPSKcodeValid } from './libp2p' +// import { CID } from 'multiformats/cid' // Fixme: dependency issue import Logger from './logger' const logger = Logger('invite') +// V1 invitation code format (p2p without relay) export const PSK_PARAM_KEY = 'k' export const OWNER_ORBIT_DB_IDENTITY_PARAM_KEY = 'o' -const DEEP_URL_SCHEME_WITH_SEPARATOR = 'quiet://' + +// V2 invitation code format (relay support) +export const CID_PARAM_KEY = 'c' +export const TOKEN_PARAM_KEY = 't' +export const INVITER_ADDRESS_PARAM_KEY = 'i' +export const SERVER_ADDRESS_PARAM_KEY = 's' + +export const DEEP_URL_SCHEME_WITH_SEPARATOR = 'quiet://' const DEEP_URL_SCHEME = 'quiet' const ONION_ADDRESS_REGEX = /^[a-z0-9]{56}$/g const PEER_ID_REGEX = /^[a-zA-Z0-9]{46}$/g @@ -16,6 +25,53 @@ interface ParseDeepUrlParams { expectedProtocol?: string } +const parseCodeV2 = (url: string): InvitationDataV2 => { + /** + * c=&t=&s=&i= + */ + const params = new URL(url).searchParams + const requiredParams = [CID_PARAM_KEY, TOKEN_PARAM_KEY, SERVER_ADDRESS_PARAM_KEY, INVITER_ADDRESS_PARAM_KEY] + + const entries = validateUrlParams(params, requiredParams) + + return { + version: InvitationDataVersion.v2, + cid: entries[CID_PARAM_KEY], + token: entries[TOKEN_PARAM_KEY], + serverAddress: entries[SERVER_ADDRESS_PARAM_KEY], + inviterAddress: entries[INVITER_ADDRESS_PARAM_KEY], + } +} + +const parseCodeV1 = (url: string): InvitationDataV1 => { + /** + * =&=...&k=&o= + */ + const params = new URL(url).searchParams + const requiredParams = [PSK_PARAM_KEY, OWNER_ORBIT_DB_IDENTITY_PARAM_KEY] + + const entries = validateUrlParams(params, requiredParams) + + const codes: InvitationPair[] = [] + + params.forEach((onionAddress, peerId) => { + if (!peerDataValid({ peerId, onionAddress })) return + codes.push({ + peerId, + onionAddress, + }) + }) + + if (codes.length === 0) throw new Error(`No valid peer addresses found in invitation code '${url}'`) + + return { + version: InvitationDataVersion.v1, + pairs: codes, + psk: entries[PSK_PARAM_KEY], + ownerOrbitDbIdentity: entries[OWNER_ORBIT_DB_IDENTITY_PARAM_KEY], + } +} + const parseDeepUrl = ({ url, expectedProtocol = `${DEEP_URL_SCHEME}:` }: ParseDeepUrlParams): InvitationData => { let _url = url let validUrl: URL | null = null @@ -23,7 +79,7 @@ const parseDeepUrl = ({ url, expectedProtocol = `${DEEP_URL_SCHEME}:` }: ParseDe if (!expectedProtocol) { // Create a full url to be able to use the same URL parsing mechanism expectedProtocol = `${DEEP_URL_SCHEME}:` - _url = `${DEEP_URL_SCHEME}://?${url}` + _url = `${DEEP_URL_SCHEME_WITH_SEPARATOR}?${url}` } try { @@ -38,32 +94,22 @@ const parseDeepUrl = ({ url, expectedProtocol = `${DEEP_URL_SCHEME}:` }: ParseDe } const params = validUrl.searchParams - const codes: InvitationPair[] = [] - let psk = params.get(PSK_PARAM_KEY) - if (!psk) throw new Error(`No psk found in invitation code '${url}'`) - psk = decodeURIComponent(psk) - if (!isPSKcodeValid(psk)) throw new Error(`Invalid psk in invitation code '${url}'`) - params.delete(PSK_PARAM_KEY) + const psk = params.get(PSK_PARAM_KEY) + const cid = params.get(CID_PARAM_KEY) + if (!psk && !cid) throw new Error(`Invitation code does not match either v1 or v2 format '${url}'`) - let ownerOrbitDbIdentity = params.get(OWNER_ORBIT_DB_IDENTITY_PARAM_KEY) - if (!ownerOrbitDbIdentity) throw new Error(`No owner OrbitDB identity found in invitation code '${url}'`) - ownerOrbitDbIdentity = decodeURIComponent(ownerOrbitDbIdentity) - params.delete(OWNER_ORBIT_DB_IDENTITY_PARAM_KEY) - - params.forEach((onionAddress, peerId) => { - if (!peerDataValid({ peerId, onionAddress })) return - codes.push({ - peerId, - onionAddress, - }) - }) - logger('Retrieved data:', codes) - return { - pairs: codes, - psk, - ownerOrbitDbIdentity, + let data: InvitationData + if (psk) { + data = parseCodeV1(_url) + } else { + data = parseCodeV2(_url) } + + if (!data) throw new Error(`Could not parse invitation code from deep url '${url}'`) + + logger(`Invitation data '${data}' parsed`) + return data } /** @@ -81,15 +127,12 @@ export const parseInvitationCode = (code: string): InvitationData => { return parseDeepUrl({ url: code, expectedProtocol: '' }) } -/** - * @arg {string[]} peers - List of peer's p2p addresses - * @arg psk - Pre shared key in base64 - * @returns {string} - Complete shareable invitation link, e.g. - * https://tryquiet.org/join/#=&=&k=&o= - */ -export const invitationShareUrl = (peers: string[] = [], psk: string, ownerOrbitDbIdentity: string): string => { +export const p2pAddressesToPairs = (addresses: string[]): InvitationPair[] => { + /** + * @arg {string[]} addresses - List of peer's p2p addresses + */ const pairs: InvitationPair[] = [] - for (const peerAddress of peers) { + for (const peerAddress of addresses) { let peerId: string let onionAddress: string try { @@ -110,10 +153,11 @@ export const invitationShareUrl = (peers: string[] = [], psk: string, ownerOrbit continue } const rawAddress = onionAddress.endsWith('.onion') ? onionAddress.split('.')[0] : onionAddress + if (!peerDataValid({ peerId, onionAddress: rawAddress })) continue + pairs.push({ peerId: peerId, onionAddress: rawAddress }) } - - return composeInvitationShareUrl({ pairs, psk, ownerOrbitDbIdentity }) + return pairs } export const pairsToP2pAddresses = (pairs: InvitationPair[]): string[] => { @@ -125,6 +169,10 @@ export const pairsToP2pAddresses = (pairs: InvitationPair[]): string[] => { } export const composeInvitationShareUrl = (data: InvitationData) => { + /** + * @returns {string} - Complete shareable invitation link, e.g. + * https://tryquiet.org/join/#=&=&k=&o= + */ return composeInvitationUrl(`${QUIET_JOIN_PAGE}`, data).replace('?', '#') } @@ -132,13 +180,26 @@ export const composeInvitationDeepUrl = (data: InvitationData): string => { return composeInvitationUrl(`${DEEP_URL_SCHEME_WITH_SEPARATOR}`, data) } -const composeInvitationUrl = (baseUrl: string, data: InvitationData): string => { +const composeInvitationUrl = (baseUrl: string, data: InvitationDataV1 | InvitationDataV2): string => { const url = new URL(baseUrl) - for (const pair of data.pairs) { - url.searchParams.append(pair.peerId, pair.onionAddress) + + if (!data.version) data.version = InvitationDataVersion.v1 + + switch (data.version) { + case InvitationDataVersion.v1: + for (const pair of data.pairs) { + url.searchParams.append(pair.peerId, pair.onionAddress) + } + url.searchParams.append(PSK_PARAM_KEY, data.psk) + url.searchParams.append(OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, data.ownerOrbitDbIdentity) + break + case InvitationDataVersion.v2: + url.searchParams.append(CID_PARAM_KEY, data.cid) + url.searchParams.append(TOKEN_PARAM_KEY, data.token) + url.searchParams.append(SERVER_ADDRESS_PARAM_KEY, data.serverAddress) + url.searchParams.append(INVITER_ADDRESS_PARAM_KEY, data.inviterAddress) + break } - url.searchParams.append(PSK_PARAM_KEY, data.psk) - url.searchParams.append(OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, data.ownerOrbitDbIdentity) return url.href } @@ -148,15 +209,19 @@ const composeInvitationUrl = (baseUrl: string, data: InvitationData): string => export const argvInvitationCode = (argv: string[]): InvitationData | null => { let invitationData: InvitationData | null = null for (const arg of argv) { - try { - invitationData = parseInvitationCodeDeepUrl(arg) - } catch (e) { + if (!arg.startsWith(DEEP_URL_SCHEME_WITH_SEPARATOR)) { + console.log('Not a deep url, not parsing', arg) continue } - if (invitationData.pairs.length > 0) { - break - } else { - invitationData = null + console.log('Parsing deep url', arg) + invitationData = parseInvitationCodeDeepUrl(arg) + switch (invitationData.version) { + case InvitationDataVersion.v1: + if (invitationData.pairs.length > 0) { + break + } else { + invitationData = null + } } } return invitationData @@ -174,3 +239,60 @@ const peerDataValid = ({ peerId, onionAddress }: { peerId: string; onionAddress: } return true } + +const validateUrlParams = (params: URLSearchParams, requiredParams: string[]) => { + const entries = Object.fromEntries(params) + + requiredParams.forEach(key => { + const value = params.get(key) + if (!value) { + throw new Error(`Missing key '${key}' in invitation code`) + } + entries[key] = decodeURIComponent(value) + if (!isParamValid(key, entries[key])) { + throw new Error(`Invalid value '${value}' for key '${key}' in invitation code`) + } + params.delete(key) + }) + return entries +} + +const isParamValid = (param: string, value: string) => { + logger(`Validating param ${param} with value ${value}`) + switch (param) { + case CID_PARAM_KEY: + // try { + // CID.parse(value) + // } catch (e) { + // logger.error(e.message) + // return false + // } + return Boolean(value.match(PEER_ID_REGEX)) + + case TOKEN_PARAM_KEY: + // TODO: validate token format + return true + + case SERVER_ADDRESS_PARAM_KEY: + try { + new URL(value) + } catch (e) { + logger.error(e.message) + return false + } + return true + + case INVITER_ADDRESS_PARAM_KEY: + return Boolean(value.trim().match(ONION_ADDRESS_REGEX)) + + case PSK_PARAM_KEY: + return isPSKcodeValid(value) + + case OWNER_ORBIT_DB_IDENTITY_PARAM_KEY: + // TODO: validate orbit db identity format? + return true + + default: + return false + } +} diff --git a/packages/common/src/process.ts b/packages/common/src/process.ts index a5d85b6d8a..fdc6111a4b 100644 --- a/packages/common/src/process.ts +++ b/packages/common/src/process.ts @@ -1,5 +1,8 @@ import { type SupportedPlatform } from '@quiet/types' +/** + * Commands should output hanging backend pid + */ export const hangingBackendProcessCommand = ({ backendBundlePath, dataDir, @@ -7,13 +10,10 @@ export const hangingBackendProcessCommand = ({ backendBundlePath: string dataDir: string }): string => { - /** - * Commands should output hanging backend pid - */ const byPlatform = { - android: `pgrep -af "${backendBundlePath}" | grep -v pgrep | grep "${dataDir}" | awk '{print $1}'`, - linux: `pgrep -af "${backendBundlePath}" | grep -v egrep | grep "${dataDir}" | awk '{print $1}'`, - darwin: `ps -A | grep "${backendBundlePath}" | grep -v egrep | grep "${dataDir}" | awk '{print $1}'`, + android: `pgrep -af "${backendBundlePath}" | grep -v pgrep | grep -e "${dataDir}$" -e "${dataDir}[[:space:]]" | awk '{print $1}'`, + linux: `pgrep -af "${backendBundlePath}" | grep -v egrep | grep -e "${dataDir}$" -e "${dataDir}[[:space:]]" | awk '{print $1}'`, + darwin: `ps -A | grep "${backendBundlePath}" | grep -v egrep | grep -e "${dataDir}$" -e "${dataDir}[[:space:]]" | awk '{print $1}'`, win32: `powershell "Get-WmiObject Win32_process -Filter {commandline LIKE '%${backendBundlePath.replace( /\\/g, '\\\\' diff --git a/packages/common/src/sortPeers.ts b/packages/common/src/sortPeers.ts index 682111c1f2..634a79cfaf 100644 --- a/packages/common/src/sortPeers.ts +++ b/packages/common/src/sortPeers.ts @@ -1,5 +1,4 @@ import { type NetworkStats } from '@quiet/types' -import { isDefined } from './helpers' import { filterValidAddresses } from './libp2p' /** @@ -14,9 +13,11 @@ This is the very simple algorithm for evaluating the most wanted peers. export const filterAndSortPeers = ( peersAddresses: string[], stats: NetworkStats[], - localPeerAddress?: string + localPeerAddress?: string, + includeLocalPeerAddress: boolean = true ): string[] => { peersAddresses = filterValidAddresses(peersAddresses) + const currentlyConnected = [...stats].filter(peer => peer.connectionTime === 0) const lastSeenSorted = [...stats].sort((a, b) => { return b.lastSeen - a.lastSeen }) @@ -24,7 +25,7 @@ export const filterAndSortPeers = ( return b.connectionTime - a.connectionTime }) - const mostWantedPeers: NetworkStats[] = [] + const mostWantedPeers: NetworkStats[] = currentlyConnected for (let i = 0; i < stats.length; i++) { const peerOne = lastSeenSorted[i] @@ -39,22 +40,28 @@ export const filterAndSortPeers = ( } } - const peerList = mostWantedPeers.map(peerId => { - return peersAddresses.find(peerAddress => { + const peerSet: Set = new Set() + if (includeLocalPeerAddress && localPeerAddress) { + peerSet.add(localPeerAddress) + } + + mostWantedPeers.forEach(peer => { + const found = peersAddresses.find(peerAddress => { const id = peerAddress.split('/')[7] - if (id === peerId.peerId) { + if (id === peer.peerId) { peersAddresses.splice(peersAddresses.indexOf(peerAddress), 1) return true } }) + if (found && found !== '') { + peerSet.add(found) + } + }) + peersAddresses.forEach(peerAddress => { + if (!peerSet.has(peerAddress)) { + peerSet.add(peerAddress) + } }) - return [ - ...new Set([ - localPeerAddress, // Set local peer as first - ...peerList.concat(peersAddresses), - ]), - ] - .filter(address => address !== null && address !== '') - .filter(isDefined) + return [...peerSet] } diff --git a/packages/common/src/tests.ts b/packages/common/src/tests.ts index 92acc606cf..6c4791f4bb 100644 --- a/packages/common/src/tests.ts +++ b/packages/common/src/tests.ts @@ -1,8 +1,8 @@ -import { InvitationData } from '@quiet/types' +import { InvitationData, InvitationDataV1, InvitationDataV2, InvitationDataVersion } from '@quiet/types' import { composeInvitationDeepUrl, composeInvitationShareUrl } from './invitationCode' import { QUIET_JOIN_PAGE } from './static' -export const validInvitationCodeTestData: InvitationData[] = [ +export const validInvitationDatav1: InvitationDataV1[] = [ { pairs: [ { @@ -25,7 +25,26 @@ export const validInvitationCodeTestData: InvitationData[] = [ }, ] -export const getValidInvitationUrlTestData = (data: InvitationData) => { +export const validInvitationDatav2: InvitationDataV2[] = [ + { + version: InvitationDataVersion.v2, + cid: 'QmaRchXhkPWq8iLiMZwFfd2Yi4iESWhAYYJt8cTCVXSwpG', + token: 'BNlxfE2WBF7LrlpIX0CvECN5o1oZtA16PkAb7GYiwYw', + serverAddress: 'https://tryquiet.org/api/', + inviterAddress: 'pgzlcstu4ljvma7jqyalimcxlvss5bwlbba3c3iszgtwxee4qjdlgeqd', + }, +] + +export const validInvitationCodeTestData: InvitationData[] = [...validInvitationDatav1] + +type TestData = { + shareUrl: () => string + deepUrl: () => string + code: () => string + data: T +} + +export function getValidInvitationUrlTestData(data: T): TestData { return { shareUrl: () => composeInvitationShareUrl(data), deepUrl: () => composeInvitationDeepUrl(data), @@ -33,3 +52,12 @@ export const getValidInvitationUrlTestData = (data: InvitationData) => { data: data, } } + +// export const getValidInvitationUrlTestData = (data: InvitationData) => { +// return { +// shareUrl: () => composeInvitationShareUrl(data), +// deepUrl: () => composeInvitationDeepUrl(data), +// code: () => composeInvitationShareUrl(data).split(QUIET_JOIN_PAGE + '#')[1], +// data: data, +// } +// } diff --git a/packages/desktop/CHANGELOG.md b/packages/desktop/CHANGELOG.md index dc3bd2fff0..e5ad80e5c2 100644 --- a/packages/desktop/CHANGELOG.md +++ b/packages/desktop/CHANGELOG.md @@ -1,6 +1,27 @@ [unreleased] +# New features: + +# Refactorings: + +# Fixes: + +[2.2.0] + +# New features: + +* Add utilities for emoji detection in messages and make all-emoji message larger font size ([#519](https://github.com/TryQuiet/quiet/issues/519)) + +# Refactorings: + +* Use ack for CREATE_NETWORK and simplify +* Move Community model to the backend + +# Fixes: +* Allow JPEG and GIF files as profile photos ([#2332](https://github.com/TryQuiet/quiet/issues/2332)) +* Fix issues with recreating general channel when deleted while offline ([#2334](https://github.com/TryQuiet/quiet/issues/2334)) +* Fix package.json license inconsistency [2.1.2] @@ -14,6 +35,7 @@ # Fixes: +* Fixes channel name creation logic * Remove duplicate introduction messages once again * Prevent channel creation with names that start with special character, then a hyphen * Choose random ports for Tor services (iOS) diff --git a/packages/desktop/package-lock.json b/packages/desktop/package-lock.json index 70400be6ee..c9e049edb0 100644 --- a/packages/desktop/package-lock.json +++ b/packages/desktop/package-lock.json @@ -1,12 +1,12 @@ { "name": "@quiet/desktop", - "version": "2.1.2-alpha.14", + "version": "2.2.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@quiet/desktop", - "version": "2.1.2-alpha.14", + "version": "2.2.0-alpha.1", "license": "GPL-3.0-or-later", "dependencies": { "@electron/remote": "^2.0.8", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 5987982f61..f8bb9b22ca 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -80,7 +80,7 @@ }, "homepage": "https://github.com/TryQuiet", "@comment version": "To build new version for specific platform, just replace platform in version tag to one of following linux, mac, windows", - "version": "2.1.2-alpha.14", + "version": "2.2.0-alpha.1", "description": "Decentralized team chat", "main": "dist/main/main.js", "scripts": { diff --git a/packages/desktop/src/main/invitation.ts b/packages/desktop/src/main/invitation.ts index 2616059683..cfc1bf429a 100644 --- a/packages/desktop/src/main/invitation.ts +++ b/packages/desktop/src/main/invitation.ts @@ -3,15 +3,12 @@ import path from 'path' import os from 'os' import { execSync } from 'child_process' import { BrowserWindow } from 'electron' -import { InvitationData, InvitationPair } from '@quiet/types' -export const processInvitationCode = (mainWindow: BrowserWindow, data: InvitationData | null) => { - if (!data || data?.pairs.length === 0) { - console.log('No valid invitation codes, not processing') - return - } +export const processInvitationCode = (mainWindow: BrowserWindow, code: string | string[]) => { + console.log('processInvitationCode:', code) + if (!code || !code.length) return mainWindow.webContents.send('invitation', { - data, + code, }) } diff --git a/packages/desktop/src/main/main.test.ts b/packages/desktop/src/main/main.test.ts index dca57a360c..66d2873457 100644 --- a/packages/desktop/src/main/main.test.ts +++ b/packages/desktop/src/main/main.test.ts @@ -250,27 +250,28 @@ describe('Invitation code', () => { expect(mockAppOnCalls[1][0]).toBe('open-url') const event = { preventDefault: () => {} } - mockAppOnCalls[1][1](event, composeInvitationDeepUrl(codes)) - expect(mockWindowWebContentsSend).toHaveBeenCalledWith('invitation', { data: codes }) + const deepUrl = composeInvitationDeepUrl(codes) + mockAppOnCalls[1][1](event, deepUrl) + expect(mockWindowWebContentsSend).toHaveBeenCalledWith('invitation', { code: deepUrl }) }) - it('do not process invitation code on open-url event (on macos) if url is invalid', async () => { - codes['psk'] = '12345' + it('do not process invitation code on open-url event (on macos) if url is empty', async () => { expect(mockAppOnCalls[2][0]).toBe('ready') await mockAppOnCalls[2][1]() expect(mockAppOnCalls[1][0]).toBe('open-url') const event = { preventDefault: () => {} } - mockAppOnCalls[1][1](event, composeInvitationDeepUrl(codes)) - expect(mockWindowWebContentsSend).not.toHaveBeenCalledWith('invitation', { data: codes }) + mockAppOnCalls[1][1](event, '') + expect(mockWindowWebContentsSend).not.toHaveBeenCalledWith('invitation', { code: '' }) }) it('process invitation code on second-instance event', async () => { await mockAppOnCalls[2][1]() - const commandLine = ['/tmp/.mount_Quiet-TVQc6s/quiet', composeInvitationDeepUrl(codes)] + const deepUrl = composeInvitationDeepUrl(codes) + const commandLine = ['/tmp/.mount_Quiet-TVQc6s/quiet', deepUrl, 'something/else'] expect(mockAppOnCalls[0][0]).toBe('second-instance') const event = { preventDefault: () => {} } mockAppOnCalls[0][1](event, commandLine) - expect(mockWindowWebContentsSend).toHaveBeenCalledWith('invitation', { data: codes }) + expect(mockWindowWebContentsSend).toHaveBeenCalledWith('invitation', { code: deepUrl }) }) }) diff --git a/packages/desktop/src/main/main.ts b/packages/desktop/src/main/main.ts index b1b65199b4..7b0c4b96be 100644 --- a/packages/desktop/src/main/main.ts +++ b/packages/desktop/src/main/main.ts @@ -79,8 +79,7 @@ if (!gotTheLock) { if (mainWindow) { if (mainWindow.isMinimized()) mainWindow.restore() mainWindow.focus() - const invitationCode = argvInvitationCode(commandLine) - processInvitationCode(mainWindow, invitationCode) + processInvitationCode(mainWindow, commandLine) } }) } @@ -156,12 +155,7 @@ app.on('open-url', (event, url) => { event.preventDefault() if (mainWindow) { invitationUrl = null - try { - const invitationData = parseInvitationCodeDeepUrl(url) - processInvitationCode(mainWindow, invitationData) - } catch (e) { - console.warn(e.message) - } + processInvitationCode(mainWindow, url) } }) @@ -494,8 +488,7 @@ app.on('ready', async () => { } if (process.platform === 'darwin' && invitationUrl) { try { - const invitationData = parseInvitationCodeDeepUrl(invitationUrl) - processInvitationCode(mainWindow, invitationData) + processInvitationCode(mainWindow, invitationUrl) } catch (e) { console.warn(e.message) } finally { @@ -504,8 +497,7 @@ app.on('ready', async () => { } if (process.platform !== 'darwin' && process.argv) { try { - const invitationCode = argvInvitationCode(process.argv) - processInvitationCode(mainWindow, invitationCode) + processInvitationCode(mainWindow, process.argv) } catch (e) { console.warn(e.message) } diff --git a/packages/desktop/src/renderer/Root.tsx b/packages/desktop/src/renderer/Root.tsx index 8cc8cb6089..32c931de55 100644 --- a/packages/desktop/src/renderer/Root.tsx +++ b/packages/desktop/src/renderer/Root.tsx @@ -35,9 +35,11 @@ import DuplicateModalContainer from './components/widgets/userLabel/duplicate/Du import UsernameTakenModalContainer from './components/widgets/usernameTakenModal/UsernameTakenModal.container' import PossibleImpersonationAttackModalContainer from './components/widgets/possibleImpersonationAttackModal/PossibleImpersonationAttackModal.container' import BreakingChangesWarning from './containers/widgets/breakingChangesWarning/BreakingChangesWarning' +import { communities } from '@quiet/state-manager' // Trigger lerna export const persistor = persistStore(store) + export default () => { return ( diff --git a/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx b/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx index 0a302125e0..b9c82b83be 100644 --- a/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx +++ b/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx @@ -66,10 +66,6 @@ const Template: ComponentStory = () => { privKey: 'privKey', pubKey: 'pubKey', }, - dmKeys: { - publicKey: 'publicKey', - privateKey: 'privateKey', - }, userCsr: { userCsr: 'userCsr', userKey: 'userKey', diff --git a/packages/desktop/src/renderer/components/Channel/Channel.stories.tsx b/packages/desktop/src/renderer/components/Channel/Channel.stories.tsx index 36593326c1..948bfc678a 100644 --- a/packages/desktop/src/renderer/components/Channel/Channel.stories.tsx +++ b/packages/desktop/src/renderer/components/Channel/Channel.stories.tsx @@ -25,10 +25,6 @@ const args: Partial = { privKey: 'privKey', pubKey: 'pubKey', }, - dmKeys: { - publicKey: 'publicKey', - privateKey: 'privateKey', - }, userCsr: { userCsr: 'userCsr', userKey: 'userKey', diff --git a/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.test.tsx b/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.test.tsx index ee51e711e2..6d3d270fc8 100644 --- a/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.test.tsx +++ b/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.test.tsx @@ -23,10 +23,11 @@ import { validInvitationCodeTestData, getValidInvitationUrlTestData, PSK_PARAM_KEY, + validInvitationDatav1, } from '@quiet/common' describe('join community', () => { - const { code, data } = getValidInvitationUrlTestData(validInvitationCodeTestData[0]) + const { code, data } = getValidInvitationUrlTestData(validInvitationDatav1[0]) const validCode = code() diff --git a/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.tsx b/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.tsx index d4a63352ab..0d03c60f01 100644 --- a/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.tsx +++ b/packages/desktop/src/renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity.tsx @@ -1,11 +1,11 @@ +import { communities, connection, identity } from '@quiet/state-manager' +import { CommunityOwnership, InvitationData } from '@quiet/types' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { socketSelectors } from '../../../sagas/socket/socket.selectors' -import { CommunityOwnership, CreateNetworkPayload, InvitationData, InvitationPair } from '@quiet/types' -import { communities, identity, connection, network } from '@quiet/state-manager' import PerformCommunityActionComponent from '../../../components/CreateJoinCommunity/PerformCommunityActionComponent' -import { ModalName } from '../../../sagas/modals/modals.types' import { useModal } from '../../../containers/hooks' +import { ModalName } from '../../../sagas/modals/modals.types' +import { socketSelectors } from '../../../sagas/socket/socket.selectors' const JoinCommunity = () => { const dispatch = useDispatch() @@ -15,10 +15,6 @@ const JoinCommunity = () => { const currentCommunity = useSelector(communities.selectors.currentCommunity) const currentIdentity = useSelector(identity.selectors.currentIdentity) - // Invitation link data should be already available if user joined via deep link - const invitationCodes = useSelector(communities.selectors.invitationCodes) - const psk = useSelector(communities.selectors.psk) - const joinCommunityModal = useModal(ModalName.joinCommunityModal) const createCommunityModal = useModal(ModalName.createCommunityModal) @@ -39,13 +35,7 @@ const JoinCommunity = () => { }, [currentCommunity]) const handleCommunityAction = (data: InvitationData) => { - const payload: CreateNetworkPayload = { - ownership: CommunityOwnership.User, - peers: data.pairs, - psk: data.psk, - ownerOrbitDbIdentity: data.ownerOrbitDbIdentity, - } - dispatch(communities.actions.createNetwork(payload)) + dispatch(communities.actions.joinNetwork(data)) } // From 'You can create a new community instead' link @@ -72,8 +62,6 @@ const JoinCommunity = () => { hasReceivedResponse={Boolean(currentIdentity && !currentIdentity.userCertificate)} revealInputValue={revealInputValue} handleClickInputReveal={handleClickInputReveal} - invitationCode={invitationCodes} - psk={psk} /> ) } diff --git a/packages/desktop/src/renderer/components/CreateJoinCommunity/PerformCommunityActionComponent.tsx b/packages/desktop/src/renderer/components/CreateJoinCommunity/PerformCommunityActionComponent.tsx index 754bb453f4..5bff2b131f 100644 --- a/packages/desktop/src/renderer/components/CreateJoinCommunity/PerformCommunityActionComponent.tsx +++ b/packages/desktop/src/renderer/components/CreateJoinCommunity/PerformCommunityActionComponent.tsx @@ -137,9 +137,6 @@ export interface PerformCommunityActionProps { hasReceivedResponse: boolean revealInputValue?: boolean handleClickInputReveal?: () => void - invitationCode?: InvitationPair[] - psk?: string - ownerOrbitDbIdentity?: string } export const PerformCommunityActionComponent: React.FC = ({ @@ -153,9 +150,6 @@ export const PerformCommunityActionComponent: React.FC { const [formSent, setFormSent] = useState(false) @@ -219,18 +213,6 @@ export const PerformCommunityActionComponent: React.FC { - if (communityOwnership === CommunityOwnership.User && invitationCode?.length && psk && ownerOrbitDbIdentity) { - setFormSent(true) - setValue('name', composeInvitationShareUrl({ pairs: invitationCode, psk, ownerOrbitDbIdentity })) - } - }, [communityOwnership, invitationCode]) - useEffect(() => { if (!open) { setValue('name', '') diff --git a/packages/desktop/src/renderer/components/MathMessage/MathMessageComponent.test.tsx b/packages/desktop/src/renderer/components/MathMessage/MathMessageComponent.test.tsx index f0610a8787..3a4a5afeb4 100644 --- a/packages/desktop/src/renderer/components/MathMessage/MathMessageComponent.test.tsx +++ b/packages/desktop/src/renderer/components/MathMessage/MathMessageComponent.test.tsx @@ -107,7 +107,7 @@ describe('MathMessageComponent', () => {
It is @@ -187,7 +187,7 @@ describe('MathMessageComponent', () => { and @@ -484,7 +484,7 @@ describe('MathMessageComponent', () => {
    { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 @@ -177,7 +177,7 @@ describe('BasicMessage', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 @@ -187,7 +187,7 @@ describe('BasicMessage', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message1 @@ -279,7 +279,7 @@ describe('BasicMessage', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 @@ -289,7 +289,7 @@ describe('BasicMessage', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message1 @@ -379,7 +379,7 @@ describe('BasicMessage', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 @@ -389,7 +389,7 @@ describe('BasicMessage', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 diff --git a/packages/desktop/src/renderer/components/widgets/channels/ChannelMessages.test.tsx b/packages/desktop/src/renderer/components/widgets/channels/ChannelMessages.test.tsx index b991dad766..6c0b32cfc8 100644 --- a/packages/desktop/src/renderer/components/widgets/channels/ChannelMessages.test.tsx +++ b/packages/desktop/src/renderer/components/widgets/channels/ChannelMessages.test.tsx @@ -139,7 +139,7 @@ describe('ChannelMessages', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > string diff --git a/packages/desktop/src/renderer/components/widgets/channels/NestedMessageContent.test.tsx b/packages/desktop/src/renderer/components/widgets/channels/NestedMessageContent.test.tsx index f10e9dbaa9..77c423288e 100644 --- a/packages/desktop/src/renderer/components/widgets/channels/NestedMessageContent.test.tsx +++ b/packages/desktop/src/renderer/components/widgets/channels/NestedMessageContent.test.tsx @@ -19,7 +19,7 @@ describe('NestedMessageContent', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 @@ -40,7 +40,7 @@ describe('NestedMessageContent', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 @@ -97,7 +97,7 @@ describe('NestedMessageContent', () => { class="MuiGrid-root MuiGrid-item css-15myz84-MuiGrid-root" > message0 diff --git a/packages/desktop/src/renderer/components/widgets/channels/TextMessage.tsx b/packages/desktop/src/renderer/components/widgets/channels/TextMessage.tsx index 93dc4c4a49..a129eb8236 100644 --- a/packages/desktop/src/renderer/components/widgets/channels/TextMessage.tsx +++ b/packages/desktop/src/renderer/components/widgets/channels/TextMessage.tsx @@ -4,11 +4,13 @@ import React, { ReactNode } from 'react' import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' import theme from '../../../theme' +import { isAllEmoji } from '../../../../../../common/src/emojis' const PREFIX = 'TextMessage' const classes = { message: `${PREFIX}message`, + emojiMessage: `${PREFIX}emojiMessage`, pending: `${PREFIX}pending`, blockquote: `${PREFIX}blockquote`, code: `${PREFIX}code`, @@ -29,7 +31,10 @@ const StyledTypography = styled(Typography)(() => ({ lineHeight: '21px', overflowWrap: 'anywhere', }, - + [`&.${classes.emojiMessage}`]: { + fontSize: '1.7rem', // Double the normal fontSize + lineHeight: '42px', // Double the normal lineHeight + }, [`&.${classes.pending}`]: { color: theme.palette.colors.lightGray, }, @@ -127,6 +132,7 @@ export const TextMessageComponent: React.FC = ({ mess className={classNames({ [classes.message]: true, [classes.pending]: pending, + [classes.emojiMessage]: isAllEmoji(message), })} data-testid={`messagesGroupContent-${messageId}`} > diff --git a/packages/desktop/src/renderer/index.tsx b/packages/desktop/src/renderer/index.tsx index 3c478402b2..c73254eb47 100644 --- a/packages/desktop/src/renderer/index.tsx +++ b/packages/desktop/src/renderer/index.tsx @@ -20,10 +20,18 @@ ipcRenderer.on('force-save-state', async _event => { ipcRenderer.send('state-saved') }) -ipcRenderer.on('invitation', (_event, invitation: { data: InvitationData }) => { - if (!invitation.data) return - console.log('invitation', invitation.data.pairs, 'dispatching action') - store.dispatch(communities.actions.customProtocol(invitation.data)) +ipcRenderer.on('invitation', (_event, invitation: { code: string | string[] }) => { + console.log('ipcRenderer.on(invitation)', invitation) + if (!invitation.code) return + + let invitationData: string[] + if (typeof invitation.code === 'string') { + invitationData = [invitation.code] + } else { + invitationData = invitation.code + } + console.log('invitation', invitationData, 'dispatching action') + store.dispatch(communities.actions.customProtocol(invitationData)) }) ipcRenderer.on('socketIOSecret', (_event, socketIOSecret) => { diff --git a/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.test.ts b/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.test.ts index ac732ee519..c97078e808 100644 --- a/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.test.ts +++ b/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.test.ts @@ -1,5 +1,5 @@ import { communities, getFactory, Store } from '@quiet/state-manager' -import { Community, CommunityOwnership, CreateNetworkPayload, InvitationData } from '@quiet/types' +import { Community, CommunityOwnership, CreateNetworkPayload, InvitationData, InvitationDataV1 } from '@quiet/types' import { FactoryGirl } from 'factory-girl' import { expectSaga } from 'redux-saga-test-plan' import { customProtocolSaga } from './customProtocol.saga' @@ -8,13 +8,14 @@ import { prepareStore } from '../../testUtils/prepareStore' import { StoreKeys } from '../../store/store.keys' import { modalsActions } from '../modals/modals.slice' import { ModalName } from '../modals/modals.types' -import { validInvitationCodeTestData, getValidInvitationUrlTestData } from '@quiet/common' +import { getValidInvitationUrlTestData, validInvitationDatav1, validInvitationDatav2 } from '@quiet/common' describe('Handle invitation code', () => { let store: Store let factory: FactoryGirl let community: Community - let validInvitationData: InvitationData + let validInvitationData: InvitationDataV1 + let validInvitationDeepUrl: string beforeEach(async () => { store = ( @@ -28,19 +29,23 @@ describe('Handle invitation code', () => { factory = await getFactory(store) - validInvitationData = getValidInvitationUrlTestData(validInvitationCodeTestData[0]).data + validInvitationData = getValidInvitationUrlTestData(validInvitationDatav1[0]).data + validInvitationDeepUrl = getValidInvitationUrlTestData(validInvitationDatav1[0]).deepUrl() }) - it('creates network if code is valid', async () => { - const payload: CreateNetworkPayload = { - ownership: CommunityOwnership.User, - peers: validInvitationData.pairs, - psk: validInvitationData.psk, - ownerOrbitDbIdentity: validInvitationData.ownerOrbitDbIdentity, - } - await expectSaga(customProtocolSaga, communities.actions.customProtocol(validInvitationData)) + it('joins network if code is valid', async () => { + await expectSaga(customProtocolSaga, communities.actions.customProtocol([validInvitationDeepUrl])) + .withState(store.getState()) + .put(communities.actions.joinNetwork(validInvitationData)) + .run() + }) + + it('joins network if v2 code is valid', async () => { + const validInvitationData = getValidInvitationUrlTestData(validInvitationDatav2[0]).data + const validInvitationDeepUrl = getValidInvitationUrlTestData(validInvitationDatav2[0]).deepUrl() + await expectSaga(customProtocolSaga, communities.actions.customProtocol([validInvitationDeepUrl])) .withState(store.getState()) - .put(communities.actions.createNetwork(payload)) + .put(communities.actions.joinNetwork(validInvitationData)) .run() }) @@ -52,7 +57,7 @@ describe('Handle invitation code', () => { psk: validInvitationData.psk, } - await expectSaga(customProtocolSaga, communities.actions.customProtocol(validInvitationData)) + await expectSaga(customProtocolSaga, communities.actions.customProtocol([validInvitationDeepUrl])) .withState(store.getState()) .put( modalsActions.openModal({ @@ -67,7 +72,7 @@ describe('Handle invitation code', () => { .run() }) - it('does not try to create network if code is missing addresses', async () => { + it('does not try to create network if code is missing psk', async () => { const payload: CreateNetworkPayload = { ownership: CommunityOwnership.User, peers: [], @@ -75,11 +80,7 @@ describe('Handle invitation code', () => { await expectSaga( customProtocolSaga, - communities.actions.customProtocol({ - pairs: [], - psk: '12345', - ownerOrbitDbIdentity: 'testOwnerOrbitDbIdentity', - }) + communities.actions.customProtocol(['someArg', 'quiet://?k=BNlxfE2WBF7LrlpIX0CvECN5o1oZtA16PkAb7GYiwYw=']) ) .withState(store.getState()) .put(communities.actions.clearInvitationCodes()) @@ -104,11 +105,9 @@ describe('Handle invitation code', () => { await expectSaga( customProtocolSaga, - communities.actions.customProtocol({ - pairs: validInvitationData.pairs, - psk: '', - ownerOrbitDbIdentity: 'testOwnerOrbitDbIdentity', - }) + communities.actions.customProtocol([ + 'quiet://?QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE=y7yczmugl2tekami7sbdz5pfaemvx7bahwthrdvcbzw5vex2crsr26qd', + ]) ) .withState(store.getState()) .put(communities.actions.clearInvitationCodes()) diff --git a/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.ts b/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.ts index 98a26e3035..0e889f7ed1 100644 --- a/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.ts +++ b/packages/desktop/src/renderer/sagas/invitation/customProtocol.saga.ts @@ -1,14 +1,20 @@ import { PayloadAction } from '@reduxjs/toolkit' import { select, put, delay } from 'typed-redux-saga' -import { CommunityOwnership, CreateNetworkPayload } from '@quiet/types' +import { InvitationData, InvitationDataVersion } from '@quiet/types' import { communities } from '@quiet/state-manager' import { socketSelectors } from '../socket/socket.selectors' import { ModalName } from '../modals/modals.types' import { modalsActions } from '../modals/modals.slice' +import { argvInvitationCode } from '@quiet/common' export function* customProtocolSaga( action: PayloadAction['payload']> ): Generator { + // TODO: refactor to remove code duplication. This is a slightly adjusted code from deepLink.saga.ts + const code = action.payload + + console.log('INIT_NAVIGATION: Waiting for websocket connection before proceeding with deep link flow.') + while (true) { const connected = yield* select(socketSelectors.isConnected) if (connected) { @@ -17,8 +23,56 @@ export function* customProtocolSaga( yield* delay(500) } + console.log('INIT_NAVIGATION: Continuing on deep link flow.') + + let data: InvitationData | null + + try { + data = argvInvitationCode(code) + } catch (e) { + console.warn(e.message) + + yield* put(communities.actions.clearInvitationCodes()) + yield* put( + modalsActions.openModal({ + name: ModalName.warningModal, + args: { + title: 'Invalid link', + subtitle: 'The invite link you received is not valid. Please check it and try again.', + }, + }) + ) + return + } + + if (data === null) { + console.log(`Not processing invitation code ${code}`) + return + } + const community = yield* select(communities.selectors.currentCommunity) - if (community) { + + let isJoiningAnotherCommunity = false + + switch (data.version) { + case InvitationDataVersion.v1: + const storedPsk = yield* select(communities.selectors.psk) + const currentPsk = data.psk + + console.log('Stored psk', storedPsk) + console.log('Current psk', currentPsk) + + isJoiningAnotherCommunity = Boolean(storedPsk && storedPsk !== currentPsk) + break + } + + const isAlreadyConnected = Boolean(community?.name) + const connectingWithAnotherCommunity = isJoiningAnotherCommunity && !isAlreadyConnected + + // User already belongs to a community + if (isAlreadyConnected) { + console.log('INIT_NAVIGATION: Displaying error (user already belongs to a community).') + yield* put(communities.actions.clearInvitationCodes()) // TODO: check out yield* put( modalsActions.openModal({ name: ModalName.warningModal, @@ -28,27 +82,25 @@ export function* customProtocolSaga( }, }) ) + return } - const invitationData = action.payload - if (invitationData && invitationData.pairs.length > 0 && invitationData.psk && invitationData.ownerOrbitDbIdentity) { - const payload: CreateNetworkPayload = { - ownership: CommunityOwnership.User, - peers: invitationData.pairs, - psk: invitationData.psk, - ownerOrbitDbIdentity: invitationData.ownerOrbitDbIdentity, - } - yield* put(communities.actions.createNetwork(payload)) - } else { - yield* put(communities.actions.clearInvitationCodes()) + + if (connectingWithAnotherCommunity) { + console.log('INIT_NAVIGATION: Displaying error (user is already connecting to another community).') + yield* put(communities.actions.clearInvitationCodes()) // TODO: check out yield* put( modalsActions.openModal({ name: ModalName.warningModal, args: { - title: 'Invalid link', - subtitle: 'The invite link you received is not valid. Please check it and try again.', + title: 'You already started to connect to another community', + subtitle: "We're sorry but for now you can only be a member of a single community at a time.", }, }) ) + + return } + + yield* put(communities.actions.joinNetwork(data)) } diff --git a/packages/desktop/src/renderer/store/reducers.ts b/packages/desktop/src/renderer/store/reducers.ts index 14a778fcd0..8d987605e1 100644 --- a/packages/desktop/src/renderer/store/reducers.ts +++ b/packages/desktop/src/renderer/store/reducers.ts @@ -2,7 +2,7 @@ import { AnyAction, combineReducers } from '@reduxjs/toolkit' import ElectronStore from 'electron-store' import createElectronStorage from 'redux-persist-electron-storage' import path from 'path' -import { persistReducer } from 'redux-persist' +import { createMigrate, persistReducer } from 'redux-persist' import stateManagerReducers, { storeKeys as StateManagerStoreKeys, @@ -14,6 +14,7 @@ import stateManagerReducers, { ConnectionTransform, resetStateAndSaveTorConnectionData, UsersTransform, + storeMigrations, } from '@quiet/state-manager' import { StoreType } from './handlers/types' @@ -26,17 +27,11 @@ import { navigationReducer } from './navigation/navigation.slice' import appHandlers from './handlers/app' import { Store } from '../sagas/store.types' -import { DESKTOP_DATA_DIR, DESKTOP_DEV_DATA_DIR } from '@quiet/common' - -const dataPath = - process.env.APPDATA || - (process.platform === 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + '/.config') -const appPath = - process.env.DATA_DIR || (process.env.NODE_ENV === 'development' ? DESKTOP_DEV_DATA_DIR : DESKTOP_DATA_DIR) +import { getAppDataPath } from '@quiet/common' const options = { projectName: 'quiet', - cwd: path.join(dataPath, appPath), + cwd: getAppDataPath(), } const store = new ElectronStore(options) @@ -45,6 +40,7 @@ const reduxStorage = createElectronStorage({ electronStore: store }) const persistConfig = { key: 'root', + version: 0, storage: reduxStorage, throttle: 1000, whitelist: [ @@ -66,6 +62,7 @@ const persistConfig = { ConnectionTransform, UsersTransform, ], + migrate: createMigrate(storeMigrations, { debug: true }), } export const reducers = { diff --git a/packages/desktop/src/renderer/testUtils/index.ts b/packages/desktop/src/renderer/testUtils/index.ts index 2a8f54c14e..8138beb934 100644 --- a/packages/desktop/src/renderer/testUtils/index.ts +++ b/packages/desktop/src/renderer/testUtils/index.ts @@ -1,4 +1,3 @@ export * from './generateMessages' export * from './prepareStore' export * from './renderComponent' -export * from './socket' diff --git a/packages/desktop/src/rtl-tests/channel.add.test.tsx b/packages/desktop/src/rtl-tests/channel.add.test.tsx index 06534239b6..027949c65c 100644 --- a/packages/desktop/src/rtl-tests/channel.add.test.tsx +++ b/packages/desktop/src/rtl-tests/channel.add.test.tsx @@ -6,7 +6,7 @@ import { act } from 'react-dom/test-utils' import { take } from 'typed-redux-saga' import MockedSocket from 'socket.io-mock' import { ioMock } from '../shared/setupTests' -import { socketEventData } from '../renderer/testUtils/socket' +import { socketEventData } from '@quiet/types' import { renderComponent } from '../renderer/testUtils/renderComponent' import { prepareStore } from '../renderer/testUtils/prepareStore' import { StoreKeys } from '../renderer/store/store.keys' diff --git a/packages/desktop/src/rtl-tests/channel.main.test.tsx b/packages/desktop/src/rtl-tests/channel.main.test.tsx index 514c485fc5..c4148b6ac0 100644 --- a/packages/desktop/src/rtl-tests/channel.main.test.tsx +++ b/packages/desktop/src/rtl-tests/channel.main.test.tsx @@ -6,7 +6,7 @@ import { apply, take } from 'typed-redux-saga' import userEvent from '@testing-library/user-event' import MockedSocket from 'socket.io-mock' import { ioMock } from '../shared/setupTests' -import { socketEventData } from '../renderer/testUtils/socket' +import { socketEventData } from '@quiet/types' import { renderComponent } from '../renderer/testUtils/renderComponent' import { prepareStore } from '../renderer/testUtils/prepareStore' import Channel from '../renderer/components/Channel/Channel' @@ -767,7 +767,7 @@ describe('Channel', () => { const uploadingDelay = 100 - jest.spyOn(socket, 'emit').mockImplementation(async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { + const mockEmitImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { const action = input[0] if (action === SocketActionTypes.LAUNCH_COMMUNITY) { const data = input[1] as InitCommunityPayload @@ -816,7 +816,11 @@ describe('Channel', () => { peerId: alice.peerId.id, }) } - }) + } + + jest.spyOn(socket, 'emit').mockImplementation(mockEmitImpl) + // @ts-ignore + socket.emitWithAck = mockEmitImpl const { store, runSaga } = await prepareStore( initialState.getState(), @@ -899,7 +903,7 @@ describe('Channel', () => { const community: Community = await factory.create< ReturnType['payload'] - >('Community', { rootCa: 'rootCa', privateKey: 'privateKey' }) + >('Community', { rootCa: 'rootCa' }) const alice = await factory.create['payload']>('Identity', { id: community.id, @@ -964,7 +968,7 @@ describe('Channel', () => { }) ) - jest.spyOn(socket, 'emit').mockImplementation(async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { + const mockEmitImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { const action = input[0] if (action === SocketActionTypes.LAUNCH_COMMUNITY) { const data = input[1] as InitCommunityPayload @@ -983,7 +987,11 @@ describe('Channel', () => { path: `${__dirname}/test-image.jpeg`, }) } - }) + } + + jest.spyOn(socket, 'emit').mockImplementation(mockEmitImpl) + // @ts-ignore + socket.emitWithAck = mockEmitImpl const { store, runSaga } = await prepareStore( initialState.getState(), diff --git a/packages/desktop/src/rtl-tests/community.create.test.tsx b/packages/desktop/src/rtl-tests/community.create.test.tsx index e7ba494763..d5f747cb65 100644 --- a/packages/desktop/src/rtl-tests/community.create.test.tsx +++ b/packages/desktop/src/rtl-tests/community.create.test.tsx @@ -13,15 +13,18 @@ import { ModalName } from '../renderer/sagas/modals/modals.types' import { CreateCommunityDictionary } from '../renderer/components/CreateJoinCommunity/community.dictionary' import MockedSocket from 'socket.io-mock' import { ioMock } from '../shared/setupTests' -import { socketEventData } from '../renderer/testUtils/socket' -import { Community, type NetworkInfo, SavedOwnerCertificatePayload, SocketActionTypes } from '@quiet/types' +import { socketEventData } from '@quiet/types' import { - ChannelsReplicatedPayload, - InitCommunityPayload, - publicChannels, - RegisterOwnerCertificatePayload, - ResponseLaunchCommunityPayload, -} from '@quiet/state-manager' + Community, + type InitCommunityPayload, + type NetworkInfo, + SavedOwnerCertificatePayload, + SocketActionTypes, + type ChannelsReplicatedPayload, + type RegisterOwnerCertificatePayload, + type ResponseLaunchCommunityPayload, +} from '@quiet/types' +import { publicChannels } from '@quiet/state-manager' import Channel from '../renderer/components/Channel/Channel' import LoadingPanel from '../renderer/components/LoadingPanel/LoadingPanel' import { AnyAction } from 'redux' @@ -70,8 +73,6 @@ describe('User', () => { const mockEmitImpl = (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { const action = input[0] if (action === SocketActionTypes.CREATE_NETWORK) { - const data = input[1] as Community - const payload = { ...data, privateKey: 'privateKey' } return { hiddenService: { onionAddress: 'onionAddress', @@ -82,23 +83,11 @@ describe('User', () => { }, } } - if (action === SocketActionTypes.REGISTER_OWNER_CERTIFICATE) { - const payload = input[1] as RegisterOwnerCertificatePayload - socket.socketClient.emit(SocketActionTypes.OWNER_CERTIFICATE_ISSUED, { - communityId: payload.communityId, - network: { - certificate: payload.permsData.certificate, - }, - }) - } if (action === SocketActionTypes.CREATE_COMMUNITY) { const payload = input[1] as InitCommunityPayload socket.socketClient.emit(SocketActionTypes.COMMUNITY_LAUNCHED, { id: payload.id, }) - socket.socketClient.emit(SocketActionTypes.COMMUNITY_CREATED, { - id: payload.id, - }) socket.socketClient.emit(SocketActionTypes.CHANNELS_STORED, { channels: { @@ -111,6 +100,8 @@ describe('User', () => { }, }, }) + + return { id: payload.id, ownerCertificate: 'cert' } } } @@ -173,22 +164,19 @@ describe('User', () => { "Network/setLoadingPanelType", "Modals/openModal", "Identity/registerCertificate", - "Communities/updateCommunity", - "Identity/storeUserCertificate", - "Identity/savedOwnerCertificate", - "Communities/updateCommunityData", - "Communities/sendCommunityCaData", + "Communities/createCommunity", "Files/checkForMissingFiles", "Network/addInitializedCommunity", "Communities/clearInvitationCodes", - "Communities/sendCommunityMetadata", - "PublicChannels/createGeneralChannel", - "Identity/saveUserCsr", "PublicChannels/channelsReplicated", - "PublicChannels/createChannel", + "Communities/updateCommunityData", "PublicChannels/addChannel", - "PublicChannels/setCurrentChannel", + "Identity/storeUserCertificate", "Messages/addPublicChannelsMessagesBase", + "PublicChannels/createGeneralChannel", + "PublicChannels/createChannel", + "Identity/saveUserCsr", + "PublicChannels/setCurrentChannel", "PublicChannels/clearUnreadChannel", "Modals/closeModal", "Messages/lazyLoading", diff --git a/packages/desktop/src/rtl-tests/community.join.test.tsx b/packages/desktop/src/rtl-tests/community.join.test.tsx index 9ddf17c4e7..6b7d0331ff 100644 --- a/packages/desktop/src/rtl-tests/community.join.test.tsx +++ b/packages/desktop/src/rtl-tests/community.join.test.tsx @@ -13,11 +13,10 @@ import { ModalName } from '../renderer/sagas/modals/modals.types' import { JoinCommunityDictionary } from '../renderer/components/CreateJoinCommunity/community.dictionary' import MockedSocket from 'socket.io-mock' import { ioMock } from '../shared/setupTests' -import { socketEventData } from '../renderer/testUtils/socket' +import { socketEventData } from '@quiet/types' import { communities, RegisterUserCertificatePayload, - InitCommunityPayload, ErrorCodes, ErrorMessages, getFactory, @@ -32,6 +31,7 @@ import { ChannelSubscribedPayload, Community, ErrorPayload, + type InitCommunityPayload, type NetworkInfo, ResponseLaunchCommunityPayload, SocketActionTypes, @@ -85,10 +85,9 @@ describe('User', () => { const factory = await getFactory(store) - const mockImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { + const mockEmitImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { const action = input[0] if (action === SocketActionTypes.CREATE_NETWORK) { - const payload = input[1] as Community return { hiddenService: { onionAddress: 'onionAddress', @@ -123,9 +122,9 @@ describe('User', () => { } } - jest.spyOn(socket, 'emit').mockImplementation(mockImpl) + jest.spyOn(socket, 'emit').mockImplementation(mockEmitImpl) // @ts-ignore - socket.emitWithAck = mockImpl + socket.emitWithAck = mockEmitImpl // Log all the dispatched actions in order const actions: AnyAction[] = [] @@ -170,20 +169,19 @@ describe('User', () => { expect(actions).toMatchInlineSnapshot(` Array [ + "Communities/joinNetwork", "Communities/createNetwork", - "Communities/setInvitationCodes", - "Communities/savePSK", "Communities/addNewCommunity", "Communities/setCurrentCommunity", + "Communities/setInvitationCodes", + "Identity/addNewIdentity", "Modals/closeModal", "Modals/openModal", - "Identity/addNewIdentity", "Identity/registerUsername", "Network/setLoadingPanelType", "Modals/openModal", "Identity/registerCertificate", "Communities/launchCommunity", - "Communities/sendCommunityCaData", "Files/checkForMissingFiles", "Network/addInitializedCommunity", "Communities/clearInvitationCodes", @@ -228,11 +226,10 @@ describe('User', () => { store ) - jest.spyOn(socket, 'emit').mockImplementation(async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { + const mockEmitImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { const action = input[0] if (action === SocketActionTypes.CREATE_NETWORK) { - const payload = input[1] as Community - return socket.socketClient.emit(SocketActionTypes.NETWORK_CREATED, { + return { hiddenService: { onionAddress: 'onionAddress', privateKey: 'privKey', @@ -240,7 +237,7 @@ describe('User', () => { peerId: { id: 'peerId', }, - }) + } } if (action === SocketActionTypes.REGISTER_USER_CERTIFICATE) { const payload = input[1] as RegisterUserCertificatePayload @@ -253,7 +250,11 @@ describe('User', () => { community: community?.id, }) } - }) + } + + jest.spyOn(socket, 'emit').mockImplementation(mockEmitImpl) + // @ts-ignore + socket.emitWithAck = mockEmitImpl // Log all the dispatched actions in order const actions: AnyAction[] = [] @@ -313,11 +314,10 @@ describe('User', () => { store ) - jest.spyOn(socket, 'emit').mockImplementation(async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { + const mockEmitImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { const action = input[0] if (action === SocketActionTypes.CREATE_NETWORK) { - const payload = input[1] as Community - return socket.socketClient.emit(SocketActionTypes.NETWORK_CREATED, { + return { hiddenService: { onionAddress: 'onionAddress', privateKey: 'privKey', @@ -325,9 +325,12 @@ describe('User', () => { peerId: { id: 'peerId', }, - }) + } } - }) + } + + // @ts-ignore + socket.emitWithAck = mockEmitImpl // Log all the dispatched actions in order const actions: AnyAction[] = [] diff --git a/packages/desktop/src/rtl-tests/customProtocol.test.tsx b/packages/desktop/src/rtl-tests/customProtocol.test.tsx index 9cacc8ece9..3064efc590 100644 --- a/packages/desktop/src/rtl-tests/customProtocol.test.tsx +++ b/packages/desktop/src/rtl-tests/customProtocol.test.tsx @@ -11,6 +11,7 @@ import { ModalName } from '../renderer/sagas/modals/modals.types' import JoinCommunity from '../renderer/components/CreateJoinCommunity/JoinCommunity/JoinCommunity' import CreateUsername from '../renderer/components/CreateUsername/CreateUsername' import { type Community, type InvitationData } from '@quiet/types' +import { composeInvitationDeepUrl } from '@quiet/common' jest.setTimeout(20_000) @@ -29,8 +30,6 @@ describe('Opening app through custom protocol', () => { rootCa: '', peerList: [], onionAddress: '', - privateKey: '', - port: 0, ownerCertificate: '', } @@ -65,7 +64,7 @@ describe('Opening app through custom protocol', () => { ownerOrbitDbIdentity: 'testOwnerOrbitDbIdentity', } - store.dispatch(communities.actions.customProtocol(invitationCodes)) + store.dispatch(communities.actions.customProtocol([composeInvitationDeepUrl(invitationCodes)])) store.dispatch(modalsActions.openModal({ name: ModalName.joinCommunityModal })) diff --git a/packages/desktop/src/rtl-tests/deep.linking.test.tsx b/packages/desktop/src/rtl-tests/deep.linking.test.tsx index 0fc27b8317..983523353e 100644 --- a/packages/desktop/src/rtl-tests/deep.linking.test.tsx +++ b/packages/desktop/src/rtl-tests/deep.linking.test.tsx @@ -7,7 +7,7 @@ import MockedSocket from 'socket.io-mock' import { ioMock } from '../shared/setupTests' import { prepareStore } from '../renderer/testUtils/prepareStore' import { renderComponent } from '../renderer/testUtils/renderComponent' -import { validInvitationCodeTestData } from '@quiet/common' +import { getValidInvitationUrlTestData, validInvitationCodeTestData } from '@quiet/common' import { communities } from '@quiet/state-manager' describe('Deep linking', () => { @@ -34,13 +34,17 @@ describe('Deep linking', () => { renderComponent(<>, store) - store.dispatch(communities.actions.customProtocol(validInvitationCodeTestData[0])) + store.dispatch( + communities.actions.customProtocol([getValidInvitationUrlTestData(validInvitationCodeTestData[0]).deepUrl()]) + ) await act(async () => {}) const originalPair = communities.selectors.invitationCodes(store.getState()) // Redo the action to provoke renewed saga runs - store.dispatch(communities.actions.customProtocol(validInvitationCodeTestData[1])) + store.dispatch( + communities.actions.customProtocol([getValidInvitationUrlTestData(validInvitationCodeTestData[1]).deepUrl()]) + ) await act(async () => {}) const currentPair = communities.selectors.invitationCodes(store.getState()) @@ -50,11 +54,11 @@ describe('Deep linking', () => { expect(actions).toMatchInlineSnapshot(` Array [ "Communities/customProtocol", + "Communities/joinNetwork", "Communities/createNetwork", - "Communities/setInvitationCodes", - "Communities/savePSK", "Communities/addNewCommunity", "Communities/setCurrentCommunity", + "Communities/setInvitationCodes", "Communities/customProtocol", ] `) diff --git a/packages/desktop/src/rtl-tests/generalChannel.create.test.tsx b/packages/desktop/src/rtl-tests/generalChannel.create.test.tsx deleted file mode 100644 index 858ce482c6..0000000000 --- a/packages/desktop/src/rtl-tests/generalChannel.create.test.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react' -import { act } from 'react-dom/test-utils' -import '@testing-library/jest-dom/extend-expect' -import { apply, fork, take } from 'typed-redux-saga' -import { renderComponent } from '../renderer/testUtils/renderComponent' -import { prepareStore } from '../renderer/testUtils/prepareStore' -import MockedSocket from 'socket.io-mock' -import { ioMock } from '../shared/setupTests' -import { socketEventData } from '../renderer/testUtils/socket' -import { AnyAction } from 'redux' -import { identity, publicChannels, getFactory, ChannelsReplicatedPayload } from '@quiet/state-manager' -import { SocketActionTypes } from '@quiet/types' -import Channel from '../renderer/components/Channel/Channel' - -jest.setTimeout(20_000) - -describe('General channel', () => { - let socket: MockedSocket - let communityId: string - - beforeEach(() => { - socket = new MockedSocket() - ioMock.mockImplementation(() => socket) - window.ResizeObserver = jest.fn().mockImplementation(() => ({ - observe: jest.fn(), - unobserve: jest.fn(), - disconnect: jest.fn(), - })) - }) - - it('create automatically along with creating community', async () => { - const { store, runSaga } = await prepareStore( - {}, - socket // Fork state manager's sagas - ) - - window.HTMLElement.prototype.scrollTo = jest.fn() - - renderComponent( - <> - - , - store - ) - - const factory = await getFactory(store) - - await factory.create['payload']>('Identity', { - nickname: 'alice', - }) - - const mockImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => { - const action = input[0] - if (action === SocketActionTypes.CREATE_CHANNEL) { - const payload = input[1] as ChannelsReplicatedPayload - expect(payload.channels.channel?.name).toEqual('general') - } - } - - jest.spyOn(socket, 'emit').mockImplementation(mockImpl) - // @ts-ignore - socket.emitWithAck = mockImpl - - // Log all the dispatched actions in order - const actions: AnyAction[] = [] - runSaga(function* (): Generator { - while (true) { - const action = yield* take() - actions.push(action.type) - } - }) - - await act(async () => { - await runSaga(testCreateGeneralChannelSaga).toPromise() - }) - - function* mockNewCommunityEvent(): Generator { - yield* apply(socket.socketClient, socket.socketClient.emit, [ - SocketActionTypes.COMMUNITY_CREATED, - { - id: communityId, - }, - ]) - } - - function* testCreateGeneralChannelSaga(): Generator { - yield* fork(mockNewCommunityEvent) - yield* take(publicChannels.actions.createChannel) - yield* take(publicChannels.actions.setCurrentChannel) - } - - expect(actions).toMatchInlineSnapshot(` - Array [ - "Communities/sendCommunityMetadata", - "PublicChannels/createGeneralChannel", - "Identity/saveUserCsr", - "PublicChannels/createChannel", - "PublicChannels/setCurrentChannel", - "PublicChannels/clearUnreadChannel", - "Messages/lazyLoading", - "Messages/resetCurrentPublicChannelCache", - ] - `) - }) -}) diff --git a/packages/e2e-tests/.gitignore b/packages/e2e-tests/.gitignore index 3d928d694b..6ca1a6bae7 100644 --- a/packages/e2e-tests/.gitignore +++ b/packages/e2e-tests/.gitignore @@ -2,4 +2,5 @@ lib/ screenshots/ .DS_Store -Quiet/Quiet** \ No newline at end of file +Quiet/Quiet** +.env \ No newline at end of file diff --git a/packages/e2e-tests/package-lock.json b/packages/e2e-tests/package-lock.json index bbcfdb5f02..7e083ff08a 100644 --- a/packages/e2e-tests/package-lock.json +++ b/packages/e2e-tests/package-lock.json @@ -21,6 +21,7 @@ "@types/jest": "^29.2.6", "@types/selenium-webdriver": "^4.1.10", "babel-jest": "^29.3.1", + "dotenv": "16.4.5", "lint-staged": "^15.2.2", "ts-jest": "^29.0.5", "typescript": "^4.9.3" @@ -2178,6 +2179,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/electron-chromedriver": { "version": "23.3.13", "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-23.3.13.tgz", @@ -7821,6 +7834,12 @@ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.2.tgz", "integrity": "sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw==" }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true + }, "electron-chromedriver": { "version": "23.3.13", "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-23.3.13.tgz", diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 9ea42b05f4..3628d6e810 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -16,7 +16,8 @@ "test": "cross-env TEST_MODE=true jest --runInBand --detectOpenHandles --forceExit", "test:localBinary": "cross-env TEST_MODE=true IS_LOCAL=true jest --runInBand --detectOpenHandles --forceExit --verbose --", "test:prod": "jest --runInBand --detectOpenHandles --forceExit", - "test:watch": "jest --watchAll" + "test:watch": "jest --watchAll", + "linux:copy": "node scripts/copyAppImage.js" }, "devDependencies": { "@quiet/eslint-config": "^2.0.2-alpha.0", @@ -25,7 +26,8 @@ "babel-jest": "^29.3.1", "lint-staged": "^15.2.2", "ts-jest": "^29.0.5", - "typescript": "^4.9.3" + "typescript": "^4.9.3", + "dotenv": "16.4.5" }, "dependencies": { "@quiet/common": "^2.0.2-alpha.1", diff --git a/packages/e2e-tests/scripts/copyAppImage.js b/packages/e2e-tests/scripts/copyAppImage.js new file mode 100644 index 0000000000..8843b85535 --- /dev/null +++ b/packages/e2e-tests/scripts/copyAppImage.js @@ -0,0 +1,16 @@ +// Copy built AppImage to Quiet directory and set the version in .env file +const { execFileSync } = require('child_process') +const path = require('path') +const fs = require('fs') + +const desktop = path.join(__dirname, '..', '..', 'desktop') +const e2e = path.join(__dirname, '..') +const appVersion = JSON.parse(require('fs').readFileSync(path.join(desktop, 'package.json'), 'utf8')).version +const fileName = `Quiet-${appVersion}.AppImage` + +execFileSync('rm', ['-rf', path.join(desktop, 'dist', 'squashfs-root')]) + +console.log(`Copying file ${fileName} for e2e tests`) +execFileSync('cp', [path.join(desktop, 'dist', fileName), path.join(e2e, 'Quiet', fileName)]) + +fs.writeFileSync(path.join(e2e, '.env'), `FILE_NAME=${fileName}`) diff --git a/packages/e2e-tests/src/selectors.ts b/packages/e2e-tests/src/selectors.ts index 95e7a2e4d8..bcd637b221 100644 --- a/packages/e2e-tests/src/selectors.ts +++ b/packages/e2e-tests/src/selectors.ts @@ -51,6 +51,14 @@ export class App { console.log('App closed', this.buildSetup.dataDir) } + async cleanup() { + console.log(`Performing app cleanup`, this.buildSetup.dataDir) + if (this.isOpened) { + throw new Error(`App with dataDir ${this.buildSetup.dataDir} is still open, close before cleaning up!`) + } + this.buildSetup.clearDataDir() + } + get saveStateButton() { return this.driver.wait(until.elementLocated(By.xpath('//div[@data-testid="save-state-button"]'))) } diff --git a/packages/e2e-tests/src/tests/backwardsCompatibility.test.ts b/packages/e2e-tests/src/tests/backwardsCompatibility.test.ts index 4d6f44b452..e238cbb81a 100644 --- a/packages/e2e-tests/src/tests/backwardsCompatibility.test.ts +++ b/packages/e2e-tests/src/tests/backwardsCompatibility.test.ts @@ -8,7 +8,7 @@ import { RegisterUsernameModal, Sidebar, } from '../selectors' -import { BACKWARD_COMPATIBILITY_BASE_VERSION, copyInstallerFile, downloadInstaller } from '../utils' +import { BACKWARD_COMPATIBILITY_BASE_VERSION, BuildSetup, copyInstallerFile, downloadInstaller } from '../utils' jest.setTimeout(1200000) describe('Backwards Compatibility', () => { @@ -26,7 +26,7 @@ describe('Backwards Compatibility', () => { const loopMessages = 'ąbc'.split('') const newChannelName = 'mid-night-club' - const isAlpha = process.env.FILE_NAME?.toString().includes('alpha') + const isAlpha = BuildSetup.getEnvFileName()?.toString().includes('alpha') beforeAll(async () => { // download the old version of the app @@ -42,6 +42,9 @@ describe('Backwards Compatibility', () => { afterAll(async () => { await new Promise(resolve => setTimeout(() => resolve(), 5000)) await ownerAppNewVersion?.close() + await ownerAppNewVersion?.cleanup() + await ownerAppOldVersion?.close() + await ownerAppOldVersion?.cleanup() }) describe('User opens app for the first time', () => { it('Owner opens the app', async () => { diff --git a/packages/e2e-tests/src/tests/invitationLink.test.ts b/packages/e2e-tests/src/tests/invitationLink.test.ts index 6deef6627c..472780f041 100644 --- a/packages/e2e-tests/src/tests/invitationLink.test.ts +++ b/packages/e2e-tests/src/tests/invitationLink.test.ts @@ -34,7 +34,9 @@ describe('New user joins using invitation link while having app opened', () => { afterAll(async () => { await ownerApp?.close() + await ownerApp?.cleanup() await guestApp?.close() + await guestApp?.cleanup() }) describe('Stages:', () => { diff --git a/packages/e2e-tests/src/tests/multipleClients.test.ts b/packages/e2e-tests/src/tests/multipleClients.test.ts index 5ec4b301aa..59ad62e03a 100644 --- a/packages/e2e-tests/src/tests/multipleClients.test.ts +++ b/packages/e2e-tests/src/tests/multipleClients.test.ts @@ -25,6 +25,8 @@ describe('Multiple Clients', () => { let secondChannelUser1: Channel + let thirdChannelOwner: Channel + let channelContextMenuOwner: ChannelContextMenu let invitationCode: string @@ -37,6 +39,7 @@ describe('Multiple Clients', () => { const communityName = 'testcommunity' const displayedCommunityName = 'Testcommunity' const newChannelName = 'mid-night-club' + const thirdChannelName = 'delete-this' const sleep = async (time = 1000) => { await new Promise(resolve => @@ -75,6 +78,7 @@ describe('Multiple Clients', () => { afterAll(async () => { for (const user of Object.values(users)) { await user.app.close() + await user.app.cleanup() } }) @@ -342,16 +346,42 @@ describe('Multiple Clients', () => { const channels = await sidebarOwner.getChannelList() expect(channels.length).toEqual(2) }) + + it('Channel deletion - Owner creates third channel', async () => { + await sidebarOwner.addNewChannel(thirdChannelName) + await sidebarOwner.switchChannel(thirdChannelName) + thirdChannelOwner = new Channel(users.owner.app.driver, thirdChannelName) + const messages = await thirdChannelOwner.getUserMessages(users.owner.username) + expect(messages.length).toEqual(1) + await new Promise(resolve => + setTimeout(() => { + resolve() + }, 2000) + ) + const channels = await sidebarUser1.getChannelList() + expect(channels.length).toEqual(3) + }) + // End of tests for Windows if (process.platform !== 'win32') { - it('Leave community', async () => { - console.log('TEST 2') - const settingsModal = await new Sidebar(users.user1.app.driver).openSettings() - const isSettingsModal = await settingsModal.element.isDisplayed() - expect(isSettingsModal).toBeTruthy() - await settingsModal.openLeaveCommunityModal() - await settingsModal.leaveCommunityButton() + it('User 1 closes app', async () => { + console.log('User 1 closes app') + await users.user1.app?.close() }) + + // Delete third channel while guest is absent + it('Channel deletion - Owner deletes third channel', async () => { + console.log('TEST 2.5') + await new Promise(resolve => setTimeout(() => resolve(), 10000)) + const isThirdChannel = await thirdChannelOwner.messageInput.isDisplayed() + expect(isThirdChannel).toBeTruthy() + await channelContextMenuOwner.openMenu() + await channelContextMenuOwner.openDeletionChannelModal() + await channelContextMenuOwner.deleteChannel() + const channels = await sidebarOwner.getChannelList() + expect(channels.length).toEqual(2) + }) + // Delete general channel while guest is absent it('Channel deletion - Owner recreates general channel', async () => { console.log('TEST 3') @@ -365,6 +395,47 @@ describe('Multiple Clients', () => { expect(channels.length).toEqual(2) }) + it('User 1 re-opens app', async () => { + console.log('User 1 re-opens app') + await users.user1.app?.open() + await new Promise(resolve => setTimeout(() => resolve(), 30000)) + }) + + // Check correct channels replication + it('Channel deletion - User sees information about recreation general channel and see correct amount of messages (#2334)', async () => { + console.log('TESTING - ISSUE 2334') + generalChannelUser1 = new Channel(users.user1.app.driver, 'general') + await generalChannelUser1.element.isDisplayed() + console.timeEnd(`[${users.user1.app.name}] '${users.user2.username}' joining community time`) + await new Promise(resolve => + setTimeout(() => { + resolve() + }, 10000) + ) + + await generalChannelUser1.waitForUserMessage( + users.owner.username, + `@${users.owner.username} deleted all messages in #general` + ) + await generalChannelUser1.waitForUserMessage( + users.owner.username, + `@${users.owner.username} deleted #${thirdChannelName}` + ) + await generalChannelUser1.waitForUserMessage( + users.owner.username, + `@${users.user2.username} has joined Testcommunity! 🎉` + ) + }) + + it('Leave community', async () => { + console.log('TEST 2') + const settingsModal = await new Sidebar(users.user1.app.driver).openSettings() + const isSettingsModal = await settingsModal.element.isDisplayed() + expect(isSettingsModal).toBeTruthy() + await settingsModal.openLeaveCommunityModal() + await settingsModal.leaveCommunityButton() + }) + it('Leave community - Guest re-join to community successfully', async () => { console.log('TEST 4') const debugModal = new DebugModeModal(users.user1.app.driver) diff --git a/packages/e2e-tests/src/tests/oneClient.test.ts b/packages/e2e-tests/src/tests/oneClient.test.ts index 05d22a077f..1dab965c39 100644 --- a/packages/e2e-tests/src/tests/oneClient.test.ts +++ b/packages/e2e-tests/src/tests/oneClient.test.ts @@ -23,6 +23,7 @@ describe('One Client', () => { afterAll(async () => { await app.close() + await app.cleanup() }) describe('User opens app for the first time', () => { it('Get opened app process data', () => { diff --git a/packages/e2e-tests/src/tests/userProfile.test.ts b/packages/e2e-tests/src/tests/userProfile.test.ts index efd0e67d47..6584dc5175 100644 --- a/packages/e2e-tests/src/tests/userProfile.test.ts +++ b/packages/e2e-tests/src/tests/userProfile.test.ts @@ -50,6 +50,7 @@ describe('User Profile Feature', () => { afterAll(async () => { for (const user of Object.values(users)) { await user.app.close() + await user.app.cleanup() } }) diff --git a/packages/e2e-tests/src/utils.ts b/packages/e2e-tests/src/utils.ts index c6cb437999..cb38d7a977 100644 --- a/packages/e2e-tests/src/utils.ts +++ b/packages/e2e-tests/src/utils.ts @@ -4,7 +4,8 @@ import { type SupportedPlatformDesktop } from '@quiet/types' import getPort from 'get-port' import path from 'path' import fs from 'fs' -import { DESKTOP_DATA_DIR } from '@quiet/common' +import { DESKTOP_DATA_DIR, getAppDataPath } from '@quiet/common' +import { config } from 'dotenv' export const BACKWARD_COMPATIBILITY_BASE_VERSION = '2.0.1' // Pre-latest production version const appImagesPath = `${__dirname}/../Quiet` @@ -22,6 +23,7 @@ export class BuildSetup { public port?: number public debugPort?: number public dataDir?: string + public dataDirPath: string private child?: ChildProcessWithoutNullStreams private defaultDataDir: boolean private fileName?: string @@ -36,6 +38,7 @@ export class BuildSetup { if (!this.dataDir) { this.dataDir = `e2e_${(Math.random() * 10 ** 18).toString(36)}` } + this.dataDirPath = getAppDataPath({ dataDir: this.dataDir }) } async initPorts() { @@ -43,11 +46,17 @@ export class BuildSetup { this.debugPort = await getPort() } + static getEnvFileName() { + const { parsed, error } = config() + console.log('Dotenv config', { parsed, error }) + return process.env.FILE_NAME + } + private getBinaryLocation() { console.log('filename', this.fileName) switch (process.platform) { case 'linux': - return `${__dirname}/../Quiet/${this.fileName ? this.fileName : process.env.FILE_NAME}` + return `${__dirname}/../Quiet/${this.fileName ? this.fileName : BuildSetup.getEnvFileName()}` case 'win32': return `${process.env.LOCALAPPDATA}\\Programs\\@quietdesktop\\Quiet.exe` case 'darwin': @@ -69,7 +78,7 @@ export class BuildSetup { } public getVersionFromEnv() { - const envFileName = process.env.FILE_NAME + const envFileName = BuildSetup.getEnvFileName() if (!envFileName) { throw new Error('file name not specified') } @@ -224,6 +233,15 @@ export class BuildSetup { await this.driver?.close() } + public clearDataDir() { + if (process.env.IS_CI === 'true') { + console.warn('Not deleting data directory because we are running in CI') + return + } + console.log(`Deleting data directory at ${this.dataDirPath}`) + fs.rmdirSync(this.dataDirPath, { recursive: true }) + } + public getProcessData = () => { let dataDirPath = '' let resourcesPath = '' diff --git a/packages/identity/src/common.ts b/packages/identity/src/common.ts index 3b6f828e0b..dbd7619b7b 100644 --- a/packages/identity/src/common.ts +++ b/packages/identity/src/common.ts @@ -9,6 +9,7 @@ export enum CertFieldsTypes { subjectAltName = '2.5.29.17', nickName = '1.3.6.1.4.1.50715.2.1', peerId = '1.3.6.1.2.1.15.3.1.1', + // DEPRECATED dmPublicKey = '1.2.840.113549.1.9.12', } @@ -100,17 +101,9 @@ export const getCertFieldValue = (cert: Certificate, fieldType: CertFieldsTypes } else { const ext = cert.extensions?.find(tav => tav.extnID === fieldType) if (ext) { - if (fieldType === CertFieldsTypes.dmPublicKey) { - const extObj = ext?.extnValue.valueBlock.value[0] - // @ts-ignore - const arrayBuffer = extObj.valueBlock.valueHex - - return arrayBufferToHexString(arrayBuffer) - } else { - const extObj = ext?.extnValue.valueBlock.value[0] - // @ts-ignore - return extObj.valueBlock.value - } + const extObj = ext?.extnValue.valueBlock.value[0] + // @ts-ignore + return extObj.valueBlock.value } else { return null } @@ -131,12 +124,7 @@ export const getReqFieldValue = ( } else { const ext = csr.attributes?.find(tav => tav.type === fieldType) if (ext) { - if (fieldType === CertFieldsTypes.dmPublicKey) { - const extObj = ext.values[0].valueBlock.valueHex - return arrayBufferToHexString(extObj) - } else { - return ext.values[0].valueBlock.value - } + return ext.values[0].valueBlock.value } else { return null } diff --git a/packages/identity/src/createUserCert.ts b/packages/identity/src/createUserCert.ts index d8e53b4837..c8cb455bcf 100644 --- a/packages/identity/src/createUserCert.ts +++ b/packages/identity/src/createUserCert.ts @@ -69,14 +69,17 @@ async function generateUserCertificate({ ], }) const attr: Attribute[] | undefined = pkcs10.attributes - let dmPubKey = null let nickname = null let peerId = null let onionAddress = null let altNames try { - dmPubKey = attr?.[1].values[0].valueBlock.valueHex + // publicKey = attr[0] + + // DEPRECATED + // dmPublicKey = attr[1] + nickname = attr?.[2].values[0].valueBlock.value peerId = attr?.[3].values[0].valueBlock.value onionAddress = attr?.[4].values[0].valueBlock.value @@ -89,6 +92,7 @@ async function generateUserCertificate({ ], }) } catch (err) { + console.error(err) throw new Error('Cannot get certificate request extension') } @@ -114,11 +118,6 @@ async function generateUserCertificate({ extnValue: extKeyUsage.toSchema().toBER(false), parsedValue: extKeyUsage, // Parsed value for well-known extensions }), - new Extension({ - extnID: CertFieldsTypes.dmPublicKey, - critical: false, - extnValue: new OctetString({ valueHex: dmPubKey }).toBER(false), - }), new Extension({ extnID: CertFieldsTypes.nickName, critical: false, diff --git a/packages/identity/src/createUserCsr.ts b/packages/identity/src/createUserCsr.ts index eee73dbc27..1266f1f6c3 100644 --- a/packages/identity/src/createUserCsr.ts +++ b/packages/identity/src/createUserCsr.ts @@ -20,13 +20,11 @@ export const createUserCsr = async ({ nickname, commonName, peerId, - dmPublicKey, existingKeyPair, }: { nickname: string commonName: string peerId: string - dmPublicKey: string signAlg: string hashAlg: string existingKeyPair?: CryptoKeyPair @@ -35,7 +33,6 @@ export const createUserCsr = async ({ nickname, commonName, peerId, - dmPublicKey, signAlg: config.signAlg, hashAlg: config.hashAlg, existingKeyPair, @@ -59,7 +56,6 @@ async function requestCertificate({ nickname, commonName, peerId, - dmPublicKey, signAlg = config.signAlg, hashAlg = config.hashAlg, existingKeyPair, @@ -67,15 +63,12 @@ async function requestCertificate({ nickname: string commonName: string peerId: string - dmPublicKey: string signAlg: string hashAlg: string existingKeyPair?: CryptoKeyPair }): Promise { const keyPair: CryptoKeyPair = existingKeyPair ? existingKeyPair : await generateKeyPair({ signAlg }) - const arrayBufferDmPubKey = hexStringToArrayBuffer(dmPublicKey) - const pkcs10 = new CertificationRequest({ version: 0, attributes: [], @@ -110,10 +103,17 @@ async function requestCertificate({ }).toSchema(), ], }), + + // DEPRECATED + // + // We can only remove this attribute when all owners upgrade to + // the version that contains this commit. Otherwise, there could + // be Quiet instances that still reference this attribute. new Attribute({ type: CertFieldsTypes.dmPublicKey, - values: [new OctetString({ valueHex: arrayBufferDmPubKey })], + values: [new OctetString({ valueHex: hexStringToArrayBuffer('') })], }), + new Attribute({ type: CertFieldsTypes.nickName, values: [new PrintableString({ value: nickname })], diff --git a/packages/identity/src/test/helpers.ts b/packages/identity/src/test/helpers.ts index 68760bfbb8..b663df43d2 100644 --- a/packages/identity/src/test/helpers.ts +++ b/packages/identity/src/test/helpers.ts @@ -9,7 +9,6 @@ export const userData = { nickname: 'userName', commonName: 'nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', - dmPublicKey: '0bfb475810c0e26c9fab590d47c3d60ec533bb3c451596acc3cd4f21602e9ad9', signAlg: config.signAlg, hashAlg: config.hashAlg, } @@ -62,7 +61,6 @@ export const createUserCertificateTestHelper = async ( nickname: string commonName: string peerId: string - dmPublicKey: string }, rootCA?: Pick | null ): Promise<{ @@ -73,7 +71,6 @@ export const createUserCertificateTestHelper = async ( nickname: user.nickname, commonName: user.commonName, peerId: user.peerId, - dmPublicKey: user.dmPublicKey, signAlg: config.signAlg, hashAlg: config.hashAlg, }) diff --git a/packages/identity/src/test/index.test.ts b/packages/identity/src/test/index.test.ts index 23a1f69dfb..b6af8010ea 100644 --- a/packages/identity/src/test/index.test.ts +++ b/packages/identity/src/test/index.test.ts @@ -87,7 +87,6 @@ describe('Certificate', () => { [CertFieldsTypes.commonName]: userData.commonName, [CertFieldsTypes.nickName]: userData.nickname, [CertFieldsTypes.peerId]: userData.peerId, - [CertFieldsTypes.dmPublicKey]: userData.dmPublicKey, } type CertFieldsTypesKeys = keyof typeof certTypeData @@ -107,7 +106,6 @@ describe('Certificate', () => { [CertFieldsTypes.commonName]: userData.commonName, [CertFieldsTypes.nickName]: userData.nickname, [CertFieldsTypes.peerId]: userData.peerId, - [CertFieldsTypes.dmPublicKey]: userData.dmPublicKey, } type CertFieldsTypesKeys = keyof typeof certTypeData @@ -126,7 +124,6 @@ describe('Certificate', () => { 'MIIB7TCCAZMCBgF641h5xzAKBggqhkjOPQQDAjASMRAwDgYDVQQDEwdaYmF5IENBMB4XDTIxMDcyNjE1MDQyNFoXDTMwMDIwMTAwMDAwMFowgc4xgcswHAYKKwYBBAGDjBsCARMOZGV2OTlkZXY5OXlvZGEwPwYDVQQDEzgzNWNzNmZramJoZmJiMnppYnIzNm5rdXY0cWlld2x2NXBmcGprbHh2N2xtcGphM2hydTN3NDdpZDA7BgkrBgECAQ8DAQETLlFtVmIxbUZ2Z1hKZXRKS0o1NmRtR1Q2Rkd1TnJtM0VhVFZ6V3VHaGtxcjZodjUwLQYJKoZIhvcNAQkMBCCf3wijnripB3ZADnDgT1ZIr1zUGjHVZI2K4kt6Yb7CazBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDKw/zcoE2Vahw3q9CdRQsCXikFU8PhEIN/y65hrB6yAxWH4Ut9QBKMMAnaG8JlzvEeaScQiu5Jyyx0O0xAadQ+jHTAbMAwGA1UdEwQFMAMCAQMwCwYDVR0PBAQDAgAGMAoGCCqGSM49BAMCA0gAMEUCIQCRz+6W3K3SI7Q7uYDVVIJXnWud/DGvpqHCuLJ+gnJLMgIgBmS1D8s1xnGOQpARx40vus4b/f49LQeG2YxPCSHVQOM=' ) - expect(getCertFieldValue(parsedCert, CertFieldsTypes.dmPublicKey)).toEqual(null) expect(getCertFieldValue(parsedCert, CertFieldsTypes.subjectAltName)).toEqual(null) expect(getCertFieldValue(parsedCert, CertFieldsTypes.peerId)).toEqual(null) expect(getCertFieldValue(parsedCert, CertFieldsTypes.nickName)).toEqual(null) diff --git a/packages/integration-tests/src/integrationTests/appActions.ts b/packages/integration-tests/src/integrationTests/appActions.ts index bcbff3e67e..dd789afdb7 100644 --- a/packages/integration-tests/src/integrationTests/appActions.ts +++ b/packages/integration-tests/src/integrationTests/appActions.ts @@ -252,7 +252,7 @@ export const getCommunityOwnerData = (ownerStore: Store) => { communityId: community.id, ownerPeerId: ownerIdentityState.identities.entities[ownerIdentityState.identities.ids[0]].peerId.id, ownerRootCA: community.rootCa, - registrarPort: community.port, + registrarPort: 0, } } diff --git a/packages/mobile/CHANGELOG.md b/packages/mobile/CHANGELOG.md index dc3bd2fff0..e5ad80e5c2 100644 --- a/packages/mobile/CHANGELOG.md +++ b/packages/mobile/CHANGELOG.md @@ -1,6 +1,27 @@ [unreleased] +# New features: + +# Refactorings: + +# Fixes: + +[2.2.0] + +# New features: + +* Add utilities for emoji detection in messages and make all-emoji message larger font size ([#519](https://github.com/TryQuiet/quiet/issues/519)) + +# Refactorings: + +* Use ack for CREATE_NETWORK and simplify +* Move Community model to the backend + +# Fixes: +* Allow JPEG and GIF files as profile photos ([#2332](https://github.com/TryQuiet/quiet/issues/2332)) +* Fix issues with recreating general channel when deleted while offline ([#2334](https://github.com/TryQuiet/quiet/issues/2334)) +* Fix package.json license inconsistency [2.1.2] @@ -14,6 +35,7 @@ # Fixes: +* Fixes channel name creation logic * Remove duplicate introduction messages once again * Prevent channel creation with names that start with special character, then a hyphen * Choose random ports for Tor services (iOS) diff --git a/packages/mobile/android/app/CMakeLists.txt b/packages/mobile/android/app/CMakeLists.txt index cfa13b4744..04a447615b 100644 --- a/packages/mobile/android/app/CMakeLists.txt +++ b/packages/mobile/android/app/CMakeLists.txt @@ -11,45 +11,31 @@ cmake_minimum_required(VERSION 3.4.1) # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. - node-wrapper + own-native-lib - # Sets the library as a shared library. - SHARED + # Sets the library as a shared library. + SHARED - # Provides a relative path to your source file(s). - src/main/cpp/node-wrapper.cpp - src/main/cpp/rn-bridge.cpp ) - -add_library( - tor-wrapper - SHARED - src/main/cpp/tor-wrapper.cpp ) + # Provides a relative path to your source file(s). + src/main/cpp/own-native-lib.cpp + src/main/cpp/rn-bridge.cpp + ) include_directories(libnode/include/node/) -include_directories(libtor/include/tor/) include_directories(src/main/cpp/) add_library( libnode - SHARED - IMPORTED ) - -add_library( libtor - SHARED - IMPORTED ) + SHARED + IMPORTED ) set_target_properties( # Specifies the target library. - libnode + libnode - # Specifies the parameter you want to define. - PROPERTIES IMPORTED_LOCATION + # Specifies the parameter you want to define. + PROPERTIES IMPORTED_LOCATION - # Provides the path to the library you want to import. - ${CMAKE_SOURCE_DIR}/libnode/bin/libnode.so ) - -set_target_properties( - libtor - PROPERTIES IMPORTED_LOCATION - ${CMAKE_SOURCE_DIR}/libtor/bin/libtor.so ) + # Provides the path to the library you want to import. + ${CMAKE_SOURCE_DIR}/libnode/bin/${ANDROID_ABI}/libnode.so ) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by @@ -58,26 +44,21 @@ set_target_properties( # completing its build. find_library( # Sets the name of the path variable. - log-lib + log-lib - # Specifies the name of the NDK library that - # you want CMake to locate. - log ) + # Specifies the name of the NDK library that + # you want CMake to locate. + log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. - node-wrapper - - libnode + own-native-lib - # Links the target library to the log library - # included in the NDK. - ${log-lib} ) + libnode -target_link_libraries( - tor-wrapper - libtor - ${log-lib} ) + # Links the target library to the log library + # included in the NDK. + ${log-lib} ) \ No newline at end of file diff --git a/packages/mobile/android/app/build.gradle b/packages/mobile/android/app/build.gradle index 7ba2de94cd..d74a8bbe60 100644 --- a/packages/mobile/android/app/build.gradle +++ b/packages/mobile/android/app/build.gradle @@ -180,6 +180,10 @@ android { pickFirst 'lib/x86_64/libfbjni.so' pickFirst 'lib/armeabi-v7a/libfbjni.so' pickFirst 'lib/arm64-v8a/libfbjni.so' + + jniLibs { + useLegacyPackaging = true + } } namespace "com.quietmobile" @@ -188,8 +192,8 @@ android { applicationId "com.quietmobile" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 410 - versionName "2.1.2-alpha.14" + versionCode 413 + versionName "2.2.0-alpha.1" resValue "string", "build_config_package", "com.quietmobile" testBuildType System.getProperty('testBuildType', 'debug') testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' @@ -201,6 +205,11 @@ android { cppFlags "" } } + externalNativeBuild { + cmake { + cppFlags "" + } + } } splits { abi { @@ -315,7 +324,7 @@ dependencies { implementation group: 'commons-io', name: 'commons-io', version: '2.6' - // implementation 'info.guardianproject:tor-android:0.4.5.7' + implementation 'info.guardianproject:tor-android:0.4.5.7' implementation 'info.guardianproject:jtorctl:0.4.5.7' // Websockets connection diff --git a/packages/mobile/android/app/libnode/bin/libnode.so b/packages/mobile/android/app/libnode/bin/arm64-v8a/libnode.so similarity index 100% rename from packages/mobile/android/app/libnode/bin/libnode.so rename to packages/mobile/android/app/libnode/bin/arm64-v8a/libnode.so diff --git a/packages/mobile/android/app/libtor/bin/libtor.so b/packages/mobile/android/app/libtor/bin/libtor.so deleted file mode 100755 index 985df9f4e2..0000000000 Binary files a/packages/mobile/android/app/libtor/bin/libtor.so and /dev/null differ diff --git a/packages/mobile/android/app/libtor/include/tor/org_torproject_jni_TorService.h b/packages/mobile/android/app/libtor/include/tor/org_torproject_jni_TorService.h deleted file mode 100644 index 7dcc6af69d..0000000000 --- a/packages/mobile/android/app/libtor/include/tor/org_torproject_jni_TorService.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * The code in this file is from - * https://github.com/guardianproject/tor/blob/86771dade0937520a0a164ca571c5c7a8a1c20cc/src/feature/api/org_torproject_jni_TorService.h - * and is licensed under external-licenses/tor.license.txt. - */ - -/* Copyright (c) 2019, Matthew Finkel. - * Copyright (c) 2019, Hans-Christoph Steiner. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -#ifndef ORG_TORPROJECT_JNI_TORSERVICE_H -#define ORG_TORPROJECT_JNI_TORSERVICE_H - -#include - -/* - * Class: org_torproject_jni_TorService - * Method: createTorConfiguration - * Signature: ()Z - */ -extern "C" JNIEXPORT jboolean JNICALL - Java_org_torproject_jni_TorService_createTorConfiguration - (JNIEnv *, jobject); - -/* - * Class: org_torproject_jni_TorService - * Method: mainConfigurationSetCommandLine - * Signature: ([Ljava/lang/String;)Z - */ -extern "C" JNIEXPORT jboolean JNICALL - Java_org_torproject_jni_TorService_mainConfigurationSetCommandLine - (JNIEnv *, jobject, jobjectArray); - -/* - * Class: org_torproject_jni_TorService - * Method: mainConfigurationSetupControlSocket - * Signature: ()Z - */ -extern "C" JNIEXPORT jboolean JNICALL - Java_org_torproject_jni_TorService_mainConfigurationSetupControlSocket - (JNIEnv *, jobject); - -/* - * Class: org_torproject_jni_TorService - * Method: mainConfigurationFree - * Signature: ()V - */ -extern "C" JNIEXPORT void JNICALL - Java_org_torproject_jni_TorService_mainConfigurationFree - (JNIEnv *, jobject); - -/* - * Class: org_torproject_jni_TorService - * Method: apiGetProviderVersion - * Signature: ()Ljava/lang/String; - */ -extern "C" JNIEXPORT jstring JNICALL - Java_org_torproject_jni_TorService_apiGetProviderVersion - (JNIEnv *, jobject); - -/* - * Class: org_torproject_jni_TorService - * Method: runMain - * Signature: ()I - */ -extern "C" JNIEXPORT jint JNICALL - Java_org_torproject_jni_TorService_runMain - (JNIEnv *, jobject); - -/* - * Class: org_torproject_jni_TorService - * Method: prepareFileDescriptor - */ -extern "C" JNIEXPORT jobject JNICALL -Java_org_torproject_jni_TorService_prepareFileDescriptor - (JNIEnv *env, jclass, jstring); - -#endif /* !defined(ORG_TORPROJECT_JNI_TORSERVICE_H) */ diff --git a/packages/mobile/android/app/src/main/cpp/node-wrapper.cpp b/packages/mobile/android/app/src/main/cpp/own-native-lib.cpp similarity index 95% rename from packages/mobile/android/app/src/main/cpp/node-wrapper.cpp rename to packages/mobile/android/app/src/main/cpp/own-native-lib.cpp index a73ba72595..805c862814 100644 --- a/packages/mobile/android/app/src/main/cpp/node-wrapper.cpp +++ b/packages/mobile/android/app/src/main/cpp/own-native-lib.cpp @@ -1,8 +1,3 @@ -/** - * The code in this file is from - * https://github.com/nodejs-mobile/nodejs-mobile-react-native/blob/c27c483698e2eb0dcaf87028bc4963a321b4d4f8/android/src/main/cpp/native-lib.cpp - * and is licensed under external-licenses/nodejs-mobile-react-native.license.txt. - */ #include #include #include diff --git a/packages/mobile/android/app/src/main/cpp/rn-bridge.cpp b/packages/mobile/android/app/src/main/cpp/rn-bridge.cpp index abc63f4d2a..1bb2f5c2a2 100644 --- a/packages/mobile/android/app/src/main/cpp/rn-bridge.cpp +++ b/packages/mobile/android/app/src/main/cpp/rn-bridge.cpp @@ -1,11 +1,3 @@ -/** - * The code in this file is from - * https://github.com/nodejs-mobile/nodejs-mobile-react-native/blob/fb61fc106794d945dacea943915ea893aca08a52/android/src/main/cpp/rn-bridge.cpp - * and - * https://github.com/nodejs-mobile/nodejs-mobile-react-native/blob/7069d4bd84d66c264eda7ea99599ef3957b36de9/android/src/main/cpp/rn-bridge.cpp - * and is licensed under - * external-licenses/nodejs-mobile-react-native.license.txt. - */ #define NAPI_VERSION 3 #include "node_api.h" #include "uv.h" @@ -364,3 +356,4 @@ void rn_bridge_notify(const char* channelName, const char *message) { } NAPI_MODULE_X(rn_bridge, Init, NULL, NM_F_LINKED) + diff --git a/packages/mobile/android/app/src/main/cpp/rn-bridge.h b/packages/mobile/android/app/src/main/cpp/rn-bridge.h index 0a57d3ef9d..2c357af717 100644 --- a/packages/mobile/android/app/src/main/cpp/rn-bridge.h +++ b/packages/mobile/android/app/src/main/cpp/rn-bridge.h @@ -1,10 +1,3 @@ -/** - * The code in this file is from - * https://github.com/nodejs-mobile/nodejs-mobile-react-native/blob/c27c483698e2eb0dcaf87028bc4963a321b4d4f8/android/src/main/cpp/rn-bridge.h - * and is licensed under - * external-licenses/nodejs-mobile-react-native.license.txt. - */ - #ifndef SRC_RN_BRIDGE_H_ #define SRC_RN_BRIDGE_H_ diff --git a/packages/mobile/android/app/src/main/cpp/tor-wrapper.cpp b/packages/mobile/android/app/src/main/cpp/tor-wrapper.cpp deleted file mode 100644 index 7be19302b8..0000000000 --- a/packages/mobile/android/app/src/main/cpp/tor-wrapper.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include - -#include "org_torproject_jni_TorService.h" - -extern "C" JNIEXPORT void JNICALL -Java_com_quietmobile_Backend_TorHandler_mainConfigurationSetupControlSocket( - JNIEnv *env, - jobject thisObj) -{ - Java_org_torproject_jni_TorService_mainConfigurationSetupControlSocket(env, thisObj); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_quietmobile_Backend_TorHandler_runMain( - JNIEnv *env, - jobject thisObj) -{ - Java_org_torproject_jni_TorService_runMain(env, thisObj); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_quietmobile_Backend_TorHandler_createTorConfiguration( - JNIEnv *env, - jobject thisObj) -{ - Java_org_torproject_jni_TorService_createTorConfiguration(env, thisObj); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_quietmobile_Backend_TorHandler_prepareFileDescriptor( - JNIEnv *env, - jclass thisClass, - jstring stringArgv) -{ - Java_org_torproject_jni_TorService_prepareFileDescriptor(env, thisClass, stringArgv); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_quietmobile_Backend_TorHandler_mainConfigurationSetCommandLine( - JNIEnv *env, - jobject thisObj, - jobjectArray arrArgv) -{ - Java_org_torproject_jni_TorService_mainConfigurationSetCommandLine(env, thisObj, arrArgv); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_quietmobile_Backend_TorHandler_mainConfigurationFree( - JNIEnv *env, - jobject thisObj) -{ - Java_org_torproject_jni_TorService_mainConfigurationFree(env, thisObj); -} diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt b/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt index 753bc6308b..b25ff8ef7f 100644 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt +++ b/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt @@ -39,12 +39,10 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters // Use dedicated class for composing and displaying notifications private lateinit var notificationHandler: NotificationHandler - private lateinit var torHandler: TorHandler - companion object { init { + System.loadLibrary("own-native-lib") System.loadLibrary("node") - System.loadLibrary("node-wrapper") } } @@ -99,19 +97,10 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters withContext(Dispatchers.IO) { - val dataPath = Utils.createDirectory(context) + // Get and store data port for usage in methods across the app val dataPort = Utils.getOpenPort(11000) - val socketIOSecret = Utils.generateRandomString(20) - launch { - torHandler = TorHandler(context) - torHandler.controlPort = Utils.getOpenPort(Utils.generateRandomInt()) - torHandler.socksPort = Utils.getOpenPort(Utils.generateRandomInt()) - torHandler.httpTunnelPort = Utils.getOpenPort(Utils.generateRandomInt()) - torHandler.startTorThread() - } - // Init nodejs project launch { nodeProject.init() @@ -136,6 +125,13 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters startWebsocketConnection(dataPort, socketIOSecret) } + val dataPath = Utils.createDirectory(context) + + val appInfo = context.packageManager.getApplicationInfo(context.packageName, 0) + val torBinary = appInfo.nativeLibraryDir + "/libtor.so" + + val platform = "mobile" + launch { /* * The point of this delay is to prevent startup race condition @@ -143,7 +139,7 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters * https://github.com/TryQuiet/quiet/issues/2214 */ delay(500) - startNodeProjectWithArguments("bundle.cjs --authCookie ${torHandler.authCookie} --controlPort ${torHandler.controlPort} --httpTunnelPort ${torHandler.httpTunnelPort} --dataPath $dataPath --dataPort $dataPort --socketIOSecret $socketIOSecret --platform mobile") + startNodeProjectWithArguments("bundle.cjs --torBinary $torBinary --dataPath $dataPath --dataPort $dataPort --platform $platform --socketIOSecret $socketIOSecret") } } diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/TorHandler.java b/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/TorHandler.java deleted file mode 100644 index e400d83df1..0000000000 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/TorHandler.java +++ /dev/null @@ -1,318 +0,0 @@ -/** - * The code in this file is from - * https://github.com/guardianproject/tor-android/blob/56c5105b6e12748a388778d0bbb36fb85c295f4b/tor-android-binary/src/main/java/org/torproject/jni/TorService.java - * and is licensed under external-licenses/tor-android.license.txt. - * - * This code has been modified to work with Tor control port instead - * of control socket. - */ -package com.quietmobile.Backend; - -import static android.content.Context.MODE_PRIVATE; - -import android.content.Context; -import android.os.FileObserver; -import android.os.Process; -import android.util.Log; - -import androidx.annotation.Nullable; - -import com.quietmobile.Utils.Utils; - -import net.freehaven.tor.control.TorControlCommands; -import net.freehaven.tor.control.TorControlConnection; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - - -public class TorHandler { - - static { - System.loadLibrary("tor"); - System.loadLibrary("tor-wrapper"); - } - - private static final boolean ENABLE_CONTROL_SOCKET = false; - - private static final String CONTROL_SOCKET_NAME = "ControlSocket"; - - private final Context context; - - public TorHandler(Context applicationContext) { - this.context = applicationContext; - } - - public int controlPort = -1; - public int socksPort = -1; - public int httpTunnelPort = -1; - - public static final String TAG = "TorHandler"; - - /** - * @return a {@link File} pointing to the location of the optional - * {@code torrc} file. - * @see Tor configuration file format - */ - public static File getTorrc(Context context) { - return new File(getAppTorHandlerDir(context), "torrc"); - } - - /** - * @return a {@link File} pointing to the location of the optional - * {@code torrc-defaults} file. - * @see Tor configuration file format - */ - public static File getDefaultsTorrc(Context context) { - return new File(getAppTorHandlerDir(context), "torrc-defaults"); - } - - private static File getControlSocket(Context context) { - if (controlSocket == null) { - controlSocket = new File(getAppTorHandlerDataDir(context), CONTROL_SOCKET_NAME); - } - return controlSocket; - } - - /** - * Get the directory that {@link TorHandler} uses for: - *
      - *
    • writing {@code ControlPort.txt} // TODO - *
    • reading {@code torrc} and {@code torrc-defaults} - *
    • {@code DataDirectory} and {@code CacheDirectory} - *
    • the debug log file - *
    - */ - private static File getAppTorHandlerDir(Context context) { - if (appTorHandlerDir == null) { - appTorHandlerDir = context.getDir("AppTorHandler", MODE_PRIVATE); - } - return appTorHandlerDir; - } - - /** - * Tor stores private, internal data in this directory. - */ - private static File getAppTorHandlerDataDir(Context context) { - File dir = new File(getAppTorHandlerDir(context), "data"); - dir.mkdir(); - if (!(dir.setReadable(true, true) && dir.setWritable(true, true) && dir.setExecutable(true, true))) { - throw new IllegalStateException("Cannot create " + dir); - } - return dir; - } - - @Nullable - private Path getAuthCookiePath() { - String dataDirectoryPath = getAppTorHandlerDataDir(context).getPath(); - return Paths.get(dataDirectoryPath, "control_auth_cookie"); - } - - private void removeAuthCookie() { - Path path = getAuthCookiePath(); - try { - Files.deleteIfExists(path); - } catch (IOException e) { - Log.i("QUIET_TOR", "Cannot remove auth cookie", e); - } - } - - @Nullable - public String getAuthCookie() { - String hex = null; - try { - Path path = getAuthCookiePath(); - hex = Utils.readFileAsHex(path); - } catch (IOException e) { - Log.e("QUIET_TOR", "Cannot get auth cookie path", e); - } - return hex; - } - - private static File appTorHandlerDir = null; - private static File controlSocket = null; - - // Store the opaque reference as a long (pointer) for the native code - @SuppressWarnings({"FieldMayBeFinal", "unused"}) - private long torConfiguration = -1; - @SuppressWarnings({"FieldMayBeFinal"," unused"}) - private int torControlFd = -1; - - private volatile TorControlConnection torControlConnection; - - /** - * This lock must be acquired before calling createTorConfiguration() and - * held until mainConfigurationFree() has been called. - */ - private static final ReentrantLock runLock = new ReentrantLock(); - - private native boolean createTorConfiguration(); - - private native void mainConfigurationFree(); - - private native static FileDescriptor prepareFileDescriptor(String path); - private native boolean mainConfigurationSetCommandLine(String[] args); - - private native boolean mainConfigurationSetupControlSocket(); - - private native int runMain(); - - /** - * This waits for {@link #CONTROL_SOCKET_NAME} to be created by {@code tor}, - * then continues on to connect to the {@code ControlSocket} as described in - * {@link #getControlSocket(Context)}. As a failsafe, this will only wait - * 10 seconds, after that it will check whether the {@code ControlSocket} - * file exists, and if not, throw a {@link IllegalStateException}. - */ - private final Thread controlPortThread = new Thread(CONTROL_SOCKET_NAME) { - @Override - public void run() { - android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - try { - final CountDownLatch countDownLatch = new CountDownLatch(1); - final String observeDir = getAppTorHandlerDataDir(context).getAbsolutePath(); - FileObserver controlPortFileObserver = new FileObserver(observeDir) { - @Override - public void onEvent(int event, @Nullable String name) { - if ((event & FileObserver.CREATE) > 0 && CONTROL_SOCKET_NAME.equals(name)) { - countDownLatch.countDown(); - } - } - }; - controlPortFileObserver.startWatching(); - controlPortThreadStarted.countDown(); - countDownLatch.await(10, TimeUnit.SECONDS); - controlPortFileObserver.stopWatching(); - File controlSocket = new File(observeDir, CONTROL_SOCKET_NAME); - if (!controlSocket.canRead()) { - throw new IOException("cannot read " + controlSocket); - } - - FileDescriptor controlSocketFd = prepareFileDescriptor(getControlSocket(context).getAbsolutePath()); - InputStream is = new FileInputStream(controlSocketFd); - OutputStream os = new FileOutputStream(controlSocketFd); - torControlConnection = new TorControlConnection(is, os); - torControlConnection.launchThread(true); - torControlConnection.authenticate(new byte[0]); - torControlConnection.setEvents(Collections.singletonList(TorControlCommands.EVENT_CIRCUIT_STATUS)); - - } catch (IOException | ArrayIndexOutOfBoundsException | InterruptedException e) { - e.printStackTrace(); - } - } - }; - - private volatile CountDownLatch controlPortThreadStarted; - - private final Thread torThread = new Thread("tor") { - @Override - public void run() { - try { - /* - Prevent services hooking up on a control port - from possibly using stale auth cookie generated with previous run. - */ - removeAuthCookie(); - - createTorConfiguration(); - - ArrayList lines = new ArrayList<>(Arrays.asList("tor", "--verify-config", // must always be here - "--RunAsDaemon", "0", - "-f", getTorrc(context).getAbsolutePath(), - "--defaults-torrc", getDefaultsTorrc(context).getAbsolutePath(), - "--ignore-missing-torrc", - "--SyslogIdentityTag", TAG, - "--CacheDirectory", new File(context.getCacheDir(), TAG).getAbsolutePath(), - "--DataDirectory", getAppTorHandlerDataDir(context).getAbsolutePath(), - "--ControlPort", String.valueOf(controlPort), - "--SOCKSPort", String.valueOf(socksPort), - "--HTTPTunnelPort", String.valueOf(httpTunnelPort), - "--CookieAuthentication", "1", - "--LogMessageDomains", "1", - "--TruncateLogFile", "1" - )); - - if (ENABLE_CONTROL_SOCKET) { - lines.addAll(Arrays.asList( - "--ControlSocket", getControlSocket(context).getAbsolutePath() - )); - } - - String[] verifyLines = lines.toArray(new String[0]); - if (!mainConfigurationSetCommandLine(verifyLines)) { - throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(verifyLines)); - } - - int result = runMain(); // run verify - if (result != 0) { - throw new IllegalArgumentException("Bad command flags: " + Arrays.toString(verifyLines)); - } - - if (ENABLE_CONTROL_SOCKET) { - controlPortThreadStarted = new CountDownLatch(1); - controlPortThread.start(); - controlPortThreadStarted.await(); - } - - String[] runLines = new String[lines.size() - 1]; - runLines[0] = "tor"; - for (int i = 2; i < lines.size(); i++) { - runLines[i - 1] = lines.get(i); - } - if (!mainConfigurationSetCommandLine(runLines)) { - throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(runLines)); - } - if (ENABLE_CONTROL_SOCKET && !mainConfigurationSetupControlSocket()) { - throw new IllegalStateException("Setting up ControlPort failed!"); - } - if (runMain() != 0) { - throw new IllegalStateException("Tor could not start!"); - } - - } catch (IllegalStateException | IllegalArgumentException | InterruptedException e) { - e.printStackTrace(); - } finally { - mainConfigurationFree(); - runLock.unlock(); - } - } - }; - - /** - * Start Tor in a {@link Thread} with the minimum required config. The - * rest of the config should happen via the Control Port. First Tor - * runs with {@code --verify-config} to check the command line flags and - * any {@code torrc} config. Then finally Tor is - * started in its own {@code Thread}. - *

    - * Tor daemon does not output early debug messages to logcat, only after it - * tries to connect to the ports. So it is important that Tor does not run - * into port conflicts when first starting. - * - * @see #32036 output debug logs to logcat as early as possible on Android - * @see options that must be on the command line - */ - public void startTorThread() { - if (runLock.isLocked()) { - Log.i(TAG, "Waiting for lock"); - } - runLock.lock(); - Log.i(TAG, "Acquired lock"); - torThread.start(); - } - -} diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt b/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt index b879283539..29491191a0 100644 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt +++ b/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt @@ -2,19 +2,14 @@ package com.quietmobile.Utils import android.content.Context import android.util.Log +import com.quietmobile.Utils.Const.TAG_NOTICE import java.io.* -import java.math.BigInteger import java.net.ConnectException import java.net.InetSocketAddress import java.net.Socket -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths import java.security.SecureRandom import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine -import kotlin.math.pow -import kotlin.random.Random object Utils { fun writeToFile(file: String, data: String, context: Context) { @@ -35,12 +30,6 @@ object Utils { return dataDirectory.absolutePath } - fun generateRandomInt(length: Int = 4): Int { - val start = 10.0.pow((length - 1).toDouble()).toInt() - val end = 10.0.pow(length.toDouble()).toInt() - 1 - return Random.nextInt(start, end) - } - fun generateRandomString(length: Int): String { val CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" val secureRandom = SecureRandom() @@ -93,11 +82,4 @@ object Utils { } } - @Throws(IOException::class) - @JvmStatic - fun readFileAsHex(filePath: Path?): String? { - val fileBytes = Files.readAllBytes(filePath) - return BigInteger(1, fileBytes).toString(16) - } - } diff --git a/packages/mobile/ios/Quiet/AppDelegate.m b/packages/mobile/ios/Quiet/AppDelegate.m index 733bdcc4b2..cb92136270 100644 --- a/packages/mobile/ios/Quiet/AppDelegate.m +++ b/packages/mobile/ios/Quiet/AppDelegate.m @@ -73,9 +73,9 @@ - (void) spinupBackend:(BOOL)init { self.dataPort = [findFreePort getFirstStartingFromPort:11000]; - uint16_t socksPort = [findFreePort getFirstStartingFromPort:arc4random_uniform(65535 - 1024) + 1024]; - uint16_t controlPort = [findFreePort getFirstStartingFromPort:arc4random_uniform(65535 - 1024) + 1024]; - uint16_t httpTunnelPort = [findFreePort getFirstStartingFromPort:arc4random_uniform(65535 - 1024) + 1024]; + uint16_t socksPort = [findFreePort getFirstStartingFromPort:arc4random_uniform(65000 - 1024) + 1024]; + uint16_t controlPort = [findFreePort getFirstStartingFromPort:arc4random_uniform(65000 - 1024) + 1024]; + uint16_t httpTunnelPort = [findFreePort getFirstStartingFromPort:arc4random_uniform(65000 - 1024) + 1024]; // (2/6) Spawn tor with proper configuration diff --git a/packages/mobile/ios/Quiet/Info.plist b/packages/mobile/ios/Quiet/Info.plist index 1897b20e95..01a2cc8c61 100644 --- a/packages/mobile/ios/Quiet/Info.plist +++ b/packages/mobile/ios/Quiet/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.1.2 + 2.2.0 CFBundleSignature ???? CFBundleURLTypes @@ -34,28 +34,28 @@ CFBundleVersion - 367 + 370 ITSAppUsesNonExemptEncryption - + LSRequiresIPhoneOS - + NSAppTransportSecurity NSAllowsArbitraryLoads - + NSAllowsLocalNetworking - + NSExceptionDomains localhost NSExceptionAllowsInsecureHTTPLoads - + NSLocationWhenInUseUsageDescription - + UIAppFonts Rubik-Black.ttf @@ -74,7 +74,7 @@ Rubik-SemiBoldItalic.ttf UIBackgroundModes - + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -88,6 +88,6 @@ UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance - + diff --git a/packages/mobile/ios/QuietTests/Info.plist b/packages/mobile/ios/QuietTests/Info.plist index de8a430076..167b0126a2 100644 --- a/packages/mobile/ios/QuietTests/Info.plist +++ b/packages/mobile/ios/QuietTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 2.1.2 + 2.2.0 CFBundleSignature ???? CFBundleVersion - 367 + 370 diff --git a/packages/mobile/package-lock.json b/packages/mobile/package-lock.json index ecc41ac4b9..5f0c2a9a1a 100644 --- a/packages/mobile/package-lock.json +++ b/packages/mobile/package-lock.json @@ -1,12 +1,12 @@ { "name": "@quiet/mobile", - "version": "2.1.2-alpha.14", + "version": "2.2.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@quiet/mobile", - "version": "2.1.2-alpha.14", + "version": "2.2.0-alpha.1", "dependencies": { "@peculiar/webcrypto": "^1.4.3", "@react-native-clipboard/clipboard": "^1.13.2", diff --git a/packages/mobile/package.json b/packages/mobile/package.json index 33ed6a90d9..3f052532e6 100644 --- a/packages/mobile/package.json +++ b/packages/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@quiet/mobile", - "version": "2.1.2-alpha.14", + "version": "2.2.0-alpha.1", "scripts": { "build": "tsc -p tsconfig.build.json --noEmit", "storybook-android": "ENVFILE=.env.storybook react-native run-android --mode=storybookDebug --appIdSuffix=storybook.debug", diff --git a/packages/mobile/src/App.tsx b/packages/mobile/src/App.tsx index b3c64c879b..f5128ddc39 100644 --- a/packages/mobile/src/App.tsx +++ b/packages/mobile/src/App.tsx @@ -85,7 +85,6 @@ function App(): JSX.Element { ref={navigationRef} linking={linking} onReady={() => { - dispatch(initActions.blindWebsocketConnection()) dispatch(navigationActions.redirection()) }} > diff --git a/packages/mobile/src/components/Registration/UsernameRegistration.component.tsx b/packages/mobile/src/components/Registration/UsernameRegistration.component.tsx index 236eb5fe3c..93e10f684e 100644 --- a/packages/mobile/src/components/Registration/UsernameRegistration.component.tsx +++ b/packages/mobile/src/components/Registration/UsernameRegistration.component.tsx @@ -124,7 +124,7 @@ export const UsernameRegistration: FC = ({ hint={ isNewUser ? 'Your username cannot have any spaces or special characters, must be lowercase letters and numbers only.' - : 'Your username will be public, but you can choose any name you like. No spaces or special characters. Lowercase letters and numbers only. ' + : 'Your username will be public, but you can choose any name you like. No spaces or special characters. Lowercase letters and numbers only.' } disabled={loading} validation={inputError} diff --git a/packages/mobile/src/components/Registration/UsernameRegistration.test.tsx b/packages/mobile/src/components/Registration/UsernameRegistration.test.tsx index 057b535a23..b9b0fc51fa 100644 --- a/packages/mobile/src/components/Registration/UsernameRegistration.test.tsx +++ b/packages/mobile/src/components/Registration/UsernameRegistration.test.tsx @@ -254,15 +254,11 @@ describe('UsernameRegistration', () => { currentUsername={'john'} registeredUsers={{ 'BCidRGCBqBPNGNrZ1oml99/qtHjZ6ZtliVzJPpReZk9YC6+aQ1zeooOlpyzv7rNG6nMX2R5ffaVkZZFgEMdNEBg=': { - dmPublicKey: - '1c63a0152f0b0221f96c80aab6777e2569d27a14e991dccd086e34cda1c55d9d6e898efdb9cb5a16d2f90b4155e34abf3261c84e76936ba0105929922feda1fb0615f3254cc56c056cb6144076d0cbdba67cf0fb6687a97d9bb6621bb6b38dcf08aa509f1164212118111f045edc5dab8d315d6e1241cdd10c40883ea420d10d560e48329e086154645035af0668e372a381fbd8aa0912f3581de34b50361cc31adf7a8e811504b6970c9093c058f0fb41ae27df64b09bcb13df84bd23d47a0024463cbb92ee917af3b77b168deb93f6da2d0d13a361969447e16bf249edd872b4797125fa86aad1ce35b1d6ee449359f31c9224a70997d0f0ca38c1f796cede660dd0bb3b1fc9ec251f896bc0aec1603ee8e1278c76d9d1e52adcfa0a06658d631486016efb3b5f44e0c3fb1ce4299834cdf05e', onionAddress: 'zpu47hphczcuyt3auu5pr2knvimf3adm76gt3g7zbspungjbm3tsy3ad.onion', peerId: 'QmPrgB2jSFvr7yP3vbLKMLW4JS9hoA9kj2fhN8VjE2NWvJ', username: 'owner', }, 'BJ50trLih9tvIznBAi69dLNpBV5YiQHCU610UfH3Qm9t3cki9QHWAAhvrfOX+763BH1fwqkOU3JsoBAEF1+USvM=': { - dmPublicKey: - '01161f217d3b372ddefe390b6aed6ada3f21c7ca0d2aacd125840d0c420030b5caec93fbcc1825bb19f38448c1573be814c827b3bce99f6d37b427044687b63799ce0cd7133a654eb2c5644405380399ed0b9140cf0f6d2937008929be8c8ad97cba64e08f7608bb54e0148c8bb30fd2c6df2b8d237cdbfe7ae3d300d896c0ce9e3c5006b687f2e573bedb68152db1954869c21243ef1557eb6d442138ad98e47285f5dd9475fac3a06d2972ae775bdc50d5ab59676d27367c15954b64b0b1a29083ac78934f3f1d0088b73389e29d84f61c60c321770550ecdffa9a24cf0c7fdd279974b5703ce105f22d683530c2f62b36945b3d97f88256f31e1146c3861993a989f5cd99bda647d8744068c3bb44eea407f33109c9c1a0f790f745a6ff2bfd45f5be741fc351549b11d54a4980c4d6d7afb4', onionAddress: 'lr5d3d64p4hx4mw3uue3ufews23jhl6bfqnsimt7j52igjqdv2zrmsyd.onion', peerId: 'QmWwMev68izPUKB1PGxkG3UHHXiappQQAnkvUwPSTzrUyy', username: 'johnny', @@ -577,7 +573,7 @@ describe('UsernameRegistration', () => { } verticalTextAlign="center" > - Your username will be public, but you can choose any name you like. No spaces or special characters. Lowercase letters and numbers only. + Your username will be public, but you can choose any name you like. No spaces or special characters. Lowercase letters and numbers only. = ({ route }) => const joinCommunityAction = useCallback( (data: InvitationData) => { - const payload: CreateNetworkPayload = { - ownership: CommunityOwnership.User, - peers: data.pairs, - psk: data.psk, - ownerOrbitDbIdentity: data.ownerOrbitDbIdentity, - } - dispatch(communities.actions.createNetwork(payload)) + dispatch(communities.actions.joinNetwork(data)) dispatch( navigationActions.navigation({ screen: ScreenNames.UsernameRegistrationScreen, diff --git a/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts b/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts index b019eb86c7..a74e6f8eb2 100644 --- a/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts +++ b/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts @@ -8,16 +8,21 @@ import { initActions } from '../init.slice' import { navigationActions } from '../../navigation/navigation.slice' import { ScreenNames } from '../../../const/ScreenNames.enum' import { deepLinkSaga } from './deepLink.saga' -import { type Community, CommunityOwnership, ConnectionProcessInfo, type Identity, InvitationData } from '@quiet/types' -import { composeInvitationShareUrl, validInvitationCodeTestData, getValidInvitationUrlTestData } from '@quiet/common' +import { type Community, CommunityOwnership, type Identity, InvitationData, InvitationDataVersion } from '@quiet/types' +import { + composeInvitationShareUrl, + validInvitationCodeTestData, + getValidInvitationUrlTestData, + validInvitationDatav1, +} from '@quiet/common' describe('deepLinkSaga', () => { let store: Store - const { code, data } = getValidInvitationUrlTestData(validInvitationCodeTestData[0]) + const { code } = getValidInvitationUrlTestData(validInvitationDatav1[0]) const validCode = code() - const validData = data + const validData = validInvitationDatav1[0] const id = '00d045ab' @@ -31,8 +36,6 @@ describe('deepLinkSaga', () => { rootCa: '', peerList: [], onionAddress: '', - privateKey: '', - port: 0, ownerCertificate: '', } @@ -61,11 +64,9 @@ describe('deepLinkSaga', () => { .withState(store.getState()) .put(initActions.resetDeepLink()) .put( - communities.actions.createNetwork({ - ownership: CommunityOwnership.User, - peers: validData.pairs, - psk: validData.psk, - ownerOrbitDbIdentity: validData.ownerOrbitDbIdentity, + communities.actions.joinNetwork({ + version: InvitationDataVersion.v1, + ...validData, }) ) .put( @@ -76,45 +77,6 @@ describe('deepLinkSaga', () => { .run() }) - // FIXME: Currently there's no way to actually check whether the redirection destionation is correct - test.skip('opens channel list screen if the same url has been used', async () => { - store.dispatch( - initActions.setWebsocketConnected({ - dataPort: 5001, - socketIOSecret: 'secret', - }) - ) - - store.dispatch(communities.actions.setInvitationCodes(validData.pairs)) - store.dispatch( - communities.actions.addNewCommunity({ - ...community, - name: 'rockets', - }) - ) - - store.dispatch( - // @ts-expect-error - identity.actions.addNewIdentity({ ..._identity, userCertificate: 'certificate' }) - ) - - store.dispatch(communities.actions.setCurrentCommunity(community.id)) - - const reducer = combineReducers(reducers) - await expectSaga(deepLinkSaga, initActions.deepLink(validCode)) - .withReducer(reducer) - .withState(store.getState()) - .not.put( - communities.actions.createNetwork({ - ownership: CommunityOwnership.User, - peers: validData.pairs, - psk: validData.psk, - ownerOrbitDbIdentity: validData.ownerOrbitDbIdentity, - }) - ) - .run() - }) - test('displays error if user already belongs to a community', async () => { store.dispatch( initActions.setWebsocketConnected({ @@ -123,10 +85,6 @@ describe('deepLinkSaga', () => { }) ) - // Store other communitys' invitation data in redux - const invitationData = getValidInvitationUrlTestData(validInvitationCodeTestData[1]) - store.dispatch(communities.actions.setInvitationCodes(invitationData.data.pairs)) - store.dispatch( communities.actions.addNewCommunity({ ...community, @@ -167,13 +125,12 @@ describe('deepLinkSaga', () => { }) ) + community.psk = validData.psk + store.dispatch(communities.actions.addNewCommunity(community)) store.dispatch(communities.actions.setCurrentCommunity(community.id)) - const invitationCodes = getInvitationCodes(validCode) - store.dispatch(communities.actions.setInvitationCodes(invitationCodes.pairs)) - const reducer = combineReducers(reducers) await expectSaga(deepLinkSaga, initActions.deepLink(validCode)) .withReducer(reducer) @@ -192,11 +149,10 @@ describe('deepLinkSaga', () => { }) .put.like({ action: { - type: communities.actions.createNetwork.type, + type: communities.actions.joinNetwork.type, payload: { - ownership: CommunityOwnership.User, - peers: validData.pairs, - psk: validData.psk, + version: InvitationDataVersion.v1, + ...validData, }, }, }) @@ -238,11 +194,9 @@ describe('deepLinkSaga', () => { }, }) .not.put( - communities.actions.createNetwork({ - ownership: CommunityOwnership.User, - peers: validData.pairs, - psk: validData.psk, - ownerOrbitDbIdentity: validData.ownerOrbitDbIdentity, + communities.actions.joinNetwork({ + version: InvitationDataVersion.v1, + ...validData, }) ) .run() diff --git a/packages/mobile/src/store/init/deepLink/deepLink.saga.ts b/packages/mobile/src/store/init/deepLink/deepLink.saga.ts index 4c98593786..28d7a03fc8 100644 --- a/packages/mobile/src/store/init/deepLink/deepLink.saga.ts +++ b/packages/mobile/src/store/init/deepLink/deepLink.saga.ts @@ -7,8 +7,7 @@ import { initSelectors } from '../init.selectors' import { initActions } from '../init.slice' import { appImages } from '../../../assets' import { replaceScreen } from '../../../RootNavigation' -import { CommunityOwnership, CreateNetworkPayload, InvitationData } from '@quiet/types' -import { areObjectsEqual } from '../../../utils/functions/areObjectsEqual/areObjectsEqual' +import { InvitationData, InvitationDataVersion } from '@quiet/types' export function* deepLinkSaga(action: PayloadAction['payload']>): Generator { const code = action.payload @@ -49,49 +48,25 @@ export function* deepLinkSaga(action: PayloadAction - currentInvitationCodes.some(currentCode => areObjectsEqual(storedCode, currentCode)) - ) + isJoiningAnotherCommunity = Boolean(storedPsk && storedPsk !== currentPsk) + break } - console.log('Is invitation data valid', isInvitationDataValid) - const isAlreadyConnected = Boolean(community?.name) - - const alreadyBelongsWithAnotherCommunity = !isInvitationDataValid && isAlreadyConnected - const connectingWithAnotherCommunity = !isInvitationDataValid && !isAlreadyConnected - const alreadyBelongsWithCurrentCommunity = isInvitationDataValid && isAlreadyConnected - const connectingWithCurrentCommunity = isInvitationDataValid && !isAlreadyConnected - - if (alreadyBelongsWithAnotherCommunity) { - console.log('INIT_NAVIGATION: ABORTING: Already belongs with another community.') - } - - if (connectingWithAnotherCommunity) { - console.log('INIT_NAVIGATION: ABORTING: Proceeding with connection to another community.') - } - - if (alreadyBelongsWithCurrentCommunity) { - console.log('INIT_NAVIGATION: ABORTING: Already connected with the current community.') - } - - if (connectingWithCurrentCommunity) { - console.log('INIT_NAVIGATION: Proceeding with connection to the community.') - } + const connectingWithAnotherCommunity = isJoiningAnotherCommunity && !isAlreadyConnected // User already belongs to a community - if (alreadyBelongsWithAnotherCommunity || alreadyBelongsWithCurrentCommunity) { + if (isAlreadyConnected) { console.log('INIT_NAVIGATION: Displaying error (user already belongs to a community).') yield* put( @@ -127,16 +102,7 @@ export function* deepLinkSaga(action: PayloadAction]) => { + const action = input[0] + if (action === SocketActionTypes.CREATE_NETWORK) { + const data: NetworkInfo = { + hiddenService: { + onionAddress: 'onionAddress', + privateKey: 'privateKey', + }, + peerId: createPeerIdTestHelper(), + } + return data + } +} describe('Deep linking', () => { let socket: MockedSocket @@ -17,6 +32,9 @@ describe('Deep linking', () => { beforeEach(async () => { socket = new MockedSocket() ioMock.mockImplementation(() => socket) + jest.spyOn(socket, 'emit').mockImplementation(mockEmitImpl) + // @ts-ignore + socket.emitWithAck = mockEmitImpl }) test('does not override network data if triggered twice', async () => { @@ -50,13 +68,16 @@ describe('Deep linking', () => { [ "Init/deepLink", "Init/resetDeepLink", + "Communities/joinNetwork", "Communities/createNetwork", - "Communities/setInvitationCodes", "Navigation/replaceScreen", - "Communities/savePSK", "Communities/addNewCommunity", "Communities/setCurrentCommunity", + "Communities/setInvitationCodes", + "Identity/addNewIdentity", "Init/deepLink", + "Init/resetDeepLink", + "Navigation/replaceScreen", ] `) diff --git a/packages/state-manager/src/index.ts b/packages/state-manager/src/index.ts index a67b2ed234..21809eecb6 100644 --- a/packages/state-manager/src/index.ts +++ b/packages/state-manager/src/index.ts @@ -53,6 +53,7 @@ export { LoadingPanelType } from './sagas/network/network.types' export type { Store } from './sagas/store.types' export type { TestStore, TestStoreState } from './utils/tests/types' export { StoreKeys } from './sagas/store.keys' +export { storeMigrations } from './sagas/store.migrations' export { prepareStore } from './utils/tests/prepareStore' export { useIO } from './sagas/socket/startConnection/startConnection.saga' diff --git a/packages/state-manager/src/sagas/app/app.master.saga.ts b/packages/state-manager/src/sagas/app/app.master.saga.ts index f905fdf992..07dca44027 100644 --- a/packages/state-manager/src/sagas/app/app.master.saga.ts +++ b/packages/state-manager/src/sagas/app/app.master.saga.ts @@ -3,10 +3,12 @@ import { all, takeEvery, takeLeading } from 'typed-redux-saga' import { appActions } from './app.slice' import { closeServicesSaga } from './closeServices.saga' import { stopBackendSaga } from './stopBackend/stopBackend.saga' +import { loadMigrationDataSaga } from './loadMigrationData/loadMigrationData.saga' export function* appMasterSaga(socket: Socket): Generator { yield* all([ takeLeading(appActions.closeServices.type, closeServicesSaga, socket), takeEvery(appActions.stopBackend.type, stopBackendSaga, socket), + takeEvery(appActions.loadMigrationData.type, loadMigrationDataSaga, socket), ]) } diff --git a/packages/state-manager/src/sagas/app/app.slice.ts b/packages/state-manager/src/sagas/app/app.slice.ts index e4ba4f2ef8..4b69d07204 100644 --- a/packages/state-manager/src/sagas/app/app.slice.ts +++ b/packages/state-manager/src/sagas/app/app.slice.ts @@ -1,4 +1,4 @@ -import { createSlice } from '@reduxjs/toolkit' +import { createSlice, type PayloadAction } from '@reduxjs/toolkit' import { StoreKeys } from '../store.keys' // eslint-disable-next-line @typescript-eslint/no-extraneous-class @@ -10,6 +10,7 @@ export const appSlice = createSlice({ reducers: { closeServices: state => state, stopBackend: state => state, + loadMigrationData: (state, action: PayloadAction) => state, }, }) diff --git a/packages/state-manager/src/sagas/app/loadMigrationData/loadMigrationData.saga.ts b/packages/state-manager/src/sagas/app/loadMigrationData/loadMigrationData.saga.ts new file mode 100644 index 0000000000..74893658fa --- /dev/null +++ b/packages/state-manager/src/sagas/app/loadMigrationData/loadMigrationData.saga.ts @@ -0,0 +1,33 @@ +import { type PayloadAction } from '@reduxjs/toolkit' +import { apply, select } from 'typed-redux-saga' + +import { SocketActionTypes } from '@quiet/types' + +import { type appActions } from '../app.slice' +import { type Socket, applyEmitParams } from '../../../types' +import { communitiesSelectors } from '../../communities/communities.selectors' +import { identitySelectors } from '../../identity/identity.selectors' + +export function* loadMigrationDataSaga( + socket: Socket, + action: PayloadAction['payload']> +): Generator { + const keys = action.payload + const data: Record = {} + + for (const key of keys) { + if (key === 'communities') { + data[key] = yield* select(communitiesSelectors.selectEntities) + } + + if (key === 'currentCommunityId') { + data[key] = yield* select(communitiesSelectors.currentCommunityId) + } + + if (key === 'identities') { + data[key] = yield* select(identitySelectors.selectEntities) + } + } + + yield* apply(socket, socket.emit, applyEmitParams(SocketActionTypes.LOAD_MIGRATION_DATA, data)) +} diff --git a/packages/state-manager/src/sagas/appConnection/connection.selectors.test.ts b/packages/state-manager/src/sagas/appConnection/connection.selectors.test.ts index 3f298c92ea..184546cc84 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.selectors.test.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.selectors.test.ts @@ -7,7 +7,7 @@ import { communitiesActions } from '../communities/communities.slice' import { connectionActions } from './connection.slice' import { type FactoryGirl } from 'factory-girl' import { type Community } from '@quiet/types' -import { createLibp2pAddress, invitationShareUrl } from '@quiet/common' +import { composeInvitationShareUrl, createLibp2pAddress, p2pAddressesToPairs } from '@quiet/common' describe('communitiesSelectors', () => { setupCrypto() @@ -112,11 +112,12 @@ describe('communitiesSelectors', () => { const ownerOrbitDbIdentity = 'testOwnerOrbitDbIdentity' await factory.create['payload']>('Community', { peerList, + psk, ownerOrbitDbIdentity, }) - store.dispatch(communitiesActions.savePSK(psk)) const selectorInvitationUrl = connectionSelectors.invitationUrl(store.getState()) - const expectedUrl = invitationShareUrl(peerList, psk, ownerOrbitDbIdentity) + const pairs = p2pAddressesToPairs(peerList) + const expectedUrl = composeInvitationShareUrl({ pairs, psk, ownerOrbitDbIdentity }) expect(expectedUrl).not.toEqual('') expect(selectorInvitationUrl).toEqual(expectedUrl) }) diff --git a/packages/state-manager/src/sagas/appConnection/connection.selectors.ts b/packages/state-manager/src/sagas/appConnection/connection.selectors.ts index 1bce105c4c..72f8cfd9f1 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.selectors.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.selectors.ts @@ -6,7 +6,7 @@ import { peersStatsAdapter } from './connection.adapter' import { connectedPeers, isCurrentCommunityInitialized } from '../network/network.selectors' import { type NetworkStats } from './connection.types' import { type User } from '../users/users.types' -import { filterAndSortPeers, invitationShareUrl } from '@quiet/common' +import { composeInvitationShareUrl, filterAndSortPeers, p2pAddressesToPairs } from '@quiet/common' import { areMessagesLoaded, areChannelsLoaded } from '../publicChannels/publicChannels.selectors' import { identitySelectors } from '../identity/identity.selectors' import { communitiesSelectors } from '../communities/communities.selectors' @@ -54,7 +54,8 @@ export const invitationUrl = createSelector( if (!communityPsk) return '' if (!ownerOrbitDbIdentity) return '' const initialPeers = sortedPeerList.slice(0, 3) - return invitationShareUrl(initialPeers, communityPsk, ownerOrbitDbIdentity) + const pairs = p2pAddressesToPairs(initialPeers) + return composeInvitationShareUrl({ pairs, psk: communityPsk, ownerOrbitDbIdentity }) } ) diff --git a/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts b/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts index d666926f07..5a21072fd9 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts @@ -77,7 +77,6 @@ describe('connectionReducer', () => { username: alice.nickname, onionAddress: alice.hiddenService.onionAddress, peerId: alice.peerId.id, - dmPublicKey: alice.dmKeys.publicKey, isDuplicated: false, isRegistered: true, pubKey, diff --git a/packages/state-manager/src/sagas/communities/communities.master.saga.ts b/packages/state-manager/src/sagas/communities/communities.master.saga.ts index 4188795afb..e904dd16ad 100644 --- a/packages/state-manager/src/sagas/communities/communities.master.saga.ts +++ b/packages/state-manager/src/sagas/communities/communities.master.saga.ts @@ -2,21 +2,17 @@ import { type Socket } from '../../types' import { all, takeEvery } from 'typed-redux-saga' import { communitiesActions } from './communities.slice' import { connectionActions } from '../appConnection/connection.slice' -import { updateCommunitySaga } from './updateCommunity/updateCommunity.saga' +import { createCommunitySaga } from './createCommunity/createCommunity.saga' import { initCommunities, launchCommunitySaga } from './launchCommunity/launchCommunity.saga' import { createNetworkSaga } from './createNetwork/createNetwork.saga' -import { saveCommunityMetadataSaga } from './saveCommunityMetadata/saveCommunityMetadata.saga' -import { sendCommunityMetadataSaga } from './updateCommunityMetadata/updateCommunityMetadata.saga' -import { sendCommunityCaDataSaga } from './sendCommunityCaData/sendCommunityCaData.saga' +import { joinNetworkSaga } from './joinNetwork/joinNetwork.saga' export function* communitiesMasterSaga(socket: Socket): Generator { yield all([ takeEvery(communitiesActions.createNetwork.type, createNetworkSaga, socket), - takeEvery(communitiesActions.updateCommunity.type, updateCommunitySaga), + takeEvery(communitiesActions.joinNetwork.type, joinNetworkSaga, socket), takeEvery(connectionActions.torBootstrapped.type, initCommunities), + takeEvery(communitiesActions.createCommunity.type, createCommunitySaga, socket), takeEvery(communitiesActions.launchCommunity.type, launchCommunitySaga, socket), - takeEvery(communitiesActions.saveCommunityMetadata.type, saveCommunityMetadataSaga, socket), - takeEvery(communitiesActions.sendCommunityMetadata.type, sendCommunityMetadataSaga, socket), - takeEvery(communitiesActions.sendCommunityCaData.type, sendCommunityCaDataSaga, socket), ]) } diff --git a/packages/state-manager/src/sagas/communities/communities.selectors.test.ts b/packages/state-manager/src/sagas/communities/communities.selectors.test.ts index 1cccbaa515..f545a49fe3 100644 --- a/packages/state-manager/src/sagas/communities/communities.selectors.test.ts +++ b/packages/state-manager/src/sagas/communities/communities.selectors.test.ts @@ -1,10 +1,8 @@ -import { createLibp2pAddress, invitationShareUrl } from '@quiet/common' import { setupCrypto } from '@quiet/identity' import { type Store } from '@reduxjs/toolkit' import { getFactory } from '../../utils/tests/factories' import { prepareStore } from '../../utils/tests/prepareStore' import { type identityActions } from '../identity/identity.slice' -import { usersActions } from '../users/users.slice' import { communitiesSelectors } from './communities.selectors' import { communitiesActions } from './communities.slice' import { type Community, type Identity } from '@quiet/types' @@ -41,7 +39,7 @@ describe('communitiesSelectors', () => { it('select current community', () => { const community = communitiesSelectors.currentCommunity(store.getState()) - expect(community).toEqual({ ...communityAlpha }) + expect(community).toEqual({ ...communityAlpha, ownerCertificate: identity.userCertificate }) }) it('returns proper ownerNickname - ownerCertificate exist', async () => { diff --git a/packages/state-manager/src/sagas/communities/communities.selectors.ts b/packages/state-manager/src/sagas/communities/communities.selectors.ts index 2c324ce148..1e01a4c16c 100644 --- a/packages/state-manager/src/sagas/communities/communities.selectors.ts +++ b/packages/state-manager/src/sagas/communities/communities.selectors.ts @@ -36,8 +36,8 @@ export const invitationCodes = createSelector(communitiesSlice, reducerState => return reducerState.invitationCodes }) -export const psk = createSelector(communitiesSlice, reducerState => { - return reducerState.psk +export const psk = createSelector(currentCommunity, currentCommunity => { + return currentCommunity?.psk }) export const ownerCertificate = createSelector(currentCommunity, currentCommunity => { diff --git a/packages/state-manager/src/sagas/communities/communities.slice.ts b/packages/state-manager/src/sagas/communities/communities.slice.ts index 188c75ca6b..228ef912fb 100644 --- a/packages/state-manager/src/sagas/communities/communities.slice.ts +++ b/packages/state-manager/src/sagas/communities/communities.slice.ts @@ -15,7 +15,6 @@ export class CommunitiesState { public invitationCodes: InvitationPair[] = [] public currentCommunity = '' public communities: EntityState = communitiesAdapter.getInitialState() - public psk: string | undefined } export const communitiesSlice = createSlice({ @@ -28,7 +27,6 @@ export const communitiesSlice = createSlice({ addNewCommunity: (state, action: PayloadAction) => { communitiesAdapter.addOne(state.communities, action.payload) }, - updateCommunity: (state, _action: PayloadAction) => state, updateCommunityData: (state, action: PayloadAction) => { communitiesAdapter.updateOne(state.communities, { id: action.payload.id, @@ -37,30 +35,18 @@ export const communitiesSlice = createSlice({ }, }) }, - sendCommunityCaData: state => state, - sendCommunityMetadata: state => state, createNetwork: (state, _action: PayloadAction) => state, - storePeerList: (state, action: PayloadAction) => { - communitiesAdapter.updateOne(state.communities, { - id: action.payload.communityId, - changes: { - ...action.payload, - }, - }) - }, + joinNetwork: (state, _action: PayloadAction) => state, resetApp: (state, _action) => state, + createCommunity: (state, _action: PayloadAction) => state, launchCommunity: (state, _action: PayloadAction) => state, - customProtocol: (state, _action: PayloadAction) => state, + customProtocol: (state, _action: PayloadAction) => state, setInvitationCodes: (state, action: PayloadAction) => { state.invitationCodes = action.payload }, clearInvitationCodes: state => { state.invitationCodes = [] }, - saveCommunityMetadata: (state, _action: PayloadAction) => state, - savePSK: (state, action: PayloadAction) => { - state.psk = action.payload - }, }, }) diff --git a/packages/state-manager/src/sagas/communities/communities.types.ts b/packages/state-manager/src/sagas/communities/communities.types.ts index 8ac9db480d..1789c00362 100644 --- a/packages/state-manager/src/sagas/communities/communities.types.ts +++ b/packages/state-manager/src/sagas/communities/communities.types.ts @@ -18,14 +18,6 @@ export interface Certificates { CA: string[] } -export interface InitCommunityPayload { - id: string - peerId: PeerId - hiddenService: HiddenService - certs: Certificates - peers?: string[] -} - export interface StorePeerListPayload { communityId: string peerList: string[] diff --git a/packages/state-manager/src/sagas/communities/createCommunity/createCommunity.saga.ts b/packages/state-manager/src/sagas/communities/createCommunity/createCommunity.saga.ts new file mode 100644 index 0000000000..ebed5ee240 --- /dev/null +++ b/packages/state-manager/src/sagas/communities/createCommunity/createCommunity.saga.ts @@ -0,0 +1,63 @@ +import { type Socket, applyEmitParams } from '../../../types' +import { select, apply, put } from 'typed-redux-saga' +import { type PayloadAction } from '@reduxjs/toolkit' +import { identityActions } from '../../identity/identity.slice' +import { communitiesSelectors } from '../communities.selectors' +import { communitiesActions } from '../communities.slice' +import { identitySelectors } from '../../identity/identity.selectors' +import { publicChannelsActions } from '../../publicChannels/publicChannels.slice' +import { type Community, type InitCommunityPayload, SocketActionTypes } from '@quiet/types' + +export function* createCommunitySaga( + socket: Socket, + action: PayloadAction['payload']> +): Generator { + let communityId: string = action.payload + + if (!communityId) { + communityId = yield* select(communitiesSelectors.currentCommunityId) + } + + const community = yield* select(communitiesSelectors.selectById(communityId)) + const identity = yield* select(identitySelectors.selectById(communityId)) + + if (!identity) return + + const payload: InitCommunityPayload = { + id: communityId, + name: community?.name, + peerId: identity.peerId, + hiddenService: identity.hiddenService, + CA: community?.CA, + rootCa: community?.rootCa, + // Type mismatch between `userCsr | null` in Identity and `ownerCsr?` in + // InitCommunityPayload + ownerCsr: identity.userCsr ?? undefined, + } + + const createdCommunity: Community | undefined = yield* apply( + socket, + socket.emitWithAck, + applyEmitParams(SocketActionTypes.CREATE_COMMUNITY, payload) + ) + + if (!createdCommunity || !createdCommunity.ownerCertificate) return + + yield* put(communitiesActions.updateCommunityData(createdCommunity)) + + yield* put( + identityActions.storeUserCertificate({ + communityId: createdCommunity.id, + userCertificate: createdCommunity.ownerCertificate, + }) + ) + + yield* put(publicChannelsActions.createGeneralChannel()) + // TODO: We can likely refactor this a bit. Currently, we issue the owner's + // certificate before creating the community, but then we add the owner's CSR + // to the OrbitDB store after creating the community (in the following saga). + // We can likely add the owner's CSR when creating the community or decouple + // community creation from CSR/certificate creation and create the community + // first and then add the owner's CSR and issue their certificate. + yield* put(identityActions.saveUserCsr()) +} diff --git a/packages/state-manager/src/sagas/communities/createNetwork/createNetwork.saga.ts b/packages/state-manager/src/sagas/communities/createNetwork/createNetwork.saga.ts index 69a80947ac..719d9c2354 100644 --- a/packages/state-manager/src/sagas/communities/createNetwork/createNetwork.saga.ts +++ b/packages/state-manager/src/sagas/communities/createNetwork/createNetwork.saga.ts @@ -5,8 +5,7 @@ import { generateId } from '../../../utils/cryptography/cryptography' import { communitiesActions } from '../communities.slice' import { identityActions } from '../../identity/identity.slice' import { createRootCA } from '@quiet/identity' -import { type Community, CommunityOwnership, type Identity, SocketActionTypes } from '@quiet/types' -import { generateDmKeyPair } from '../../../utils/cryptography/cryptography' +import { type Community, CommunityOwnership, type Identity, SocketActionTypes, NetworkInfo } from '@quiet/types' import { Socket, applyEmitParams } from '../../../types' export function* createNetworkSaga( @@ -14,6 +13,17 @@ export function* createNetworkSaga( action: PayloadAction['payload']> ) { console.log('create network saga') + + // Community IDs are only local identifiers + const id = yield* call(generateId) + + const network: NetworkInfo = yield* apply( + socket, + socket.emitWithAck, + applyEmitParams(SocketActionTypes.CREATE_NETWORK, id) + ) + + // TODO: Move CA generation to backend when creating Community let CA: null | { rootCertString: string rootKeyString: string @@ -31,7 +41,6 @@ export function* createNetworkSaga( ) } - const id = yield* call(generateId) const community: Community = { id, name: action.payload.name, @@ -41,32 +50,20 @@ export function* createNetworkSaga( ownerOrbitDbIdentity: action.payload.ownerOrbitDbIdentity, } + yield* put(communitiesActions.addNewCommunity(community)) + yield* put(communitiesActions.setCurrentCommunity(id)) + const invitationPeers = action.payload.peers if (invitationPeers) { yield* put(communitiesActions.setInvitationCodes(invitationPeers)) } - const psk = action.payload.psk - if (psk) { - console.log('create network saga: saving PSK') - yield* put(communitiesActions.savePSK(psk)) - } - - yield* put(communitiesActions.addNewCommunity(community)) - yield* put(communitiesActions.setCurrentCommunity(id)) - - const network = yield* apply( - socket, - socket.emitWithAck, - applyEmitParams(SocketActionTypes.CREATE_NETWORK, community.id) - ) - const dmKeys = yield* call(generateDmKeyPair) + // Identities are tied to communities for now const identity: Identity = { id: community.id, nickname: '', hiddenService: network.hiddenService, peerId: network.peerId, - dmKeys, userCsr: null, userCertificate: null, joinTimestamp: null, diff --git a/packages/state-manager/src/sagas/communities/joinNetwork/joinNetwork.saga.test.ts b/packages/state-manager/src/sagas/communities/joinNetwork/joinNetwork.saga.test.ts new file mode 100644 index 0000000000..151d16cf0b --- /dev/null +++ b/packages/state-manager/src/sagas/communities/joinNetwork/joinNetwork.saga.test.ts @@ -0,0 +1,45 @@ +import { getValidInvitationUrlTestData, validInvitationDatav1 } from '@quiet/common' +import { CommunityOwnership, CreateNetworkPayload, InvitationDataV1 } from '@quiet/types' +import { FactoryGirl } from 'factory-girl' +import { expectSaga } from 'redux-saga-test-plan' +import { Socket } from '../../../types' +import { getFactory } from '../../../utils/tests/factories' +import { prepareStore } from '../../../utils/tests/prepareStore' +import { Store } from '../../store.types' +import { communitiesActions } from '../communities.slice' +import { joinNetworkSaga } from './joinNetwork.saga' + +describe('Join network saga', () => { + let store: Store + let factory: FactoryGirl + let validInvitationData: InvitationDataV1 + let validInvitationDeepUrl: string + const socket = { + emit: jest.fn(), + emitWithAck: jest.fn(() => { + return {} + }), + on: jest.fn(), + } as unknown as Socket + + beforeEach(async () => { + store = prepareStore().store + factory = await getFactory(store) + + validInvitationData = getValidInvitationUrlTestData(validInvitationDatav1[0]).data + validInvitationDeepUrl = getValidInvitationUrlTestData(validInvitationDatav1[0]).deepUrl() + }) + + it('creates network for v1 invitation data', async () => { + const payload: CreateNetworkPayload = { + ownership: CommunityOwnership.User, + peers: validInvitationData.pairs, + psk: validInvitationData.psk, + ownerOrbitDbIdentity: validInvitationData.ownerOrbitDbIdentity, + } + await expectSaga(joinNetworkSaga, socket, communitiesActions.joinNetwork(validInvitationData)) + .withState(store.getState()) + .put(communitiesActions.createNetwork(payload)) + .run() + }) +}) diff --git a/packages/state-manager/src/sagas/communities/joinNetwork/joinNetwork.saga.ts b/packages/state-manager/src/sagas/communities/joinNetwork/joinNetwork.saga.ts new file mode 100644 index 0000000000..53cb44b3b8 --- /dev/null +++ b/packages/state-manager/src/sagas/communities/joinNetwork/joinNetwork.saga.ts @@ -0,0 +1,47 @@ +import { CommunityOwnership, CreateNetworkPayload, InvitationDataVersion, SocketActionTypes } from '@quiet/types' +import { PayloadAction } from '@reduxjs/toolkit' +import { apply, put } from 'typed-redux-saga' +import { Socket, applyEmitParams } from '../../../types' +import { communitiesActions } from '../communities.slice' + +export function* joinNetworkSaga( + socket: Socket, + action: PayloadAction['payload']> +) { + console.log('join network saga', action.payload) + const data = action.payload + let payload: CreateNetworkPayload + + data.version = data.version || InvitationDataVersion.v1 + switch (data.version) { + case InvitationDataVersion.v1: + console.log('join network saga invitation data v1') + payload = { + ownership: CommunityOwnership.User, + peers: data.pairs, + psk: data.psk, + ownerOrbitDbIdentity: data.ownerOrbitDbIdentity, + } + break + case InvitationDataVersion.v2: + console.log('join network saga invitation data v2') + const response: CreateNetworkPayload = yield* apply( + socket, + socket.emitWithAck, + applyEmitParams(SocketActionTypes.DOWNLOAD_INVITE_DATA, { + serverAddress: data.serverAddress, + cid: data.cid, + }) + ) + payload = { + ownership: CommunityOwnership.User, + peers: response.peers, + psk: response.psk, + ownerOrbitDbIdentity: response.ownerOrbitDbIdentity, + } + break + } + + console.log('join network saga payload', payload) + yield* put(communitiesActions.createNetwork(payload)) +} diff --git a/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.test.ts b/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.test.ts index 79c41e8435..8a69c7b4db 100644 --- a/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.test.ts +++ b/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.test.ts @@ -59,7 +59,7 @@ describe('launchCommunity', () => { }) test('launch certain community instead of current community', async () => { - const socket = { emit: jest.fn(), on: jest.fn() } as unknown as Socket + const socket = { emit: jest.fn(), emitWithAck: jest.fn(), on: jest.fn() } as unknown as Socket const community = await factory.create['payload']>('Community') @@ -76,14 +76,9 @@ describe('launchCommunity', () => { id: community.id, peerId: identity.peerId, hiddenService: identity.hiddenService, - certs: { - // @ts-expect-error - certificate: identity.userCertificate, - // @ts-expect-error - key: identity.userCsr.userKey, - CA: [communityWithRootCa.rootCa], - }, peers: community.peerList, + psk: undefined, + ownerOrbitDbIdentity: undefined, } await expectSaga(launchCommunitySaga, socket, communitiesActions.launchCommunity(community.id)) @@ -108,22 +103,12 @@ describe('launchCommunity', () => { }, } ) - .apply(socket, socket.emit, [ - SocketActionTypes.LAUNCH_COMMUNITY, - { - id: launchCommunityPayload.id, - peerId: launchCommunityPayload.peerId, - hiddenService: launchCommunityPayload.hiddenService, - peers: launchCommunityPayload.peers, - psk: undefined, - ownerOrbitDbIdentity: undefined, - }, - ]) + .apply(socket, socket.emitWithAck, [SocketActionTypes.LAUNCH_COMMUNITY, launchCommunityPayload]) .run() }) test('launch current community', async () => { - const socket = { emit: jest.fn(), on: jest.fn() } as unknown as Socket + const socket = { emit: jest.fn(), emitWithAck: jest.fn(), on: jest.fn() } as unknown as Socket const community = await factory.create['payload']>('Community') @@ -140,14 +125,9 @@ describe('launchCommunity', () => { id: community.id, peerId: identity.peerId, hiddenService: identity.hiddenService, - certs: { - // @ts-expect-error - certificate: identity.userCertificate, - // @ts-expect-error - key: identity.userCsr.userKey, - CA: [communityWithRootCa.rootCa], - }, peers: community.peerList, + psk: undefined, + ownerOrbitDbIdentity: undefined, } await expectSaga(launchCommunitySaga, socket, communitiesActions.launchCommunity(community.id)) @@ -172,22 +152,12 @@ describe('launchCommunity', () => { }, } ) - .apply(socket, socket.emit, [ - SocketActionTypes.LAUNCH_COMMUNITY, - { - id: launchCommunityPayload.id, - peerId: launchCommunityPayload.peerId, - hiddenService: launchCommunityPayload.hiddenService, - peers: launchCommunityPayload.peers, - psk: undefined, - ownerOrbitDbIdentity: undefined, - }, - ]) + .apply(socket, socket.emitWithAck, [SocketActionTypes.LAUNCH_COMMUNITY, launchCommunityPayload]) .run() }) test('do not launch current community if it does not have rootCa', async () => { - const socket = { emit: jest.fn(), on: jest.fn() } as unknown as Socket + const socket = { emit: jest.fn(), emitWithAck: jest.fn(), on: jest.fn() } as unknown as Socket const community = await factory.create['payload']>('Community') @@ -201,14 +171,6 @@ describe('launchCommunity', () => { id: community.id, peerId: identity.peerId, hiddenService: identity.hiddenService, - certs: { - // @ts-expect-error - certificate: identity.userCertificate, - // @ts-expect-error - key: identity.userCsr.userKey, - // @ts-expect-error - CA: [community.rootCa], - }, peers: community.peerList, } @@ -234,18 +196,7 @@ describe('launchCommunity', () => { }, } ) - .not.apply(socket, socket.emit, [ - SocketActionTypes.LAUNCH_COMMUNITY, - { - id: launchCommunityPayload.id, - peerId: launchCommunityPayload.peerId, - hiddenService: launchCommunityPayload.hiddenService, - certs: launchCommunityPayload.certs, - peers: launchCommunityPayload.peers, - psk: undefined, - ownerOrbitDbIdentity: undefined, - }, - ]) + .not.apply(socket, socket.emitWithAck, [SocketActionTypes.LAUNCH_COMMUNITY, launchCommunityPayload]) .run() }) diff --git a/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.ts b/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.ts index 303545f750..c7f620567d 100644 --- a/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.ts +++ b/packages/state-manager/src/sagas/communities/launchCommunity/launchCommunity.saga.ts @@ -9,9 +9,8 @@ import { getCurrentTime } from '../../messages/utils/message.utils' import { connectionSelectors } from '../../appConnection/connection.selectors' import { networkSelectors } from '../../network/network.selectors' import { pairsToP2pAddresses } from '@quiet/common' -import { type InitCommunityPayload, SocketActionTypes } from '@quiet/types' +import { type Community, type InitCommunityPayload, SocketActionTypes } from '@quiet/types' -// TODO: Remove if unused export function* initCommunities(): Generator { const joinedCommunities = yield* select(identitySelectors.joinedCommunities) @@ -30,12 +29,19 @@ export function* launchCommunitySaga( socket: Socket, action: PayloadAction['payload']> ): Generator { + console.log('LAUNCH COMMUNITY SAGA') const communityId = action.payload + + if (!communityId) { + console.error('Could not launch community, missing community ID') + return + } + const community = yield* select(communitiesSelectors.selectById(communityId)) const identity = yield* select(identitySelectors.selectById(communityId)) - if (!identity?.userCsr?.userKey) { - console.error('Could not launch community, No identity private key') + if (!community || !identity?.userCsr?.userKey) { + console.error('Could not launch community, missing community or user private key') return } @@ -53,9 +59,9 @@ export function* launchCommunitySaga( peerId: identity.peerId, hiddenService: identity.hiddenService, peers: peerList, - psk: community?.psk, - ownerOrbitDbIdentity: community?.ownerOrbitDbIdentity, + psk: community.psk, + ownerOrbitDbIdentity: community.ownerOrbitDbIdentity, } - yield* apply(socket, socket.emit, applyEmitParams(SocketActionTypes.LAUNCH_COMMUNITY, payload)) + yield* apply(socket, socket.emitWithAck, applyEmitParams(SocketActionTypes.LAUNCH_COMMUNITY, payload)) } diff --git a/packages/state-manager/src/sagas/communities/saveCommunityMetadata/saveCommunityMetadata.saga.ts b/packages/state-manager/src/sagas/communities/saveCommunityMetadata/saveCommunityMetadata.saga.ts deleted file mode 100644 index baadddbbb1..0000000000 --- a/packages/state-manager/src/sagas/communities/saveCommunityMetadata/saveCommunityMetadata.saga.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { type PayloadAction } from '@reduxjs/toolkit' -import { put, select } from 'typed-redux-saga' -import { type Socket } from '../../../types' -import { publicChannelsActions } from '../../publicChannels/publicChannels.slice' -import { communitiesSelectors } from '../communities.selectors' -import { communitiesActions } from '../communities.slice' - -export function* saveCommunityMetadataSaga( - socket: Socket, - action: PayloadAction['payload']> -): Generator { - const communityId = yield* select(communitiesSelectors.currentCommunityId) - console.log('save community metadata', action.payload) - yield* put( - communitiesActions.updateCommunity({ - id: communityId, - rootCa: action.payload.rootCa, - ownerOrbitDbIdentity: action.payload.ownerOrbitDbIdentity, - ownerCertificate: action.payload.ownerCertificate, - }) - ) -} diff --git a/packages/state-manager/src/sagas/communities/sendCommunityCaData/sendCommunityCaData.saga.ts b/packages/state-manager/src/sagas/communities/sendCommunityCaData/sendCommunityCaData.saga.ts deleted file mode 100644 index c0810903f3..0000000000 --- a/packages/state-manager/src/sagas/communities/sendCommunityCaData/sendCommunityCaData.saga.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { apply, select } from 'typed-redux-saga' -import { type PayloadAction } from '@reduxjs/toolkit' - -import { applyEmitParams, type Socket } from '../../../types' -import { communitiesSelectors } from '../communities.selectors' -import { type communitiesActions } from '../communities.slice' -import { type PermsData, SocketActionTypes } from '@quiet/types' - -export function* sendCommunityCaDataSaga( - socket: Socket, - _action: PayloadAction['payload']> -): Generator { - const community = yield* select(communitiesSelectors.currentCommunity) - - if (!community) { - console.error('Cannot send community metadata, no community') - return - } - - if (!community.CA) { - console.log('Cannot send community metadata, no CA in community') - return - } - - const payload: PermsData = { - certificate: community.CA.rootCertString, - privKey: community.CA.rootKeyString, - } - yield* apply(socket, socket.emit, applyEmitParams(SocketActionTypes.SET_COMMUNITY_CA_DATA, payload)) -} diff --git a/packages/state-manager/src/sagas/communities/updateCommunity/updateCommunity.saga.test.ts b/packages/state-manager/src/sagas/communities/updateCommunity/updateCommunity.saga.test.ts deleted file mode 100644 index 6473949a8f..0000000000 --- a/packages/state-manager/src/sagas/communities/updateCommunity/updateCommunity.saga.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { combineReducers } from '@reduxjs/toolkit' -import { expectSaga } from 'redux-saga-test-plan' -import { setupCrypto } from '@quiet/identity' -import { prepareStore } from '../../../utils/tests/prepareStore' -import { getFactory } from '../../../utils/tests/factories' -import { communitiesActions } from '../communities.slice' -import { updateCommunitySaga } from './updateCommunity.saga' -import { reducers } from '../../reducers' -import { type Community } from '@quiet/types' - -describe('updateCommunitySaga', () => { - test('update community', async () => { - setupCrypto() - - const store = prepareStore().store - - const factory = await getFactory(store) - - const community: Community = - await factory.create['payload']>('Community') - - const rootCa = - 'MIIBYDCCAQagAwIBAgIBATAKBggqhkjOPQQDAjAZMRcwFQYDVQQDEw5xdWlldGNvbW11bml0eTAeFw0xMDEyMjgxMDEwMTBaFw0zMDEyMjgxMDEwMTBaMBkxFzAVBgNVBAMTDnF1aWV0Y29tbXVuaXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQhderWYwXEfJ/SY7BLkPlgrqj6I1nwICH7TUCCZ+YD2j2m7WqJ2HfWMxjF//hInzIcSwZLJEDPCJroS13tn37KM/MD0wDwYDVR0TBAgwBgEB/wIBAzALBgNVHQ8EBAMCAIYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAoGCCqGSM49BAMCA0gAMEUCIGZqjtn6WU65HtCjIi6sWnwsre1HdGfBQYV1z8tCSsVpAiEAjQ04iRlFT7UZOxn5Y9j1jLHtp/KvhcW7g5vgbnY0EIQ=' - - const reducer = combineReducers(reducers) - await expectSaga( - updateCommunitySaga, - communitiesActions.updateCommunity({ - id: community.id, - rootCa, - }) - ) - .withReducer(reducer) - .withState(store.getState()) - .put( - communitiesActions.updateCommunityData({ - id: community.id, - rootCa, - name: 'quietcommunity', - }) - ) - .run() - }) -}) diff --git a/packages/state-manager/src/sagas/communities/updateCommunity/updateCommunity.saga.ts b/packages/state-manager/src/sagas/communities/updateCommunity/updateCommunity.saga.ts deleted file mode 100644 index 651f4f1499..0000000000 --- a/packages/state-manager/src/sagas/communities/updateCommunity/updateCommunity.saga.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { call, put } from 'typed-redux-saga' -import { type Certificate } from 'pkijs' - -import { CertFieldsTypes, getCertFieldValue, loadCertificate } from '@quiet/identity' -import { type PayloadAction } from '@reduxjs/toolkit' - -import { communitiesActions } from '../communities.slice' - -export function* updateCommunitySaga( - action: PayloadAction['payload']> -): Generator { - let rootCa: Certificate - let communityName: string | null = null - - if (action.payload.rootCa) { - rootCa = loadCertificate(action.payload.rootCa) - communityName = yield* call(getCertFieldValue, rootCa, CertFieldsTypes.commonName) - - if (!communityName) { - console.error(`Could not retrieve ${CertFieldsTypes.commonName} from rootca`) - } - } - - const payload: { - id: string - name?: string - rootCa?: string - ownerCertificate?: string - ownerOrbitDbIdentity?: string - } = { - id: action.payload.id, - } - - if (communityName) { - payload.name = communityName - } - - if (action.payload.rootCa) { - payload.rootCa = action.payload.rootCa - } - - if (action.payload.ownerOrbitDbIdentity) { - payload.ownerOrbitDbIdentity = action.payload.ownerOrbitDbIdentity - } - - if (action.payload.ownerCertificate) { - payload.ownerCertificate = action.payload.ownerCertificate - } - - yield* put(communitiesActions.updateCommunityData(payload)) -} diff --git a/packages/state-manager/src/sagas/communities/updateCommunityMetadata/updateCommunityMetadata.saga.ts b/packages/state-manager/src/sagas/communities/updateCommunityMetadata/updateCommunityMetadata.saga.ts deleted file mode 100644 index 494a8b67ff..0000000000 --- a/packages/state-manager/src/sagas/communities/updateCommunityMetadata/updateCommunityMetadata.saga.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { CommunityMetadata, SocketActionTypes } from '@quiet/types' -import { type PayloadAction } from '@reduxjs/toolkit' -import { apply, select, put, take } from 'typed-redux-saga' -import { channel } from 'redux-saga' -import { applyEmitParams, type Socket } from '../../../types' -import { communitiesSelectors } from '../communities.selectors' -import { communitiesActions } from '../communities.slice' -import { identitySelectors } from '../../identity/identity.selectors' - -export function* sendCommunityMetadataSaga( - socket: Socket, - _action: PayloadAction['payload']> -): Generator { - const identity = yield* select(identitySelectors.currentIdentity) - const community = yield* select(communitiesSelectors.currentCommunity) - - if (!identity?.userCertificate) { - console.error('Cannot send community metadata, no owner certificate') - return - } - - if (!community) { - console.error('Cannot send community metadata, no community') - return - } - - if (!community.rootCa || !community.CA) { - console.log('Cannot send community metadata, no rootCa or CA in community') - return - } - - const communityMetadataPayload: CommunityMetadata = { - id: community.id, - ownerCertificate: identity.userCertificate, - rootCa: community.rootCa, - } - - const meta = yield* apply( - socket, - socket.emitWithAck, - applyEmitParams(SocketActionTypes.SET_COMMUNITY_METADATA, communityMetadataPayload) - ) - - if (meta) { - yield* put(communitiesActions.saveCommunityMetadata(meta)) - } -} diff --git a/packages/state-manager/src/sagas/identity/checkLocalCsr/checkLocalCsr.saga.test.ts b/packages/state-manager/src/sagas/identity/checkLocalCsr/checkLocalCsr.saga.test.ts index 160e6ec004..7804f2fc5c 100644 --- a/packages/state-manager/src/sagas/identity/checkLocalCsr/checkLocalCsr.saga.test.ts +++ b/packages/state-manager/src/sagas/identity/checkLocalCsr/checkLocalCsr.saga.test.ts @@ -61,7 +61,6 @@ describe('checkLocalCsr', () => { nickname: 'alice', commonName: identity.hiddenService.onionAddress, peerId: identity.peerId.id, - dmPublicKey: identity.dmKeys.publicKey, signAlg: 'ECDSA', hashAlg: 'sha-256', existingKeyPair, diff --git a/packages/state-manager/src/sagas/identity/identity.master.saga.ts b/packages/state-manager/src/sagas/identity/identity.master.saga.ts index a2488685bc..471398a152 100644 --- a/packages/state-manager/src/sagas/identity/identity.master.saga.ts +++ b/packages/state-manager/src/sagas/identity/identity.master.saga.ts @@ -5,7 +5,6 @@ import { registerCertificateSaga } from './registerCertificate/registerCertifica import { registerUsernameSaga } from './registerUsername/registerUsername.saga' import { verifyJoinTimestampSaga } from './verifyJoinTimestamp/verifyJoinTimestamp.saga' import { saveUserCsrSaga } from './saveUserCsr/saveUserCsr.saga' -import { savedOwnerCertificateSaga } from './savedOwnerCertificate/savedOwnerCertificate.saga' import { usersActions } from '../users/users.slice' import { updateCertificateSaga } from './updateCertificate/updateCertificate.saga' import { checkLocalCsrSaga } from './checkLocalCsr/checkLocalCsr.saga' @@ -14,7 +13,6 @@ export function* identityMasterSaga(socket: Socket): Generator { yield all([ takeEvery(identityActions.registerUsername.type, registerUsernameSaga, socket), takeEvery(identityActions.registerCertificate.type, registerCertificateSaga, socket), - takeEvery(identityActions.savedOwnerCertificate.type, savedOwnerCertificateSaga, socket), takeEvery(identityActions.verifyJoinTimestamp.type, verifyJoinTimestampSaga), takeEvery(identityActions.checkLocalCsr.type, checkLocalCsrSaga), takeEvery(identityActions.saveUserCsr.type, saveUserCsrSaga, socket), diff --git a/packages/state-manager/src/sagas/identity/identity.slice.ts b/packages/state-manager/src/sagas/identity/identity.slice.ts index 2692933611..ec7eb25502 100644 --- a/packages/state-manager/src/sagas/identity/identity.slice.ts +++ b/packages/state-manager/src/sagas/identity/identity.slice.ts @@ -30,7 +30,6 @@ export const identitySlice = createSlice({ }) }, createUserCsr: (state, _action: PayloadAction) => state, - savedOwnerCertificate: (state, _action: PayloadAction) => state, registerUsername: (state, _action: PayloadAction) => state, registerCertificate: (state, action: PayloadAction) => { identityAdapter.updateOne(state.identities, { diff --git a/packages/state-manager/src/sagas/identity/identity.types.ts b/packages/state-manager/src/sagas/identity/identity.types.ts index 31bd088788..74819b8aee 100644 --- a/packages/state-manager/src/sagas/identity/identity.types.ts +++ b/packages/state-manager/src/sagas/identity/identity.types.ts @@ -10,11 +10,6 @@ export interface UserCsr { pkcs10: CertData } -export interface CreateDmKeyPairPayload { - dmPublicKey: string - dmPrivateKey: string -} - export interface HiddenService { onionAddress: string privateKey: string @@ -26,16 +21,10 @@ export interface PeerId { privKey?: string } -export interface DmKeys { - publicKey: string - privateKey: string -} - export interface Identity { id: string nickname: string hiddenService: HiddenService - dmKeys: DmKeys peerId: PeerId userCsr: UserCsr | null userCertificate: string | null @@ -46,7 +35,6 @@ export interface CreateUserCsrPayload { nickname: string commonName: string peerId: string - dmPublicKey: string signAlg: string hashAlg: string } @@ -63,29 +51,6 @@ export interface RegisterUserCertificatePayload { serviceAddress: string } -export interface PermsData { - certificate: string - privKey: string -} - -export interface RegisterOwnerCertificatePayload { - communityId: string - userCsr: UserCsr - permsData: PermsData -} - -export interface SaveCertificatePayload { - certificate: string - rootPermsData: PermsData -} - -export interface SaveOwnerCertificatePayload { - id: string - peerId: string - certificate: string - permsData: PermsData -} - export interface StoreUserCertificatePayload { userCertificate: string communityId: string diff --git a/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.test.ts b/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.test.ts index ad829c8650..43da4a2ade 100644 --- a/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.test.ts +++ b/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.test.ts @@ -11,7 +11,7 @@ import { registerCertificateSaga } from './registerCertificate.saga' import { type CertData, type RegisterCertificatePayload, SocketActionTypes, type UserCsr } from '@quiet/types' describe('registerCertificateSaga', () => { - it('request certificate registration when user is community owner', async () => { + it('create community when user is community owner', async () => { setupCrypto() const socket = { emit: jest.fn(), on: jest.fn() } as unknown as Socket const store = prepareStore().store @@ -35,17 +35,7 @@ describe('registerCertificateSaga', () => { await expectSaga(registerCertificateSaga, socket, identityActions.registerCertificate(registerCertificatePayload)) .withReducer(reducer) .withState(store.getState()) - .apply(socket, socket.emit, [ - SocketActionTypes.REGISTER_OWNER_CERTIFICATE, - { - communityId: community.id, - userCsr: identity.userCsr, - permsData: { - certificate: community.CA?.rootCertString, - privKey: community.CA?.rootKeyString, - }, - }, - ]) + .put(communitiesActions.createCommunity(community.id)) .not.apply(socket, socket.emit, [SocketActionTypes.REGISTER_USER_CERTIFICATE]) .run() }) @@ -67,8 +57,6 @@ describe('registerCertificateSaga', () => { rootCa: 'rootCa', peerList: [], onionAddress: '', - privateKey: '', - port: 0, } ) @@ -98,7 +86,7 @@ describe('registerCertificateSaga', () => { await expectSaga(registerCertificateSaga, socket, identityActions.registerCertificate(registerCertificatePayload)) .withReducer(reducer) .withState(store.getState()) - .not.apply(socket, socket.emit, [SocketActionTypes.REGISTER_OWNER_CERTIFICATE]) + .not.put(communitiesActions.createCommunity(community.id)) .put(communitiesActions.launchCommunity(community.id)) .run() }) @@ -120,8 +108,6 @@ describe('registerCertificateSaga', () => { rootCa: 'rootCa', peerList: [], onionAddress: '', - privateKey: '', - port: 0, } ) @@ -152,7 +138,7 @@ describe('registerCertificateSaga', () => { await expectSaga(registerCertificateSaga, socket, identityActions.registerCertificate(registerCertificatePayload)) .withReducer(reducer) .withState(store.getState()) - .not.apply(socket, socket.emit, [SocketActionTypes.REGISTER_OWNER_CERTIFICATE]) + .not.put(communitiesActions.createCommunity(community.id)) .not.put(communitiesActions.launchCommunity(community.id)) .put(identityActions.saveUserCsr()) .run() diff --git a/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.ts b/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.ts index aef5910547..31a46349ee 100644 --- a/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.ts +++ b/packages/state-manager/src/sagas/identity/registerCertificate/registerCertificate.saga.ts @@ -16,22 +16,14 @@ export function* registerCertificateSaga( ): Generator { const currentCommunity = yield* select(communitiesSelectors.currentCommunity) const isUsernameTaken = action.payload.isUsernameTaken + if (!currentCommunity) { console.error('Could not register certificate, no current community') return } if (currentCommunity.CA?.rootCertString) { - const payload: RegisterOwnerCertificatePayload = { - communityId: action.payload.communityId, - userCsr: action.payload.userCsr, - permsData: { - certificate: currentCommunity.CA.rootCertString, - privKey: currentCommunity.CA.rootKeyString, - }, - } - - yield* apply(socket, socket.emit, applyEmitParams(SocketActionTypes.REGISTER_OWNER_CERTIFICATE, payload)) + yield* put(communitiesActions.createCommunity(action.payload.communityId)) } else { if (!isUsernameTaken) { yield* put(communitiesActions.launchCommunity(action.payload.communityId)) diff --git a/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.test.ts b/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.test.ts index ac86b7c5da..5acf2b3e7b 100644 --- a/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.test.ts +++ b/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.test.ts @@ -48,14 +48,11 @@ describe('registerUsernameSaga', () => { nickname: 'nickname', commonName: identity.hiddenService.onionAddress, peerId: identity.peerId.id, - dmPublicKey: identity.dmKeys.publicKey, signAlg: config.signAlg, hashAlg: config.hashAlg, } const reducer = combineReducers(reducers) - const psk = '12345' - store.dispatch(communitiesActions.savePSK(psk)) await expectSaga(registerUsernameSaga, socket, identityActions.registerUsername({ nickname: 'nickname' })) .withReducer(reducer) .withState(store.getState()) @@ -107,7 +104,6 @@ describe('registerUsernameSaga', () => { nickname: newNickname, commonName: identity.hiddenService.onionAddress, peerId: identity.peerId.id, - dmPublicKey: identity.dmKeys.publicKey, signAlg: config.signAlg, hashAlg: config.hashAlg, existingKeyPair: { @@ -219,8 +215,6 @@ describe('registerUsernameSaga', () => { rootCa: 'rootCa', peerList: [], onionAddress: '', - privateKey: '', - port: 0, } ) @@ -251,7 +245,6 @@ describe('registerUsernameSaga', () => { nickname: 'nickname', commonName: identity.hiddenService.onionAddress, peerId: identity.peerId.id, - dmPublicKey: identity.dmKeys.publicKey, signAlg: config.signAlg, hashAlg: config.hashAlg, } diff --git a/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.ts b/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.ts index 6899f03c21..4622539f7f 100644 --- a/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.ts +++ b/packages/state-manager/src/sagas/identity/registerUsername/registerUsername.saga.ts @@ -54,7 +54,6 @@ export function* registerUsernameSaga( nickname, commonName: identity.hiddenService.onionAddress, peerId: identity.peerId.id, - dmPublicKey: identity.dmKeys.publicKey, signAlg: config.signAlg, hashAlg: config.hashAlg, existingKeyPair, @@ -71,7 +70,6 @@ export function* registerUsernameSaga( nickname, commonName: identity.hiddenService.onionAddress, peerId: identity.peerId.id, - dmPublicKey: identity.dmKeys.publicKey, signAlg: config.signAlg, hashAlg: config.hashAlg, } diff --git a/packages/state-manager/src/sagas/identity/savedOwnerCertificate/savedOwnerCertificate.saga.ts b/packages/state-manager/src/sagas/identity/savedOwnerCertificate/savedOwnerCertificate.saga.ts deleted file mode 100644 index 20ba7793fe..0000000000 --- a/packages/state-manager/src/sagas/identity/savedOwnerCertificate/savedOwnerCertificate.saga.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { type Socket, applyEmitParams } from '../../../types' -import { select, apply } from 'typed-redux-saga' -import { type PayloadAction } from '@reduxjs/toolkit' -import { type identityActions } from '../identity.slice' -import { communitiesSelectors } from '../../communities/communities.selectors' -import { identitySelectors } from '../identity.selectors' -import { type InitCommunityPayload, SocketActionTypes } from '@quiet/types' - -export function* savedOwnerCertificateSaga( - socket: Socket, - action: PayloadAction['payload']> -): Generator { - let communityId: string = action.payload - - if (!communityId) { - communityId = yield* select(communitiesSelectors.currentCommunityId) - } - - const community = yield* select(communitiesSelectors.selectById(communityId)) - const identity = yield* select(identitySelectors.selectById(communityId)) - if (!identity?.userCertificate || !identity?.userCsr || !community?.rootCa) return - - const payload: InitCommunityPayload = { - id: communityId, - peerId: identity.peerId, - hiddenService: identity.hiddenService, - certs: { - certificate: identity.userCertificate, - key: identity.userCsr.userKey, - CA: [community.rootCa], - }, - psk: community?.psk, - ownerOrbitDbIdentity: community?.ownerOrbitDbIdentity, - } - - yield* apply(socket, socket.emit, applyEmitParams(SocketActionTypes.CREATE_COMMUNITY, payload)) -} diff --git a/packages/state-manager/src/sagas/network/network.slice.ts b/packages/state-manager/src/sagas/network/network.slice.ts index 7a491e4037..ace82febd3 100644 --- a/packages/state-manager/src/sagas/network/network.slice.ts +++ b/packages/state-manager/src/sagas/network/network.slice.ts @@ -14,7 +14,6 @@ export const networkSlice = createSlice({ name: StoreKeys.Network, reducers: { addInitializedCommunity: (state, action: PayloadAction) => { - console.log('Hunting for heisenbug: adding initialized community ', action.payload) state.initializedCommunities = { ...state.initializedCommunities, [action.payload]: true, diff --git a/packages/state-manager/src/sagas/publicChannels/channelDeletionResponse/channelDeletionResponse.saga.ts b/packages/state-manager/src/sagas/publicChannels/channelDeletionResponse/channelDeletionResponse.saga.ts index 9e53eab2b2..b0d90d0182 100644 --- a/packages/state-manager/src/sagas/publicChannels/channelDeletionResponse/channelDeletionResponse.saga.ts +++ b/packages/state-manager/src/sagas/publicChannels/channelDeletionResponse/channelDeletionResponse.saga.ts @@ -60,7 +60,7 @@ export function* channelDeletionResponseSaga( let newGeneralChannel: PublicChannelStorage | undefined = yield* select(publicChannelsSelectors.generalChannel) while (!newGeneralChannel) { log('General channel has not been replicated yet') - yield* delay(500) + yield* delay(1000) newGeneralChannel = yield* select(publicChannelsSelectors.generalChannel) } yield* put(publicChannelsActions.setCurrentChannel({ channelId: newGeneralChannel.id })) diff --git a/packages/state-manager/src/sagas/publicChannels/channelsReplicated/channelsReplicated.saga.ts b/packages/state-manager/src/sagas/publicChannels/channelsReplicated/channelsReplicated.saga.ts index 4b431b4fc6..ebf15f8f16 100644 --- a/packages/state-manager/src/sagas/publicChannels/channelsReplicated/channelsReplicated.saga.ts +++ b/packages/state-manager/src/sagas/publicChannels/channelsReplicated/channelsReplicated.saga.ts @@ -13,7 +13,8 @@ const log = logger('channels') export function* channelsReplicatedSaga( action: PayloadAction['payload']> ): Generator { - log('Syncing channels') + // TODO: Refactor to use QuietLogger + log(`Syncing channels: ${JSON.stringify(action.payload, null, 2)}`) const { channels } = action.payload const _locallyStoredChannels = yield* select(publicChannelsSelectors.publicChannels) const locallyStoredChannels = _locallyStoredChannels.map(channel => channel.id) @@ -24,20 +25,10 @@ export function* channelsReplicatedSaga( const databaseStoredChannelsIds = databaseStoredChannels.map(channel => channel.id) console.log({ locallyStoredChannels, databaseStoredChannelsIds }) - // Removing channels from store - if (databaseStoredChannelsIds.length > 0) { - for (const channelId of locallyStoredChannels) { - if (!databaseStoredChannelsIds.includes(channelId)) { - log(`Removing #${channelId} from store`) - yield* put(publicChannelsActions.deleteChannel({ channelId })) - yield* take(publicChannelsActions.completeChannelDeletion) - } - } - } - // Upserting channels to local storage for (const channel of databaseStoredChannels) { if (!locallyStoredChannels.includes(channel.id)) { + // TODO: Refactor to use QuietLogger log(`Adding #${channel.name} to store`) yield* put( publicChannelsActions.addChannel({ @@ -52,6 +43,18 @@ export function* channelsReplicatedSaga( } } + // Removing channels from store + if (databaseStoredChannelsIds.length > 0) { + for (const channelId of locallyStoredChannels) { + if (!databaseStoredChannelsIds.includes(channelId)) { + // TODO: Refactor to use QuietLogger + log(`Removing #${channelId} from store`) + yield* put(publicChannelsActions.deleteChannel({ channelId })) + yield* take(publicChannelsActions.completeChannelDeletion) + } + } + } + const currentChannelCache = yield* select(publicChannelsSelectors.currentChannelMessages) const currentChannelRepository = yield* select(messagesSelectors.currentPublicChannelMessagesEntries) diff --git a/packages/state-manager/src/sagas/publicChannels/deleteChannel/deleteChannel.saga.test.ts b/packages/state-manager/src/sagas/publicChannels/deleteChannel/deleteChannel.saga.test.ts index ac250d9ec4..4b9e0f15fd 100644 --- a/packages/state-manager/src/sagas/publicChannels/deleteChannel/deleteChannel.saga.test.ts +++ b/packages/state-manager/src/sagas/publicChannels/deleteChannel/deleteChannel.saga.test.ts @@ -38,7 +38,6 @@ describe('deleteChannelSaga', () => { username: string | null onionAddress: string | null peerId: string | null - dmPublicKey: string | null pubKey: string } | null diff --git a/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.test.ts b/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.test.ts index f392b997f3..b7e92e8272 100644 --- a/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.test.ts +++ b/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.test.ts @@ -260,7 +260,6 @@ describe('publicChannelsSelectors', () => { const displayable: Record = {} for (const message of Object.values(msgs)) { const user: User = { - dmPublicKey: '', isDuplicated: false, isRegistered: true, onionAddress: '', diff --git a/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts b/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts index a43b8f034a..9c908f13ee 100644 --- a/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts +++ b/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts @@ -2,6 +2,7 @@ import { eventChannel } from 'redux-saga' import { type Socket } from '../../../types' import { all, call, fork, put, takeEvery } from 'typed-redux-saga' import logger from '../../../utils/logger' +import { appActions } from '../../app/app.slice' import { appMasterSaga } from '../../app/app.master.saga' import { connectionActions } from '../../appConnection/connection.slice' import { communitiesMasterSaga } from '../../communities/communities.master.saga' @@ -26,6 +27,7 @@ import { type ResponseLaunchCommunityPayload, type ChannelMessageIdsResponse, type ChannelsReplicatedPayload, + type Community, type CommunityId, type DownloadStatus, type ErrorPayload, @@ -63,11 +65,10 @@ export function subscribe(socket: Socket) { | ReturnType | ReturnType | ReturnType - | ReturnType | ReturnType - | ReturnType - | ReturnType + | ReturnType | ReturnType + | ReturnType | ReturnType | ReturnType | ReturnType @@ -83,11 +84,8 @@ export function subscribe(socket: Socket) { | ReturnType | ReturnType | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType | ReturnType + | ReturnType >(emit => { // UPDATE FOR APP socket.on(SocketActionTypes.TOR_INITIALIZED, () => { @@ -105,6 +103,9 @@ export function subscribe(socket: Socket) { emit(networkActions.removeConnectedPeer(payload.peer)) emit(connectionActions.updateNetworkData(payload)) }) + socket.on(SocketActionTypes.MIGRATION_DATA_REQUIRED, (keys: string[]) => { + emit(appActions.loadMigrationData(keys)) + }) // Files socket.on(SocketActionTypes.MESSAGE_MEDIA_UPDATED, (payload: FileMetadata) => { emit(filesActions.updateMessageMedia(payload)) @@ -136,33 +137,16 @@ export function subscribe(socket: Socket) { // Community - socket.on(SocketActionTypes.COMMUNITY_CREATED, async (payload: ResponseCreateCommunityPayload) => { - log(`${SocketActionTypes.COMMUNITY_CREATED}: ${payload}`) - // We can also set community metadata when we register the - // owner's certificate. I think the only issue is that we - // register the owner's certificate before initializing the - // community and thus the storage service. - emit(communitiesActions.sendCommunityMetadata()) - emit(publicChannelsActions.createGeneralChannel()) - // We also save the owner's CSR after registering their - // certificate. It works, but it might make more sense to get - // all the backend services up and running and then save the - // CSR, register the owner's certificate and set community - // metadata. - emit(identityActions.saveUserCsr()) - }) - socket.on(SocketActionTypes.PEER_LIST, (payload: StorePeerListPayload) => { - emit(communitiesActions.storePeerList(payload)) - }) socket.on(SocketActionTypes.COMMUNITY_LAUNCHED, (payload: ResponseLaunchCommunityPayload) => { - console.log('Hunting for heisenbug: Community event received in state-manager') - // TODO: We can send this once when creating the community and - // store it in the backend. - emit(communitiesActions.sendCommunityCaData()) emit(filesActions.checkForMissingFiles(payload.id)) emit(networkActions.addInitializedCommunity(payload.id)) emit(communitiesActions.clearInvitationCodes()) }) + + socket.on(SocketActionTypes.COMMUNITY_UPDATED, (payload: Community) => { + emit(communitiesActions.updateCommunityData(payload)) + }) + // Errors socket.on(SocketActionTypes.ERROR, (payload: ErrorPayload) => { // FIXME: It doesn't look like log errors have the red error @@ -182,30 +166,6 @@ export function subscribe(socket: Socket) { socket.on(SocketActionTypes.CERTIFICATES_STORED, (payload: SendCertificatesResponse) => { emit(usersActions.responseSendCertificates(payload)) }) - socket.on(SocketActionTypes.OWNER_CERTIFICATE_ISSUED, (payload: SavedOwnerCertificatePayload) => { - log(`${SocketActionTypes.OWNER_CERTIFICATE_ISSUED}: ${payload.communityId}`) - emit( - communitiesActions.updateCommunity({ - id: payload.communityId, - ownerCertificate: payload.network.certificate, - }) - ) - emit( - identityActions.storeUserCertificate({ - userCertificate: payload.network.certificate, - communityId: payload.communityId, - }) - ) - emit(identityActions.savedOwnerCertificate(payload.communityId)) - }) - socket.on(SocketActionTypes.COMMUNITY_METADATA_STORED, (payload: CommunityMetadata) => { - log(`${SocketActionTypes.COMMUNITY_METADATA_STORED}: ${payload}`) - emit(communitiesActions.saveCommunityMetadata(payload)) - }) - socket.on(SocketActionTypes.LIBP2P_PSK_STORED, (payload: { psk: string }) => { - log(`${SocketActionTypes.LIBP2P_PSK_STORED}`) - emit(communitiesActions.savePSK(payload.psk)) - }) // User Profile diff --git a/packages/state-manager/src/sagas/store.migrations.ts b/packages/state-manager/src/sagas/store.migrations.ts new file mode 100644 index 0000000000..f25b189fae --- /dev/null +++ b/packages/state-manager/src/sagas/store.migrations.ts @@ -0,0 +1,39 @@ +import { StoreKeys } from './store.keys' +import { CommunitiesState } from './communities/communities.slice' + +// TODO: It might be easier to run migrations at a higher level that this (e.g. +// once the store has already been rehydrated), so that we have access to the +// entity API and slice reducers. +// +// TODO: Note that any migration here needs to be idempotent since these will +// also run on fresh Quiet installs. We can probably fix this if we want. See: +// https://github.com/rt2zz/redux-persist/blob/d8b01a085e3679db43503a3858e8d4759d6f22fa/src/createMigrate.ts#L21-L24 +export const storeMigrations = { + // MIGRATION: Move CommunitiesState.psk to Community.psk + 0: (state: any) => { + // Removing psk from the CommunitiesState class causes type errors. Below + // is one solution. Another alternative is making CommunitiesState a union + // type, e.g. CommunitiesStateV1 | CommunitiesStateV2, or simply leaving + // the psk field in CommunitiesState and marking it deprecated in a + // comment. + const prevState = state[StoreKeys.Communities] as CommunitiesState & { psk?: string | undefined } + + if (prevState.psk) { + // At this time we only have a single community + const currentCommunity = prevState.communities.entities[prevState.currentCommunity] + + if (currentCommunity) { + currentCommunity.psk = prevState.psk + } + } + + return state + }, + // TODO: Uncomment this migration after the previous migration has been + // released. + // 1: (state: any) => { + // const prevState = state[StoreKeys.Communities] as CommunitiesState & { psk?: string | undefined } + + // delete prevState.psk + // } +} diff --git a/packages/state-manager/src/sagas/store.types.ts b/packages/state-manager/src/sagas/store.types.ts index 0679a2610d..3c96a4e0bf 100644 --- a/packages/state-manager/src/sagas/store.types.ts +++ b/packages/state-manager/src/sagas/store.types.ts @@ -1,6 +1,7 @@ import { configureStore, combineReducers, getDefaultMiddleware } from '@reduxjs/toolkit' import { reducers } from './reducers' import createSagaMiddleware from 'redux-saga' + const rootReducer = combineReducers(reducers) const sagaMiddleware = createSagaMiddleware() const store = configureStore({ diff --git a/packages/state-manager/src/sagas/users/const/certFieldTypes.ts b/packages/state-manager/src/sagas/users/const/certFieldTypes.ts index 161e0dc7f8..da39a0c858 100644 --- a/packages/state-manager/src/sagas/users/const/certFieldTypes.ts +++ b/packages/state-manager/src/sagas/users/const/certFieldTypes.ts @@ -3,7 +3,6 @@ export enum CertFieldsTypes { subjectAltName = '2.5.29.17', nickName = '1.3.6.1.4.1.50715.2.1', peerId = '1.3.6.1.2.1.15.3.1.1', - dmPublicKey = '1.2.840.113549.1.9.12', } export const config = { diff --git a/packages/state-manager/src/sagas/users/userProfile/saveUserProfile.saga.test.ts b/packages/state-manager/src/sagas/users/userProfile/saveUserProfile.saga.test.ts index 3317097d7b..fc363a5753 100644 --- a/packages/state-manager/src/sagas/users/userProfile/saveUserProfile.saga.test.ts +++ b/packages/state-manager/src/sagas/users/userProfile/saveUserProfile.saga.test.ts @@ -28,7 +28,6 @@ describe('saveUserProfileSaga', () => { nickname: '', commonName: '', peerId: '', - dmPublicKey: '', signAlg: '', hashAlg: '', }) diff --git a/packages/state-manager/src/sagas/users/userProfile/userProfile.selectors.test.ts b/packages/state-manager/src/sagas/users/userProfile/userProfile.selectors.test.ts index 02b7a66576..4159216e1d 100644 --- a/packages/state-manager/src/sagas/users/userProfile/userProfile.selectors.test.ts +++ b/packages/state-manager/src/sagas/users/userProfile/userProfile.selectors.test.ts @@ -23,7 +23,6 @@ describe('user profile selectors', () => { nickname: '', commonName: '', peerId: '', - dmPublicKey: '', signAlg: '', hashAlg: '', }) diff --git a/packages/state-manager/src/sagas/users/users.selectors.test.ts b/packages/state-manager/src/sagas/users/users.selectors.test.ts index 50af782c63..edc7fb8671 100644 --- a/packages/state-manager/src/sagas/users/users.selectors.test.ts +++ b/packages/state-manager/src/sagas/users/users.selectors.test.ts @@ -23,7 +23,6 @@ describe('users selectors', () => { let alicePublicKey: string const aliceCertificateData = { - dmPublicKey: '0bfb475810c0e26c9fab590d47c3d60ec533bb3c451596acc3cd4f21602e9ad9', onionAddress: 'nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion', peerId: 'Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6', username: 'alice', @@ -49,10 +48,6 @@ describe('users selectors', () => { peerId: { id: aliceCertificateData.peerId, }, - dmKeys: { - publicKey: aliceCertificateData.dmPublicKey, - privateKey: '', - }, }) const parsedAliceCertificate = parseCertificate(alice.userCertificate!) @@ -82,7 +77,6 @@ describe('users selectors', () => { expect(usersData[alicePublicKey]).toMatchInlineSnapshot(` Object { - "dmPublicKey": "0bfb475810c0e26c9fab590d47c3d60ec533bb3c451596acc3cd4f21602e9ad9", "onionAddress": "nqnw4kc4c77fb47lk52m5l57h4tcxceo7ymxekfn7yh5m66t4jv2olad.onion", "peerId": "Qmf3ySkYqLET9xtAtDzvAr5Pp3egK1H3C5iJAZm1SpLEp6", "username": "alice", diff --git a/packages/state-manager/src/sagas/users/users.selectors.ts b/packages/state-manager/src/sagas/users/users.selectors.ts index d9e2abc656..2f21e34b08 100644 --- a/packages/state-manager/src/sagas/users/users.selectors.ts +++ b/packages/state-manager/src/sagas/users/users.selectors.ts @@ -29,7 +29,6 @@ export const certificatesMapping = createSelector(certificates, certs => { const username = getCertFieldValue(certificate, CertFieldsTypes.nickName) const onionAddress = getCertFieldValue(certificate, CertFieldsTypes.commonName) const peerId = getCertFieldValue(certificate, CertFieldsTypes.peerId) - const dmPublicKey = getCertFieldValue(certificate, CertFieldsTypes.dmPublicKey) || '' if (!username || !onionAddress || !peerId) { console.error(`Could not parse certificate for pubkey ${pubKey}`) @@ -40,7 +39,6 @@ export const certificatesMapping = createSelector(certificates, certs => { username, onionAddress, peerId, - dmPublicKey, }) }) return mapping @@ -58,7 +56,6 @@ export const csrsMapping = createSelector(csrs, csrs => { const username = getReqFieldValue(csr, CertFieldsTypes.nickName) const onionAddress = getReqFieldValue(csr, CertFieldsTypes.commonName) const peerId = getReqFieldValue(csr, CertFieldsTypes.peerId) - const dmPublicKey = getReqFieldValue(csr, CertFieldsTypes.dmPublicKey) || '' if (!username || !onionAddress || !peerId) { console.error(`Could not parse certificate for pubkey ${pubKey}`) @@ -69,7 +66,6 @@ export const csrsMapping = createSelector(csrs, csrs => { username, onionAddress, peerId, - dmPublicKey, }) }) @@ -130,14 +126,12 @@ export const ownerData = createSelector(ownerCertificate, ownerCertificate => { const username = getCertFieldValue(ownerCert, CertFieldsTypes.nickName) const onionAddress = getCertFieldValue(ownerCert, CertFieldsTypes.commonName) const peerId = getCertFieldValue(ownerCert, CertFieldsTypes.peerId) - const dmPublicKey = getCertFieldValue(ownerCert, CertFieldsTypes.dmPublicKey) const pubKey = keyFromCertificate(ownerCert) return { username, onionAddress, peerId, - dmPublicKey, pubKey, } }) diff --git a/packages/state-manager/src/sagas/users/users.slice.test.ts b/packages/state-manager/src/sagas/users/users.slice.test.ts index 9658716a61..ccfa6bd128 100644 --- a/packages/state-manager/src/sagas/users/users.slice.test.ts +++ b/packages/state-manager/src/sagas/users/users.slice.test.ts @@ -20,8 +20,6 @@ describe('users reducer', () => { rootCa: '', peerList: [], onionAddress: '', - privateKey: '', - port: 0, ownerCertificate: '', } diff --git a/packages/state-manager/src/sagas/users/users.types.ts b/packages/state-manager/src/sagas/users/users.types.ts index 689b52cb39..b934c98478 100644 --- a/packages/state-manager/src/sagas/users/users.types.ts +++ b/packages/state-manager/src/sagas/users/users.types.ts @@ -2,7 +2,6 @@ export interface User { username: string onionAddress: string peerId: string - dmPublicKey: string } export interface SendCertificatesResponse { diff --git a/packages/state-manager/src/types.ts b/packages/state-manager/src/types.ts index d356b88e2a..c6b0ab6543 100644 --- a/packages/state-manager/src/types.ts +++ b/packages/state-manager/src/types.ts @@ -32,14 +32,13 @@ interface EventsMap { type EmitEvent void> = (payload: Payload, callback?: Callback) => void export interface EmitEvents { - [SocketActionTypes.LAUNCH_COMMUNITY]: EmitEvent + [SocketActionTypes.LAUNCH_COMMUNITY]: EmitEvent void> [SocketActionTypes.DOWNLOAD_FILE]: EmitEvent [SocketActionTypes.SEND_MESSAGE]: EmitEvent [SocketActionTypes.CANCEL_DOWNLOAD]: EmitEvent [SocketActionTypes.UPLOAD_FILE]: EmitEvent - [SocketActionTypes.REGISTER_OWNER_CERTIFICATE]: EmitEvent [SocketActionTypes.REGISTER_USER_CERTIFICATE]: EmitEvent - [SocketActionTypes.CREATE_COMMUNITY]: EmitEvent + [SocketActionTypes.CREATE_COMMUNITY]: EmitEvent void> [SocketActionTypes.GET_MESSAGES]: EmitEvent void> [SocketActionTypes.CREATE_CHANNEL]: EmitEvent void> [SocketActionTypes.DELETE_CHANNEL]: EmitEvent< @@ -49,11 +48,11 @@ export interface EmitEvents { [SocketActionTypes.DELETE_FILES_FROM_CHANNEL]: EmitEvent [SocketActionTypes.CLOSE]: () => void [SocketActionTypes.LEAVE_COMMUNITY]: () => void - [SocketActionTypes.CREATE_NETWORK]: EmitEvent void> + [SocketActionTypes.CREATE_NETWORK]: EmitEvent void> [SocketActionTypes.ADD_CSR]: EmitEvent - [SocketActionTypes.SET_COMMUNITY_METADATA]: EmitEvent void> - [SocketActionTypes.SET_COMMUNITY_CA_DATA]: EmitEvent [SocketActionTypes.SET_USER_PROFILE]: EmitEvent + [SocketActionTypes.DOWNLOAD_INVITE_DATA]: EmitEvent<{ serverAddress: string; cid: string }> + [SocketActionTypes.LOAD_MIGRATION_DATA]: EmitEvent> } export type Socket = IOSocket diff --git a/packages/state-manager/src/utils/functions/invitationCode/invitationCode.test.ts b/packages/state-manager/src/utils/functions/invitationCode/invitationCode.test.ts index 7d5ac34e7e..c5ba56193d 100644 --- a/packages/state-manager/src/utils/functions/invitationCode/invitationCode.test.ts +++ b/packages/state-manager/src/utils/functions/invitationCode/invitationCode.test.ts @@ -1,27 +1,48 @@ +import { InvitationDataV1, InvitationDataVersion } from '@quiet/types' import { getInvitationCodes } from './invitationCode' -import { OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, PSK_PARAM_KEY, QUIET_JOIN_PAGE } from '@quiet/common' +import { + CID_PARAM_KEY, + INVITER_ADDRESS_PARAM_KEY, + OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, + PSK_PARAM_KEY, + QUIET_JOIN_PAGE, + SERVER_ADDRESS_PARAM_KEY, + TOKEN_PARAM_KEY, + validInvitationDatav1, + validInvitationDatav2, +} from '@quiet/common' + +const getUrlParamsPart = (url: string) => url.split(QUIET_JOIN_PAGE + '?')[1] describe('Invitation code helper', () => { - const peerId1 = 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSA' - const address1 = 'gloao6h5plwjy4tdlze24zzgcxll6upq2ex2fmu2ohhyu4gtys4nrjad' - const peerId2 = 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE' - const address2 = 'y7yczmugl2tekami7sbdz5pfaemvx7bahwthrdvcbzw5vex2crsr26qd' - const psk = 'BNlxfE2WBF7LrlpIX0CvECN5o1oZtA16PkAb7GYiwYw=' - const ownerOrbitDbIdentity = 'testOwnerOrbitDbIdentity' - const encodedPsk = encodeURIComponent(psk) - const encodedOwnerOrbitDbIdentity = encodeURIComponent(ownerOrbitDbIdentity) + const address = 'gloao6h5plwjy4tdlze24zzgcxll6upq2ex2fmu2ohhyu4gtys4nrjad' + const peerId = 'QmZoiJNAvCffeEHBjk766nLuKVdkxkAT7wfFJDPPLsbKSE' + const data: InvitationDataV1 = { + ...validInvitationDatav1[0], + pairs: [...validInvitationDatav1[0].pairs, { peerId: peerId, onionAddress: address }], + } + const urlParams = [ + [data.pairs[0].peerId, data.pairs[0].onionAddress], + [data.pairs[1].peerId, data.pairs[1].onionAddress], + [PSK_PARAM_KEY, data.psk], + [OWNER_ORBIT_DB_IDENTITY_PARAM_KEY, data.ownerOrbitDbIdentity], + ] + + const datav2 = validInvitationDatav2[0] + const urlParamsv2 = [ + [CID_PARAM_KEY, datav2.cid], + [TOKEN_PARAM_KEY, datav2.token], + [SERVER_ADDRESS_PARAM_KEY, datav2.serverAddress], + [INVITER_ADDRESS_PARAM_KEY, datav2.inviterAddress], + ] it('retrieves invitation code if url is a proper share url', () => { - const result = getInvitationCodes( - `${QUIET_JOIN_PAGE}#${peerId1}=${address1}&${peerId2}=${address2}&${PSK_PARAM_KEY}=${encodedPsk}&${OWNER_ORBIT_DB_IDENTITY_PARAM_KEY}=${encodedOwnerOrbitDbIdentity}` - ) + const url = new URL(QUIET_JOIN_PAGE) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + const result = getInvitationCodes(url.href.replace('?', '#')) expect(result).toEqual({ - pairs: [ - { peerId: peerId1, onionAddress: address1 }, - { peerId: peerId2, onionAddress: address2 }, - ], - psk, - ownerOrbitDbIdentity, + version: InvitationDataVersion.v1, + ...data, }) }) @@ -30,38 +51,33 @@ describe('Invitation code helper', () => { }) it('throws error if code does not contain psk', () => { - expect(() => getInvitationCodes(`${peerId1}=${address1}&${peerId2}=${address2}`)).toThrow() + const url = new URL(QUIET_JOIN_PAGE) + url.searchParams.append(urlParams[0][0], urlParams[0][1]) + url.searchParams.append(urlParams[1][0], urlParams[1][1]) + expect(() => getInvitationCodes(getUrlParamsPart(url.href))).toThrow() }) it('throws error if psk has invalid format', () => { - expect(() => getInvitationCodes(`${peerId1}=${address1}&${peerId2}=${address2}&${PSK_PARAM_KEY}=12345`)).toThrow() + const url = new URL(QUIET_JOIN_PAGE) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + url.searchParams.set(PSK_PARAM_KEY, '12345') + expect(() => getInvitationCodes(getUrlParamsPart(url.href))).toThrow() }) it('retrieves invitation code if url is a proper code', () => { - const result = getInvitationCodes( - `${peerId1}=${address1}&${peerId2}=${address2}&${PSK_PARAM_KEY}=${encodedPsk}&${OWNER_ORBIT_DB_IDENTITY_PARAM_KEY}=${encodedOwnerOrbitDbIdentity}` - ) + const url = new URL(QUIET_JOIN_PAGE) + urlParams.forEach(([key, value]) => url.searchParams.append(key, value)) + const result = getInvitationCodes(getUrlParamsPart(url.href)) expect(result).toEqual({ - pairs: [ - { peerId: peerId1, onionAddress: address1 }, - { peerId: peerId2, onionAddress: address2 }, - ], - psk, - ownerOrbitDbIdentity, + version: InvitationDataVersion.v1, + ...data, }) }) - it('retrieves invitation code if url is a proper code', () => { - const result = getInvitationCodes( - `${peerId1}=${address1}&${peerId2}=${address2}&${PSK_PARAM_KEY}=${encodedPsk}&${OWNER_ORBIT_DB_IDENTITY_PARAM_KEY}=${encodedOwnerOrbitDbIdentity}` - ) - expect(result).toEqual({ - pairs: [ - { peerId: peerId1, onionAddress: address1 }, - { peerId: peerId2, onionAddress: address2 }, - ], - psk, - ownerOrbitDbIdentity, - }) + it('retrieves invitation code if url is a proper v2 code', () => { + const url = new URL(QUIET_JOIN_PAGE) + urlParamsv2.forEach(([key, value]) => url.searchParams.append(key, value)) + const result = getInvitationCodes(getUrlParamsPart(url.href)) + expect(result).toEqual(datav2) }) }) diff --git a/packages/state-manager/src/utils/functions/invitationCode/invitationCode.ts b/packages/state-manager/src/utils/functions/invitationCode/invitationCode.ts index 1fe956f338..e147a2fea8 100644 --- a/packages/state-manager/src/utils/functions/invitationCode/invitationCode.ts +++ b/packages/state-manager/src/utils/functions/invitationCode/invitationCode.ts @@ -6,7 +6,6 @@ export const getInvitationCodes = (codeOrUrl: string): InvitationData => { * Extract codes from invitation share url or return passed value for further error handling * @param codeOrUrl: full invitation link or just the code part of the link */ - let data: InvitationData | null = null let potentialCode let validUrl: URL | null = null @@ -30,11 +29,5 @@ export const getInvitationCodes = (codeOrUrl: string): InvitationData => { code = potentialCode } - data = parseInvitationCode(code) - - if (!data || data?.pairs.length === 0) { - throw new Error(`No invitation codes. Code/url passed: ${codeOrUrl}`) - } - - return data + return parseInvitationCode(code) } diff --git a/packages/state-manager/src/utils/tests/factories.ts b/packages/state-manager/src/utils/tests/factories.ts index 2eeec6cdae..9a0ee68f6a 100644 --- a/packages/state-manager/src/utils/tests/factories.ts +++ b/packages/state-manager/src/utils/tests/factories.ts @@ -93,10 +93,6 @@ export const getFactory = async (store: Store) => { 'ED25519-V3:WND1FoFZyY+c1f0uD6FBWgKvSYl4CdKSizSR7djRekW/rqw5fTw+gN80sGk0gl01sL5i25noliw85zF1BUBRDQ==', }, peerId: createPeerIdTestHelper(), - dmKeys: { - publicKey: '9f016defcbe48829db163e86b28efb10318faf3b109173105e3dc024e951bb1b', - privateKey: '4dcebbf395c0e9415bc47e52c96fcfaf4bd2485a516f45118c2477036b45fc0b', - }, nickname: factory.sequence('Identity.nickname', (n: number) => `user_${n}`), userCsr: undefined, userCertificate: undefined, @@ -115,7 +111,6 @@ export const getFactory = async (store: Store) => { nickname: action.payload.nickname, commonName: action.payload.hiddenService.onionAddress, peerId: action.payload.peerId.id, - dmPublicKey: action.payload.dmKeys.publicKey, }, community.CA ) @@ -149,7 +144,7 @@ export const getFactory = async (store: Store) => { if (!community.ownerCertificate) { store.dispatch( - communities.actions.updateCommunity({ + communities.actions.updateCommunityData({ id: community.id, ownerCertificate: action.payload.userCertificate, }) diff --git a/packages/types/src/community.ts b/packages/types/src/community.ts index d952fecfbb..607a00fe1a 100644 --- a/packages/types/src/community.ts +++ b/packages/types/src/community.ts @@ -1,4 +1,4 @@ -import { type HiddenService, type PeerId, type Identity } from './identity' +import { type HiddenService, type PeerId, type Identity, type UserCsr } from './identity' import { InvitationPair } from './network' export interface Community { @@ -11,8 +11,6 @@ export interface Community { rootCa?: string peerList?: string[] onionAddress?: string - privateKey?: string - port?: number ownerCertificate?: string psk?: string ownerOrbitDbIdentity?: string @@ -44,12 +42,18 @@ export interface Certificates { export interface InitCommunityPayload { id: string + name?: string peerId: PeerId hiddenService: HiddenService - certs?: Certificates + CA?: null | { + rootCertString: string + rootKeyString: string + } + rootCa?: string peers?: string[] psk?: string ownerOrbitDbIdentity?: string + ownerCsr?: UserCsr } export interface StorePeerListPayload { diff --git a/packages/types/src/connection.ts b/packages/types/src/connection.ts index 899c6c64cd..afee30991b 100644 --- a/packages/types/src/connection.ts +++ b/packages/types/src/connection.ts @@ -2,6 +2,9 @@ export type CommunityId = string export type ConnectedPeers = string[] +// FIXME: We can rename this to something like PeerConnInfo or +// PeerDisconnectedPayload if it's only used for the PEER_DISCONNECTED +// event. export interface NetworkDataPayload { peer: string connectionDuration: number diff --git a/packages/types/src/identity.ts b/packages/types/src/identity.ts index d00e906774..c2606e2c5d 100644 --- a/packages/types/src/identity.ts +++ b/packages/types/src/identity.ts @@ -10,11 +10,6 @@ export interface UserCsr { pkcs10: CertData } -export interface CreateDmKeyPairPayload { - dmPublicKey: string - dmPrivateKey: string -} - export interface HiddenService { onionAddress: string privateKey: string @@ -26,16 +21,10 @@ export interface PeerId { privKey?: string } -export interface DmKeys { - publicKey: string - privateKey: string -} - export interface Identity { id: string nickname: string hiddenService: HiddenService - dmKeys: DmKeys peerId: PeerId userCsr: UserCsr | null userCertificate: string | null @@ -49,7 +38,6 @@ export interface CreateUserCsrPayload { nickname: string commonName: string peerId: string - dmPublicKey: string signAlg: string hashAlg: string existingKeyPair?: CryptoKeyPair diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 3d16fdbe16..0a7902637e 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -9,3 +9,4 @@ export * from './message' export * from './files' export * from './channel' export * from './network' +export * from './test' diff --git a/packages/types/src/network.ts b/packages/types/src/network.ts index 894ca4f427..977bb063c0 100644 --- a/packages/types/src/network.ts +++ b/packages/types/src/network.ts @@ -8,8 +8,24 @@ export type InvitationPair = { onionAddress: string } -export type InvitationData = { +export enum InvitationDataVersion { + v1 = 'v1', + v2 = 'v2', +} + +export type InvitationDataV1 = { + version?: InvitationDataVersion.v1 pairs: InvitationPair[] psk: string ownerOrbitDbIdentity: string } + +export type InvitationDataV2 = { + version?: InvitationDataVersion.v2 + cid: string + token: string + serverAddress: string + inviterAddress: string +} + +export type InvitationData = InvitationDataV1 | InvitationDataV2 diff --git a/packages/types/src/socket.ts b/packages/types/src/socket.ts index 5888f41141..e9edb6c5b1 100644 --- a/packages/types/src/socket.ts +++ b/packages/types/src/socket.ts @@ -2,22 +2,26 @@ * Backend API event types. Currently, these are divided into two * groups: pure events and actions. Pure events are emitted from the * backend to notify the frontend of something and are generally named - * with the past tense (e.g. COMMUNITY_CREATED), while actions are - * emitted from the frontend in order to invoke the backend to do - * something on it's behalf and are generally named as a command (e.g. - * CREATE_COMMUNITY). + * with the past tense (e.g. COMMUNITY_LAUNCHED) or as a noun (e.g. + * CONNECTION_PROCESS_INFO), while actions are emitted from the + * frontend in order to invoke the backend to do something on it's + * behalf and are generally named as a command (e.g. + * CREATE_COMMUNITY). Events generally don't expect a response, while + * actions tend to have a callback for returning data (using Socket.IO + * acknowledgements feature to reduce the amount of events like + * EVENT_REQUEST/EVENT_RESPONSE). + * + * NOTE: I've been adding docstrings to document the events here. */ export enum SocketActionTypes { // ====== Community ====== - COMMUNITY_CREATED = 'communityCreated', COMMUNITY_LAUNCHED = 'communityLaunched', - COMMUNITY_METADATA_STORED = 'communityMetadataStored', + COMMUNITY_UPDATED = 'communityUpdated', CREATE_COMMUNITY = 'createCommunity', + DOWNLOAD_INVITE_DATA = 'downloadInviteData', LAUNCH_COMMUNITY = 'launchCommunity', LEAVE_COMMUNITY = 'leaveCommunity', - SET_COMMUNITY_CA_DATA = 'setCommunityCaData', - SET_COMMUNITY_METADATA = 'setCommunityMetadata', // ====== Channels ====== @@ -55,9 +59,7 @@ export enum SocketActionTypes { ADD_CSR = 'addCsr', CERTIFICATES_STORED = 'certificatesStored', CSRS_STORED = 'csrsStored', - OWNER_CERTIFICATE_ISSUED = 'ownerCertificateIssued', REGISTER_USER_CERTIFICATE = 'registerUserCertificate', - REGISTER_OWNER_CERTIFICATE = 'registerOwnerCertificate', // ====== Network ====== @@ -67,14 +69,23 @@ export enum SocketActionTypes { CONNECTION_PROCESS_INFO = 'connectionProcess', CREATE_NETWORK = 'createNetwork', LIBP2P_PSK_STORED = 'libp2pPskStored', - NETWORK_CREATED = 'networkCreated', PEER_CONNECTED = 'peerConnected', PEER_DISCONNECTED = 'peerDisconnected', - PEER_LIST = 'peerList', TOR_INITIALIZED = 'torInitialized', // ====== Misc ====== + /** + * For moving data from the frontend to the backend. Load migration + * data into the backend. + */ + LOAD_MIGRATION_DATA = 'loadMigrationData', + /** + * For moving data from the frontend to the backend. The backend may + * require frontend data for migrations when loading an existing + * community from storage. + */ + MIGRATION_DATA_REQUIRED = 'migrationDataRequired', PUSH_NOTIFICATION = 'pushNotification', ERROR = 'error', } diff --git a/packages/desktop/src/renderer/testUtils/socket.ts b/packages/types/src/test.ts similarity index 100% rename from packages/desktop/src/renderer/testUtils/socket.ts rename to packages/types/src/test.ts diff --git a/packages/types/src/user.ts b/packages/types/src/user.ts index 49aa963171..f7a3135624 100644 --- a/packages/types/src/user.ts +++ b/packages/types/src/user.ts @@ -2,7 +2,6 @@ export interface UserData { username: string onionAddress: string peerId: string - dmPublicKey: string } export interface User extends UserData {