diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 000000000..843c2f773 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,68 @@ +# If setting a specific version, wrap it with single quotes like '12.0' +# to pass it as string because GitHub trimmes trailing .0 from numbers +# due to https://github.com/actions/runner/issues/849 + +name: build-and-ship-android +on: + push: + branches: + - 'main' +jobs: + build-and-ship-android: + runs-on: ubuntu-latest + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/apps/skolplattformen-app-new/Gemfile + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + # changed this from GITHUB_PERSONAL_ACCESS_TOKEN_PATH to GITHUB_TOKEN + token: ${{ secrets.GITHUB_TOKEN }} + submodules: true + - name: Set up our JDK environment + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: 11 + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2.2' + bundler-cache: true + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: '18.13' + cache: 'npm' + cache-dependency-path: ${{ github.workspace }}/apps/skolplattformen-app-new/package-lock.json + - name: set npm version + run: npm install -g npm@9.6.0 && echo "secrets.GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} secrets.GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} workspace= ${{ github.workspace }} secrets.MAPS_API_KEY=${{secrets.MAPS_API_KEY}}" + - run: cd apps/skolplattformen-app-new/android && bundle install + - name: install node modules + run: cd apps/skolplattformen-app-new && npm ci + - name: Setup local.properties + run: echo "MAPS_API_KEY=${{ env.MAPS_API_KEY }}" > ${{ github.workspace }}/apps/skolplattformen-app-new/android/local.properties + env: + MAPS_API_KEY: ${{ secrets.MAPS_API_KEY }} + - name: Setup key.json + run: echo "${KEY_JSON}" > ${{ github.workspace }}/apps/skolplattformen-app-new/android/key.json + env: + KEY_JSON: ${{ secrets.KEY_JSON }} + - run: cd apps/skolplattformen-app-new/android && bundle exec fastlane android beta + env: + SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} + ALIAS_KEY_PASSWORD: ${{ secrets.ALIAS_KEY_PASSWORD }} + - name: 'Store artifact native_debug_symbols.zip' + uses: actions/upload-artifact@v3 + if: ${{ failure() }} + with: + name: native_debug_symbols.zip + path: ${{ github.workspace }}/apps/skolplattformen-app-new/android/native_debug_symbols.zip + retention-days: 5 + - name: 'Store build mappings for difficult crashlytics traces' + uses: actions/upload-artifact@v3 + if: ${{ success() }} + with: + name: mapping.txt + path: ${{ github.workspace }}/apps/skolplattformen-app-new/android/app/build/outputs/mapping/release/mapping.txt + retention-days: 500 diff --git a/.github/workflows/build-ios.yaml b/.github/workflows/build-ios.yaml new file mode 100644 index 000000000..fb198b2aa --- /dev/null +++ b/.github/workflows/build-ios.yaml @@ -0,0 +1,51 @@ +# If setting a specific version, wrap it with single quotes like '12.0' +# to pass it as string because GitHub trimmes trailing .0 from numbers +# due to https://github.com/actions/runner/issues/849 + +name: build-and-ship-ios +on: + push: + branches: + - 'main' +jobs: + build-and-ship-ios: + runs-on: macos-13 + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/apps/skolplattformen-app-new/Gemfile + steps: + - uses: actions/checkout@v3 + with: + # changed this from GITHUB_PERSONAL_ACCESS_TOKEN_PATH to GITHUB_TOKEN + token: ${{ secrets.GITHUB_TOKEN }} + submodules: true + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '14.3.1' + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2.2' + bundler-cache: true + - uses: actions/setup-node@v3 + with: + node-version: '18.13' + cache: 'npm' + cache-dependency-path: ${{ github.workspace }}/apps/skolplattformen-app-new/package-lock.json + - uses: actions/cache@v3 + with: + path: ${{ github.workspace }}/apps/skolplattformen-app-new/ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + - name: set npm version + run: npm install -g npm@9.6.0 + - name: install node modules + run: cd apps/skolplattformen-app-new && npm ci + - run: cd apps/skolplattformen-app-new/ios && bundle install + - run: cd apps/skolplattformen-app-new/ios && npx pod-install + - run: cd apps/skolplattformen-app-new/ios && bundle exec pod update hermes-engine --no-repo-update + - run: cd apps/skolplattformen-app-new/ios && export && bundle exec fastlane ios beta version:patch + env: + ASCAPI_KEY_CONTENT: ${{ secrets.ASCAPI_KEY_CONTENT }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} + ENVFILE: ${{env.ENVFILE}} diff --git a/.github/workflows/pr_check_new.yml b/.github/workflows/pr_check_new.yml new file mode 100644 index 000000000..b47f75597 --- /dev/null +++ b/.github/workflows/pr_check_new.yml @@ -0,0 +1,39 @@ +name: Run tests on PR - new + +on: + pull_request: + branches: + - main +jobs: + test: + name: Run tests + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: '18.17.0' + + - name: Setup timezone + uses: zcong1993/setup-timezone@master + with: + timezone: Europe/Stockholm + + - name: set npm version + run: npm install -g npm@10.2.0 + + - name: install node modules + run: cd apps/skolplattformen-app-new && npm ci + + - name: Run tests + run: cd apps/skolplattformen-app-new && npm test + env: + CI: true + + - name: Check linting + run: cd apps/skolplattformen-app-new && npm run lint + env: + CI: true diff --git a/README.md b/README.md index 5c912442b..41b760c69 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ The respective README files there contain more detailed descriptions. * [Architecture](#architecture) * [Apps](#apps) * [skolplattformen](#skolplattformen) + * [skolplattformen dependency upgrade](#skolplattformen-dependency-upgrade) * [website](#website) * [Libs](#embedded-api) * [api](#api) @@ -58,6 +59,9 @@ We're starting small, with more features being added over time. For more information, check out the [source code](apps/skolplattformen-app). +#### skolplattformen dependency upgrade +A dependency upgrade is currently in the works. To navigate directly to the related readme, click [here](/apps/skolplattformen-app-new/README-NEW.md). + #### website The code for the website at https://skolplattformen.org/. It's built using Next.js. diff --git a/apps/skolplattformen-app-new/.bundle/config b/apps/skolplattformen-app-new/.bundle/config new file mode 100644 index 000000000..848943bb5 --- /dev/null +++ b/apps/skolplattformen-app-new/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/apps/skolplattformen-app-new/.eslintrc.js b/apps/skolplattformen-app-new/.eslintrc.js new file mode 100644 index 000000000..072d93140 --- /dev/null +++ b/apps/skolplattformen-app-new/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: '@react-native', + rules: { + semi: ['warn', 'never'], + }, +} diff --git a/apps/skolplattformen-app-new/.gitignore b/apps/skolplattformen-app-new/.gitignore new file mode 100644 index 000000000..fba6c953a --- /dev/null +++ b/apps/skolplattformen-app-new/.gitignore @@ -0,0 +1,71 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +ios/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +!debug.keystore +release/ + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +/ios/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage + + +libraries.json + +keys.json \ No newline at end of file diff --git a/apps/skolplattformen-app-new/.prettierrc b/apps/skolplattformen-app-new/.prettierrc new file mode 100644 index 000000000..623163be0 --- /dev/null +++ b/apps/skolplattformen-app-new/.prettierrc @@ -0,0 +1,10 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": false, + "singleQuote": true, + "trailingComma": "es5", + "bracketSpacing": true, + "bracketSameLine": false +} diff --git a/apps/skolplattformen-app-new/.watchmanconfig b/apps/skolplattformen-app-new/.watchmanconfig new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/apps/skolplattformen-app-new/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/apps/skolplattformen-app-new/App.tsx b/apps/skolplattformen-app-new/App.tsx new file mode 100644 index 000000000..80500a950 --- /dev/null +++ b/apps/skolplattformen-app-new/App.tsx @@ -0,0 +1,111 @@ +import * as eva from '@eva-design/eva' +import AsyncStorage from '@react-native-async-storage/async-storage' +import { ApiProvider, Reporter } from './libs/hooks/src' +import { ApplicationProvider, IconRegistry, Text } from '@ui-kitten/components' +import { EvaIconsPack } from '@ui-kitten/eva-icons' +import React from 'react' +import { StatusBar, useColorScheme, View } from 'react-native' +import { SafeAreaProvider } from 'react-native-safe-area-context' +import { AppNavigator } from './components/navigation.component' +import { FeatureProvider } from './context/feature/featureContext' +import { LanguageProvider } from './context/language/languageContext' +import { SchoolPlatformProvider } from './context/schoolPlatform/schoolPlatformContext' +import { schoolPlatforms } from './data/schoolPlatforms' +import { default as customMapping } from './design/mapping.json' +import { darkTheme, lightTheme } from './design/themes' +import useSettingsStorage from './hooks/useSettingsStorage' +import { translations } from './utils/translation' +import { GestureHandlerRootView } from 'react-native-gesture-handler' + +const reporter: Reporter | undefined = __DEV__ + ? { + log: (message: string) => console.log(message), + error: (error: Error, label?: string) => console.log(label, error), + } + : undefined + +if (__DEV__) { + const DevMenu = require('react-native-dev-menu') + DevMenu.addItem('Clear AsyncStorage from all contents', () => + AsyncStorage.clear().then(() => logAsyncStorage()) + ) + DevMenu.addItem('Log AsyncStorage contents', () => logAsyncStorage()) +} + +const safeJsonParse = (maybeJson: string) => { + if (maybeJson) { + try { + return JSON.parse(maybeJson) + } catch (error) { + return maybeJson + } + } + return 'null' +} + +const logAsyncStorage = async () => { + const allKeys = await AsyncStorage.getAllKeys() + const keysAndValues = await AsyncStorage.multiGet(allKeys) + console.log('*** AsyncStorage contents:') + keysAndValues.forEach((keyAndValue) => { + console.log( + keyAndValue[0], + '=>', + keyAndValue[1] ? safeJsonParse(keyAndValue[1]) : 'null' + ) + }) + console.log('***') +} + +export default () => { + const [usingSystemTheme] = useSettingsStorage('usingSystemTheme') + const [currentSchoolPlatform] = useSettingsStorage('currentSchoolPlatform') + const [theme] = useSettingsStorage('theme') + const systemTheme = useColorScheme() + const colorScheme = usingSystemTheme ? systemTheme : theme + + const platform = schoolPlatforms.find((pf) => pf.id === currentSchoolPlatform) + + if (!platform) { + return ( + + ERROR + + ) + } + + return ( + + + + + + + + + + + + + + + + + + ) +} diff --git a/apps/skolplattformen-app-new/Gemfile b/apps/skolplattformen-app-new/Gemfile new file mode 100644 index 000000000..c8af24aad --- /dev/null +++ b/apps/skolplattformen-app-new/Gemfile @@ -0,0 +1,9 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 3.2.2" + +gem 'bundler' +gem 'cocoapods', '~> 1.12' +gem 'fastlane' +gem 'dotenv' diff --git a/apps/skolplattformen-app-new/Gemfile.lock b/apps/skolplattformen-app-new/Gemfile.lock new file mode 100644 index 000000000..6df4a8c18 --- /dev/null +++ b/apps/skolplattformen-app-new/Gemfile.lock @@ -0,0 +1,297 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.6) + rexml + activesupport (7.1.1) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + addressable (2.8.5) + public_suffix (>= 2.0.2, < 6.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + artifactory (3.0.15) + atomos (0.1.3) + aws-eventstream (1.2.0) + aws-partitions (1.841.0) + aws-sdk-core (3.185.1) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.72.0) + aws-sdk-core (~> 3, >= 3.184.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.136.0) + aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.6) + aws-sigv4 (1.6.0) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + base64 (0.1.1) + bigdecimal (3.1.4) + claide (1.1.0) + cocoapods (1.13.0) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.13.0) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 1.6.0, < 2.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.23.0, < 2.0) + cocoapods-core (1.13.0) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (1.6.3) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + concurrent-ruby (1.2.2) + connection_pool (2.4.1) + declarative (0.0.20) + digest-crc (0.6.5) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.8.1) + drb (2.1.1) + ruby2_keywords + emoji_regex (3.2.3) + escape (0.0.4) + ethon (0.16.0) + ffi (>= 1.15.0) + excon (0.104.0) + faraday (1.10.3) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) + fastimage (2.2.7) + fastlane (2.216.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + http-cookie (~> 1.0.5) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (>= 2.0.0, < 3.0.0) + naturally (~> 2.2) + optparse (~> 0.1.1) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (~> 3) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + ffi (1.16.3) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.51.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.1) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.19.0) + google-apis-core (>= 0.9.0, < 2.a) + google-cloud-core (1.6.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.44.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.19.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.8.1) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.5) + domain_name (~> 0.5) + httpclient (2.8.3) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + jmespath (1.6.2) + json (2.6.3) + jwt (2.7.1) + mini_magick (4.12.0) + mini_mime (1.1.5) + minitest (5.20.0) + molinillo (0.8.0) + multi_json (1.15.0) + multipart-post (2.3.0) + mutex_m (0.1.2) + nanaimo (0.3.0) + nap (1.1.0) + naturally (2.2.1) + netrc (0.11.0) + optparse (0.1.1) + os (1.1.4) + plist (3.7.0) + public_suffix (4.0.7) + rake (13.0.6) + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.2.6) + rouge (2.0.7) + ruby-macho (2.5.1) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + security (0.1.3) + signet (0.18.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.10) + CFPropertyList + naturally + terminal-notifier (2.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.1) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + typhoeus (1.4.0) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + unicode-display_width (2.5.0) + webrick (1.8.1) + word_wrap (1.0.0) + xcodeproj (1.23.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (~> 3.2.4) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + bundler + cocoapods (~> 1.12) + dotenv + fastlane + +RUBY VERSION + ruby 3.2.2p53 + +BUNDLED WITH + 2.4.21 diff --git a/apps/skolplattformen-app-new/README-NEW.md b/apps/skolplattformen-app-new/README-NEW.md new file mode 100644 index 000000000..3373ca77a --- /dev/null +++ b/apps/skolplattformen-app-new/README-NEW.md @@ -0,0 +1,102 @@ +# Skolplattformen React Native Project + +Welcome to this new [**React Native**](https://reactnative.dev) project, initiated using [`@react-native-community/cli`](https://github.com/react-native-community/cli). + +## Pre-requisites + +> **Important**: Make sure you have gone through the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) guide up to the "Creating a new application" step before moving forward. + +## Initial Setup + +### Required Software + +1. [Git](https://git-scm.com/) +2. [Node](https://nodejs.org/en/) +3. [NPM](https://docs.npmjs.com/cli/v8/commands/npm-install) + +### Minimum Node Version +Ensure you are using Node version 16 or higher. + +### Cloning the Repository + +```bash +git clone https://github.com/Home-Biz-LLS/skolplattformen-react-native +``` + +### Installing Dependencies + +```bash +cd apps/skolplattformen-app-new/ && npm i +``` + +--- + +## Running the App + +### For iOS + +**Note**: Running the iOS app requires a Mac with native support. Windows/Linux are currently not supported. + +#### Essential Guides and Tools + +* [Mac OS Setup Guide](https://reactnative.dev/docs/environment-setup) + +#### Step-by-Step Instructions + +1. **Install Xcode**: Ensure Xcode is installed on your system. + +2. **Install CocoaPods**: If not already installed, you can do this easily using Homebrew. + - [Homebrew Install Guide for CocoaPods](https://formulae.brew.sh/formula/cocoapods) + - [Official CocoaPods Guide](https://guides.cocoapods.org/using/getting-started.html) + +3. **Install Pods** + ```bash + cd apps/skolplattformen-app-new/ios && pod install + ``` + +#### Running the iOS App + + +* Option 1: Using Metro Bundler + + ![metro bundler example](/apps/skolplattformen-app-new/docs/assets/MetroBundlerExample.png) + ```bash + cd apps/skolplattformen-app-new && npm run start + ``` + then type + ```bash + i + ``` + +* Option 2: Running Directly + ```bash + npm run ios + ``` + +--- + +### For Android + +**Note**: Choose an appropriate guide based on your operating system: + +* [Mac OS](/apps/skolplattformen-app-new/docs/android_mac.md) +* [Windows](/apps/skolplattformen-app-new//docs/android_windows.md) +* [Linux](/apps/skolplattformen-app-new//docs/android_linux.md) + +#### Running the Android App + +* Option 1: Using Metro Bundler + + ![metro bundler example](/apps/skolplattformen-app-new/docs/assets/MetroBundlerExample.png) + ```bash + cd apps/skolplattformen-app-new && npm run start + ``` + then type + ```bash + a + ``` + +* Option 2: Running Directly + ```bash + npm run android + ``` \ No newline at end of file diff --git a/apps/skolplattformen-app-new/README.md b/apps/skolplattformen-app-new/README.md new file mode 100644 index 000000000..f22bc1fc4 --- /dev/null +++ b/apps/skolplattformen-app-new/README.md @@ -0,0 +1,84 @@ +This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). + +# Getting Started + +>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. + +## Getting started with Development + +### Please use node version 16 or higher + +To clone and build the project, you first need to install [git](https://git-scm.com/), [node](https://nodejs.org/en/) and [npm](https://docs.npmjs.com/cli/v8/commands/npm-install). + +Clone the repo with +```bash +$ git clone https://github.com/Home-Biz-LLS/skolplattformen-react-native +``` + +Install dependencies +```bash +cd apps/skolplattformen-app-new/ && npm i +``` + +### iOS + +If you wanna run the iOS app, you need to setup a couple of things first, we have a guide that will assist you in getting started with the iOS app. A Mac is required to build projects with native code for iOS so we do not have support for Linux / Windows. + +* [Mac OS](https://reactnative.dev/docs/environment-setup) + +#### Step 1 +Make sure you have **Xcode** installed + + +#### Step 2 +Make sure **CocoaPods** is installed (you can do it easily with homebrew) + +* [CocoaPods homebrew](https://formulae.brew.sh/formula/cocoapods) +* [CocoaPods](https://guides.cocoapods.org/using/getting-started.html) + + +#### Step 3 +```bash +cd apps/skolplattformen-app-new/ios && pod install +``` + +If you already setup everything, go into the + +"skolplattformen-app-new" directory + +Start the metro + +``` +npm run start +``` + +then + +``` +i +``` +to Start iOS app + +OR + +Start the iOS app directly +``` +npm run ios +``` + + + +### Android + +If you wanna run the Android app, you need to setup a couple of things first, we have created three different guides depending on your operating system. + +* [Mac OS](/docs/android_mac.md) +* [Windows](/docs/android_windows.md) +* [Linux](/docs/android_linux.md) + +If you already setup everything, you just need to run the following command in the project root: + +``` +yarn run android +``` + diff --git a/apps/skolplattformen-app-new/__mocks__/@react-native-async-storage/async-storage.js b/apps/skolplattformen-app-new/__mocks__/@react-native-async-storage/async-storage.js new file mode 100644 index 000000000..d78ea9256 --- /dev/null +++ b/apps/skolplattformen-app-new/__mocks__/@react-native-async-storage/async-storage.js @@ -0,0 +1,4 @@ +export { + default, + useAsyncStorage, +} from '@react-native-async-storage/async-storage/jest/async-storage-mock' diff --git a/apps/skolplattformen-app-new/__mocks__/@react-native-cookies/cookies.ts b/apps/skolplattformen-app-new/__mocks__/@react-native-cookies/cookies.ts new file mode 100644 index 000000000..7ce777bc7 --- /dev/null +++ b/apps/skolplattformen-app-new/__mocks__/@react-native-cookies/cookies.ts @@ -0,0 +1,81 @@ +import { CookieJar, Cookie as TCookie } from 'tough-cookie' + +export interface Cookie { + name: string + value: string + path?: string + domain?: string + version?: string + expires?: string + secure?: boolean + httpOnly?: boolean +} + +export interface Cookies { + [key: string]: Cookie +} + +export interface CookieManagerStatic { + set(url: string, cookie: Cookie, useWebKit?: boolean): Promise + setFromResponse(url: string, cookie: string): Promise + + get(url: string, useWebKit?: boolean): Promise + + clearAll(useWebKit?: boolean): Promise +} + +const convertTtoC = (cookie: string | TCookie): Cookie => { + if (typeof cookie === 'string') { + return convertTtoC(TCookie.parse(cookie) as TCookie) + } + return { + name: cookie.key, + value: cookie.value, + domain: cookie.domain || undefined, + expires: + cookie.expires === 'Infinity' ? undefined : cookie.expires.toUTCString(), + httpOnly: cookie.httpOnly || undefined, + path: cookie.path || undefined, + secure: cookie.secure, + } +} +const convertCtoT = (cookie: Cookie): TCookie => + new TCookie({ + key: cookie.name, + value: cookie.value, + domain: cookie.domain, + expires: cookie.expires ? new Date(cookie.expires) : undefined, + httpOnly: cookie.httpOnly || false, + path: cookie.path, + secure: cookie.secure || false, + }) +const convertCookies = (cookies: TCookie[]): Cookies => + cookies.reduce( + (map, cookie) => ({ + ...map, + [cookie.key]: convertTtoC(cookie), + }), + {} as Cookies + ) + +const jar = new CookieJar() +const CookieManager: CookieManagerStatic = { + clearAll: async () => { + await jar.removeAllCookies() + return true + }, + get: async (url) => { + const cookies = await jar.getCookies(url) + return convertCookies(cookies) + }, + set: async (url, cookie) => { + await jar.setCookie(convertCtoT(cookie), url) + return true + }, + setFromResponse: async (url, cookie) => { + await jar.setCookie(cookie, url) + return true + }, +} + +export default CookieManager diff --git a/apps/skolplattformen-app-new/__mocks__/react-native-localize.js b/apps/skolplattformen-app-new/__mocks__/react-native-localize.js new file mode 100644 index 000000000..aa1535691 --- /dev/null +++ b/apps/skolplattformen-app-new/__mocks__/react-native-localize.js @@ -0,0 +1,40 @@ +const getLocales = () => [ + { countryCode: 'EN', languageTag: 'en-US', languageCode: 'en', isRTL: false }, + { countryCode: 'SE', languageTag: 'sv-SE', languageCode: 'sv', isRTL: false }, +] + +const findBestAvailableLanguage = jest.fn(() => ({ + languageTag: 'sv', + isRTL: false, +})) + +const getNumberFormatSettings = () => ({ + decimalSeparator: '.', + groupingSeparator: ',', +}) + +const getCalendar = () => 'gregorian' +const getCountry = () => 'SE' +const getCurrencies = () => ['USD', 'SEK'] +const getTemperatureUnit = () => 'celsius' +const getTimeZone = () => 'Europe/Stockholm' +const uses24HourClock = () => true +const usesMetricSystem = () => true + +const addEventListener = jest.fn() +const removeEventListener = jest.fn() + +export { + findBestAvailableLanguage, + getLocales, + getNumberFormatSettings, + getCalendar, + getCountry, + getCurrencies, + getTemperatureUnit, + getTimeZone, + uses24HourClock, + usesMetricSystem, + addEventListener, + removeEventListener, +} diff --git a/apps/skolplattformen-app-new/__mocks__/react-native-safe-area-context.js b/apps/skolplattformen-app-new/__mocks__/react-native-safe-area-context.js new file mode 100644 index 000000000..d75b1ff61 --- /dev/null +++ b/apps/skolplattformen-app-new/__mocks__/react-native-safe-area-context.js @@ -0,0 +1,20 @@ +// __mocks__/react-native-safe-area-context.js +import React from 'react' +import { View } from 'react-native' + +const inset = { + top: 0, + right: 0, + bottom: 0, + left: 0, +} + +export const SafeAreaProvider = ({ children }) => children + +export const SafeAreaConsumer = ({ children }) => children(inset) + +export const SafeAreaView = ({ children }) => ( + {children} +) + +export const useSafeAreaInsets = () => inset diff --git a/apps/skolplattformen-app-new/android/app/build.gradle b/apps/skolplattformen-app-new/android/app/build.gradle new file mode 100644 index 000000000..9ea1a1fc7 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/build.gradle @@ -0,0 +1,129 @@ +apply plugin: "com.android.application" +apply plugin: "com.facebook.react" + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + // root = file("../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + // reactNativeDir = file("../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js + // cliFile = file("../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] +} + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'org.webkit:android-jsc:+' + +android { + ndkVersion rootProject.ext.ndkVersion + + compileSdkVersion rootProject.ext.compileSdkVersion + + namespace "com.oppna_skolplattformen_new.app" + defaultConfig { + applicationId "com.oppna_skolplattformen_new.app" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 4 + versionName "1.0" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + release { + storeFile file('release.jks') + storePassword 'leeandseb' + keyAlias 'upload' + keyPassword 'leeandseb' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.release + minifyEnabled true + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + + debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") + debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { + exclude group:'com.squareup.okhttp3', module:'okhttp' + } + + debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} + +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/apps/skolplattformen-app-new/android/app/debug.keystore b/apps/skolplattformen-app-new/android/app/debug.keystore new file mode 100644 index 000000000..364e105ed Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/debug.keystore differ diff --git a/apps/skolplattformen-app-new/android/app/proguard-rules.pro b/apps/skolplattformen-app-new/android/app/proguard-rules.pro new file mode 100644 index 000000000..11b025724 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/proguard-rules.pro @@ -0,0 +1,10 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: diff --git a/apps/skolplattformen-app-new/android/app/release.jks b/apps/skolplattformen-app-new/android/app/release.jks new file mode 100644 index 000000000..59a8aef2a Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/release.jks differ diff --git a/apps/skolplattformen-app-new/android/app/release.keystore b/apps/skolplattformen-app-new/android/app/release.keystore new file mode 100644 index 000000000..3f0a4ced3 Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/release.keystore differ diff --git a/apps/skolplattformen-app-new/android/app/src/debug/AndroidManifest.xml b/apps/skolplattformen-app-new/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..4b185bc15 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/apps/skolplattformen-app-new/android/app/src/debug/java/com/app/ReactNativeFlipper.java b/apps/skolplattformen-app-new/android/app/src/debug/java/com/app/ReactNativeFlipper.java new file mode 100644 index 000000000..9d6fd9205 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/debug/java/com/app/ReactNativeFlipper.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + */ +package com.oppna_skolplattformen_new.app; + +import android.content.Context; +import com.facebook.flipper.android.AndroidFlipperClient; +import com.facebook.flipper.android.utils.FlipperUtils; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; +import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; +import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; +import com.facebook.flipper.plugins.inspector.DescriptorMapping; +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; +import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; +import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; +import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; +import com.facebook.react.ReactInstanceEventListener; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.modules.network.NetworkingModule; +import okhttp3.OkHttpClient; + +/** + * Class responsible of loading Flipper inside your React Native application. This is the debug + * flavor of it. Here you can add your own plugins and customize the Flipper setup. + */ +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + if (FlipperUtils.shouldEnableFlipper(context)) { + final FlipperClient client = AndroidFlipperClient.getInstance(context); + + client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); + client.addPlugin(new DatabasesFlipperPlugin(context)); + client.addPlugin(new SharedPreferencesFlipperPlugin(context)); + client.addPlugin(CrashReporterPlugin.getInstance()); + + NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); + NetworkingModule.setCustomClientBuilder( + new NetworkingModule.CustomClientBuilder() { + @Override + public void apply(OkHttpClient.Builder builder) { + builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); + } + }); + client.addPlugin(networkFlipperPlugin); + client.start(); + + // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized + // Hence we run if after all native modules have been initialized + ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); + if (reactContext == null) { + reactInstanceManager.addReactInstanceEventListener( + new ReactInstanceEventListener() { + @Override + public void onReactContextInitialized(ReactContext reactContext) { + reactInstanceManager.removeReactInstanceEventListener(this); + reactContext.runOnNativeModulesQueueThread( + new Runnable() { + @Override + public void run() { + client.addPlugin(new FrescoFlipperPlugin()); + } + }); + } + }); + } else { + client.addPlugin(new FrescoFlipperPlugin()); + } + } + } +} diff --git a/apps/skolplattformen-app-new/android/app/src/main/AndroidManifest.xml b/apps/skolplattformen-app-new/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..8af2453d5 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + diff --git a/apps/skolplattformen-app-new/android/app/src/main/java/com/app/MainActivity.java b/apps/skolplattformen-app-new/android/app/src/main/java/com/app/MainActivity.java new file mode 100644 index 000000000..09b8ffcc2 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/java/com/app/MainActivity.java @@ -0,0 +1,32 @@ +package com.oppna_skolplattformen_new.app; + +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactActivityDelegate; + +public class MainActivity extends ReactActivity { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "app"; + } + + /** + * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link + * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React + * (aka React 18) with two boolean flags. + */ + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new DefaultReactActivityDelegate( + this, + getMainComponentName(), + // If you opted-in for the New Architecture, we enable the Fabric Renderer. + DefaultNewArchitectureEntryPoint.getFabricEnabled()); + } +} diff --git a/apps/skolplattformen-app-new/android/app/src/main/java/com/app/MainApplication.java b/apps/skolplattformen-app-new/android/app/src/main/java/com/app/MainApplication.java new file mode 100644 index 000000000..d15b08363 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/java/com/app/MainApplication.java @@ -0,0 +1,62 @@ +package com.oppna_skolplattformen_new.app; + +import android.app.Application; +import com.facebook.react.PackageList; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactNativeHost; +import com.facebook.soloader.SoLoader; +import java.util.List; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = + new DefaultReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @Override + protected boolean isNewArchEnabled() { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + + @Override + protected Boolean isHermesEnabled() { + return BuildConfig.IS_HERMES_ENABLED; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + DefaultNewArchitectureEntryPoint.load(); + } + ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } +} diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/drawable/rn_edit_text_material.xml b/apps/skolplattformen-app-new/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 000000000..73b37e4d9 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..036d09bc5 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..86b42de1b Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..3aeffa06e Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..5ff72be1a Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..03734664d Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..833c039ae Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..b7e9942e2 Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..ac3d3c450 Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..514d5c45b Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..262960fa0 Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..0f9612b59 Binary files /dev/null and b/apps/skolplattformen-app-new/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/values/ic_launcher_background.xml b/apps/skolplattformen-app-new/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 000000000..c5d5899fd --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/values/strings.xml b/apps/skolplattformen-app-new/android/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..6614fac3a --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Öppna Skolplattformen NEW + diff --git a/apps/skolplattformen-app-new/android/app/src/main/res/values/styles.xml b/apps/skolplattformen-app-new/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..955d15716 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/main/res/values/styles.xml @@ -0,0 +1,7 @@ + + + + diff --git a/apps/skolplattformen-app-new/android/app/src/release/java/com/app/ReactNativeFlipper.java b/apps/skolplattformen-app-new/android/app/src/release/java/com/app/ReactNativeFlipper.java new file mode 100644 index 000000000..7cdbff353 --- /dev/null +++ b/apps/skolplattformen-app-new/android/app/src/release/java/com/app/ReactNativeFlipper.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + */ +package com.oppna_skolplattformen_new.app; + +import android.content.Context; +import com.facebook.react.ReactInstanceManager; + +/** + * Class responsible of loading Flipper inside your React Native application. This is the release + * flavor of it so it's empty as we don't want to load Flipper. + */ +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + // Do nothing as we don't want to initialize Flipper on Release. + } +} diff --git a/apps/skolplattformen-app-new/android/build.gradle b/apps/skolplattformen-app-new/android/build.gradle new file mode 100644 index 000000000..34ea71819 --- /dev/null +++ b/apps/skolplattformen-app-new/android/build.gradle @@ -0,0 +1,21 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext { + buildToolsVersion = "33.0.0" + minSdkVersion = 21 + compileSdkVersion = 33 + targetSdkVersion = 33 + + // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. + ndkVersion = "23.1.7779620" + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") + } +} diff --git a/apps/skolplattformen-app-new/android/fastlane/Appfile b/apps/skolplattformen-app-new/android/fastlane/Appfile new file mode 100644 index 000000000..e99ae0f01 --- /dev/null +++ b/apps/skolplattformen-app-new/android/fastlane/Appfile @@ -0,0 +1,2 @@ +json_key_file("key.json") +package_name("com.oppna_skolplattformen_new.app") diff --git a/apps/skolplattformen-app-new/android/fastlane/Fastfile b/apps/skolplattformen-app-new/android/fastlane/Fastfile new file mode 100755 index 000000000..4c3df2a17 --- /dev/null +++ b/apps/skolplattformen-app-new/android/fastlane/Fastfile @@ -0,0 +1,109 @@ +# Filename: android/fastlane/Fastfile + +default_platform(:android) + +platform :android do + desc "Runs all the tests" + lane :test do + gradle(task: "test") + end + + desc "Submit a new Beta Build to Play Store" + lane :beta do |options| + + store_password = ENV['SIGNING_STORE_PASSWORD'] || prompt(text: "Signing Store Password: ", secure_text: true) + key_password = ENV['ALIAS_KEY_PASSWORD'] || prompt(text: "Alias Key Password: ", secure_text: true) + + # Fetch version_code from play store and bump it. Annoyingly, we always need + # to increment it, even if our version name changes. + internalVersionCode = google_play_track_version_codes(track: 'internal').max + ENV['VERSION_CODE'] = (internalVersionCode + 1).to_s + + versionNameOverride = nil + # versionNameOverride = "1.9.0" + if versionNameOverride.nil? + releaseNameSemVerArr = google_play_track_release_names(track: 'internal').max.split('.') + releaseNameSemVerArr[2] = (releaseNameSemVerArr.last.to_i + 1).to_s + ENV['VERSION_NAME'] = releaseNameSemVerArr.join('.') + ENV['GITTAGNAME'] = ENV['VERSION_NAME'].gsub(/\s+/, '').match(/\((.*?)\)/)[1] + '.' + ENV['VERSION_CODE'] + ENV['SUPPLY_VERSION_NAME'] = ENV['VERSION_NAME'] + versionFile = File.join(Dir.pwd, '..', 'version', 'version.properties').to_s + commandargs = "-n \"VERSION=#{ENV['VERSION_NAME']}\" > #{versionFile}".to_s + puts "echo #{commandargs}" + system("echo", commandargs) + else + ENV['VERSION_NAME'] = versionNameOverride + end + puts "Compiling #{ENV['VERSION_NAME']} (#{ENV['VERSION_CODE']}) " + + # Dir.pwd when running through Fastlane is app/android/fastlane + releaseFilePath = File.join(Dir.pwd, '..', 'app', "release.jks") + mappingFilePath = File.join( + Dir.pwd, + "..", + "app", + "build", + "outputs", + "mapping", + "release", + "mapping.txt" + ) + puts "Hello there - #{ENV['VERSION_CODE']}" + + gradle(task: 'clean') + gradle( + task: 'bundle', + build_type: 'Release', + print_command: false, + properties: { + "android.injected.signing.store.file" => releaseFilePath, + "android.injected.signing.store.password" => store_password, + "android.injected.signing.key.alias" => "upload", + "android.injected.signing.key.password" => key_password, + "android.injected.version.code" => ENV['VERSION_CODE'], + "android.injected.version.name" => ENV['VERSION_NAME'], + } + ) + + symbolsFilePath = File.join( + Dir.pwd, + "..", + "native_debug_symbols.zip" + ) + symbolsFolderPath = File.join( + Dir.pwd, + "..", + "app", + "build", + "intermediates", + "merged_native_libs", + "release", + "out", + "lib" + ) + system("cd #{symbolsFolderPath} && zip -r #{symbolsFilePath} .") + upload_to_play_store( + track: 'internal', + release_status: 'draft', + version_code: ENV['VERSION_CODE'], + version_name: ENV['VERSION_NAME'], + version_codes_to_retain: [], + mapping_paths: [mappingFilePath, symbolsFilePath] + ) + + system('git config user.email "leesheppard2404@gmail.com"') + system('git config user.name "Github Actions Android Pipeline"') + + + add_git_tag( + grouping: "builds", + includes_lane: true, + # prefix: "v#{ENV['VERSION_NAME']}-", + # build_number: ENV['VERSION_CODE'], + tag: "v#{ENV['GITTAGNAME']}" + ) + push_to_git_remote( + tags: true + ) + end +end \ No newline at end of file diff --git a/apps/skolplattformen-app-new/android/gradle.properties b/apps/skolplattformen-app-new/android/gradle.properties new file mode 100644 index 000000000..a3b2fa124 --- /dev/null +++ b/apps/skolplattformen-app-new/android/gradle.properties @@ -0,0 +1,44 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Version of flipper SDK to use with React Native +FLIPPER_VERSION=0.182.0 + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/apps/skolplattformen-app-new/android/gradle/wrapper/gradle-wrapper.jar b/apps/skolplattformen-app-new/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..943f0cbfa Binary files /dev/null and b/apps/skolplattformen-app-new/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/apps/skolplattformen-app-new/android/gradle/wrapper/gradle-wrapper.properties b/apps/skolplattformen-app-new/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..6ec1567a0 --- /dev/null +++ b/apps/skolplattformen-app-new/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/apps/skolplattformen-app-new/android/gradlew b/apps/skolplattformen-app-new/android/gradlew new file mode 100755 index 000000000..65dcd68d6 --- /dev/null +++ b/apps/skolplattformen-app-new/android/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/apps/skolplattformen-app-new/android/gradlew.bat b/apps/skolplattformen-app-new/android/gradlew.bat new file mode 100644 index 000000000..6689b85be --- /dev/null +++ b/apps/skolplattformen-app-new/android/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/apps/skolplattformen-app-new/android/settings.gradle b/apps/skolplattformen-app-new/android/settings.gradle new file mode 100644 index 000000000..e4bc88917 --- /dev/null +++ b/apps/skolplattformen-app-new/android/settings.gradle @@ -0,0 +1,4 @@ +rootProject.name = 'app' +apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) +include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/apps/skolplattformen-app-new/app.json b/apps/skolplattformen-app-new/app.json new file mode 100644 index 000000000..71c44557a --- /dev/null +++ b/apps/skolplattformen-app-new/app.json @@ -0,0 +1,5 @@ +{ + "name": "app", + "displayName": "app", + "schema": "oppnaskolplattformen://" +} diff --git a/apps/skolplattformen-app-new/assets/avatar.png b/apps/skolplattformen-app-new/assets/avatar.png new file mode 100644 index 000000000..4bae0b00a Binary files /dev/null and b/apps/skolplattformen-app-new/assets/avatar.png differ diff --git a/apps/skolplattformen-app-new/assets/bankid_low_rgb.png b/apps/skolplattformen-app-new/assets/bankid_low_rgb.png new file mode 100644 index 000000000..3931b98c4 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/bankid_low_rgb.png differ diff --git a/apps/skolplattformen-app-new/assets/bankid_vector_rgb.svg b/apps/skolplattformen-app-new/assets/bankid_vector_rgb.svg new file mode 100755 index 000000000..6031cee07 --- /dev/null +++ b/apps/skolplattformen-app-new/assets/bankid_vector_rgb.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + diff --git a/apps/skolplattformen-app-new/assets/boys.png b/apps/skolplattformen-app-new/assets/boys.png new file mode 100644 index 000000000..e7ecb44da Binary files /dev/null and b/apps/skolplattformen-app-new/assets/boys.png differ diff --git a/apps/skolplattformen-app-new/assets/children.png b/apps/skolplattformen-app-new/assets/children.png new file mode 100644 index 000000000..0a21526ef Binary files /dev/null and b/apps/skolplattformen-app-new/assets/children.png differ diff --git a/apps/skolplattformen-app-new/assets/fonts/OFL.txt b/apps/skolplattformen-app-new/assets/fonts/OFL.txt new file mode 100644 index 000000000..246c977c9 --- /dev/null +++ b/apps/skolplattformen-app-new/assets/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-Black.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-Black.ttf new file mode 100644 index 000000000..a9520b78a Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-Black.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-BlackItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-BlackItalic.ttf new file mode 100644 index 000000000..ebfdd707e Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-BlackItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-Bold.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-Bold.ttf new file mode 100644 index 000000000..b94d47f3a Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-Bold.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-BoldItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-BoldItalic.ttf new file mode 100644 index 000000000..e2e64456c Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-BoldItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraBold.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraBold.ttf new file mode 100644 index 000000000..8f008c368 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraBold.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraBoldItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraBoldItalic.ttf new file mode 100644 index 000000000..b2a9bf557 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraBoldItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraLight.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraLight.ttf new file mode 100644 index 000000000..ee6238251 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraLight.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraLightItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraLightItalic.ttf new file mode 100644 index 000000000..e392492ab Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-ExtraLightItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-Italic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-Italic.ttf new file mode 100644 index 000000000..46203996d Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-Italic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-Light.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-Light.ttf new file mode 100644 index 000000000..2ab022196 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-Light.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-LightItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-LightItalic.ttf new file mode 100644 index 000000000..6f9279dae Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-LightItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-Medium.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-Medium.ttf new file mode 100644 index 000000000..e90e87ed6 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-Medium.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-MediumItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-MediumItalic.ttf new file mode 100644 index 000000000..d8a251c7c Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-MediumItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-Regular.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-Regular.ttf new file mode 100644 index 000000000..be06e7fdc Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-Regular.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-SemiBold.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-SemiBold.ttf new file mode 100644 index 000000000..dabf7c242 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-SemiBold.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-SemiBoldItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-SemiBoldItalic.ttf new file mode 100644 index 000000000..29d5f7419 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-SemiBoldItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-Thin.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-Thin.ttf new file mode 100644 index 000000000..f5c0fdd53 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-Thin.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins-ThinItalic.ttf b/apps/skolplattformen-app-new/assets/fonts/Poppins-ThinItalic.ttf new file mode 100644 index 000000000..b91008931 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins-ThinItalic.ttf differ diff --git a/apps/skolplattformen-app-new/assets/fonts/Poppins.zip b/apps/skolplattformen-app-new/assets/fonts/Poppins.zip new file mode 100644 index 000000000..30d1b11e2 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/fonts/Poppins.zip differ diff --git a/apps/skolplattformen-app-new/assets/freja_eid_logo.png b/apps/skolplattformen-app-new/assets/freja_eid_logo.png new file mode 100644 index 000000000..621831083 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/freja_eid_logo.png differ diff --git a/apps/skolplattformen-app-new/assets/girls.png b/apps/skolplattformen-app-new/assets/girls.png new file mode 100644 index 000000000..3a0a166a6 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/girls.png differ diff --git a/apps/skolplattformen-app-new/assets/kvinna.png b/apps/skolplattformen-app-new/assets/kvinna.png new file mode 100644 index 000000000..ea2e88508 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/kvinna.png differ diff --git a/apps/skolplattformen-app-new/assets/logo_print.svg b/apps/skolplattformen-app-new/assets/logo_print.svg new file mode 100644 index 000000000..a49325cee --- /dev/null +++ b/apps/skolplattformen-app-new/assets/logo_print.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/skolplattformen-app-new/assets/man.png b/apps/skolplattformen-app-new/assets/man.png new file mode 100644 index 000000000..bd5d07d94 Binary files /dev/null and b/apps/skolplattformen-app-new/assets/man.png differ diff --git a/apps/skolplattformen-app-new/babel.config.js b/apps/skolplattformen-app-new/babel.config.js new file mode 100644 index 000000000..0df6ea6fa --- /dev/null +++ b/apps/skolplattformen-app-new/babel.config.js @@ -0,0 +1,23 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + [ + 'module-resolver', + { + root: ['./src/apps/skolplattformen-app-new/'], + extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'], + alias: { + '@skolplattformen/api': ['libs/api/lib/index.ts'], + '@skolplattformen/api-hjarntorget': [ + 'libs/api-hjarntorget/lib/index.ts', + ], + '@skolplattformen/api-skolplattformen': [ + 'libs/api-skolplattformen/lib/index.ts', + ], + '@skolplattformen/curriculum': ['libs/curriculum/src/index.ts'], + '@skolplattformen/hooks': ['libs/hooks/src/index.ts'], + }, + }, + ], + ], +} diff --git a/apps/skolplattformen-app-new/components/__tests__/Absence.test.js b/apps/skolplattformen-app-new/components/__tests__/Absence.test.js new file mode 100644 index 000000000..3a6901e67 --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/Absence.test.js @@ -0,0 +1,107 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' +import { useRoute } from '@react-navigation/native' +import { useUser } from '../../libs/hooks/src' +import { fireEvent, waitFor } from '@testing-library/react-native' +import Mockdate from 'mockdate' +import React from 'react' +import { useSMS } from '../../utils/SMS' +import { render } from '../../utils/testHelpers' +import Absence from '../absence.component' + +let sendSMS +let user = { personalNumber: '201701092395' } + +jest.mock('../../utils/SMS') +jest.mock('../../libs/hooks/src') + +const setup = (customProps = {}) => { + sendSMS = jest.fn() + + useSMS.mockReturnValue({ sendSMS }) + useRoute.mockReturnValue({ params: { child: { id: '1' } } }) + + const props = { + ...customProps, + } + + return render() +} + +beforeAll(() => { + // Hide errors from act + // https://github.com/callstack/react-native-testing-library/issues/379 + jest.spyOn(console, 'error').mockImplementation(() => { + // noop + }) +}) + +beforeEach(async () => { + jest.clearAllMocks() + useUser.mockReturnValue({ + data: user, + status: 'loaded', + }) + await AsyncStorage.clear() +}) + +test.skip('can fill out the form with full day absence', async () => { + const screen = setup() + + await waitFor(() => + fireEvent.changeText( + screen.getByTestId('personalIdentityNumberInput'), + '1212121212' + ) + ) + await waitFor(() => fireEvent.press(screen.getByText('Skicka'))) + + expect(screen.queryByText(/starttid/i)).toBeFalsy() + expect(screen.queryByText(/sluttid/i)).toBeFalsy() + + expect(sendSMS).toHaveBeenCalledWith('121212-1212') +}) + +test.skip('handles missing social security number', async () => { + const screen = setup() + + await waitFor(() => fireEvent.press(screen.getByText('Skicka'))) + + expect(screen.getByText(/Personnummer saknas/i)).toBeTruthy() + expect(sendSMS).not.toHaveBeenCalled() +}) + +test.skip('validates social security number', async () => { + const screen = setup() + + await waitFor(() => + fireEvent.changeText( + screen.getByTestId('personalIdentityNumberInput'), + '12121212' + ) + ) + await waitFor(() => fireEvent.press(screen.getByText('Skicka'))) + + expect(screen.getByText(/Personnumret är ogiltigt/i)).toBeTruthy() + expect(sendSMS).not.toHaveBeenCalled() +}) + +test.skip('can fill out the form with part of day absence', async () => { + Mockdate.set('2021-02-18 15:30') + + const screen = setup() + + await waitFor(() => + fireEvent.changeText( + screen.getByTestId('personalIdentityNumberInput'), + '1212121212' + ) + ) + await waitFor(() => fireEvent.press(screen.getByText('Heldag'))) + + expect(screen.getByText(/starttid/i)).toBeTruthy() + expect(screen.getByText(/sluttid/i)).toBeTruthy() + + await waitFor(() => fireEvent.press(screen.getByText('Skicka'))) + + expect(sendSMS).toHaveBeenCalledWith('121212-1212 1500-1700') +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/Children.test.js b/apps/skolplattformen-app-new/components/__tests__/Children.test.js new file mode 100644 index 000000000..0d5189936 --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/Children.test.js @@ -0,0 +1,239 @@ +import 'setImmediate' +import { useNavigation } from '@react-navigation/core' +import { + useApi, + useCalendar, + useChildList, + useClassmates, + useMenu, + useNews, + useNotifications, + useSchedule, + useTimetable, +} from '../../libs/hooks/src' +import React from 'react' +import * as RNLocalize from 'react-native-localize' +import { render } from '../../utils/testHelpers' +import { translate } from '../../utils/translation' +import { Children } from '../children.component' + +jest.mock('../../libs/hooks/src') + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +const setup = () => { + return render() +} + +beforeEach(() => { + useApi.mockReturnValue({ + api: { on: jest.fn(), off: jest.fn(), logout: jest.fn() }, + isLoggedIn: false, + }) + RNLocalize.findBestAvailableLanguage.mockImplementationOnce(() => ({ + languageTag: 'sv', + isRTL: false, + })) + useCalendar.mockReturnValueOnce({ data: [], status: 'loaded' }) + useNotifications.mockReturnValueOnce({ data: [], status: 'loaded' }) + useNews.mockReturnValueOnce({ data: [], status: 'loaded' }) + useSchedule.mockReturnValueOnce({ data: [], status: 'loaded' }) + useMenu.mockReturnValueOnce({ data: [], status: 'loaded' }) + useTimetable.mockReturnValueOnce({ data: [], status: 'loaded' }) + useClassmates.mockReturnValueOnce({ data: [], status: 'loaded' }) + useNavigation.mockReturnValue({ navigate: jest.fn(), setOptions: jest.fn() }) +}) + +test('renders loading state', async () => { + useChildList.mockImplementationOnce(() => ({ + data: [], + status: 'loading', + })) + + const screen = setup() + expect(screen.getByText(translate('general.loading'))).toBeTruthy() +}) + +test('renders empty state message', () => { + useChildList.mockImplementationOnce(() => ({ + data: [], + status: 'loaded', + })) + const screen = setup() + + expect( + screen.getByText(translate('children.noKids_description')) + ).toBeTruthy() +}) + +test('renders error state message', () => { + useChildList.mockImplementationOnce(() => ({ + data: [], + status: 'error', + })) + + const screen = setup() + + expect( + screen.getByText(translate('children.loadingErrorHeading')) + ).toBeTruthy() +}) + +test('renders child in preschool', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Test Testsson', + status: 'F', + }, + ], + status: 'loaded', + })) + + const screen = setup() + + expect(screen.getByText('Test Testsson')).toBeTruthy() +}) + +test('renders child in elementary school', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Test Testsson', + status: 'GR', + }, + ], + status: 'loaded', + })) + + const screen = setup() + + expect(screen.getByText('Test Testsson')).toBeTruthy() +}) + +test('renders child in high school', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Test Testsson', + status: 'G', + }, + ], + status: 'loaded', + })) + + const screen = setup() + + expect(screen.getByText('Test Testsson')).toBeTruthy() + expect( + screen.getByText(translate('abbrevations.upperSecondarySchool')) + ).toBeTruthy() +}) + +test('renders multiple children', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Storasyster Testsson', + status: 'G', + }, + { + name: 'Lillebror Testsson', + status: 'GR', + }, + ], + status: 'loaded', + })) + + const screen = setup() + + expect(screen.getByText('Storasyster Testsson')).toBeTruthy() + expect( + screen.getByText(translate('abbrevations.upperSecondarySchool')) + ).toBeTruthy() + + expect(screen.getByText('Lillebror Testsson')).toBeTruthy() + expect( + screen.getByText(translate('abbrevations.compulsorySchool')) + ).toBeTruthy() +}) + +test('renders child in class', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Test Testsson', + status: 'G', + schoolID: 'Vallaskolan', + }, + ], + status: 'loaded', + })) + useClassmates.mockReset() + useClassmates.mockImplementationOnce(() => ({ + data: [ + { + className: '8C', + }, + ], + status: 'loaded', + })) + const screen = setup() + + expect(screen.getByText('Test Testsson')).toBeTruthy() + expect(screen.getByText('8C • Vallaskolan')).toBeTruthy() +}) + +test('removes any parenthesis from name', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Test Testsson (elev)', + status: 'G', + }, + ], + status: 'loaded', + })) + const screen = setup() + + expect(screen.getByText('Test Testsson')).toBeTruthy() +}) + +test('handles multiple statuses for a child', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Test Testsson(elev)', + status: 'G;GR;F', + }, + ], + status: 'loaded', + })) + const screen = setup() + + var multipleStatusesRendered = `${translate( + 'abbrevations.upperSecondarySchool' + )}, ${translate('abbrevations.compulsorySchool')}, ${translate( + 'abbrevations.leisureTimeCentre' + )}` + + expect(screen.getByText('Test Testsson')).toBeTruthy() + expect(screen.getByText(multipleStatusesRendered)).toBeTruthy() +}) + +test('says if there is nothing new this week', () => { + useChildList.mockImplementationOnce(() => ({ + data: [ + { + name: 'Kanye West', + status: 'F', + }, + ], + status: 'loaded', + })) + const screen = setup() + + expect( + screen.getByText(translate('news.noNewNewsItemsThisWeek')) + ).toBeTruthy() +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/Classmates.test.js b/apps/skolplattformen-app-new/components/__tests__/Classmates.test.js new file mode 100644 index 000000000..3b47326ea --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/Classmates.test.js @@ -0,0 +1,86 @@ +import { useClassmates } from '../../libs/hooks/src' +import React from 'react' +import { render } from '../../utils/testHelpers' +import { ChildProvider } from '../childContext.component' +import { Classmates } from '../classmates.component' + +jest.mock('../../libs/hooks/src') + +const defaultClassmates = [ + { + className: '2B', + firstname: 'Tyrell', + lastname: 'Eriksson', + guardians: [ + { + firstname: 'Margaery', + lastname: 'Eriksson', + }, + { + firstname: 'Loras', + lastname: 'Eriksson', + }, + ], + }, + { + className: '2B', + firstname: 'Adam', + lastname: 'Svensson', + guardians: [ + { + firstname: 'Eva', + lastname: 'Svensson', + }, + ], + }, +] + +const setup = ({ classmates } = { classmates: defaultClassmates }) => { + useClassmates.mockReturnValue({ + data: classmates, + }) + + return render( + + + + ) +} + +test('gets the classmates for a child from context', () => { + setup() + + expect(useClassmates).toHaveBeenCalledWith({ id: 1 }) +}) + +test('renders class name', () => { + const screen = setup() + + expect(screen.getByText(/^klass 2b$/i)).toBeTruthy() +}) + +test('renders class without name', () => { + const screen = setup({ + classmates: [], + }) + + expect(screen.getByText(/^klass$/i)).toBeTruthy() +}) + +test('renders classmates sorted by first name', () => { + const screen = setup() + + expect(screen.getByLabelText('Barn 1')).toContainElement( + screen.getByText(/adam svensson/i) + ) + expect(screen.getByLabelText('Barn 2')).toContainElement( + screen.getByText(/tyrell eriksson/i) + ) +}) + +test('renders guardians sorted by first name', () => { + const screen = setup() + + expect(screen.getByText(/eva svensson/i)).toBeTruthy() + expect(screen.getByText(/^loras eriksson, margaery eriksson$/i)).toBeTruthy() +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/ContactMenu.test.js b/apps/skolplattformen-app-new/components/__tests__/ContactMenu.test.js new file mode 100644 index 000000000..a9bf97208 --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/ContactMenu.test.js @@ -0,0 +1,137 @@ +import { fireEvent } from '@testing-library/react-native' +import React from 'react' +import { Linking } from 'react-native' +import { render } from '../../utils/testHelpers' +import { ContactMenu } from '../contactMenu.component' +import { act } from 'react-test-renderer' + +const defaultGuardian = { + address: 'Testgatan', + email: 'adam@adamsson.se', + firstname: 'Adam', + lastname: 'Adamsson', + mobile: '0701234567', +} + +const defaultProps = { + contact: { + guardians: [defaultGuardian], + }, +} + +const setup = (customProps = {}) => { + const props = { + ...defaultProps, + ...customProps, + } + + return render() +} + +beforeAll(() => { + // Hide errors from state illegal state transition + // Probably due to mock + jest.spyOn(console, 'error').mockImplementation(() => { + // noop + }) +}) + +beforeEach(jest.clearAllMocks) + +test('renders a parent', () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('ShowContactInfoButton')) + + expect(screen.getByText(/adam adamsson/i)).toBeTruthy() +}) + +test('displays option to call and text guardian', () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('ShowContactInfoButton')) + + fireEvent.press(screen.getByText(/ring/i)) + expect(Linking.openURL).toHaveBeenCalledWith('tel:0701234567') + + fireEvent.press(screen.getByText(/sms/i)) + expect(Linking.openURL).toHaveBeenCalledWith('sms:0701234567') +}) + +test('hides options to call and text if no phone number', () => { + const guardianWithoutPhoneNumber = { + contact: { + guardians: [ + { + ...defaultGuardian, + mobile: null, + }, + ], + }, + } + + const screen = setup(guardianWithoutPhoneNumber) + + fireEvent.press(screen.getByTestId('ShowContactInfoButton')) + + expect(screen.queryByTestId('CallMenuItem')).toBeNull() + expect(screen.queryByTestId('SMSMenuItem')).toBeNull() +}) + +test('displays option to email guardian', () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('ShowContactInfoButton')) + + fireEvent.press(screen.getByText(/maila/i)) + expect(Linking.openURL).toHaveBeenCalledWith('mailto:adam@adamsson.se') +}) + +test('hides options to email phone number', () => { + const guardianWithoutEmail = { + contact: { + guardians: [ + { + ...defaultGuardian, + email: null, + }, + ], + }, + } + + const screen = setup(guardianWithoutEmail) + + fireEvent.press(screen.getByTestId('ShowContactInfoButton')) + + expect(screen.queryByTestId('SendEmailMenuItem')).toBeNull() +}) + +test('displays address of guardian', () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('ShowContactInfoButton')) + + fireEvent.press(screen.getByText(/adress/i)) + expect(Linking.openURL).toHaveBeenCalledWith( + 'http://maps.apple.com/?daddr=Testgatan' + ) +}) + +test('hides address if it does not exist', () => { + const guardianWithoutAddress = { + contact: { + guardians: [ + { + ...defaultGuardian, + address: null, + }, + ], + }, + } + + const screen = setup(guardianWithoutAddress) + + fireEvent.press(screen.getByTestId('ShowContactInfoButton')) + + expect(screen.queryByTestId('ShowHomeMenuItem')).toBeNull() +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/Menu.test.js b/apps/skolplattformen-app-new/components/__tests__/Menu.test.js new file mode 100644 index 000000000..4f7fad18e --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/Menu.test.js @@ -0,0 +1,50 @@ +import { useMenu } from '../../libs/hooks/src' +import React from 'react' +import { render } from '../../utils/testHelpers' +import { translate } from '../../utils/translation' +import { Menu } from '../menu.component' + +jest.mock('../../libs/hooks/src') + +const defaultItemList = [ + { + title: 'Måndag vecka 10', + description: 'Krämiga köttbullar', + }, + { + title: 'Tisdag vecka 10', + description: 'Kryddig falukorv', + }, + { + title: 'Onsdag vecka 10', + description: 'Sushi', + }, +] + +const setup = (itemList = defaultItemList) => { + useMenu.mockReturnValue({ + data: itemList, + }) + + return render(

) +} + +test('renders multiple days', () => { + const screen = setup() + + expect(screen.getByText('Måndag vecka 10')).toBeTruthy() + expect(screen.getByText('Tisdag vecka 10')).toBeTruthy() + expect(screen.getByText('Onsdag vecka 10')).toBeTruthy() +}) + +test('renders title and description', () => { + const screen = setup() + + expect(screen.getByText('Måndag vecka 10')).toBeTruthy() + expect(screen.getByText('Krämiga köttbullar')).toBeTruthy() +}) + +test('renders empty menu', () => { + const screen = setup([]) + expect(screen.getByText(translate('menu.emptyText'))).toBeTruthy() +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/NewsItem.test.js b/apps/skolplattformen-app-new/components/__tests__/NewsItem.test.js new file mode 100644 index 000000000..7d7670cf2 --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/NewsItem.test.js @@ -0,0 +1,86 @@ +import { useApi, useNewsDetails } from '../../libs/hooks/src' +import React from 'react' +import { render } from '../../utils/testHelpers' +import { NewsItem } from '../newsItem.component' + +jest.mock('../../libs/hooks/src') + +const defaultNewsItem = { + author: 'Köket', + fullImageUrl: 'test.png', + header: 'K-bullar!', + published: '2021-02-15T09:13:28.484Z', + modified: '2021-02-15T09:13:28.484Z', +} + +let navigation + +const setup = (customProps = { newsItem: {} }) => { + useApi.mockReturnValue({ api: { getSessionCookie: jest.fn() } }) + + useNewsDetails.mockReturnValue({ + data: { + body: 'Nu blir det köttbullar', + }, + }) + + navigation = { + goBack: jest.fn(), + } + + const newsItem = { + ...defaultNewsItem, + ...customProps.newsItem, + } + + const props = { + navigation, + route: { + params: { + child: { id: 1 }, + newsItem, + }, + }, + ...customProps, + } + + return render() +} + +test('gets article details using useNewsDetails', async () => { + setup() + + expect(useNewsDetails).toHaveBeenCalledWith({ id: 1 }, defaultNewsItem) +}) + +test('renders an article', () => { + const screen = setup() + + expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() + expect(screen.getByText('Publicerad: 15 feb 2021 10:13')).toBeTruthy() + expect(screen.getByText('Uppdaterad: 15 feb 2021 10:13')).toBeTruthy() +}) + +test('renders an article without published date if date is invalid', () => { + const newsItemWithoutPublishedDate = { + ...defaultNewsItem, + published: '2020-08-16T21:10:00.000+02:0', + } + const screen = setup({ newsItem: newsItemWithoutPublishedDate }) + + expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() + expect(screen.getByText('Uppdaterad: 15 feb 2021 10:13')).toBeTruthy() + expect(screen.queryByText('Publicerad: Invalid DateTime')).toBeFalsy() +}) + +test('renders an article without modified date if date is invalid', () => { + const newsItemWithoutPublishedDate = { + ...defaultNewsItem, + modified: null, + } + const screen = setup({ newsItem: newsItemWithoutPublishedDate }) + + expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() + expect(screen.getByText('Publicerad: 15 feb 2021 10:13')).toBeTruthy() + expect(screen.queryByText('Uppdaterad: Invalid DateTime')).toBeFalsy() +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/NewsListItem.test.js b/apps/skolplattformen-app-new/components/__tests__/NewsListItem.test.js new file mode 100644 index 000000000..51321df03 --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/NewsListItem.test.js @@ -0,0 +1,81 @@ +import { useNavigation } from '@react-navigation/native' +import { fireEvent } from '@testing-library/react-native' +import MockDate from 'mockdate' +import React from 'react' +import { render } from '../../utils/testHelpers' +import { ChildProvider } from '../childContext.component' +import { NewsListItem } from '../newsListItem.component' + +const defaultItem = { + author: 'Köket', + intro: 'Nu blir det köttbullar', + header: 'K-bullar!', + published: '2021-02-15T09:13:28.484Z', + modified: '2021-02-15T09:13:28.484Z', +} + +const setup = (customProps = {}) => { + const props = { + item: defaultItem, + ...customProps, + } + + return render( + + + + ) +} + +beforeEach(() => { + MockDate.set('2021-02-15T09:30:28.484Z') +}) + +test('renders an article', () => { + const screen = setup() + + expect(screen.getByText(/k-bullar!/i)).toBeTruthy() + expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() + expect(screen.getByText('Köket • för 17 minuter sedan')).toBeTruthy() +}) + +test('renders article without date', () => { + const itemWithInvalidDate = { + ...defaultItem, + published: null, + modified: null, + } + + const screen = setup({ item: itemWithInvalidDate }) + + expect(screen.getByText(/k-bullar!/i)).toBeTruthy() + expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() + expect(screen.getByText(/^köket$/i)).toBeTruthy() +}) + +test('falls back to modified date if no published date', () => { + const itemWithInvalidDate = { + ...defaultItem, + published: null, + } + + const screen = setup({ item: itemWithInvalidDate }) + + expect(screen.getByText(/k-bullar!/i)).toBeTruthy() + expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() + expect(screen.getByText('Köket • för 17 minuter sedan')).toBeTruthy() +}) + +test('navigates to news article on press', () => { + const navigate = jest.fn() + useNavigation.mockReturnValue({ navigate }) + + const screen = setup() + + fireEvent.press(screen.getByText(/k-bullar!/i)) + + expect(navigate).toHaveBeenCalledWith('NewsItem', { + child: { id: 1 }, + newsItem: defaultItem, + }) +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/Notification.test.js b/apps/skolplattformen-app-new/components/__tests__/Notification.test.js new file mode 100644 index 000000000..91bcec083 --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/Notification.test.js @@ -0,0 +1,73 @@ +import React from 'react' +import { render } from '../../utils/testHelpers' +import { Notification } from '../notification.component' +import MockDate from 'mockdate' + +const defaultItem = { + sender: 'Planering', + category: 'Bedömning', + dateCreated: '2021-02-15T09:13:28.484Z', + dateModified: '2021-02-15T09:14:28.484Z', +} + +// copied from https://github.com/react-native-webview/react-native-webview/issues/2934#issuecomment-1524101977 +jest.mock('react-native-webview', () => { + const { View } = require('react-native') + return { + WebView: View, + } +}) +// + +const setup = (customProps = {}) => { + const props = { + item: defaultItem, + ...customProps, + } + + return render() +} + +beforeEach(() => { + MockDate.set('2021-02-15T09:30:28.484Z') +}) + +test('renders subtitle with modified date', () => { + const screen = setup() + + expect(screen.getByText('Bedömning • för 16 minuter sedan')).toBeTruthy() +}) + +test('renders subtitle with created date', () => { + const itemWithoutModifiedDate = { + ...defaultItem, + dateModified: undefined, + } + + const screen = setup({ item: itemWithoutModifiedDate }) + + expect(screen.getByText('Bedömning • för 17 minuter sedan')).toBeTruthy() +}) + +test('renders subtitle without date', () => { + const itemWithoutDate = { + ...defaultItem, + dateCreated: undefined, + dateModified: undefined, + } + + const screen = setup({ item: itemWithoutDate }) + + expect(screen.getByText('Bedömning')).toBeTruthy() +}) + +test('renders subtitle without category', () => { + const itemWithoutCategory = { + ...defaultItem, + category: undefined, + } + + const screen = setup({ item: itemWithoutCategory }) + + expect(screen.getByText('för 16 minuter sedan')).toBeTruthy() +}) diff --git a/apps/skolplattformen-app-new/components/__tests__/saveToCalendar.test.js b/apps/skolplattformen-app-new/components/__tests__/saveToCalendar.test.js new file mode 100644 index 000000000..0dfbcc1b5 --- /dev/null +++ b/apps/skolplattformen-app-new/components/__tests__/saveToCalendar.test.js @@ -0,0 +1,133 @@ +import { fireEvent } from '@testing-library/react-native' +import React from 'react' +import RNCalendarEvents from 'react-native-calendar-events' +import Toast from 'react-native-simple-toast' +import { render } from '../../utils/testHelpers' +import { SaveToCalendar } from '../saveToCalendar.component' + +const defaultEvent = { + title: 'Utvecklingssamtal', + startDate: '2021-06-19 13:00', + endDate: '2021-06-19 14:00', + location: 'Gubbängsskolan', +} + +const defaultProps = { + event: defaultEvent, +} + +const setup = (customProps = {}) => { + const props = { + ...defaultProps, + ...customProps, + } + + return render() +} + +beforeAll(() => { + // Hide errors from state illegal state transition + // Probably due to mock + jest.spyOn(console, 'error').mockImplementation(() => { + // noop + }) +}) + +beforeEach(jest.clearAllMocks) + +test('renders save to calendar', () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('actionsButton')) + + expect(screen.getByText(/Spara/i)).toBeTruthy() +}) + +test('requests calendar permissons', () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('actionsButton')) + fireEvent.press(screen.getByText(/Spara/i)) + + expect(RNCalendarEvents.requestPermissions).toHaveBeenCalled() +}) + +test('can save an event to the calendar', async () => { + const screen = setup({ + event: { + ...defaultEvent, + location: null, + description: null, + }, + }) + + fireEvent.press(screen.getByTestId('actionsButton')) + fireEvent.press(screen.getByText(/Spara/i)) + await RNCalendarEvents.requestPermissions() + + expect(RNCalendarEvents.saveEvent).toHaveBeenCalledWith('Utvecklingssamtal', { + startDate: '2021-06-19T11:00:00.000Z', + endDate: '2021-06-19T12:00:00.000Z', + }) +}) + +test('removes any null values from the event', async () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('actionsButton')) + fireEvent.press(screen.getByText(/Spara/i)) + await RNCalendarEvents.requestPermissions() + + expect(RNCalendarEvents.saveEvent).toHaveBeenCalledWith('Utvecklingssamtal', { + startDate: '2021-06-19T11:00:00.000Z', + endDate: '2021-06-19T12:00:00.000Z', + location: 'Gubbängsskolan', + }) +}) + +test('calls toast with success', async () => { + const screen = setup() + + fireEvent.press(screen.getByTestId('actionsButton')) + fireEvent.press(screen.getByText(/Spara/i)) + await RNCalendarEvents.requestPermissions() + await RNCalendarEvents.saveEvent() + + expect(Toast.showWithGravity).toHaveBeenCalledWith( + '✔️ Sparad till kalender', + 'short', + 'bottom' + ) +}) + +test('says if something goes wrong', async () => { + const screen = setup() + RNCalendarEvents.saveEvent.mockRejectedValueOnce() + + fireEvent.press(screen.getByTestId('actionsButton')) + fireEvent.press(screen.getByText(/Spara/i)) + await RNCalendarEvents.requestPermissions() + await RNCalendarEvents.saveEvent() + + expect(Toast.showWithGravity).toHaveBeenCalledWith( + 'Något gick fel', + 'short', + 'bottom' + ) +}) + +test('tells user if they havent authorized calendar', async () => { + const screen = setup() + RNCalendarEvents.requestPermissions.mockResolvedValueOnce('not auth') + + fireEvent.press(screen.getByTestId('actionsButton')) + fireEvent.press(screen.getByText(/Spara/i)) + await RNCalendarEvents.requestPermissions() + await RNCalendarEvents.saveEvent() + + expect(Toast.showWithGravity).toHaveBeenCalledWith( + 'Du måste godkänna åtkomst till kalendern', + 'short', + 'bottom' + ) +}) diff --git a/apps/skolplattformen-app-new/components/absence.component.tsx b/apps/skolplattformen-app-new/components/absence.component.tsx new file mode 100644 index 000000000..05bfad47a --- /dev/null +++ b/apps/skolplattformen-app-new/components/absence.component.tsx @@ -0,0 +1,280 @@ +import { RouteProp, useRoute } from '@react-navigation/native' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import { useUser } from '../libs/hooks/src' +import { + Button, + CheckBox, + Input, + StyleService, + Text, + useStyleSheet, +} from '@ui-kitten/components' +import { Formik } from 'formik' +import moment from 'moment' +import Personnummer from 'personnummer' +import React, { useCallback } from 'react' +import { View } from 'react-native' +import DateTimePickerModal from 'react-native-modal-datetime-picker' +import * as Yup from 'yup' +import { defaultStackStyling } from '../design/navigationThemes' +// import usePersonalStorage from '../hooks/usePersonalStorage'; +import useSettingsStorage from '../hooks/useSettingsStorage' +import { Layout as LayoutStyle, Sizing, Typography } from '../styles' +import { studentName } from '../utils/peopleHelpers' +import { useSMS } from '../utils/SMS' +import { translate } from '../utils/translation' +import { AlertIcon } from './icon.component' +import { RootStackParamList } from './navigation.component' +import { NavigationTitle } from './navigationTitle.component' + +type AbsenceRouteProps = RouteProp + +interface AbsenceFormValues { + displayStartTimePicker: boolean + displayEndTimePicker: boolean + personalIdentityNumber: string + isFullDay: boolean + startTime: moment.Moment + endTime: moment.Moment +} + +export const absenceRouteOptions = + (darkMode: boolean) => + ({ + route, + }: { + route: RouteProp + }): NativeStackNavigationOptions => { + const child = route.params.child + return { + ...defaultStackStyling(darkMode), + headerTitle: () => ( + + ), + } + } + +const Absence = () => { + const AbsenceSchema = Yup.object().shape({ + personalIdentityNumber: Yup.string() + .required(translate('abscense.personalNumberMissing')) + .test('is-valid', translate('abscense.invalidPersonalNumber'), (value) => + value ? Personnummer.valid(value) : true + ), + isFullDay: Yup.bool().required(), + }) + + const { data: user } = useUser() + const route = useRoute() + const { sendSMS } = useSMS() + const { child } = route.params + const [personalIdentityNumber, setPersonalIdentityNumber] = React.useState('') + const [personalIdsFromStorage, setPersonalIdInStorage] = useSettingsStorage( + 'childPersonalIdentityNumber' + ) + const personalIdKey = `@childPersonalIdNumber.${child.id}` + const minumumDate = moment().hours(8).minute(0) + const maximumDate = moment().hours(17).minute(0) + const styles = useStyleSheet(themedStyles) + + const submit = useCallback( + async (values: AbsenceFormValues) => { + const personalIdNumber = Personnummer.parse( + values.personalIdentityNumber + ).format() + + if (values.isFullDay) { + sendSMS(personalIdNumber) + } else { + sendSMS( + `${personalIdNumber} ${moment(values.startTime).format( + 'HHmm' + )}-${moment(values.endTime).format('HHmm')}` + ) + } + + const toStore = { + ...personalIdsFromStorage, + ...{ [personalIdKey]: personalIdNumber }, + } + setPersonalIdInStorage(toStore) + }, + [personalIdKey, personalIdsFromStorage, sendSMS, setPersonalIdInStorage] + ) + + React.useEffect(() => { + const personalIdFromStorage = personalIdsFromStorage[personalIdKey] || '' + setPersonalIdentityNumber(personalIdFromStorage || '') + }, [child, personalIdKey, personalIdsFromStorage, user]) + + const initialValues: AbsenceFormValues = { + displayStartTimePicker: false, + displayEndTimePicker: false, + personalIdentityNumber: personalIdentityNumber || '', + isFullDay: true, + startTime: moment().hours(Math.max(8, new Date().getHours())).minute(0), + endTime: maximumDate, + } + + return ( + + {({ + handleChange, + handleBlur, + handleSubmit, + setFieldValue, + values, + touched, + errors, + }) => { + const hasError = (field: keyof typeof values) => + errors[field] && touched[field] + + return ( + + + + {translate('abscense.childsPersonalNumber')} + + + {hasError('personalIdentityNumber') && ( + + {errors.personalIdentityNumber} + + )} + + + setFieldValue('isFullDay', checked)} + > + {translate('abscense.entireDay')} + + + {!values.isFullDay && ( + + + + {translate('abscense.startTime')} + + + { + setFieldValue('startTime', date) + setFieldValue('displayStartTimePicker', false) + }} + onCancel={() => + setFieldValue('displayStartTimePicker', false) + } + /> + + + + + {translate('abscense.endTime')} + + + { + setFieldValue('endTime', date) + setFieldValue('displayEndTimePicker', false) + }} + onCancel={() => + setFieldValue('displayEndTimePicker', false) + } + /> + + + )} + + + ) + }} + + ) +} + +export default Absence + +const themedStyles = StyleService.create({ + wrap: { + ...LayoutStyle.flex.full, + padding: Sizing.t4, + backgroundColor: 'background-basic-color-2', + }, + field: { marginBottom: Sizing.t4 }, + partOfDay: { ...LayoutStyle.flex.row, marginBottom: Sizing.t4 }, + spacer: { width: Sizing.t2 }, + inputHalf: { ...LayoutStyle.flex.full }, + input: { + backgroundColor: 'background-basic-color-1', + borderColor: 'color-input-border', + }, + // TODO: Refactor to use mapping.json in eva design + pickerButton: { + backgroundColor: 'background-basic-color-1', + }, + label: { + ...Typography.fontSize.sm, + ...Typography.fontWeight.bold, + marginBottom: Sizing.t2, + }, + error: { + color: 'color-primary-600', + }, +}) diff --git a/apps/skolplattformen-app-new/components/auth.component.tsx b/apps/skolplattformen-app-new/components/auth.component.tsx new file mode 100644 index 000000000..c1d6ba309 --- /dev/null +++ b/apps/skolplattformen-app-new/components/auth.component.tsx @@ -0,0 +1,166 @@ +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import { StackNavigationProp } from '@react-navigation/stack' +import { + StyleService, + Text, + useStyleSheet, + useTheme, +} from '@ui-kitten/components' +import React from 'react' +import { + Image, + ImageStyle, + Keyboard, + TouchableOpacity, + TouchableWithoutFeedback, + View, +} from 'react-native' +import { useTranslation } from '../hooks/useTranslation' +import { Layout as LayoutStyle, Sizing, Typography } from '../styles' +import { fontSize } from '../styles/typography' +import { KeyboardAvoidingView } from '../ui/keyboardAvoidingView.component' +import { SafeAreaView } from '../ui/safeAreaView.component' +import { SettingsIcon } from './icon.component' +import { Login } from './login.component' +import { RootStackParamList } from './navigation.component' + +const randomWord = ( + t: (scope: I18n.Scope, options?: I18n.TranslateOptions | undefined) => string +) => { + const words = t('auth.words') + const keys = Object.keys(words) + + const randomIndex: number = Math.floor(Math.random() * keys.length) + const argumentKey: string = keys[randomIndex] + + return words[argumentKey] +} + +interface AuthProps { + navigation: StackNavigationProp +} + +export const authRouteOptions = (): NativeStackNavigationOptions => { + return { + headerShown: false, + animationTypeForReplace: 'push', + animation: 'fade', + } +} + +export const Auth: React.FC = ({ navigation }) => { + const styles = useStyleSheet(themeStyles) + const colors = useTheme() + const { t } = useTranslation() + // const t = (key: string) => key; + + return ( + + + + navigation.navigate('Settings')} + accessibilityHint={t( + 'auth.a11y_navigate_to_settings' + // defaultValue: 'Navigerar till vyn för inställningar', + )} + accessibilityLabel={t( + 'auth.a11y_settings' + // { + // // defaultValue: 'Inställningar', + // } + )} + > + + + {t('general.settings')} + + + + + + + + + + Öppna skolplattformen + + + + {t('auth.subtitle', { + word: randomWord(t), + })} + + + + + + + + ) +} + +const themeStyles = StyleService.create({ + container: { + ...LayoutStyle.mainAxis.flexStart, + ...LayoutStyle.crossAxis.flexEnd, + padding: Sizing.t6, + }, + imageWrapper: { + flex: 1, + justifyContent: 'flex-end', + }, + image: { + ...Sizing.aspectRatio(1.5, Sizing.Ratio['4:3']), + }, + content: { + ...LayoutStyle.flex.full, + }, + header: { + width: '100%', + marginBottom: Sizing.t5, + fontFamily: 'Poppins-Black', + fontWeight: '900', + }, + subtitle: { + width: '100%', + textAlign: 'center', + ...Typography.fontSize.xs, + marginTop: Sizing.t5, + }, + language: { + flexDirection: 'row', + alignItems: 'center', + padding: Sizing.t3, + paddingLeft: Sizing.t5, + }, + languageText: { + ...fontSize.sm, + marginLeft: Sizing.t1, + }, + settingsLink: { + alignSelf: 'flex-start', + zIndex: 1, + }, +}) diff --git a/apps/skolplattformen-app-new/components/calendar.component.tsx b/apps/skolplattformen-app-new/components/calendar.component.tsx new file mode 100644 index 000000000..a5b9ead43 --- /dev/null +++ b/apps/skolplattformen-app-new/components/calendar.component.tsx @@ -0,0 +1,114 @@ +import { useCalendar } from '../libs/hooks/src' +import { CalendarItem } from '@skolplattformen/api' +import { + Divider, + List, + ListItem, + StyleService, + Text, + useStyleSheet, +} from '@ui-kitten/components' +import moment from 'moment' +import React from 'react' +import { Layout as LayoutStyle, Sizing, Typography } from '../styles' +import { ListRenderItemInfo, RefreshControl, View } from 'react-native' + +import { translate } from '../utils/translation' +import { useChild } from './childContext.component' +import { CalendarOutlineIcon } from './icon.component' +import { SaveToCalendar } from './saveToCalendar.component' +import { Week } from './week.component' + +// const translate = (key: string) => key; + +export const Calendar = () => { + const child = useChild() + const { data, status, reload } = useCalendar(child) + const styles = useStyleSheet(themedStyles) + + const formatStartDate = (startDate: moment.MomentInput) => { + const date = moment(startDate) + const output = `${date.format('dddd')} ${date.format( + 'll' + )} • ${date.fromNow()}` + + // Hack to remove year if it is this year + const currentYear = moment().year().toString(10) + return output.replace(currentYear, '') + } + + const sortedData = () => { + if (!data) { + return [] + } + + return data.sort((a, b) => + a.startDate && b.startDate ? a.startDate.localeCompare(b.startDate) : 0 + ) + } + + return ( + + + + + {translate('calender.emptyHeadline')} + + + {translate('calender.emptyText')} + + + } + renderItem={({ item }: ListRenderItemInfo) => ( + ( + + {formatStartDate(item.startDate)} + + )} + accessoryLeft={CalendarOutlineIcon} + accessoryRight={() => } + /> + )} + refreshControl={ + + } + /> + + ) +} + +const themedStyles = StyleService.create({ + container: { + backgroundColor: 'background-basic-color-1', + height: '100%', + width: '100%', + }, + description: { + ...Typography.fontSize.xs, + color: 'text-hint-color', + }, + emptyState: { + ...LayoutStyle.center, + ...LayoutStyle.flex.full, + }, + emptyStateHeadline: { + ...Typography.align.center, + margin: Sizing.t4, + }, + emptyStateDescription: { + ...Typography.align.center, + lineHeight: 21, + paddingHorizontal: Sizing.t3, + margin: Sizing.t4, + }, +}) diff --git a/apps/skolplattformen-app-new/components/child.component.tsx b/apps/skolplattformen-app-new/components/child.component.tsx new file mode 100644 index 000000000..e5bd91fb2 --- /dev/null +++ b/apps/skolplattformen-app-new/components/child.component.tsx @@ -0,0 +1,216 @@ +import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' +import { + getFocusedRouteNameFromRoute, + RouteProp, + useNavigation, + useRoute, +} from '@react-navigation/native' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +// import {StackNavigationProp} from '@react-navigation/stack'; +import { Icon } from '@ui-kitten/components' +import React, { useEffect } from 'react' +// import {StyleProp, TextProps} from 'react-native'; +import { defaultStackStyling } from '../design/navigationThemes' +import { useFeature } from '../hooks/useFeature' +import { studentName } from '../utils/peopleHelpers' +import { translate } from '../utils/translation' +import { Calendar } from './calendar.component' +import { ChildProvider } from './childContext.component' +import { Classmates } from './classmates.component' +import { Menu } from './menu.component' +import { RootStackParamList } from './navigation.component' +import { NavigationTitle } from './navigationTitle.component' +import { NewsList } from './newsList.component' +import { NotificationsList } from './notificationsList.component' +import { TabBarLabel } from './tabBarLabel.component' + +// const translate = (key: string) => key; + +// type ChildNavigationProp = StackNavigationProp; +type ChildRouteProps = RouteProp + +export type ChildTabParamList = { + News: undefined + Notifications: undefined + Calendar: undefined + Menu: undefined + Classmates: undefined +} + +// interface TabTitleProps { +// children: string; +// style?: StyleProp; +// } + +const { Navigator, Screen } = createBottomTabNavigator() + +const NewsScreen = () => +const NotificationsScreen = () => +const CalendarScreen = () => +const MenuScreen = () => +const ClassmatesScreen = () => + +interface ScreenSettings { + NEWS_SCREEN: boolean + NOTIFICATIONS_SCREEN: boolean + CALENDER_SCREEN: boolean + MENU_SCREEN: boolean + CLASSMATES_SCREEN: boolean +} + +const TabNavigator = ({ + initialRouteName = 'News', + screenSettings, +}: { + initialRouteName?: keyof ChildTabParamList + screenSettings: ScreenSettings +}) => ( + { + return { + tabBarLabel: ({ focused }) => ( + + ), + tabBarIcon: ({ focused, color }) => { + let iconName = 'news' + + if (route.name === 'News') { + iconName = focused ? 'book-open' : 'book-open-outline' + } else if (route.name === 'Notifications') { + iconName = focused ? 'alert-circle' : 'alert-circle-outline' + } else if (route.name === 'Calendar') { + iconName = focused ? 'calendar' : 'calendar-outline' + } else if (route.name === 'Menu') { + iconName = focused ? 'clipboard' : 'clipboard-outline' + } else if (route.name === 'Classmates') { + iconName = focused ? 'people' : 'people-outline' + } + return + }, + } + }} + > + {screenSettings.NEWS_SCREEN && ( + + )} + {screenSettings.NOTIFICATIONS_SCREEN && ( + + )} + {screenSettings.CALENDER_SCREEN && ( + + )} + {screenSettings.MENU_SCREEN && ( + + )} + {screenSettings.CLASSMATES_SCREEN && ( + + )} + +) + +const getHeaderTitle = (route: any) => { + const routeName = + getFocusedRouteNameFromRoute(route) ?? + route.params.initialRouteName ?? + 'News' + return getRouteTitleFromName(routeName) +} + +const getRouteTitleFromName = (routeName: string) => { + switch (routeName) { + case 'News': + return translate('navigation.news') + case 'Notifications': + return translate('navigation.notifications') + case 'Calendar': + return translate('navigation.calender') + case 'Menu': + return translate('navigation.menu') + case 'Classmates': + return translate('navigation.classmates') + default: + return '' + } +} + +export const childRouteOptions = + (darkMode: boolean) => + ({ + route, + }: { + route: RouteProp + }): NativeStackNavigationOptions => { + const { child } = route.params + + return { + ...defaultStackStyling(darkMode), + headerTitle: () => ( + + ), + } + } + +export const Child = () => { + const route = useRoute() + const { child, initialRouteName } = route.params + const useFoodMenu = useFeature('FOOD_MENU') + const useClassList = useFeature('CLASS_LIST') + + const navigation = useNavigation() + + useEffect(() => { + navigation.setOptions({ title: getHeaderTitle(route) }) + }, [navigation, route]) + + const screenSettings: ScreenSettings = { + NEWS_SCREEN: true, + NOTIFICATIONS_SCREEN: true, + CALENDER_SCREEN: true, + MENU_SCREEN: useFoodMenu, + CLASSMATES_SCREEN: useClassList, + } + return ( + + + + ) +} diff --git a/apps/skolplattformen-app-new/components/childContext.component.tsx b/apps/skolplattformen-app-new/components/childContext.component.tsx new file mode 100644 index 000000000..d4bbc51bb --- /dev/null +++ b/apps/skolplattformen-app-new/components/childContext.component.tsx @@ -0,0 +1,19 @@ +import { Child } from '@skolplattformen/api' +import React, { createContext, useContext } from 'react' + +interface ChildProviderProps { + child: Child + children: React.ReactNode +} + +export const ChildContext = createContext({ + id: '', + sdsId: '', + name: '', +}) + +export const ChildProvider = ({ child, children }: ChildProviderProps) => { + return {children} +} + +export const useChild = () => useContext(ChildContext) diff --git a/apps/skolplattformen-app-new/components/childListItem.component.tsx b/apps/skolplattformen-app-new/components/childListItem.component.tsx new file mode 100644 index 000000000..ee3a36b11 --- /dev/null +++ b/apps/skolplattformen-app-new/components/childListItem.component.tsx @@ -0,0 +1,337 @@ +import { useNavigation } from '@react-navigation/native' +import { StackNavigationProp } from '@react-navigation/stack' +import { Child } from '@skolplattformen/api' +import { + useCalendar, + useClassmates, + useMenu, + useNews, + useNotifications, + useSchedule, +} from '../libs/hooks/src' +import { + Button, + StyleService, + Text, + useStyleSheet, +} from '@ui-kitten/components' +import moment, { Moment } from 'moment' +import React, { useEffect } from 'react' +import { Pressable, useColorScheme, View } from 'react-native' +import { useTranslation } from '../hooks/useTranslation' +import { Colors, Layout, Sizing } from '../styles' +import { getMeaningfulStartingDate } from '../utils/calendarHelpers' +import { studentName } from '../utils/peopleHelpers' +import { DaySummary } from './daySummary.component' +import { AlertIcon, RightArrowIcon } from './icon.component' +import { RootStackParamList } from './navigation.component' +import { StudentAvatar } from './studentAvatar.component' + +interface ChildListItemProps { + child: Child + color: string + updated: string + currentDate?: Moment +} +type ChildListItemNavigationProp = StackNavigationProp< + RootStackParamList, + 'Children' +> + +export const ChildListItem = ({ + child, + color, + updated, + currentDate = moment(), +}: ChildListItemProps) => { + // Forces rerender when child.id changes + React.useEffect(() => { + // noop + }, [child.id]) + + const navigation = useNavigation() + + const { t } = useTranslation() + + const { data: notifications, reload: notificationsReload } = + useNotifications(child) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { data: news, status: newsStatus, reload: newsReload } = useNews(child) + const { data: classmates, reload: classmatesReload } = useClassmates(child) + const { data: calendar, reload: calendarReload } = useCalendar(child) + const { data: menu, reload: menuReload } = useMenu(child) + const { data: schedule, reload: scheduleReload } = useSchedule( + child, + moment(currentDate).toISOString(), + moment(currentDate).add(7, 'days').toISOString() + ) + + useEffect(() => { + // Do not refresh if updated is empty (first render of component) + if (updated === '') { + return + } + + newsReload() + classmatesReload() + notificationsReload() + calendarReload() + menuReload() + scheduleReload() + + // Without eslint-disable below we get into a forever loop + // because the function pointers to reload functions change on every reload. + // I do not know a workaround for this. + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [updated]) + + const notificationsThisWeek = notifications.filter( + ({ dateCreated, dateModified }) => { + const date = dateModified || dateCreated + return date ? moment(date).isSame(moment(), 'week') : false + } + ) + + const newsThisWeek = news.filter(({ modified, published }) => { + const newsDate = modified || published + return newsDate ? moment(newsDate).isSame(currentDate, 'week') : false + }) + + const scheduleAndCalendarThisWeek = [ + ...(calendar ?? []), + ...(schedule ?? []), + ].filter(({ startDate }) => + startDate + ? moment(startDate).isBetween( + moment(currentDate).startOf('day'), + moment(currentDate).add(7, 'days') + ) + : false + ) + + const displayDate = (inputDate: moment.MomentInput) => { + return moment(inputDate).fromNow() + } + + const getClassName = () => { + // hack: we can find the class name (ex. 8C) from the classmates. + // let's pick the first one and select theirs class + // hack 2: we can find school namn in skola24 if child data is there + if (classmates.length > 0) { + return ( + classmates[0].className + + (child.schoolID == null ? '' : ' • ' + child.schoolID) + ) + } + + // Taken from Skolverket + // https://www.skolverket.se/skolutveckling/anordna-och-administrera-utbildning/administrera-utbildning/skoltermer-pa-engelska + const abbrevations = { + G: t('abbrevations.upperSecondarySchool'), + GR: t('abbrevations.compulsorySchool'), + F: t('abbrevations.leisureTimeCentre'), + FS: t('abbrevations.preSchool'), + } + + return child.status + ? child.status + .split(';') + .map((status) => { + const statusAsAbbreviation = status as keyof typeof abbrevations + + return abbrevations[statusAsAbbreviation] || status + }) + .join(', ') + : null + } + + const className = getClassName() + const styles = useStyleSheet(themeStyles) + const isDarkMode = useColorScheme() === 'dark' + const meaningfulStartingDate = getMeaningfulStartingDate(currentDate) + + // Hide menu if we want to show monday but it is not monday yet. + // The menu for next week is not available until monday + const shouldShowLunchMenu = + menu[meaningfulStartingDate.isoWeekday() - 1] && + !( + meaningfulStartingDate.isoWeekday() === 1 && + currentDate.isoWeekday() !== 1 + ) + + return ( + <> + + + [ + styles.cardHeaderLeft || {}, + { opacity: pressed ? 0.5 : 1 }, + ]} + onPress={() => navigation.navigate('Child', { child, color })} + > + + + + {studentName(child.name)} + {className ? {className} : null} + + + + + + + + ['' || {}, { opacity: pressed ? 0.5 : 1 }]} + onPress={() => + navigation.navigate('Child', { + child, + color, + initialRouteName: 'Calendar', + }) + } + > + + + {scheduleAndCalendarThisWeek.slice(0, 3).map((calendarItem, i) => ( + + {`${calendarItem.title} (${displayDate(calendarItem.startDate)})`} + + ))} + + ['' || {}, { opacity: pressed ? 0.5 : 1 }]} + onPress={() => + navigation.navigate('Child', { + child, + color, + initialRouteName: 'News', + }) + } + > + + {t('navigation.news')} + + {notificationsThisWeek.slice(0, 3).map((notification, i) => ( + + {notification.message} + + ))} + {newsThisWeek.slice(0, 3).map((newsItem, i) => ( + + {newsItem.header ?? ''} + + ))} + + + {scheduleAndCalendarThisWeek.length || + notificationsThisWeek.length || + newsThisWeek.length ? null : ( + + {t('news.noNewNewsItemsThisWeek')} + + )} + + {shouldShowLunchMenu ? ( + ['' || {}, { opacity: pressed ? 0.5 : 1 }]} + onPress={() => + navigation.navigate('Child', { + child, + color, + initialRouteName: 'Menu', + }) + } + > + + {meaningfulStartingDate.format( + '[' + t('schedule.lunch') + '] dddd' + )} + + + {menu[meaningfulStartingDate.isoWeekday() - 1]?.description} + + + ) : null} + + + + + + + ) +} + +const themeStyles = StyleService.create({ + card: { + borderRadius: 25, + padding: Sizing.t5, + marginBottom: Sizing.t4, + backgroundColor: 'background-basic-color-1', + }, + cardHeader: { + ...Layout.flex.row, + ...Layout.mainAxis.center, + ...Layout.crossAxis.spaceBetween, + marginBottom: Sizing.t4, + }, + cardHeaderLeft: { + ...Layout.flex.row, + ...Layout.mainAxis.center, + flex: 10, + }, + cardHeaderRight: { + ...Layout.flex.row, + ...Layout.crossAxis.flexEnd, + flex: 1, + }, + cardHeaderText: { + marginHorizontal: Sizing.t4, + flex: 10, + }, + icon: { + width: 32, + height: 32, + }, + label: { + marginTop: 10, + }, + itemFooter: { + ...Layout.flex.row, + justifyContent: 'space-between', + alignItems: 'flex-end', + marginTop: Sizing.t4, + }, + absenceButton: { + marginLeft: -20, + }, + itemFooterSpinner: { + alignSelf: 'flex-end', + }, + item: { + marginRight: 12, + paddingHorizontal: 2, + paddingVertical: 0, + marginBottom: 0, + }, + noNewNewsItemsText: {}, +}) diff --git a/apps/skolplattformen-app-new/components/children.component.tsx b/apps/skolplattformen-app-new/components/children.component.tsx new file mode 100644 index 000000000..8a7eba89d --- /dev/null +++ b/apps/skolplattformen-app-new/components/children.component.tsx @@ -0,0 +1,214 @@ +import { NavigationProp, useNavigation } from '@react-navigation/core' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import { Child } from '@skolplattformen/api' +import { useApi, useChildList } from '../libs/hooks/src' +import { + Button, + List, + Spinner, + StyleService, + Text, + TopNavigationAction, + useStyleSheet, +} from '@ui-kitten/components' +import moment from 'moment' +import React, { useCallback, useEffect, useState } from 'react' +import { + Image, + ImageStyle, + Linking, + ListRenderItemInfo, + View, +} from 'react-native' +import { defaultStackStyling } from '../design/navigationThemes' +import AppStorage from '../services/appStorage' +import { Layout as LayoutStyle, Sizing, Typography } from '../styles' +import { translate } from '../utils/translation' +import { ChildListItem } from './childListItem.component' +import { RefreshIcon, SettingsIcon } from './icon.component' +import { RootStackParamList } from './navigation.component' + +const colors = ['primary', 'success', 'info', 'warning', 'danger'] + +export const childenRouteOptions = + (darkMode: boolean) => (): NativeStackNavigationOptions => { + return { + ...defaultStackStyling(darkMode), + title: translate('children.title'), + headerLargeTitle: false, + headerLargeTitleShadowVisible: false, + } + } + +export const Children = () => { + const styles = useStyleSheet(themedStyles) + + const navigation = useNavigation>() + + const { api } = useApi() + const { data: childList, status, reload } = useChildList() + const reloadChildren = useCallback(() => { + reload() + setUpdated(moment().toISOString()) + }, [reload]) + + const [updatedAt, setUpdated] = useState('') + + const logout = useCallback(() => { + AppStorage.clearTemporaryItems().then(() => api.logout()) + }, [api]) + + useEffect(() => { + navigation.setOptions({ + headerLeft: () => { + return ( + navigation.navigate('Settings')} + /> + ) + }, + headerRight: () => { + return ( + reloadChildren()} + accessibilityHint="Reload" + accessibilityLabel="Reload" + /> + ) + }, + }) + }, [navigation, reloadChildren]) + + // We need to skip safe area view here, due to the reason that it's adding a white border + // when this view is actually lightgrey. Taking the padding top value from the use inset hook. + return status === 'loaded' ? ( + + {translate('children.noKids_title')} + + {translate('children.noKids_description')} + + + + } + renderItem={({ item: child, index }: ListRenderItemInfo) => ( + + )} + /> + ) : ( + + + {status === 'error' ? ( + + {translate('children.loadingErrorHeading')} + + {translate('children.loadingErrorInformationText')} + + + + + + + + ) : ( + + + + {translate('general.loading')} + + + )} + + ) +} + +const themedStyles = StyleService.create({ + topContainer: { + ...LayoutStyle.flex.full, + paddingBottom: 0, + }, + loading: { + ...LayoutStyle.center, + ...LayoutStyle.flex.full, + }, + loadingImage: { + ...Sizing.aspectRatio(), + }, + loadingMessage: { + ...LayoutStyle.mainAxis.center, + ...LayoutStyle.flex.row, + marginTop: Sizing.t2, + }, + loadingText: { + marginLeft: Sizing.t5, + }, + errorButtons: { + height: Sizing.screen.height * 0.2, + width: Sizing.screen.width * 0.73, + justifyContent: 'space-evenly', + }, + errorMessage: { + height: Sizing.screen.height * 0.4, + width: Sizing.screen.width * 0.73, + justifyContent: 'space-evenly', + alignItems: 'center', + marginTop: Sizing.t2, + }, + errorText: { + marginBottom: Sizing.t3, + }, + childList: { + ...LayoutStyle.flex.full, + }, + childListContainer: { + paddingVertical: Sizing.t4, + paddingHorizontal: Sizing.t3, + }, + emptyState: { + ...LayoutStyle.center, + ...LayoutStyle.flex.full, + paddingHorizontal: Sizing.t5, + }, + emptyStateDescription: { + ...Typography.align.center, + lineHeight: 21, + marginTop: Sizing.t2, + }, + emptyStateImage: { + ...Sizing.aspectRatio(0.8), + marginTop: Sizing.t5, + }, + topNavigationTitle: { + ...Typography.fontWeight.semibold, + }, +}) diff --git a/apps/skolplattformen-app-new/components/classmates.component.tsx b/apps/skolplattformen-app-new/components/classmates.component.tsx new file mode 100644 index 000000000..f9c701eff --- /dev/null +++ b/apps/skolplattformen-app-new/components/classmates.component.tsx @@ -0,0 +1,90 @@ +import { Classmate } from '@skolplattformen/api' +import { useClassmates } from '../libs/hooks/src' +import { + Divider, + Icon, + IconProps, + List, + ListItem, + Text, +} from '@ui-kitten/components' +import React from 'react' +import { ListRenderItemInfo, RefreshControl, StyleSheet } from 'react-native' +import { fullName, guardians, sortByFirstName } from '../utils/peopleHelpers' +import { translate } from '../utils/translation' +import { useChild } from './childContext.component' +import { ContactMenu } from './contactMenu.component' + +// const translate = (key: string) => key; + +// interface ClassmatesProps { +// setSelected: (value?: number | null) => void; +// } + +export const Classmates = () => { + const child = useChild() + + const { data, status, reload } = useClassmates(child) + const renderItemIcon = (props: IconProps) => ( + + ) + const [selected, setSelected] = React.useState() + const renderItem = ({ item, index }: ListRenderItemInfo) => ( + setSelected(item)} + description={guardians(item.guardians)} + accessoryLeft={renderItemIcon} + accessoryRight={() => ( + setSelected(undefined)} + /> + )} + /> + ) + return ( + + {data?.length + ? `${translate('classmates.class')} ${data[0].className}` + : translate('classmates.class')} + + } + renderItem={renderItem} + contentContainerStyle={styles.contentContainer} + refreshControl={ + + } + /> + ) +} + +const styles = StyleSheet.create({ + container: { + height: '100%', + width: '100%', + }, + contentContainer: { + margin: 10, + justifyContent: 'flex-start', + }, + topContainer: { + margin: 5, + flexDirection: 'row', + justifyContent: 'space-between', + }, + listHeader: { + paddingTop: 10, + paddingLeft: 15, + }, +}) diff --git a/apps/skolplattformen-app-new/components/contactMenu.component.tsx b/apps/skolplattformen-app-new/components/contactMenu.component.tsx new file mode 100644 index 000000000..264de9e88 --- /dev/null +++ b/apps/skolplattformen-app-new/components/contactMenu.component.tsx @@ -0,0 +1,130 @@ +import { Classmate } from '@skolplattformen/api' +import { + Button, + MenuGroup, + MenuItem, + OverflowMenu, +} from '@ui-kitten/components' +import React from 'react' +import { Linking, StyleSheet } from 'react-native' +import { fullName } from '../utils/peopleHelpers' +import { translate } from '../utils/translation' +import { + CallIcon, + EmailIcon, + MapIcon, + MoreIcon, + SMSIcon, +} from './icon.component' + +interface ContactMenuProps { + contact: Classmate + selected: boolean + setSelected: (value?: number | null) => void +} + +// const translate = (key: string) => key; + +export const ContactMenu = ({ + contact, + selected, + setSelected, +}: ContactMenuProps) => { + const [visible, setVisible] = React.useState(selected) + + const renderToggleButton = () => ( + + + + + setShowLoginMethod(false)} + backdropStyle={styles.backdrop} + > + + + {t('auth.chooseLoginMethod')} + + f.id !== 'freja') + } + ItemSeparatorComponent={Divider} + renderItem={({ item }) => ( + { + setLoginMethodId(item.id) + setShowLoginMethod(false) + }} + /> + )} + /> + + + + showModal(false)} + backdropStyle={styles.backdrop} + > + + {loginStatusText} + + + + setShowSchoolPlatformPicker(false)} + backdropStyle={styles.backdrop} + > + + + {t('auth.chooseSchoolPlatform')} + + ( + { + changeSchoolPlatform(item.id) + setShowSchoolPlatformPicker(false) + }} + /> + )} + /> + + + + + ) +} + +const themedStyles = StyleService.create({ + backdrop: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + }, + loginForm: { + ...Layout.mainAxis.flexStart, + }, + pnrInput: { minHeight: 70 }, + loginButtonGroup: { + minHeight: 45, + }, + loginButton: { ...Layout.flex.full }, + loginMethodButton: { width: 45 }, + modal: { + width: '90%', + }, + bankIdLoading: { margin: 10 }, + cancelButtonStyle: { marginTop: 15 }, + icon: { + width: 20, + height: 20, + }, + platformPicker: { + width: '100%', + }, +}) diff --git a/apps/skolplattformen-app-new/components/markdown.component.tsx b/apps/skolplattformen-app-new/components/markdown.component.tsx new file mode 100644 index 000000000..ebd0a8425 --- /dev/null +++ b/apps/skolplattformen-app-new/components/markdown.component.tsx @@ -0,0 +1,61 @@ +import { Text } from '@ui-kitten/components' +import React from 'react' +import { Dimensions, Linking, StyleSheet } from 'react-native' +import MarkdownBase, { + RenderRules, +} from '@ronradtke/react-native-markdown-display' +import { Sizing } from '../styles' +import { Image } from './image.component' + +interface MarkdownProps { + children: React.ReactNode + style?: StyleSheet.NamedStyles +} + +const rules: RenderRules = { + image: (node) => { + const { src } = node.attributes + const url = src.startsWith('/') + ? `https://elevstockholm.sharepoint.com${src}` + : src + return ( + + ) + }, + link: (node, children, _parent, styles) => { + if (children) { + return ( + Linking.openURL(node.attributes.href)} + > + {children.map((child, index) => ( + {child} + ))} + + ) + } + return null + }, +} + +export const Markdown = ({ style, children }: MarkdownProps) => { + return ( + + {children} + + ) +} + +const styles = StyleSheet.create({ + markdownImage: { width: '100%', borderRadius: 15 }, +}) diff --git a/apps/skolplattformen-app-new/components/menu.component.tsx b/apps/skolplattformen-app-new/components/menu.component.tsx new file mode 100644 index 000000000..49cc91b9c --- /dev/null +++ b/apps/skolplattformen-app-new/components/menu.component.tsx @@ -0,0 +1,86 @@ +import { MenuItem } from '@skolplattformen/api' +import { useMenu } from '../libs/hooks/src' +import { + Divider, + List, + StyleService, + Text, + useStyleSheet, +} from '@ui-kitten/components' +import 'moment/locale/sv' +import React from 'react' +import { + Image, + ImageStyle, + ListRenderItemInfo, + RefreshControl, + View, +} from 'react-native' +import { Layout as LayoutStyle, Sizing, Typography } from '../styles' +import { translate } from '../utils/translation' +import { useChild } from './childContext.component' +import { MenuListItem } from './menuListItem.component' + +// const translate = (key: string) => key; + +export const Menu = () => { + const styles = useStyleSheet(themedStyles) + const child = useChild() + const { data, status, reload } = useMenu(child) + + return ( + + {translate('menu.emptyHeadline')} + + {translate('menu.emptyText')} + + + + } + renderItem={({ item }: ListRenderItemInfo) => ( + + )} + style={styles.container} + refreshControl={ + + } + /> + ) +} + +const themedStyles = StyleService.create({ + container: { + height: '100%', + width: '100%', + padding: Sizing.t3, + }, + contentContainer: { + paddingHorizontal: Sizing.t5, + paddingVertical: Sizing.t2, + backgroundColor: 'background-basic-color-1', + borderRadius: 25, + }, + emptyState: { + ...LayoutStyle.center, + ...LayoutStyle.flex.full, + }, + emptyStateDescription: { + ...Typography.align.center, + lineHeight: 21, + paddingHorizontal: Sizing.t3, + marginTop: Sizing.t3, + }, + emptyStateImage: { + ...Sizing.aspectRatio(0.8), + marginTop: 50, + }, +}) diff --git a/apps/skolplattformen-app-new/components/menuListItem.component.tsx b/apps/skolplattformen-app-new/components/menuListItem.component.tsx new file mode 100644 index 000000000..235d9c92e --- /dev/null +++ b/apps/skolplattformen-app-new/components/menuListItem.component.tsx @@ -0,0 +1,35 @@ +import { MenuItem } from '@skolplattformen/api' +import { StyleService, Text, useStyleSheet } from '@ui-kitten/components' +import React from 'react' +import { View } from 'react-native' +import { Sizing, Typography } from '../styles' + +interface MenuListItemProps { + item: MenuItem +} + +export const MenuListItem = ({ item }: MenuListItemProps) => { + const styles = useStyleSheet(themedStyles) + return ( + + {item.title} + {item.description} + + ) +} + +const themedStyles = StyleService.create({ + container: { + width: '100%', + paddingVertical: Sizing.t3, + }, + topContainer: { + margin: Sizing.t1, + flexDirection: 'row', + justifyContent: 'space-between', + }, + title: { + ...Typography.header, + marginBottom: Sizing.t1, + }, +}) diff --git a/apps/skolplattformen-app-new/components/modalWebView.component.tsx b/apps/skolplattformen-app-new/components/modalWebView.component.tsx new file mode 100644 index 000000000..071d23e00 --- /dev/null +++ b/apps/skolplattformen-app-new/components/modalWebView.component.tsx @@ -0,0 +1,130 @@ +import { useApi } from '../libs/hooks/src' +import { StyleService, Text, useStyleSheet } from '@ui-kitten/components' +import React, { useEffect, useState } from 'react' +import { Linking, Modal, TouchableOpacity, View } from 'react-native' +import { SafeAreaView } from 'react-native-safe-area-context' +import { WebView } from 'react-native-webview' +import { Layout, Sizing } from '../styles' +import { BackIcon, ExternalLinkIcon } from './icon.component' + +interface ModalWebViewProps { + url: string + sharedCookiesEnabled: boolean + onClose: () => void +} +export const ModalWebView = ({ + url, + onClose, + sharedCookiesEnabled, +}: ModalWebViewProps) => { + const [modalVisible, setModalVisible] = React.useState(true) + const { api } = useApi() + const [title, setTitle] = React.useState('...') + const [headers, setHeaders] = useState<{ [index: string]: string }>() + + useEffect(() => { + const getHeaders = async (urlToGetSessionFor: string) => { + if (sharedCookiesEnabled) { + return + } + const newHeaders = await api.getSessionHeaders(urlToGetSessionFor) + setHeaders(newHeaders) + } + + getHeaders(url) + }, [url, sharedCookiesEnabled, api]) + + const closeModal = () => { + setModalVisible(false) + onClose() + } + const openInApp = () => { + Linking.openURL(url) + } + + const styles = useStyleSheet(themedStyles) + + return ( + + + + + + + + + {title} + + + + + + + {(headers || sharedCookiesEnabled) && ( + { + setTitle(event.nativeEvent.title) + }} + /> + )} + + + ) +} + +const themedStyles = StyleService.create({ + container: { + flex: 1, + backgroundColor: 'background-basic-color-2', + }, + headerWrapper: { + marginTop: Sizing.t1, + padding: Sizing.t1, + borderRadius: 2, + borderColor: 'basic-color-200', + borderBottomWidth: 1, + backgroundColor: 'background-basic-color-2', + }, + backdrop: { + backgroundColor: 'color-basic-transparent-600', + }, + headerText: { + overflow: 'hidden', + width: '85%', + paddingRight: 2, + }, + header: { + ...Layout.flex.row, + ...Layout.mainAxis.center, + paddingHorizontal: Sizing.t3, + paddingVertical: Sizing.t1, + backgroundColor: 'background-basic-color-2', + }, + shareIcon: { + width: 24, + height: 24, + shadowColor: 'color-basic-600', + }, + backIcon: { + width: 24, + height: 24, + marginRight: Sizing.t4, + shadowColor: 'color-basic-600', + }, + webview: {}, +}) diff --git a/apps/skolplattformen-app-new/components/navigation.component.tsx b/apps/skolplattformen-app-new/components/navigation.component.tsx new file mode 100644 index 000000000..e1d8ff4bd --- /dev/null +++ b/apps/skolplattformen-app-new/components/navigation.component.tsx @@ -0,0 +1,193 @@ +import { NavigationContainer } from '@react-navigation/native' +import { createNativeStackNavigator } from '@react-navigation/native-stack' +import { + Child as ChildType, + NewsItem as NewsItemType, +} from '@skolplattformen/api' +import { useApi } from '../libs/hooks/src' +import { useTheme } from '@ui-kitten/components' +import { Library } from 'libraries.json' +import React, { useEffect } from 'react' +import { StatusBar, useColorScheme } from 'react-native' +import { schema } from '../app.json' +import { + darkNavigationTheme, + lightNavigationTheme, +} from '../design/navigationThemes' +import { useAppState } from '../hooks/useAppState' +import { useLangCode } from '../hooks/useLangCode' +import useSettingsStorage, { + initializeSettingsState, +} from '../hooks/useSettingsStorage' +import { isRTL } from '../services/languageService' +import Absence, { absenceRouteOptions } from './absence.component' +import { Auth, authRouteOptions } from './auth.component' +import { Child, childRouteOptions } from './child.component' +import { childenRouteOptions, Children } from './children.component' +import { libraryRouteOptions, LibraryScreen } from './library.component' +import { NewsItem, newsItemRouteOptions } from './newsItem.component' +import { SetLanguage, setLanguageRouteOptions } from './setLanguage.component' +import { settingsRouteOptions, SettingsScreen } from './settings.component' +import { + settingsAppearanceRouteOptions, + SettingsAppearanceScreen, +} from './settingsAppearance.component' +import { + settingsAppearanceThemeRouteOptions, + SettingsAppearanceThemeScreen, +} from './settingsAppearanceTheme.component' +import { + settingsLicensesRouteOptions, + SettingsLicensesScreen, +} from './settingsLicenses.component' + +export type RootStackParamList = { + Login: undefined + IsLoggedIn: undefined + Children: undefined + Settings: { rand?: number } | undefined + SettingsAppearance: undefined + SettingsAppearanceTheme: undefined + SettingsLicenses: undefined + Library: { + library: Library + } + Child: { + child: ChildType + color: string + initialRouteName?: string + } + NewsItem: { newsItem: NewsItemType; child: ChildType } + Absence: { child: ChildType } + SetLanguage: undefined +} + +const { Navigator, Screen } = createNativeStackNavigator() + +const linking = { + prefixes: [schema], + config: { + screens: { + Login: 'login', + }, + }, +} + +export const AppNavigator = () => { + const { isLoggedIn, api } = useApi() + + const [usingSystemTheme] = useSettingsStorage('usingSystemTheme') + const [theme] = useSettingsStorage('theme') + const systemTheme = useColorScheme() + const colorScheme = usingSystemTheme ? systemTheme : theme + const langCode = useLangCode() + + const colors = useTheme() + + const currentAppState = useAppState() + + useEffect(() => { + initializeSettingsState() + }, []) + + useEffect(() => { + const checkUser = async () => { + if (currentAppState === 'active' && isLoggedIn) { + const { isAuthenticated } = await api.getUser() + + if (!isAuthenticated) { + await api.logout() + } + } + } + checkUser() + }, [currentAppState, isLoggedIn, api]) + + return ( + + + + ({ + headerLargeTitle: false, + headerLargeTitleHideShadow: true, + direction: isRTL(langCode) ? 'rtl' : 'ltr', + headerStyle: { + backgroundColor: + colorScheme === 'dark' + ? colors['background-basic-color-2'] + : colors['background-basic-color-1'], + }, + headerLargeStyle: { + backgroundColor: colors['background-basic-color-2'], + }, + headerLargeTitleStyle: { + fontFamily: 'Poppins-ExtraBold', + }, + })} + > + {isLoggedIn ? ( + <> + + + + + + ) : ( + + )} + + + + + + + + + ) +} diff --git a/apps/skolplattformen-app-new/components/navigationTitle.component.tsx b/apps/skolplattformen-app-new/components/navigationTitle.component.tsx new file mode 100644 index 000000000..5543175bc --- /dev/null +++ b/apps/skolplattformen-app-new/components/navigationTitle.component.tsx @@ -0,0 +1,40 @@ +import { Text } from '@ui-kitten/components' +import React from 'react' +import { StyleSheet, View } from 'react-native' +import { Layout } from '../styles' +import { fontSize } from '../styles/typography' + +interface NavigationTitleProps { + title?: string + subtitle?: string +} +/** + * Navigation Title with a smaller subtitle. + */ +export const NavigationTitle = ({ title, subtitle }: NavigationTitleProps) => { + return ( + + {title && ( + + {title} + + )} + {subtitle && ( + + {subtitle.substring(0, subtitle.indexOf(' '))} + + )} + + ) +} + +const styles = StyleSheet.create({ + container: { + ...Layout.center, + }, + title: { + ...fontSize.sm, + fontWeight: '500', + }, + subtitle: { ...fontSize.base }, +}) diff --git a/apps/skolplattformen-app-new/components/newsItem.component.tsx b/apps/skolplattformen-app-new/components/newsItem.component.tsx new file mode 100644 index 000000000..972ad663d --- /dev/null +++ b/apps/skolplattformen-app-new/components/newsItem.component.tsx @@ -0,0 +1,157 @@ +import { RouteProp } from '@react-navigation/native' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import { StackNavigationProp } from '@react-navigation/stack' +import { useNewsDetails } from '../libs/hooks/src' +import { StyleService, Text, useStyleSheet } from '@ui-kitten/components' +import moment from 'moment' +import 'moment/locale/sv' +import React from 'react' +import { + Dimensions, + ImageStyle, + RefreshControl, + ScrollView, + View, +} from 'react-native' +import { defaultStackStyling } from '../design/navigationThemes' +import { Layout, Sizing, Typography } from '../styles' +import { studentName } from '../utils/peopleHelpers' +import { translate } from '../utils/translation' +import { Image } from './image.component' +import { Markdown } from './markdown.component' +import { RootStackParamList } from './navigation.component' +import { NavigationTitle } from './navigationTitle.component' + +// const translate = (key: string) => key; + +interface NewsItemProps { + navigation: StackNavigationProp + route: RouteProp +} + +const displayDate = (date: string | undefined) => moment(date).format('lll') + +const dateIsValid = (date: string | undefined) => + moment(date, moment.ISO_8601).isValid() + +export const newsItemRouteOptions = + (darkMode: boolean) => + ({ + route, + }: { + route: RouteProp + }): NativeStackNavigationOptions => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const newsItem = route.params.newsItem + const { child } = route.params + return { + ...defaultStackStyling(darkMode), + headerTitle: () => , + } + } + +export const NewsItem = ({ route }: NewsItemProps) => { + const { newsItem, child } = route.params + const { data, status, reload } = useNewsDetails(child, newsItem) + const styles = useStyleSheet(themedStyles) + const stylesMarkdown = useStyleSheet(themedStylesMarkdown) + + return ( + + } + > + + {newsItem.header} + + {dateIsValid(newsItem.published) && ( + + {translate('news.published')}:{' '} + {displayDate(newsItem.published)} + + )} + {dateIsValid(newsItem.modified) && ( + + {translate('news.updated')}:{' '} + {displayDate(newsItem.modified)} + + )} + + {data.body} + {newsItem.fullImageUrl && ( + + )} + + + ) +} + +const themedStylesMarkdown = StyleService.create({ + body: { + ...Typography.fontSize.base, + color: 'text-basic-color', + lineHeight: 26, + }, + heading1: { + ...Typography.fontSize.xl, + color: 'text-basic-color', + }, + heading2: { + ...Typography.fontSize.lg, + color: 'text-basic-color', + }, + code_block: { + color: 'text-basic-color', + backgroundColor: 'background-basic-color-1', + borderColor: 'color-basic-400', + }, +}) + +const themedStyles = StyleService.create({ + article: { + padding: Sizing.t5, + backgroundColor: 'background-basic-color-1', + }, + scrollView: { + ...Layout.flex.full, + }, + image: { + width: '100%', + marginTop: Sizing.t4, + borderRadius: 15, + }, + title: { + ...Typography.fontWeight.bold, + fontSize: 30, + marginBottom: 8, + }, + subtitle: { + ...Typography.fontSize.xs, + color: 'text-hint-color', + }, + strong: { + ...Typography.fontSize.xs, + ...Typography.fontWeight.bold, + color: 'text-hint-color', + }, + published: { + marginBottom: Sizing.t1, + }, + body: { + marginTop: Sizing.t4, + }, + topNavigationTitle: { + ...Typography.fontWeight.semibold, + }, +}) diff --git a/apps/skolplattformen-app-new/components/newsList.component.tsx b/apps/skolplattformen-app-new/components/newsList.component.tsx new file mode 100644 index 000000000..21179f2b0 --- /dev/null +++ b/apps/skolplattformen-app-new/components/newsList.component.tsx @@ -0,0 +1,117 @@ +import { useNews } from '../libs/hooks/src' +import { Input, List, StyleService, useStyleSheet } from '@ui-kitten/components' +import React, { useMemo, useState } from 'react' +import { TouchableOpacity, View, RefreshControl } from 'react-native' +import { Sizing } from '../styles' +import { + renderSearchResultPreview, + useNewsListSearchResults, +} from '../utils/search' +import { translate } from '../utils/translation' +import { useChild } from './childContext.component' +import { CloseOutlineIcon, SearchIcon } from './icon.component' +import { NewsListItem } from './newsListItem.component' + +// const translate = (key: string) => key; + +export const NewsList = () => { + const styles = useStyleSheet(themedStyles) + const child = useChild() + const { data, status, reload } = useNews(child) + + const [searchQuery, setSearchQuery] = useState('') + const searchResults = useNewsListSearchResults(searchQuery) + + const header = useMemo( + () => ( + + searchQuery.length > 0 ? ( + setSearchQuery('')}> + + + ) : ( + + ) + } + /> + ), + [searchQuery, styles.search] + ) + + if (searchQuery) { + return ( + ( + + {renderSearchResultPreview(searchResult)} + + )} + refreshControl={ + + } + /> + ) + } + + return ( + } + refreshControl={ + + } + /> + ) +} + +const themedStyles = StyleService.create({ + container: { + height: '100%', + width: '100%', + }, + contentContainer: { + paddingVertical: Sizing.t3, + paddingHorizontal: Sizing.t3, + }, + search: { + backgroundColor: 'background-basic-color-1', + borderRadius: 40, + marginBottom: Sizing.t2, + }, +}) diff --git a/apps/skolplattformen-app-new/components/newsListItem.component.tsx b/apps/skolplattformen-app-new/components/newsListItem.component.tsx new file mode 100644 index 000000000..1b917043d --- /dev/null +++ b/apps/skolplattformen-app-new/components/newsListItem.component.tsx @@ -0,0 +1,103 @@ +import { useNavigation } from '@react-navigation/native' +import { StackNavigationProp } from '@react-navigation/stack' +import { NewsItem } from '@skolplattformen/api' +import { StyleService, useStyleSheet } from '@ui-kitten/components' +import moment from 'moment' +import React, { ReactNode } from 'react' +import { + Dimensions, + ImageStyle, + Text, + TouchableOpacity, + View, +} from 'react-native' +import { Layout, Sizing, Typography } from '../styles' +import { useChild } from './childContext.component' +import { Image } from './image.component' +import { RootStackParamList } from './navigation.component' + +interface NewsListItemProps { + item: NewsItem + children?: ReactNode +} + +type NewsListItemNavigationProp = StackNavigationProp< + RootStackParamList, + 'NewsItem' +> + +const { width } = Dimensions.get('window') + +export const NewsListItem = ({ item, children }: NewsListItemProps) => { + const styles = useStyleSheet(themedStyles) + const navigation = useNavigation() + const child = useChild() + const hasDate = item.modified || item.published + + const displayDate = hasDate ? moment(hasDate).fromNow() : null + + return ( + navigation.navigate('NewsItem', { newsItem: item, child })} + > + + {width > 320 && item.fullImageUrl ? ( + + ) : null} + + + {item.header} + + {item.author} + {item.author && displayDate ? ' • ' : ''} + {displayDate} + + + {children ?? item.intro} + + + + + + ) +} + +const themedStyles = StyleService.create({ + card: { + ...Layout.flex.full, + ...Layout.flex.row, + borderRadius: 15, + paddingVertical: Sizing.t4, + paddingHorizontal: Sizing.t4, + marginBottom: Sizing.t3, + backgroundColor: 'background-basic-color-1', + }, + text: { + ...Layout.flex.full, + }, + title: { + ...Typography.header, + marginBottom: Sizing.t1, + color: 'text-basic-color', + }, + subtitle: { + ...Typography.fontSize.xs, + marginBottom: Sizing.t2, + color: 'text-hint-color', + }, + intro: { + ...Typography.fontSize.sm, + color: 'text-basic-color', + }, + image: { + borderRadius: 50, + width: 50, + height: 50, + marginRight: Sizing.t3, + }, +}) diff --git a/apps/skolplattformen-app-new/components/notification.component.tsx b/apps/skolplattformen-app-new/components/notification.component.tsx new file mode 100644 index 000000000..e859d0268 --- /dev/null +++ b/apps/skolplattformen-app-new/components/notification.component.tsx @@ -0,0 +1,72 @@ +import { Notification as NotificationType } from '@skolplattformen/api' +import { StyleService, Text, useStyleSheet } from '@ui-kitten/components' +import moment from 'moment' +import React from 'react' +import { TouchableOpacity, View } from 'react-native' +import { Layout, Sizing, Typography } from '../styles' +import { ModalWebView } from './modalWebView.component' + +interface NotificationProps { + item: NotificationType +} + +export const Notification = ({ item }: NotificationProps) => { + const styles = useStyleSheet(themedStyles) + const [isOpen, setIsOpen] = React.useState(false) + const open = () => setIsOpen(true) + const close = () => setIsOpen(false) + + const date = item.dateModified || item.dateCreated + const displayDate = date ? moment(date).fromNow() : null + + const sharedCookiesEnabled = Boolean( + item.url && + (item.url.startsWith('https://start.unikum.net/') || + item.url.startsWith('https://hjarntorget.goteborg.se')) + ) + + return ( + <> + + + + {item.sender} + + {item.category ? item.category : ''} + {item.category && displayDate ? ' • ' : ''} + {displayDate ? displayDate : ''} + + + {item.message} + + + {isOpen && ( + + )} + + ) +} + +const themedStyles = StyleService.create({ + card: { + ...Layout.flex.full, + borderRadius: 15, + paddingVertical: Sizing.t4, + paddingHorizontal: Sizing.t4, + marginBottom: Sizing.t3, + backgroundColor: 'background-basic-color-1', + }, + title: { + ...Typography.header, + marginBottom: Sizing.t1, + }, + subtitle: { + ...Typography.fontSize.xs, + color: 'text-hint-color', + marginBottom: Sizing.t2, + }, +}) diff --git a/apps/skolplattformen-app-new/components/notificationsList.component.tsx b/apps/skolplattformen-app-new/components/notificationsList.component.tsx new file mode 100644 index 000000000..8e0209c2a --- /dev/null +++ b/apps/skolplattformen-app-new/components/notificationsList.component.tsx @@ -0,0 +1,38 @@ +import { useNotifications } from '../libs/hooks/src' +import { List, StyleService, useStyleSheet } from '@ui-kitten/components' +import React from 'react' +import { RefreshControl } from 'react-native' +import { Sizing } from '../styles' +import { useChild } from './childContext.component' +import { Notification } from './notification.component' + +export const NotificationsList = () => { + const styles = useStyleSheet(themedStyles) + const child = useChild() + const { data, status, reload } = useNotifications(child) + + return ( + ( + + )} + refreshControl={ + + } + /> + ) +} + +const themedStyles = StyleService.create({ + container: { + height: '100%', + width: '100%', + }, + contentContainer: { + paddingHorizontal: Sizing.t3, + paddingVertical: Sizing.t3, + }, +}) diff --git a/apps/skolplattformen-app-new/components/saveToCalendar.component.tsx b/apps/skolplattformen-app-new/components/saveToCalendar.component.tsx new file mode 100644 index 000000000..9b368cdf5 --- /dev/null +++ b/apps/skolplattformen-app-new/components/saveToCalendar.component.tsx @@ -0,0 +1,92 @@ +import { CalendarItem } from '@skolplattformen/api' +import { Button, MenuItem, OverflowMenu, Text } from '@ui-kitten/components' +import React from 'react' +import RNCalendarEvents from 'react-native-calendar-events' +import Toast from 'react-native-simple-toast' +import { translate } from '../utils/translation' +import { CalendarOutlineIcon, MoreIcon } from './icon.component' + +interface SaveToCalendarProps { + event: CalendarItem +} + +// const translate = (key: string) => key; + +export const SaveToCalendar = ({ event }: SaveToCalendarProps) => { + const [visible, setVisible] = React.useState(false) + + const renderToggleButton = () => ( + + + + ) +} + +const themedStyles = StyleService.create({ + languageList: { + flex: 1, + alignSelf: 'stretch', + flexDirection: 'column', + marginTop: 8, + paddingHorizontal: Sizing.t4, + }, + icon: { + width: 30, + height: 30, + }, + container: { + flex: 1, + }, + scrollView: { + padding: Sizing.t4, + }, + buttonGroup: { + minHeight: 45, + marginTop: 20, + marginHorizontal: Sizing.t5, + }, + button: { ...LayoutStyle.flex.full }, +}) diff --git a/apps/skolplattformen-app-new/components/settings.component.tsx b/apps/skolplattformen-app-new/components/settings.component.tsx new file mode 100644 index 000000000..1b41eacec --- /dev/null +++ b/apps/skolplattformen-app-new/components/settings.component.tsx @@ -0,0 +1,89 @@ +import { NavigationProp, useNavigation } from '@react-navigation/core' +import { useApi, useUser } from '../libs/hooks/src' +import React, { useCallback } from 'react' +import { ScrollView, Text } from 'react-native' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import useSettingsStorage from '../hooks/useSettingsStorage' +import AppStorage from '../services/appStorage' +import { LanguageService } from '../services/languageService' +import { Layout as LayoutStyle, Sizing } from '../styles' +import { languages, translate } from '../utils/translation' +import { AwardIcon, BrushIcon, GlobeIcon } from './icon.component' +import { RootStackParamList } from './navigation.component' +import { + SettingGroup, + SettingListItem, + SettingListSeparator, +} from './settingsComponents.component' +import { VersionInfo } from './versionInfo.component' + +export const settingsRouteOptions = (): NativeStackNavigationOptions => ({ + title: translate('settings.settings'), +}) + +export const SettingsScreen = () => { + const [isUsingSystemTheme] = useSettingsStorage('usingSystemTheme') + const [settingsTheme] = useSettingsStorage('theme') + const navigation = useNavigation>() + const langCode = LanguageService.getLanguageCode() + const language = languages.find((l) => l.langCode === langCode) + const { api } = useApi() + const { data: user } = useUser() + + const logout = useCallback(async () => { + await AppStorage.clearTemporaryItems() + await AppStorage.clearPersonalData(user) + await api.logout() + navigation.reset({ + routes: [{ name: 'Login' }], + }) + }, [api, navigation, user]) + + return ( + + Settings + + navigation.navigate('SettingsAppearance')} + /> + + navigation.navigate('SetLanguage')} + /> + + + navigation.navigate('SettingsLicenses')} + /> + + + {api.isLoggedIn && ( + + + + )} + + + + ) +} diff --git a/apps/skolplattformen-app-new/components/settingsAppearance.component.tsx b/apps/skolplattformen-app-new/components/settingsAppearance.component.tsx new file mode 100644 index 000000000..442622a78 --- /dev/null +++ b/apps/skolplattformen-app-new/components/settingsAppearance.component.tsx @@ -0,0 +1,58 @@ +import { NavigationProp, useNavigation } from '@react-navigation/core' +import React from 'react' +import { ScrollView, StyleSheet, Switch } from 'react-native' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import useSettingsStorage from '../hooks/useSettingsStorage' +import { Layout as LayoutStyle, Sizing } from '../styles' +import { translate } from '../utils/translation' +import { RootStackParamList } from './navigation.component' +import { + SettingGroup, + SettingListItem, + SettingListSeparator, +} from './settingsComponents.component' + +export const settingsAppearanceRouteOptions = + (): NativeStackNavigationOptions => ({ + title: translate('settings.appearance'), + }) + +export const SettingsAppearanceScreen = () => { + const [isUsingSystemTheme, setUsingSystemTheme] = + useSettingsStorage('usingSystemTheme') + const navigation = useNavigation>() + + const [settingsTheme] = useSettingsStorage('theme') + + return ( + + + + + + {!isUsingSystemTheme && ( + <> + + navigation.navigate('SettingsAppearanceTheme')} + /> + + )} + + + ) +} + +const styles = StyleSheet.create({ + container: { + padding: Sizing.t4, + }, +}) diff --git a/apps/skolplattformen-app-new/components/settingsAppearanceTheme.component.tsx b/apps/skolplattformen-app-new/components/settingsAppearanceTheme.component.tsx new file mode 100644 index 000000000..7e792b960 --- /dev/null +++ b/apps/skolplattformen-app-new/components/settingsAppearanceTheme.component.tsx @@ -0,0 +1,52 @@ +import React from 'react' +import { ScrollView, StyleSheet, View } from 'react-native' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import useSettingsStorage from '../hooks/useSettingsStorage' +import { Layout as LayoutStyle, Sizing } from '../styles' +import { translate } from '../utils/translation' +import { + SettingGroup, + SettingListItemSelectable, +} from './settingsComponents.component' + +export const settingsAppearanceThemeRouteOptions = + (): NativeStackNavigationOptions => ({ + title: translate('settings.theme'), + }) + +const themes = ['light', 'dark'] + +export const SettingsAppearanceThemeScreen = () => { + const [settingsTheme, setSettingsTheme] = useSettingsStorage('theme') + + return ( + + + + {themes.map((theme) => { + return ( + setSettingsTheme(theme)} + title={translate(`themes.${theme}`)} + isSelected={theme === settingsTheme} + /> + ) + })} + + + + ) +} + +const styles = StyleSheet.create({ + container: { + padding: Sizing.t4, + }, + themeList: { + paddingHorizontal: Sizing.t4, + }, +}) diff --git a/apps/skolplattformen-app-new/components/settingsComponents.component.tsx b/apps/skolplattformen-app-new/components/settingsComponents.component.tsx new file mode 100644 index 000000000..dd00822c1 --- /dev/null +++ b/apps/skolplattformen-app-new/components/settingsComponents.component.tsx @@ -0,0 +1,194 @@ +import { + IconProps, + StyleService, + Text, + useStyleSheet, + useTheme, +} from '@ui-kitten/components' +import React, { useState } from 'react' +import { Pressable, TouchableOpacity, View } from 'react-native' +import { useLangRTL } from '../hooks/useLangRTL' +import { Sizing } from '../styles' +import { fontSize } from '../styles/typography' +import { CheckIcon, RightArrowIcon } from './icon.component' + +export const SettingListItem = ({ + label, + value, + icon: Icon, + onNavigate, + onPress, + children, +}: { + label?: string + value?: string + icon?: (props: IconProps) => JSX.Element + onNavigate?: () => void + onPress?: () => void + children?: React.ReactNode +}) => { + const textHintColor = useTheme()['text-hint-color'] + const styles = useStyleSheet(themedStyles) + const isRTL = useLangRTL() + + const [isPressing, setIsPressing] = useState(false) + + return ( + setIsPressing(true)} + onPressOut={() => setIsPressing(false)} + > + + {Icon && ( + + + + )} + + {label && ( + + {label} + + )} + {value && {value}} + {children} + + {onNavigate && ( + + + + )} + + + ) +} + +export const SettingListSeparator = () => { + const styles = useStyleSheet(themedStyles) + return +} + +export const SettingListItemWrapper = ({ + children, + isPressing = false, +}: { + isPressing?: boolean + children?: React.ReactNode +}) => { + const styles = useStyleSheet(themedStyles) + return ( + + {children} + + ) +} + +export const SettingGroup = ({ children }: { children?: React.ReactNode }) => { + const styles = useStyleSheet(themedStyles) + + return {children} +} + +export const SettingListItemSelectable = ({ + title, + subTitle, + isSelected, + onPress, +}: { + title: string + subTitle?: string + isSelected?: boolean + onPress: () => void +}) => { + const styles = useStyleSheet(themedStyles) + const colors = useTheme() + + return ( + + + {title} + {subTitle && ( + {subTitle} + )} + + {isSelected ? ( + + ) : null} + + ) +} + +const themedStyles = StyleService.create({ + group: { + backgroundColor: 'background-basic-color-1', + borderRadius: 15, + marginBottom: Sizing.t5, + overflow: 'hidden', + }, + listItem: { + paddingHorizontal: Sizing.t4, + paddingVertical: Sizing.t2, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + listItemButton: { + color: 'color-tab-focused', + }, + listItemPressed: { + backgroundColor: 'color-separator', + }, + listItemText: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + listItemLabel: { + ...fontSize.sm, + }, + listItemValue: { + ...fontSize.xs, + color: 'text-hint-color', + flexShrink: 0, + }, + separator: { + height: 1, + marginLeft: Sizing.t4, + backgroundColor: 'color-separator', + }, + icon: { + backgroundColor: 'color-primary-500', + borderRadius: 5, + padding: 3, + marginRight: Sizing.t3, + }, + arrow: { flexShrink: 0 }, + selectableButton: { + paddingVertical: Sizing.t2, + minHeight: 45, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + selectableButtonTitle: { + ...fontSize.base, + textAlign: 'left', + }, + selectableButtonSubtitle: { + ...fontSize.sm, + color: 'text-hint-color', + textAlign: 'left', + }, +}) diff --git a/apps/skolplattformen-app-new/components/settingsLicenses.component.tsx b/apps/skolplattformen-app-new/components/settingsLicenses.component.tsx new file mode 100644 index 000000000..03e78fed9 --- /dev/null +++ b/apps/skolplattformen-app-new/components/settingsLicenses.component.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import libraries from '../libraries.json' +import { translate } from '../utils/translation' +import { LibraryList } from './libraryList.component' + +export const settingsLicensesRouteOptions = + (): NativeStackNavigationOptions => ({ + title: `${translate('settings.licenses')}`, + }) + +export const SettingsLicensesScreen = () => { + return +} diff --git a/apps/skolplattformen-app-new/components/studentAvatar.component.tsx b/apps/skolplattformen-app-new/components/studentAvatar.component.tsx new file mode 100644 index 000000000..2989ca6b7 --- /dev/null +++ b/apps/skolplattformen-app-new/components/studentAvatar.component.tsx @@ -0,0 +1,37 @@ +import { Text, useTheme } from '@ui-kitten/components' +import React from 'react' +import { StyleSheet, View } from 'react-native' +import { fontSize } from '../styles/typography' +import { initials } from '../utils/peopleHelpers' + +export type StudentAvatarProps = { + name?: string + color: string +} + +export const StudentAvatar = ({ name, color }: StudentAvatarProps) => { + const colors = useTheme() + const bgColor = colors[`color-${color}-100`] + const textColor = colors[`color-${color}-900`] + + return ( + + {initials(name)} + + ) +} + +export const styles = StyleSheet.create({ + container: { + height: 44, + width: 44, + borderRadius: 300, + alignItems: 'center', + justifyContent: 'center', + }, + text: { + ...fontSize.lg, + fontFamily: 'Poppins-Medium', + fontWeight: '500', + }, +}) diff --git a/apps/skolplattformen-app-new/components/tabBarLabel.component.tsx b/apps/skolplattformen-app-new/components/tabBarLabel.component.tsx new file mode 100644 index 000000000..77336577f --- /dev/null +++ b/apps/skolplattformen-app-new/components/tabBarLabel.component.tsx @@ -0,0 +1,37 @@ +import { StyleService, Text, useStyleSheet } from '@ui-kitten/components' +import React from 'react' +import { View } from 'react-native' +import { fontSize } from '../styles/typography' + +export type TabBarLabelProps = { + label: string + focused: boolean +} + +export const TabBarLabel = ({ label, focused }: TabBarLabelProps) => { + const styles = useStyleSheet(themedStyles) + + return ( + + + {label} + + + ) +} + +const themedStyles = StyleService.create({ + label: { + fontWeight: '500', + color: 'color-tab-default', + ...fontSize.xxs, + }, + focused: { + color: 'color-tab-focused', + }, +}) diff --git a/apps/skolplattformen-app-new/components/transitionView.component.tsx b/apps/skolplattformen-app-new/components/transitionView.component.tsx new file mode 100644 index 000000000..fc85da387 --- /dev/null +++ b/apps/skolplattformen-app-new/components/transitionView.component.tsx @@ -0,0 +1,28 @@ +import React, { FunctionComponent } from 'react' +import { ViewProps } from 'react-native' +import * as Animatable from 'react-native-animatable' + +interface TransitionViewPropsType extends ViewProps { + animation?: string + duration?: number + index?: number +} +const transitionDuration = 500 + +export const TransitionView: FunctionComponent = ({ + index, + children, + ...rest +}) => { + return ( + + {children} + + ) +} diff --git a/apps/skolplattformen-app-new/components/versionInfo.component.tsx b/apps/skolplattformen-app-new/components/versionInfo.component.tsx new file mode 100644 index 000000000..810739084 --- /dev/null +++ b/apps/skolplattformen-app-new/components/versionInfo.component.tsx @@ -0,0 +1,20 @@ +import { Text } from '@ui-kitten/components' +import React from 'react' +import { StyleSheet, View } from 'react-native' +import { getBuildNumber, getVersion } from 'react-native-device-info' + +export const VersionInfo = () => { + return ( + + + v{getVersion()} ({getBuildNumber()}) + + + ) +} + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + }, +}) diff --git a/apps/skolplattformen-app-new/components/week.component.tsx b/apps/skolplattformen-app-new/components/week.component.tsx new file mode 100644 index 000000000..b55fd2530 --- /dev/null +++ b/apps/skolplattformen-app-new/components/week.component.tsx @@ -0,0 +1,277 @@ +import { Child, MenuItem, TimetableEntry } from '@skolplattformen/api' +import { useMenu, useTimetable } from '../libs/hooks/src' +import { + List, + ListItem, + StyleService, + Tab, + TabBar, + Text, + useStyleSheet, + ViewPager, +} from '@ui-kitten/components' +import moment from 'moment' +import React, { useEffect, useState } from 'react' +import { View } from 'react-native' +import { LanguageService } from '../services/languageService' +import { Sizing, Typography } from '../styles' +import { TransitionView } from './transitionView.component' +import { getMeaningfulStartingDate } from '../utils/calendarHelpers' +import { translate } from '../utils/translation' + +interface WeekProps { + child: Child +} + +interface LessonListProps { + lessons: TimetableEntry[] + lunch?: MenuItem + header: string +} + +interface DayProps { + weekDay: string + lunch?: MenuItem + lessons: TimetableEntry[] +} + +const LessonList = ({ lessons, header, lunch }: LessonListProps) => { + const styles = useStyleSheet(themedStyles) + + return ( + ( + + {header} + + )} + renderItem={({ + item: { id, code, name, timeStart, timeEnd, teacher, location }, + }) => ( + ( + + + {name} + + + )} + description={() => ( + + {`${timeStart.slice(0, 5)}-${timeEnd.slice(0, 5)} ${ + location === '' ? '' : '(' + location + ')' + } `} + + {code?.toUpperCase() === 'LUNCH' ? lunch?.description : teacher} + + + )} + /> + )} + /> + ) +} + +export const Day = ({ weekDay, lunch, lessons }: DayProps) => { + const styles = useStyleSheet(themedStyles) + + if (lessons.length <= 0) { + return null + } + return ( + + timeStart < '12:00')} + /> + timeStart >= '12:00')} + /> + + ) +} + +export const Week = ({ child }: WeekProps) => { + // const translate = (key: string) => key; + + moment.locale(LanguageService.getLocale()) + const days = moment.weekdaysShort().slice(1, 6) + const displayDate = getMeaningfulStartingDate(moment()) + + const currentDayIndex = Math.min(moment(displayDate).isoWeekday() - 1, 5) + const [selectedIndex, setSelectedIndex] = useState(currentDayIndex) + const [showSchema, setShowSchema] = useState(false) + const [year, week] = [displayDate.isoWeekYear(), displayDate.isoWeek()] + const { data: lessons } = useTimetable( + child, + week, + year, + LanguageService.getLanguageCode() + ) + let { data: menu } = useMenu(child) + + // Hide menu if we want to show next week but it is not monday yet. + // The menu for next week is not available until monday + const currentDate = moment() + const shouldShowLunchMenu = + menu[displayDate.isoWeekday() - 1] && + !(displayDate.isoWeekday() === 1 && currentDate.isoWeekday() !== 1) + if (!shouldShowLunchMenu) { + menu = [] + } + + const styles = useStyleSheet(themedStyles) + + useEffect(() => { + const shouldShowSchema = lessons.length > 0 + setShowSchema(shouldShowSchema) + }, [lessons]) + + const getWeekText = (date = moment()) => { + return `${translate('schedule.week')} ${date.isoWeek()}` + } + + return showSchema ? ( + + + {getWeekText(displayDate)} + setSelectedIndex(index)} + > + {days.map((weekDay, index) => ( + ( + <> + {weekDay} + + {displayDate + .startOf('isoWeek') + .add(index, 'day') + .format('D')} + + + )} + /> + ))} + + + setSelectedIndex(index)} + > + {days.map((weekDay, index) => ( + days[lesson.dayOfWeek - 1] === weekDay) + .sort((a, b) => a.timeStart.localeCompare(b.timeStart))} + /> + ))} + + + + ) : null +} + +const themedStyles = StyleService.create({ + view: { + backgroundColor: 'background-basic-color-1', + maxHeight: '65%', + paddingBottom: 0, + margin: 0, + }, + innerView: { + paddingBottom: 170, + margin: 0, + }, + part: { + backgroundColor: 'transparent', + width: '33%', + }, + tab: { + flexDirection: 'row', + padding: 0, + }, + item: { + height: 90, + backgroundColor: 'background-basic-color-2', + paddingHorizontal: 0, + borderRadius: 2, + margin: 2, + paddingLeft: Sizing.t2, + paddingRight: Sizing.t2, + width: '90%', + }, + time: { + color: 'color-basic-500', + fontSize: 9, + }, + dayTab: { + textAlign: 'left', + }, + summary: { + paddingRight: 20, + paddingLeft: 2, + }, + startTime: { + paddingBottom: 2, + }, + lunchLabel: { + paddingTop: 10, + paddingBottom: 2, + }, + lunch: { + width: 100, + }, + endTime: { + paddingTop: 10, + }, + pager: { + margin: 10, + ...Typography.fontWeight.bold, + }, + header: { + paddingLeft: 10, + }, + lessonTitle: { + ...Typography.fontWeight.semibold, + fontSize: 13, + }, + lessonDescription: { + fontSize: 13, + }, + lesson: { + flexDirection: 'column', + }, + weekNumber: { + marginLeft: 10, + marginTop: 10, + ...Typography.fontWeight.bold, + }, + tabTitle: { + textAlign: 'center', + }, + tabTitleDate: { + textAlign: 'center', + }, +}) diff --git a/apps/skolplattformen-app-new/context/feature/featureContext.tsx b/apps/skolplattformen-app-new/context/feature/featureContext.tsx new file mode 100644 index 000000000..8b4d21948 --- /dev/null +++ b/apps/skolplattformen-app-new/context/feature/featureContext.tsx @@ -0,0 +1,23 @@ +import { Features } from '@skolplattformen/api' + +import React from 'react' + +export const FeatureFlagsContext = React.createContext({ + LOGIN_BANK_ID_SAME_DEVICE_WITHOUT_ID: true, + FOOD_MENU: false, + CLASS_LIST: true, + LOGIN_FREJA_EID: false, //! this has been added +}) + +interface Props { + features: Features + children: React.ReactNode //! this has been added +} + +export const FeatureProvider: React.FC = (props) => { + return ( + + {props.children} + + ) +} diff --git a/apps/skolplattformen-app-new/context/language/languageContext.tsx b/apps/skolplattformen-app-new/context/language/languageContext.tsx new file mode 100644 index 000000000..3148e6887 --- /dev/null +++ b/apps/skolplattformen-app-new/context/language/languageContext.tsx @@ -0,0 +1,100 @@ +import React, { useState, useEffect, ReactNode } from 'react' +import * as RNLocalize from 'react-native-localize' +import { LoadingComponent } from '../../components/loading.component' + +import { LanguageService } from '../../services/languageService' +import { translations } from '../../utils/translation' + +import AppStorage from '../../services/appStorage' + +interface LanguageContextProps { + Strings: Record + languageCode?: string +} + +export const LanguageContext = React.createContext({ + Strings: {}, + languageCode: '', +}) + +interface Props { + children: ReactNode + data: any + initialLanguageCode?: string + cache: any +} + +export const LanguageProvider: React.FC = ({ + children, + data, + initialLanguageCode, + cache, +}) => { + const fallBack = { languageTag: 'sv', isRTL: false } + + LanguageService.setAllData({ data }) + + const [languageCode, setLanguageCode] = useState( + undefined + ) + + const setLanguageConfig = (langCode: string) => { + LanguageService.setLanguageCode({ langCode: langCode }) + LanguageService.seti18nConfig({ langCode: langCode }) + setLanguageCode(langCode) + } + + const [Strings, setStrings] = useState(() => { + if (initialLanguageCode && data[initialLanguageCode]) { + setLanguageConfig(initialLanguageCode) + + return data[initialLanguageCode] + } + + const { languageTag } = + RNLocalize.findBestLanguageTag(Object.keys(translations)) || fallBack + + const bestStrings = data[languageTag] + + return bestStrings + }) + + useEffect(() => { + LanguageService.onChange( + { key: 'LanguageProvider' }, + (langCode: string) => { + if (langCode && data[langCode]) { + setLanguageCode(langCode) + setStrings(data[langCode]) + if (cache) { + AppStorage.setSetting('langCode', langCode) + } + } + } + ) + + const checkLanguageLocal = async () => { + // Saved language + if (cache) { + // Get cached lang + const cachedLang = await AppStorage.getSetting('langCode') + + // Try to find best suited language + const { languageTag } = + RNLocalize.findBestLanguageTag(Object.keys(translations)) || fallBack + + const currentLanguageCode = cachedLang || languageTag + + setLanguageConfig(currentLanguageCode) + } + } + checkLanguageLocal() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + return ( + + {languageCode ? children : } + + ) +} diff --git a/apps/skolplattformen-app-new/context/schoolPlatform/schoolPlatformContext.tsx b/apps/skolplattformen-app-new/context/schoolPlatform/schoolPlatformContext.tsx new file mode 100644 index 000000000..e9bc4265a --- /dev/null +++ b/apps/skolplattformen-app-new/context/schoolPlatform/schoolPlatformContext.tsx @@ -0,0 +1,42 @@ +import useSettingsStorage from '../../hooks/useSettingsStorage' +import React, { createContext } from 'react' + +interface SchoolPlatformProps { + currentSchoolPlatform?: string + changeSchoolPlatform: (platform: string) => void +} + +const defaultState: SchoolPlatformProps = { + changeSchoolPlatform: (platform: string) => + console.log('DEBUG ONLY: changing to', platform), +} + +type SchoolPlatformProviderProps = { + children: React.ReactNode +} + +export const SchoolPlatformProvider: React.FC = ({ + children, +}) => { + const [currentSchoolPlatform, setCurrentSchoolPlatform] = useSettingsStorage( + 'currentSchoolPlatform' + ) + + const changeSchoolPlatform = (platform: any) => { + setCurrentSchoolPlatform(platform) + } + + return ( + + {children} + + ) +} + +export const SchoolPlatformContext = + createContext(defaultState) diff --git a/apps/skolplattformen-app-new/data/schoolPlatforms.ts b/apps/skolplattformen-app-new/data/schoolPlatforms.ts new file mode 100644 index 000000000..37ad63e3a --- /dev/null +++ b/apps/skolplattformen-app-new/data/schoolPlatforms.ts @@ -0,0 +1,22 @@ +import CookieManager from '@react-native-cookies/cookies' +import initHjarntorget, { + features as featuresHjarntorget, +} from '../libs/api-hjarntorget/lib/' +import initSkolplattformen, { + features as featuresSkolPlattformen, +} from '../libs/api-skolplattformen/lib/' + +export const schoolPlatforms = [ + { + id: 'stockholm-skolplattformen', + displayName: 'Stockholms stad (Skolplattformen)', + api: initSkolplattformen(fetch as any, CookieManager), + features: featuresSkolPlattformen, + }, + { + id: 'goteborg-hjarntorget', + displayName: 'Göteborgs Stad (Hjärntorget)', + api: initHjarntorget(fetch as any, CookieManager), + features: featuresHjarntorget, + }, +] diff --git a/apps/skolplattformen-app-new/design/dark.json b/apps/skolplattformen-app-new/design/dark.json new file mode 100644 index 000000000..ba349dbe3 --- /dev/null +++ b/apps/skolplattformen-app-new/design/dark.json @@ -0,0 +1,83 @@ +{ + "color-primary-50": "#FFECF9", + "color-primary-100": "#FEC9EF", + "color-primary-200": "#FD82DA", + "color-primary-300": "#FB3CC6", + "color-primary-400": "#EC04AB", + "color-primary-500": "#A60378", + "color-primary-600": "#880262", + "color-primary-700": "#6A024D", + "color-primary-800": "#4C0137", + "color-primary-900": "#2E0121", + "color-primary-transparent-100": "rgba(219, 37, 117, 0.08)", + "color-primary-transparent-200": "rgba(219, 37, 117, 0.16)", + "color-primary-transparent-300": "rgba(219, 37, 117, 0.24)", + "color-primary-transparent-400": "rgba(219, 37, 117, 0.32)", + "color-primary-transparent-500": "rgba(219, 37, 117, 0.4)", + "color-primary-transparent-600": "rgba(219, 37, 117, 0.48)", + "color-success-100": "#EEFACF", + "color-success-200": "#DAF6A1", + "color-success-300": "#B8E36F", + "color-success-400": "#93C948", + "color-success-500": "#64A518", + "color-success-600": "#4E8D11", + "color-success-700": "#3B760C", + "color-success-800": "#2A5F07", + "color-success-900": "#1E4F04", + "color-success-transparent-100": "rgba(100, 165, 24, 0.08)", + "color-success-transparent-200": "rgba(100, 165, 24, 0.16)", + "color-success-transparent-300": "rgba(100, 165, 24, 0.24)", + "color-success-transparent-400": "rgba(100, 165, 24, 0.32)", + "color-success-transparent-500": "rgba(100, 165, 24, 0.4)", + "color-success-transparent-600": "rgba(100, 165, 24, 0.48)", + "color-info-100": "#CFE3FB", + "color-info-200": "#A1C5F8", + "color-info-300": "#6F9EEA", + "color-info-400": "#4A7AD5", + "color-info-500": "#184BBA", + "color-info-600": "#11399F", + "color-info-700": "#0C2A85", + "color-info-800": "#071D6B", + "color-info-900": "#041459", + "color-info-transparent-100": "rgba(24, 75, 186, 0.08)", + "color-info-transparent-200": "rgba(24, 75, 186, 0.16)", + "color-info-transparent-300": "rgba(24, 75, 186, 0.24)", + "color-info-transparent-400": "rgba(24, 75, 186, 0.32)", + "color-info-transparent-500": "rgba(24, 75, 186, 0.4)", + "color-info-transparent-600": "rgba(24, 75, 186, 0.48)", + "color-warning-transparent-100": "rgba(204, 130, 4, 0.08)", + "color-warning-transparent-200": "rgba(204, 130, 4, 0.16)", + "color-warning-transparent-300": "rgba(204, 130, 4, 0.24)", + "color-warning-transparent-400": "rgba(204, 130, 4, 0.32)", + "color-warning-transparent-500": "rgba(204, 130, 4, 0.4)", + "color-warning-transparent-600": "rgba(204, 130, 4, 0.48)", + "color-danger-100": "#FBD6DC", + "color-danger-200": "#F8AFC2", + "color-danger-300": "#EA83A9", + "color-danger-400": "#D56097", + "color-danger-500": "#BA327F", + "color-danger-600": "#9F2476", + "color-danger-700": "#85196C", + "color-danger-800": "#6B0F5F", + "color-danger-900": "#590956", + "color-danger-transparent-100": "rgba(186, 50, 127, 0.08)", + "color-danger-transparent-200": "rgba(186, 50, 127, 0.16)", + "color-danger-transparent-300": "rgba(186, 50, 127, 0.24)", + "color-danger-transparent-400": "rgba(186, 50, 127, 0.32)", + "color-danger-transparent-500": "rgba(186, 50, 127, 0.4)", + "color-danger-transparent-600": "rgba(186, 50, 127, 0.48)", + "background-basic-color-1": "#0F1117", + "background-basic-color-2": "#030200", + "text-hint-color": "#B3BBCB", + "color-control-default": "#E5E7EB", + "color-basic-default": "$color-primary-800", + "color-basic-focus": "$color-primary-700", + "color-basic-hover": "$color-primary-700", + "color-basic-active": "$color-primary-700", + "color-basic-text": "$color-primary-100", + "color-input-border": "$color-basic-300", + "color-tab-default": "$color-primary-50", + "color-tab-focused": "$color-primary-200", + "color-button-ghost-text": "$color-primary-200", + "color-separator": "$color-basic-900" +} diff --git a/apps/skolplattformen-app-new/design/light.json b/apps/skolplattformen-app-new/design/light.json new file mode 100644 index 000000000..2fd6fadfa --- /dev/null +++ b/apps/skolplattformen-app-new/design/light.json @@ -0,0 +1,91 @@ +{ + "color-primary-50": "#FFECF9", + "color-primary-100": "#FEC9EF", + "color-primary-200": "#FD82DA", + "color-primary-300": "#FB3CC6", + "color-primary-400": "#EC04AB", + "color-primary-500": "#A60378", + "color-primary-600": "#880262", + "color-primary-700": "#6A024D", + "color-primary-800": "#4C0137", + "color-primary-900": "#2E0121", + "color-primary-transparent-100": "rgba(219, 37, 117, 0.08)", + "color-primary-transparent-200": "rgba(219, 37, 117, 0.16)", + "color-primary-transparent-300": "rgba(219, 37, 117, 0.24)", + "color-primary-transparent-400": "rgba(219, 37, 117, 0.32)", + "color-primary-transparent-500": "rgba(219, 37, 117, 0.4)", + "color-primary-transparent-600": "rgba(219, 37, 117, 0.48)", + "color-success-100": "#EEFACF", + "color-success-200": "#DAF6A1", + "color-success-300": "#B8E36F", + "color-success-400": "#93C948", + "color-success-500": "#64A518", + "color-success-600": "#4E8D11", + "color-success-700": "#3B760C", + "color-success-800": "#2A5F07", + "color-success-900": "#1E4F04", + "color-success-transparent-100": "rgba(100, 165, 24, 0.08)", + "color-success-transparent-200": "rgba(100, 165, 24, 0.16)", + "color-success-transparent-300": "rgba(100, 165, 24, 0.24)", + "color-success-transparent-400": "rgba(100, 165, 24, 0.32)", + "color-success-transparent-500": "rgba(100, 165, 24, 0.4)", + "color-success-transparent-600": "rgba(100, 165, 24, 0.48)", + "color-info-100": "#C6EEF8", + "color-info-200": "#90D9F1", + "color-info-300": "#55AED5", + "color-info-400": "#2B7DAC", + "color-info-500": "#004475", + "color-info-600": "#003464", + "color-info-700": "#002754", + "color-info-800": "#001B43", + "color-info-900": "#001338", + "color-info-transparent-100": "rgba(0, 68, 117, 0.08)", + "color-info-transparent-200": "rgba(0, 68, 117, 0.16)", + "color-info-transparent-300": "rgba(0, 68, 117, 0.24)", + "color-info-transparent-400": "rgba(0, 68, 117, 0.32)", + "color-info-transparent-500": "rgba(0, 68, 117, 0.4)", + "color-info-transparent-600": "rgba(0, 68, 117, 0.48)", + "color-warning-100": "#FCF1CA", + "color-warning-200": "#F9E097", + "color-warning-300": "#EFC662", + "color-warning-400": "#E0A93B", + "color-warning-500": "#CC8204", + "color-warning-600": "#AF6902", + "color-warning-700": "#925202", + "color-warning-800": "#763D01", + "color-warning-900": "#612F00", + "color-warning-transparent-100": "rgba(204, 130, 4, 0.08)", + "color-warning-transparent-200": "rgba(204, 130, 4, 0.16)", + "color-warning-transparent-300": "rgba(204, 130, 4, 0.24)", + "color-warning-transparent-400": "rgba(204, 130, 4, 0.32)", + "color-warning-transparent-500": "rgba(204, 130, 4, 0.4)", + "color-warning-transparent-600": "rgba(204, 130, 4, 0.48)", + "color-danger-100": "#FBD6DC", + "color-danger-200": "#F8AFC2", + "color-danger-300": "#EA83A9", + "color-danger-400": "#D56097", + "color-danger-500": "#BA327F", + "color-danger-600": "#9F2476", + "color-danger-700": "#85196C", + "color-danger-800": "#6B0F5F", + "color-danger-900": "#590956", + "color-danger-transparent-100": "rgba(186, 50, 127, 0.08)", + "color-danger-transparent-200": "rgba(186, 50, 127, 0.16)", + "color-danger-transparent-300": "rgba(186, 50, 127, 0.24)", + "color-danger-transparent-400": "rgba(186, 50, 127, 0.32)", + "color-danger-transparent-500": "rgba(186, 50, 127, 0.4)", + "color-danger-transparent-600": "rgba(186, 50, 127, 0.48)", + "text-hint-color": "#4B5466", + "color-basic-default": "$color-primary-50", + "color-basic-focus": "$color-primary-100", + "color-basic-hover": "$color-primary-100", + "color-basic-active": "$color-primary-100", + "color-basic-text": "$color-primary-800", + "color-input-border": "$color-basic-800", + "background-basic-color-1": "#fff", + "background-basic-color-2": "#F2F1F6", + "color-tab-default": "$color-basic-700", + "color-tab-focused": "$color-primary-500", + "color-button-ghost-text": "$color-primary-500", + "color-separator": "$color-basic-400" +} diff --git a/apps/skolplattformen-app-new/design/mapping.json b/apps/skolplattformen-app-new/design/mapping.json new file mode 100644 index 000000000..673f12c5b --- /dev/null +++ b/apps/skolplattformen-app-new/design/mapping.json @@ -0,0 +1,33 @@ +{ + "strict": { + "text-font-family": "Poppins-Regular", + "border-radius": 10 + }, + "components": { + "Button": { + "meta": {}, + "appearances": { + "ghost": { + "variantGroups": { + "status": { + "primary": { + "textColor": "$color-button-ghost-text", + "iconTintColor": "$color-button-ghost-text" + } + } + } + }, + "filled": { + "mapping": {}, + "variantGroups": { + "status": { + "basic": { + "textColor": "$color-basic-text" + } + } + } + } + } + } + } +} diff --git a/apps/skolplattformen-app-new/design/navigationThemes.ts b/apps/skolplattformen-app-new/design/navigationThemes.ts new file mode 100644 index 000000000..88f6d5f5c --- /dev/null +++ b/apps/skolplattformen-app-new/design/navigationThemes.ts @@ -0,0 +1,49 @@ +import { DarkTheme, DefaultTheme, Theme } from '@react-navigation/native' +import { NativeStackNavigationOptions } from '@react-navigation/native-stack' +import { darkTheme, lightTheme } from './themes' + +export const darkNavigationTheme: Theme = { + ...DarkTheme, + colors: { + ...DarkTheme.colors, + background: darkTheme['background-basic-color-2'], + border: darkTheme['background-basic-color-2'], + card: darkTheme['background-basic-color-2'], + primary: darkTheme['color-primary-200'], + text: '#ddd', + }, +} + +export const lightNavigationTheme: Theme = { + ...DefaultTheme, + colors: { + ...DefaultTheme.colors, + background: lightTheme['background-basic-color-2'], + border: lightTheme['background-basic-color-1'], + card: lightTheme['background-basic-color-1'], + primary: lightTheme['color-primary-500'], + }, +} + +export const defaultStackStyling = ( + darkMode: boolean +): NativeStackNavigationOptions => { + return { + headerStyle: { + backgroundColor: darkMode + ? darkTheme['background-basic-color-2'] + : lightTheme['background-basic-color-1'], + }, + headerLargeStyle: { + backgroundColor: darkMode + ? darkTheme['background-basic-color-2'] + : lightTheme['background-basic-color-2'], + }, + headerTitleStyle: { + fontFamily: 'Poppins-Medium', + }, + headerBackTitleStyle: { + fontFamily: 'Poppins-Regular', + }, + } +} diff --git a/apps/skolplattformen-app-new/design/themes.ts b/apps/skolplattformen-app-new/design/themes.ts new file mode 100644 index 000000000..83722b7e4 --- /dev/null +++ b/apps/skolplattformen-app-new/design/themes.ts @@ -0,0 +1,12 @@ +import * as eva from '@eva-design/eva' +import darkJsonTheme from './dark.json' +import lightJsonTheme from './light.json' + +export const darkTheme = { + ...eva.dark, + ...darkJsonTheme, +} +export const lightTheme = { + ...eva.light, + ...lightJsonTheme, +} diff --git a/apps/skolplattformen-app-new/docs/android_linux.md b/apps/skolplattformen-app-new/docs/android_linux.md new file mode 100644 index 000000000..db5fd7316 --- /dev/null +++ b/apps/skolplattformen-app-new/docs/android_linux.md @@ -0,0 +1,110 @@ +# Running Skolplattformen Android app on Linux + +## Installing dependencies + +You will need Node, the React Native command line interface, a JDK, and Android Studio. + +While you can use any editor of your choice to develop your app, you will need to install Android Studio in order to set up the necessary tooling to build your React Native app for Android. + +### Node + +Follow the [installation instructions for your Linux distribution](https://nodejs.org/en/download/package-manager/) to install Node 12 or newer. + +### Java Development Kit + +React Native requires at least the version 8 of the Java SE Development Kit (JDK). You may download and install [OpenJDK](http://openjdk.java.net) from [AdoptOpenJDK](https://adoptopenjdk.net/) or your system packager. You may also [Download and install Oracle JDK 14](https://www.oracle.com/java/technologies/javase-jdk14-downloads.html) if desired. + +### Android development environment + +Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. + +#### 1. Install Android Studio + +[Download and install Android Studio](https://developer.android.com/studio/index.html). While on Android Studio installation wizard, make sure the boxes next to all of the following items are checked: + +- `Android SDK` +- `Android SDK Platform` +- `Android Virtual Device` + +Then, click "Next" to install all of these components. + +> If the checkboxes are grayed out, you will have a chance to install these components later on. + +Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. + +#### 2. Install the Android SDK + +Android Studio installs the latest Android SDK by default. Building a React Native app with native code, however, requires the `Android 10 (Q)` SDK in particular. Additional Android SDKs can be installed through the SDK Manager in Android Studio. + +To do that, open Android Studio, click on "Configure" button and select "SDK Manager". + +> The SDK Manager can also be found within the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. + +Select the "SDK Platforms" tab from within the SDK Manager, then check the box next to "Show Package Details" in the bottom right corner. Look for and expand the `Android 10 (Q)` entry, then make sure the following items are checked: + +- `Android SDK Platform 29` +- `Intel x86 Atom_64 System Image` or `Google APIs Intel x86 Atom System Image` + +Next, select the "SDK Tools" tab and check the box next to "Show Package Details" here as well. Look for and expand the "Android SDK Build-Tools" entry, then make sure that `29.0.2` is selected. + +Finally, click "Apply" to download and install the Android SDK and related build tools. + +#### 3. Configure the ANDROID_HOME environment variable + +The React Native tools require some environment variables to be set up in order to build apps with native code. + +Add the following lines to your `$HOME/.bash_profile` or `$HOME/.bashrc` (if you are using `zsh` then `~/.zprofile` or `~/.zshrc`) config file: + +```shell +export ANDROID_HOME=$HOME/Android/Sdk +export PATH=$PATH:$ANDROID_HOME/emulator +export PATH=$PATH:$ANDROID_HOME/tools +export PATH=$PATH:$ANDROID_HOME/tools/bin +export PATH=$PATH:$ANDROID_HOME/platform-tools +``` + +> `.bash_profile` is specific to `bash`. If you're using another shell, you will need to edit the appropriate shell-specific config file. + +Type `source $HOME/.bash_profile` for `bash` or `source $HOME/.zprofile` to load the config into your current shell. Verify that ANDROID_HOME has been set by running `echo $ANDROID_HOME` and the appropriate directories have been added to your path by running `echo $PATH`. + +> Please make sure you use the correct Android SDK path. You can find the actual location of the SDK in the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. + +### Watchman + +Follow the [Watchman installation guide](https://facebook.github.io/watchman/docs/install/#buildinstall) to compile and install Watchman from source. + +> [Watchman](https://facebook.github.io/watchman/docs/install/) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance and increased compatibility in certain edge cases (translation: you may be able to get by without installing this, but your mileage may vary; installing this now may save you from a headache later). + +### React Native Command Line Interface + +React Native has a built-in command line interface. Rather than install and manage a specific version of the CLI globally, we recommend you access the current version at runtime using `npx`, which ships with Node.js. With `npx react-native `, the current stable version of the CLI will be downloaded and executed at the time the command is run. + +## Preparing the Android device + +You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. + +Either way, you will need to prepare the device to run Android apps for development. + +### Using a physical device + +If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable and following the instructions [here](https://reactnative.dev/docs/running-on-device). + +### Using a virtual device + +If you use Android Studio to open `./apps/skolplattformen-app/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: + +![Android Studio AVD Manager](/docs/assets/avd_icon.png) + +If you have recently installed Android Studio, you will likely need to [create a new AVD](https://developer.android.com/studio/run/managing-avds.html). Select "Create Virtual Device...", then pick any Phone from the list and click "Next", then select the **Q** API Level 29 image. + +> We recommend configuring [VM acceleration](https://developer.android.com/studio/run/emulator-acceleration.html#vm-linux) on your system to improve performance. Once you've followed those instructions, go back to the AVD Manager. + +Click "Next" then "Finish" to create your AVD. At this point you should be able to click on the green triangle button next to your AVD to launch it, then proceed to the next step. + +## Running the app + +Go to the root of the project and run the following command + +```shell +yarn run start:android +``` diff --git a/apps/skolplattformen-app-new/docs/android_mac.md b/apps/skolplattformen-app-new/docs/android_mac.md new file mode 100644 index 000000000..e55a450b3 --- /dev/null +++ b/apps/skolplattformen-app-new/docs/android_mac.md @@ -0,0 +1,112 @@ +# Running Skolplattformen Android app on Mac OS + +## Installing dependencies + +You will need Node, Watchman, the React Native command line interface, a JDK, and Android Studio. + +While you can use any editor of your choice to develop your app, you will need to install Android Studio in order to set up the necessary tooling to build your React Native app for Android. + +### Node & Watchman + +We recommend installing Node and Watchman using [Homebrew](http://brew.sh/). Run the following commands in a Terminal after installing Homebrew: + +```shell +brew install node +brew install watchman +``` + +If you have already installed Node on your system, make sure it is Node 16 or newer. + +[Watchman](https://facebook.github.io/watchman) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance. + +### Java Development Kit + +We recommend installing JDK using [Homebrew](http://brew.sh/). Run the following commands in a Terminal after installing Homebrew: + +```shell +brew install --cask adoptopenjdk/openjdk/adoptopenjdk8 +``` + +If you have already installed JDK on your system, make sure it is JDK 8 or newer. + +### Android development environment + +Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. + +#### 1. Install Android Studio + +[Download and install Android Studio](https://developer.android.com/studio/index.html). While on Android Studio installation wizard, make sure the boxes next to all of the following items are checked: + +- `Android SDK` +- `Android SDK Platform` +- `Android Virtual Device` + +Then, click "Next" to install all of these components. + +> If the checkboxes are grayed out, you will have a chance to install these components later on. + +Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. + +#### 2. Install the Android SDK + +Android Studio installs the latest Android SDK by default. Additional Android SDKs can be installed through the SDK Manager in Android Studio. + +To do that, open Android Studio, click on "Configure" button and select "SDK Manager". + +![Android Studio Welcome](/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeMacOS.png) + +> The SDK Manager can also be found within the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. + +Select the "SDK Platforms" tab from within the SDK Manager, then check the box next to "Show Package Details" in the bottom right corner. + +Next, select the "SDK Tools" tab and check the box next to "Show Package Details" here as well. + +Finally, click "Apply" to download and install the Android SDK and related build tools. + +#### 3. Configure the ANDROID_HOME environment variable + +The React Native tools require some environment variables to be set up in order to build apps with native code. + +Add the following lines to your `$HOME/.bash_profile` or `$HOME/.bashrc` (if you are using `zsh` then `~/.zprofile` or `~/.zshrc`) config file: + +```shell +export ANDROID_HOME=$HOME/Library/Android/sdk +export PATH=$PATH:$ANDROID_HOME/emulator +export PATH=$PATH:$ANDROID_HOME/tools +export PATH=$PATH:$ANDROID_HOME/tools/bin +export PATH=$PATH:$ANDROID_HOME/platform-tools +``` + +> `.bash_profile` is specific to `bash`. If you're using another shell, you will need to edit the appropriate shell-specific config file. + +Type `source $HOME/.bash_profile` for `bash` or `source $HOME/.zprofile` to load the config into your current shell. Verify that ANDROID_HOME has been set by running `echo $ANDROID_HOME` and the appropriate directories have been added to your path by running `echo $PATH`. + +> Please make sure you use the correct Android SDK path. You can find the actual location of the SDK in the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. + +### Preparing the Android device + +You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. + +Either way, you will need to prepare the device to run Android apps for development. + +### Using a physical device + +If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable. Read [running on a device](https://reactnative.dev/docs/running-on-device) for more information. + +### Using a virtual device + +If you use Android Studio to open `./apps/skolplattformen-app-new/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: + +![Android Studio AVD Manager](/apps/skolplattformen-app-new/docs/assets/avd_icon.png) + +If you have recently installed Android Studio, you will likely need to [create a new AVD](https://developer.android.com/studio/run/managing-avds.html). Select "Create Virtual Device...", then pick any Phone from the list and click "Next", then select the **Q** API Level 29 image. + +Click "Next" then "Finish" to create your AVD. At this point you should be able to click on the green triangle button next to your AVD to launch it, then proceed to the next step. + +## Running the app + +Go to the root of the project and run the following command + +```shell +npm run start android +``` diff --git a/apps/skolplattformen-app-new/docs/android_windows.md b/apps/skolplattformen-app-new/docs/android_windows.md new file mode 100644 index 000000000..39bf26721 --- /dev/null +++ b/apps/skolplattformen-app-new/docs/android_windows.md @@ -0,0 +1,130 @@ +# Running Skolplattformen Android app on Windows + +## Installing dependencies + +You will need Node, the React Native command line interface, a JDK, and Android Studio. + +While you can use any editor of your choice to develop your app, you will need to install Android Studio in order to set up the necessary tooling to build your React Native app for Android. + +### Node, JDK + +We recommend installing Node via [Chocolatey](https://chocolatey.org), a popular package manager for Windows. + +If you want to be able to switch between different Node versions, you might want to install Node via [nvm-windows](https://github.com/coreybutler/nvm-windows), a Node version manager for Windows. + +React Native also requires [Java SE Development Kit (JDK)](https://openjdk.java.net/projects/jdk8/), which can be installed using Chocolatey as well. + +Open an Administrator Command Prompt (right click Command Prompt and select "Run as Administrator"), then run the following command: + +```powershell +choco install -y nodejs.install openjdk8 +``` + +If you have already installed Node on your system, make sure it is Node 16 or newer. If you already have a JDK on your system, make sure it is version 8 or newer. + +> You can find additional installation options on [Node's Downloads page](https://nodejs.org/en/download/). + +> If you're using the latest version of Java Development Kit, you'll need to change the Gradle version of your project so it can recognize the JDK. You can do that by going to `apps\skolplattformen-app\android\gradle\wrapper\gradle-wrapper.properties` and changing the `distributionUrl` value to upgrade the Gradle version. You can check out [here the lastest releases of Gradle](https://gradle.org/releases/). + +### Android development environment + +Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. + +#### 1. Install Android Studio + +[Download and install Android Studio](https://developer.android.com/studio/index.html). While on Android Studio installation wizard, make sure the boxes next to all of the following items are checked: + +- `Android SDK` +- `Android SDK Platform` +- `Android Virtual Device` +- If you are not already using Hyper-V: `Performance (Intel ® HAXM)` ([See here for AMD or Hyper-V](https://android-developers.googleblog.com/2018/07/android-emulator-amd-processor-hyper-v.html)) + +Then, click "Next" to install all of these components. + +> If the checkboxes are grayed out, you will have a chance to install these components later on. + +Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. + +#### 2. Install the Android SDK + +Android Studio installs the latest Android SDK by default. Additional Android SDKs can be installed through the SDK Manager in Android Studio. + +To do that, open Android Studio, click on "Configure" button and select "SDK Manager". + +![Android Studio Welcome](/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeWindows.png) + +> The SDK Manager can also be found within the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. + +Select the "SDK Platforms" tab from within the SDK Manager, then check the box next to "Show Package Details" in the bottom right corner. + +Finally, click "Apply" to download and install the Android SDK and related build tools. + +#### 3. Configure the ANDROID_HOME environment variable + +The React Native tools require some environment variables to be set up in order to build apps with native code. + +1. Open the **Windows Control Panel.** +2. Click on **User Accounts,** then click **User Accounts** again +3. Click on **Change my environment variables** +4. Click on **New...** to create a new `ANDROID_HOME` user variable that points to the path to your Android SDK: + +![ANDROID_HOME Environment Variable](/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidEnvironmentVariableANDROID_HOME.png) + +The SDK is installed, by default, at the following location: + +```powershell +%LOCALAPPDATA%\Android\Sdk +``` + +You can find the actual location of the SDK in the Android Studio "Settings" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. + +Open a new Command Prompt window to ensure the new environment variable is loaded before proceeding to the next step. + +1. Open powershell +2. Copy and paste **Get-ChildItem -Path Env:\\** into powershell +3. Verify `ANDROID_HOME` has been added + +

4. Add platform-tools to Path

+ +1. Open the **Windows Control Panel.** +2. Click on **User Accounts,** then click **User Accounts** again +3. Click on **Change my environment variables** +4. Select the **Path** variable. +5. Click **Edit.** +6. Click **New** and add the path to platform-tools to the list. + +The default location for this folder is: + +```powershell +%LOCALAPPDATA%\Android\Sdk\platform-tools +``` + +### Preparing the Android device + +You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. + +Either way, you will need to prepare the device to run Android apps for development. + +### Using a physical device + +If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable and following the instructions [here](https://reactnative.dev/docs/running-on-device). + +### Using a virtual device + +If you use Android Studio to open `./apps/skolplattformen-app-new/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: + +![Android Studio AVD Manager](/apps/skolplattformen-app-new/docs/assets/avd_icon.png) + +If you have recently installed Android Studio, you will likely need to [create a new AVD](https://developer.android.com/studio/run/managing-avds.html). Select "Create Virtual Device...", then pick any Phone from the list. + +> If you don't have HAXM installed, click on "Install HAXM" or follow [these instructions](https://github.com/intel/haxm/wiki/Installation-Instructions-on-Windows) to set it up, then go back to the AVD Manager. + +Click "Next" then "Finish" to create your AVD. At this point you should be able to click on the green triangle button next to your AVD to launch it, then proceed to the next step. + +## Running the app + +Go to the root of the project and run the following command + +```shell +npm run start android +``` diff --git a/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidEnvironmentVariableANDROID_HOME.png b/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidEnvironmentVariableANDROID_HOME.png new file mode 100644 index 000000000..1d80d18cb Binary files /dev/null and b/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidEnvironmentVariableANDROID_HOME.png differ diff --git a/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeMacOS.png b/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeMacOS.png new file mode 100644 index 000000000..9a4399476 Binary files /dev/null and b/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeMacOS.png differ diff --git a/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeWindows.png b/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeWindows.png new file mode 100644 index 000000000..61348c1e3 Binary files /dev/null and b/apps/skolplattformen-app-new/docs/assets/GettingStartedAndroidStudioWelcomeWindows.png differ diff --git a/apps/skolplattformen-app-new/docs/assets/GettingStartedXcodeCommandLineTools.png b/apps/skolplattformen-app-new/docs/assets/GettingStartedXcodeCommandLineTools.png new file mode 100644 index 000000000..8b0d66a7c Binary files /dev/null and b/apps/skolplattformen-app-new/docs/assets/GettingStartedXcodeCommandLineTools.png differ diff --git a/apps/skolplattformen-app-new/docs/assets/MetroBundlerExample.png b/apps/skolplattformen-app-new/docs/assets/MetroBundlerExample.png new file mode 100644 index 000000000..a55cbb2c1 Binary files /dev/null and b/apps/skolplattformen-app-new/docs/assets/MetroBundlerExample.png differ diff --git a/apps/skolplattformen-app-new/docs/assets/avd_icon.png b/apps/skolplattformen-app-new/docs/assets/avd_icon.png new file mode 100644 index 000000000..2c872516e Binary files /dev/null and b/apps/skolplattformen-app-new/docs/assets/avd_icon.png differ diff --git a/apps/skolplattformen-app-new/docs/ios_mac.md b/apps/skolplattformen-app-new/docs/ios_mac.md new file mode 100644 index 000000000..180fe22de --- /dev/null +++ b/apps/skolplattformen-app-new/docs/ios_mac.md @@ -0,0 +1,60 @@ +# Running Skolplattformen iOS + +## Installing dependencies + +You will need Node, Watchman, the React Native command line interface, Xcode and CocoaPods. + +While you can use any editor of your choice to develop your app, you will need to install Xcode in order to set up the necessary tooling to build your React Native app for iOS. + +### Node & Watchman + +We recommend installing Node and Watchman using [Homebrew](http://brew.sh/). Run the following commands in a Terminal after installing Homebrew: + +```shell +brew install node +brew install watchman +``` + +If you have already installed Node on your system, make sure it is Node 12 or newer. + +[Watchman](https://facebook.github.io/watchman) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance. + +### Xcode + +The easiest way to install Xcode is via the [Mac App Store](https://itunes.apple.com/us/app/xcode/id497799835?mt=12). Installing Xcode will also install the iOS Simulator and all the necessary tools to build your iOS app. + +If you have already installed Xcode on your system, make sure it is version 10 or newer. + +#### Command Line Tools + +You will also need to install the Xcode Command Line Tools. Open Xcode, then choose "Preferences..." from the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown. + +![Xcode Command Line Tools](/docs/assets/GettingStartedXcodeCommandLineTools.png) + +#### Installing an iOS Simulator in Xcode + +To install a simulator, open Xcode > Preferences... and select the Components tab. Select a simulator with the corresponding version of iOS you wish to use. + +#### CocoaPods + +[CocoaPods](https://cocoapods.org/) is built with Ruby and it will be installable with the default Ruby available on macOS. You can use a Ruby Version manager, however we recommend that you use the standard Ruby available on macOS unless you know what you're doing. + +Using the default Ruby install will require you to use `sudo` when installing gems. (This is only an issue for the duration of the gem installation, though.) + +```shell +sudo gem install cocoapods +``` + +For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html). + +### Running on a device + +The above command will automatically run your app on the iOS Simulator by default. If you want to run the app on an actual physical iOS device, please follow the instructions [here](https://reactnative.dev/docs/running-on-device. + +## Running the app + +Go to the root of the project and run the following command + +```shell +npm run start ios +``` diff --git a/apps/skolplattformen-app-new/hooks/__tests__/usePersonalStorage.tests.ts b/apps/skolplattformen-app-new/hooks/__tests__/usePersonalStorage.tests.ts new file mode 100644 index 000000000..5a14ebf7f --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/__tests__/usePersonalStorage.tests.ts @@ -0,0 +1,82 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' +import { User } from '@skolplattformen/api' +import { act, renderHook } from '@testing-library/react' +import usePersonalStorage from '../usePersonalStorage' + +beforeEach(async () => { + jest.clearAllMocks() + await AsyncStorage.clear() +}) + +const user: User = { personalNumber: '201701012393' } +const prefix = user.personalNumber + '_' + +test('use key prefix on set', async () => { + const { result } = renderHook(() => usePersonalStorage(user, 'key', '')) + + const [, setValue] = result.current + await act(() => { + setValue('foo') + }) + + expect(await AsyncStorage.getItem(prefix + 'key')).toEqual( + JSON.stringify('foo') + ) +}) + +test('return inital value if no set', async () => { + const { result } = renderHook(() => + usePersonalStorage(user, 'key', 'initialValue') + ) + + const [value] = result.current + + expect(value).toEqual('initialValue') + expect(await AsyncStorage.getItem(prefix + 'key')).toEqual(null) +}) + +test('update value', async () => { + const { result } = renderHook(() => + usePersonalStorage(user, 'key', 'initialValue') + ) + + const [initValue, setValue] = result.current + + await act(() => { + setValue('update') + }) + + const [updateValue] = result.current + + expect(initValue).toEqual('initialValue') + expect(updateValue).toEqual('update') + + expect(await AsyncStorage.getItem(prefix + 'key')).toEqual( + JSON.stringify('update') + ) +}) + +test('do nothing if personalId is empty', async () => { + const emptyUser: User = { personalNumber: '' } + let hookUser = emptyUser + const { result, rerender } = renderHook(() => + usePersonalStorage(hookUser, 'key', '') + ) + + await act(() => { + const [, setValue] = result.current + setValue('foo') + }) + + expect(AsyncStorage.setItem).not.toHaveBeenCalled() + + hookUser = user + rerender() + + await act(() => { + const [, setValue] = result.current + setValue('foo') + }) + + expect(AsyncStorage.setItem).toHaveBeenCalled() +}) diff --git a/apps/skolplattformen-app-new/hooks/__tests__/useSettingsStorage.tests.ts b/apps/skolplattformen-app-new/hooks/__tests__/useSettingsStorage.tests.ts new file mode 100644 index 000000000..b79d339f5 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/__tests__/useSettingsStorage.tests.ts @@ -0,0 +1,47 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' +import { act, renderHook } from '@testing-library/react' +import AppStorage from '../../services/appStorage' +import useSettingsStorage, { settingsState } from '../useSettingsStorage' + +beforeEach(() => { + AsyncStorage.clear() + // TODO: This is a bit ugly. Should probably fix that. + settingsState.settings.theme = 'light' +}) + +const prefix = AppStorage.settingsStorageKeyPrefix + +test('use key prefix on set', async () => { + const { result } = renderHook(() => useSettingsStorage('theme')) + + const [, setValue] = result.current + + await act(async () => { + setValue('dark') + }) + + const data = await AsyncStorage.getItem(prefix + 'SETTINGS') + const parsed = JSON.parse(data ?? '') + + expect(parsed.theme).toEqual('dark') +}) + +test('update value', async () => { + const { result } = renderHook(() => useSettingsStorage('theme')) + + const [initValue, setValue] = result.current + + await act(async () => { + setValue('dark') + }) + + const [updateValue] = result.current + + expect(initValue).toEqual('light') + expect(updateValue).toEqual('dark') + + const data = await AsyncStorage.getItem(prefix + 'SETTINGS') + const parsed = JSON.parse(data ?? '') + + expect(parsed.theme).toEqual('dark') +}) diff --git a/apps/skolplattformen-app-new/hooks/__tests__/useTempStorage.tests.ts b/apps/skolplattformen-app-new/hooks/__tests__/useTempStorage.tests.ts new file mode 100644 index 000000000..898216704 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/__tests__/useTempStorage.tests.ts @@ -0,0 +1,51 @@ +import { renderHook, act } from '@testing-library/react' +import AsyncStorage from '@react-native-async-storage/async-storage' +import useTempStorage from '../useTempStorage' +import AppStorage from '../../services/appStorage' + +beforeEach(() => { + AsyncStorage.clear() +}) + +const prefix = AppStorage.tempStorageKeyPrefix + +test('use key prefix on set', async () => { + const { result } = renderHook(() => useTempStorage('key', '')) + + await act(() => { + const [, setValue] = result.current + setValue('foo') + }) + + expect(await AsyncStorage.getItem(prefix + 'key')).toEqual( + JSON.stringify('foo') + ) +}) + +test('return inital value if no set', async () => { + const { result } = renderHook(() => useTempStorage('key', 'initialValue')) + + const [value] = result.current + + expect(value).toEqual('initialValue') + expect(await AsyncStorage.getItem(prefix + 'key')).toEqual(null) +}) + +test('update value', async () => { + const { result } = renderHook(() => useTempStorage('key', 'initialValue')) + + const [initValue, setValue] = result.current + + await act(() => { + setValue('update') + }) + + const [updateValue] = result.current + + expect(initValue).toEqual('initialValue') + expect(updateValue).toEqual('update') + + expect(await AsyncStorage.getItem(prefix + 'key')).toEqual( + JSON.stringify('update') + ) +}) diff --git a/apps/skolplattformen-app-new/hooks/useAppState.tsx b/apps/skolplattformen-app-new/hooks/useAppState.tsx new file mode 100644 index 000000000..e59c1d0b9 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useAppState.tsx @@ -0,0 +1,21 @@ +import { useEffect, useState } from 'react' +import { AppState, AppStateStatus } from 'react-native' + +export const useAppState = () => { + const currentState = AppState.currentState + const [appState, setAppState] = useState(currentState) + + function onChange(newState: AppStateStatus) { + setAppState(newState) + } + + useEffect(() => { + AppState.addEventListener('change', onChange) + + // return () => { + // AppState.removeEventListener('change', onChange); + // }; + }, []) + + return appState +} diff --git a/apps/skolplattformen-app-new/hooks/useAsyncStorage.tsx b/apps/skolplattformen-app-new/hooks/useAsyncStorage.tsx new file mode 100644 index 000000000..84868fa27 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useAsyncStorage.tsx @@ -0,0 +1,41 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' +import { useEffect, useState } from 'react' + +export default function useAsyncStorage( + storageKey: string, + defaultValue: T +): [T, (val: T) => void] { + const [storageItem, setStorageItem] = useState(defaultValue) + + async function setStoredValue(value: T) { + try { + if (!storageKey) { + return + } + await AsyncStorage.setItem(storageKey, JSON.stringify(value)) + setStorageItem(value) + } catch (e) { + // noop + } + } + + useEffect(() => { + async function getStoredValue() { + try { + const data = await AsyncStorage.getItem(storageKey) + if (typeof data === 'string') { + setStorageItem(JSON.parse(data)) + } + } catch (e) { + // noop + } + } + + getStoredValue() + }, [storageKey]) + + return [ + storageItem !== undefined ? storageItem : defaultValue, + setStoredValue, + ] +} diff --git a/apps/skolplattformen-app-new/hooks/useFeature.tsx b/apps/skolplattformen-app-new/hooks/useFeature.tsx new file mode 100644 index 000000000..fb822ddb6 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useFeature.tsx @@ -0,0 +1,12 @@ +import { Features, FeatureType } from '@skolplattformen/api' +import React from 'react' +import { FeatureFlagsContext } from '../context/feature/featureContext' + +export const useFeature = (name: FeatureType) => { + const features = React.useContext(FeatureFlagsContext) + if (features === null) { + throw new Error('You must wrap your components in a FeatureProvider.') + } + + return features[name] +} diff --git a/apps/skolplattformen-app-new/hooks/useLangCode.tsx b/apps/skolplattformen-app-new/hooks/useLangCode.tsx new file mode 100644 index 000000000..014c532ec --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useLangCode.tsx @@ -0,0 +1,25 @@ +import { useEffect, useRef, useState } from 'react' +import { LanguageService } from '../services/languageService' + +const generateKey = () => { + return `${Date.now()}-${Math.random() * 1000}` +} + +export const useLangCode = () => { + const [langCode, setLangCode] = useState(LanguageService.getLanguageCode()) + + const key = useRef(generateKey()) + + useEffect(() => { + const unsubscribe = LanguageService.onChange( + { key: key.current }, + (lang) => { + setLangCode(lang) + } + ) + + return () => unsubscribe() + }, []) + + return langCode +} diff --git a/apps/skolplattformen-app-new/hooks/useLangRTL.tsx b/apps/skolplattformen-app-new/hooks/useLangRTL.tsx new file mode 100644 index 000000000..747b8f7b6 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useLangRTL.tsx @@ -0,0 +1,7 @@ +import { isRTL } from '../services/languageService' +import { useLangCode } from './useLangCode' + +export const useLangRTL = () => { + const langCode = useLangCode() + return isRTL(langCode) +} diff --git a/apps/skolplattformen-app-new/hooks/useLanguage.tsx b/apps/skolplattformen-app-new/hooks/useLanguage.tsx new file mode 100644 index 000000000..b6c815c7d --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useLanguage.tsx @@ -0,0 +1,14 @@ +import { useContext } from 'react' +import { LanguageContext } from '../context/language/languageContext' +import { LanguageService } from '../services/languageService' + +export const useLanguage = () => { + const { Strings } = useContext(LanguageContext) + + const setLanguageCode = ({ languageCode }: { languageCode: string }) => { + LanguageService.setLanguageCode({ langCode: languageCode }) + LanguageService.seti18nConfig({ langCode: languageCode }) + } + + return { Strings, setLanguageCode } +} diff --git a/apps/skolplattformen-app-new/hooks/usePersonalStorage.tsx b/apps/skolplattformen-app-new/hooks/usePersonalStorage.tsx new file mode 100644 index 000000000..7143a5f72 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/usePersonalStorage.tsx @@ -0,0 +1,12 @@ +import { User } from '@skolplattformen/api' +import useAsyncStorage from './useAsyncStorage' + +export default function usePersonalStorage( + user: User, + storageKey: string, + defaultValue: T +): [T, (val: T) => void] { + const internalKey = + user && user.personalNumber ? user.personalNumber + '_' + storageKey : '' + return useAsyncStorage(internalKey, defaultValue) +} diff --git a/apps/skolplattformen-app-new/hooks/useSettingsStorage.tsx b/apps/skolplattformen-app-new/hooks/useSettingsStorage.tsx new file mode 100644 index 000000000..90e82460f --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useSettingsStorage.tsx @@ -0,0 +1,60 @@ +import { useCallback } from 'react' +import { proxy, subscribe, useSnapshot } from 'valtio' +import AppStorage from '../services/appStorage' + +export type ChildPersonalNumbers = Record + +export const settingsState = proxy({ + hydrated: false, + settings: { + loginMethodId: 'thisdevice' as + | 'thisdevice' + | 'otherdevice' + | 'testuser' + | 'freja', + usingSystemTheme: true, + theme: 'light', + cachedPersonalIdentityNumber: '', + currentSchoolPlatform: 'stockholm-skolplattformen' as + | 'stockholm-skolplattformen' + | 'goteborg-hjarntorget', + childPersonalIdentityNumber: {} as ChildPersonalNumbers, + }, +}) + +export type Settings = (typeof settingsState)['settings'] + +const SETTINGS_STORAGE_KEY = 'SETTINGS' + +subscribe(settingsState, () => { + AppStorage.setSetting(SETTINGS_STORAGE_KEY, settingsState.settings) +}) + +export const initializeSettingsState = async () => { + const settings = await AppStorage.getSetting(SETTINGS_STORAGE_KEY) + + settingsState.hydrated = true + + if (settings) { + settingsState.settings = { + ...settingsState.settings, + ...settings, + } + } +} + +export default function useSettingsStorage< + TKey extends keyof Settings, + TValue = Settings[TKey] +>(key: TKey) { + const { settings } = useSnapshot(settingsState) + + const setter = useCallback( + (value: TValue) => { + settingsState.settings[key] = value as any + }, + [key] + ) + + return [settings[key], setter] as const +} diff --git a/apps/skolplattformen-app-new/hooks/useTempStorage.tsx b/apps/skolplattformen-app-new/hooks/useTempStorage.tsx new file mode 100644 index 000000000..3de5875d1 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useTempStorage.tsx @@ -0,0 +1,10 @@ +import useAsyncStorage from './useAsyncStorage' +import AppStorage from '../services/appStorage' + +export default function useTempStorage( + storageKey: string, + defaultValue: T +): [T, (val: T) => void] { + const tempKey = AppStorage.tempStorageKeyPrefix + storageKey + return useAsyncStorage(tempKey, defaultValue) +} diff --git a/apps/skolplattformen-app-new/hooks/useTranslation.tsx b/apps/skolplattformen-app-new/hooks/useTranslation.tsx new file mode 100644 index 000000000..973e71c03 --- /dev/null +++ b/apps/skolplattformen-app-new/hooks/useTranslation.tsx @@ -0,0 +1,13 @@ +import i18n from 'i18n-js' +import { useMemo } from 'react' +import { useLangCode } from './useLangCode' + +// const i18n = new I18n(); + +export const useTranslation = () => { + const langCode = useLangCode() + const output = useMemo(() => { + return { t: i18n.t, langCode } + }, [langCode]) + return output +} diff --git a/apps/skolplattformen-app-new/index.js b/apps/skolplattformen-app-new/index.js new file mode 100644 index 000000000..cbef63e56 --- /dev/null +++ b/apps/skolplattformen-app-new/index.js @@ -0,0 +1,9 @@ +/** + * @format + */ + +import { AppRegistry } from 'react-native' +import App from './App' +import { name as appName } from './app.json' + +AppRegistry.registerComponent(appName, () => App) diff --git a/apps/skolplattformen-app-new/ios/.xcode.env b/apps/skolplattformen-app-new/ios/.xcode.env new file mode 100644 index 000000000..3d5782c71 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/apps/skolplattformen-app-new/ios/Podfile b/apps/skolplattformen-app-new/ios/Podfile new file mode 100644 index 000000000..f1b703868 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/Podfile @@ -0,0 +1,62 @@ +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip + +platform :ios, min_ios_version_supported +prepare_react_native_project! + +# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. +# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded +# +# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` +# ```js +# module.exports = { +# dependencies: { +# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), +# ``` +flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled + +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + +target 'app' do + config = use_native_modules! + + # Flags change depending on the env values. + flags = get_default_flags() + + use_react_native!( + :path => config[:reactNativePath], + # Hermes is now enabled by default. Disable by setting this flag to false. + :hermes_enabled => flags[:hermes_enabled], + :fabric_enabled => flags[:fabric_enabled], + # Enables Flipper. + # + # Note that if you have use_frameworks! enabled, Flipper will not work and + # you should disable the next line. + :flipper_configuration => flipper_config, + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}/.." + ) + + target 'appTests' do + inherit! :complete + # Pods for testing + end + + post_install do |installer| + # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 + react_native_post_install( + installer, + config[:reactNativePath], + :mac_catalyst_enabled => false + ) + __apply_Xcode_12_5_M1_post_install_workaround(installer) + end +end diff --git a/apps/skolplattformen-app-new/ios/Podfile.lock b/apps/skolplattformen-app-new/ios/Podfile.lock new file mode 100644 index 000000000..4764324b2 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/Podfile.lock @@ -0,0 +1,804 @@ +PODS: + - boost (1.76.0) + - CocoaAsyncSocket (7.6.5) + - DoubleConversion (1.1.6) + - FBLazyVector (0.72.5) + - FBReactNativeSpec (0.72.5): + - RCT-Folly (= 2021.07.22.00) + - RCTRequired (= 0.72.5) + - RCTTypeSafety (= 0.72.5) + - React-Core (= 0.72.5) + - React-jsi (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - Flipper (0.182.0): + - Flipper-Folly (~> 2.6) + - Flipper-Boost-iOSX (1.76.0.1.11) + - Flipper-DoubleConversion (3.2.0.1) + - Flipper-Fmt (7.1.7) + - Flipper-Folly (2.6.10): + - Flipper-Boost-iOSX + - Flipper-DoubleConversion + - Flipper-Fmt (= 7.1.7) + - Flipper-Glog + - libevent (~> 2.1.12) + - OpenSSL-Universal (= 1.1.1100) + - Flipper-Glog (0.5.0.5) + - Flipper-PeerTalk (0.0.4) + - FlipperKit (0.182.0): + - FlipperKit/Core (= 0.182.0) + - FlipperKit/Core (0.182.0): + - Flipper (~> 0.182.0) + - FlipperKit/CppBridge + - FlipperKit/FBCxxFollyDynamicConvert + - FlipperKit/FBDefines + - FlipperKit/FKPortForwarding + - SocketRocket (~> 0.6.0) + - FlipperKit/CppBridge (0.182.0): + - Flipper (~> 0.182.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.182.0): + - Flipper-Folly (~> 2.6) + - FlipperKit/FBDefines (0.182.0) + - FlipperKit/FKPortForwarding (0.182.0): + - CocoaAsyncSocket (~> 7.6) + - Flipper-PeerTalk (~> 0.0.4) + - FlipperKit/FlipperKitHighlightOverlay (0.182.0) + - FlipperKit/FlipperKitLayoutHelpers (0.182.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutTextSearchable + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.182.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutHelpers + - YogaKit (~> 1.18) + - FlipperKit/FlipperKitLayoutPlugin (0.182.0): + - FlipperKit/Core + - FlipperKit/FlipperKitHighlightOverlay + - FlipperKit/FlipperKitLayoutHelpers + - FlipperKit/FlipperKitLayoutIOSDescriptors + - FlipperKit/FlipperKitLayoutTextSearchable + - YogaKit (~> 1.18) + - FlipperKit/FlipperKitLayoutTextSearchable (0.182.0) + - FlipperKit/FlipperKitNetworkPlugin (0.182.0): + - FlipperKit/Core + - FlipperKit/FlipperKitReactPlugin (0.182.0): + - FlipperKit/Core + - FlipperKit/FlipperKitUserDefaultsPlugin (0.182.0): + - FlipperKit/Core + - FlipperKit/SKIOSNetworkPlugin (0.182.0): + - FlipperKit/Core + - FlipperKit/FlipperKitNetworkPlugin + - fmt (6.2.1) + - glog (0.3.5) + - hermes-engine (0.72.5): + - hermes-engine/Pre-built (= 0.72.5) + - hermes-engine/Pre-built (0.72.5) + - libevent (2.1.12) + - OpenSSL-Universal (1.1.1100) + - RCT-Folly (2021.07.22.00): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - RCT-Folly/Default (= 2021.07.22.00) + - RCT-Folly/Default (2021.07.22.00): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - RCT-Folly/Futures (2021.07.22.00): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - libevent + - RCTRequired (0.72.5) + - RCTTypeSafety (0.72.5): + - FBLazyVector (= 0.72.5) + - RCTRequired (= 0.72.5) + - React-Core (= 0.72.5) + - React (0.72.5): + - React-Core (= 0.72.5) + - React-Core/DevSupport (= 0.72.5) + - React-Core/RCTWebSocket (= 0.72.5) + - React-RCTActionSheet (= 0.72.5) + - React-RCTAnimation (= 0.72.5) + - React-RCTBlob (= 0.72.5) + - React-RCTImage (= 0.72.5) + - React-RCTLinking (= 0.72.5) + - React-RCTNetwork (= 0.72.5) + - React-RCTSettings (= 0.72.5) + - React-RCTText (= 0.72.5) + - React-RCTVibration (= 0.72.5) + - React-callinvoker (0.72.5) + - React-Codegen (0.72.5): + - DoubleConversion + - FBReactNativeSpec + - glog + - hermes-engine + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-Core + - React-jsi + - React-jsiexecutor + - React-NativeModulesApple + - React-rncore + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - React-Core (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default (= 0.72.5) + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/CoreModulesHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/Default (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/DevSupport (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default (= 0.72.5) + - React-Core/RCTWebSocket (= 0.72.5) + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector (= 0.72.5) + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTActionSheetHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTAnimationHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTBlobHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTImageHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTLinkingHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTNetworkHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTSettingsHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTTextHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTVibrationHeaders (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-Core/RCTWebSocket (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default (= 0.72.5) + - React-cxxreact + - React-hermes + - React-jsi + - React-jsiexecutor + - React-perflogger + - React-runtimeexecutor + - React-utils + - SocketRocket (= 0.6.1) + - Yoga + - React-CoreModules (0.72.5): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.72.5) + - React-Codegen (= 0.72.5) + - React-Core/CoreModulesHeaders (= 0.72.5) + - React-jsi (= 0.72.5) + - React-RCTBlob + - React-RCTImage (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - SocketRocket (= 0.6.1) + - React-cxxreact (0.72.5): + - boost (= 1.76.0) + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-callinvoker (= 0.72.5) + - React-debug (= 0.72.5) + - React-jsi (= 0.72.5) + - React-jsinspector (= 0.72.5) + - React-logger (= 0.72.5) + - React-perflogger (= 0.72.5) + - React-runtimeexecutor (= 0.72.5) + - React-debug (0.72.5) + - React-hermes (0.72.5): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - RCT-Folly/Futures (= 2021.07.22.00) + - React-cxxreact (= 0.72.5) + - React-jsi + - React-jsiexecutor (= 0.72.5) + - React-jsinspector (= 0.72.5) + - React-perflogger (= 0.72.5) + - React-jsi (0.72.5): + - boost (= 1.76.0) + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-jsiexecutor (0.72.5): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-cxxreact (= 0.72.5) + - React-jsi (= 0.72.5) + - React-perflogger (= 0.72.5) + - React-jsinspector (0.72.5) + - React-logger (0.72.5): + - glog + - react-native-cookies (6.2.1): + - React-Core + - react-native-restart (0.0.27): + - React-Core + - react-native-safe-area-context (4.7.2): + - React-Core + - react-native-simple-toast (3.0.1): + - React-Core + - Toast (~> 4) + - react-native-webview (13.6.0): + - React-Core + - React-NativeModulesApple (0.72.5): + - hermes-engine + - React-callinvoker + - React-Core + - React-cxxreact + - React-jsi + - React-runtimeexecutor + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - React-perflogger (0.72.5) + - React-RCTActionSheet (0.72.5): + - React-Core/RCTActionSheetHeaders (= 0.72.5) + - React-RCTAnimation (0.72.5): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.72.5) + - React-Codegen (= 0.72.5) + - React-Core/RCTAnimationHeaders (= 0.72.5) + - React-jsi (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - React-RCTAppDelegate (0.72.5): + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-Core + - React-CoreModules + - React-hermes + - React-NativeModulesApple + - React-RCTImage + - React-RCTNetwork + - React-runtimescheduler + - ReactCommon/turbomodule/core + - React-RCTBlob (0.72.5): + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Codegen (= 0.72.5) + - React-Core/RCTBlobHeaders (= 0.72.5) + - React-Core/RCTWebSocket (= 0.72.5) + - React-jsi (= 0.72.5) + - React-RCTNetwork (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - React-RCTImage (0.72.5): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.72.5) + - React-Codegen (= 0.72.5) + - React-Core/RCTImageHeaders (= 0.72.5) + - React-jsi (= 0.72.5) + - React-RCTNetwork (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - React-RCTLinking (0.72.5): + - React-Codegen (= 0.72.5) + - React-Core/RCTLinkingHeaders (= 0.72.5) + - React-jsi (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - React-RCTNetwork (0.72.5): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.72.5) + - React-Codegen (= 0.72.5) + - React-Core/RCTNetworkHeaders (= 0.72.5) + - React-jsi (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - React-RCTSettings (0.72.5): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.72.5) + - React-Codegen (= 0.72.5) + - React-Core/RCTSettingsHeaders (= 0.72.5) + - React-jsi (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - React-RCTText (0.72.5): + - React-Core/RCTTextHeaders (= 0.72.5) + - React-RCTVibration (0.72.5): + - RCT-Folly (= 2021.07.22.00) + - React-Codegen (= 0.72.5) + - React-Core/RCTVibrationHeaders (= 0.72.5) + - React-jsi (= 0.72.5) + - ReactCommon/turbomodule/core (= 0.72.5) + - React-rncore (0.72.5) + - React-runtimeexecutor (0.72.5): + - React-jsi (= 0.72.5) + - React-runtimescheduler (0.72.5): + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-callinvoker + - React-debug + - React-jsi + - React-runtimeexecutor + - React-utils (0.72.5): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-debug + - ReactCommon/turbomodule/bridging (0.72.5): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-callinvoker (= 0.72.5) + - React-cxxreact (= 0.72.5) + - React-jsi (= 0.72.5) + - React-logger (= 0.72.5) + - React-perflogger (= 0.72.5) + - ReactCommon/turbomodule/core (0.72.5): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-callinvoker (= 0.72.5) + - React-cxxreact (= 0.72.5) + - React-jsi (= 0.72.5) + - React-logger (= 0.72.5) + - React-perflogger (= 0.72.5) + - RNCalendarEvents (2.2.0): + - React + - RNCAsyncStorage (1.19.3): + - React-Core + - RNDateTimePicker (7.6.0): + - React-Core + - RNDeviceInfo (10.11.0): + - React-Core + - RNDevMenu (4.1.1): + - React-Core + - React-Core/DevSupport + - React-RCTNetwork + - RNGestureHandler (2.13.1): + - React-Core + - RNLocalize (3.0.2): + - React-Core + - RNScreens (3.25.0): + - React-Core + - React-RCTImage + - RNSVG (13.14.0): + - React-Core + - SocketRocket (0.6.1) + - Toast (4.0.0) + - Yoga (1.14.0) + - YogaKit (1.18.1): + - Yoga (~> 1.14) + +DEPENDENCIES: + - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) + - Flipper (= 0.182.0) + - Flipper-Boost-iOSX (= 1.76.0.1.11) + - Flipper-DoubleConversion (= 3.2.0.1) + - Flipper-Fmt (= 7.1.7) + - Flipper-Folly (= 2.6.10) + - Flipper-Glog (= 0.5.0.5) + - Flipper-PeerTalk (= 0.0.4) + - FlipperKit (= 0.182.0) + - FlipperKit/Core (= 0.182.0) + - FlipperKit/CppBridge (= 0.182.0) + - FlipperKit/FBCxxFollyDynamicConvert (= 0.182.0) + - FlipperKit/FBDefines (= 0.182.0) + - FlipperKit/FKPortForwarding (= 0.182.0) + - FlipperKit/FlipperKitHighlightOverlay (= 0.182.0) + - FlipperKit/FlipperKitLayoutPlugin (= 0.182.0) + - FlipperKit/FlipperKitLayoutTextSearchable (= 0.182.0) + - FlipperKit/FlipperKitNetworkPlugin (= 0.182.0) + - FlipperKit/FlipperKitReactPlugin (= 0.182.0) + - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.182.0) + - FlipperKit/SKIOSNetworkPlugin (= 0.182.0) + - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - libevent (~> 2.1.12) + - OpenSSL-Universal (= 1.1.1100) + - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) + - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../node_modules/react-native/`) + - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) + - React-Codegen (from `build/generated/ios`) + - React-Core (from `../node_modules/react-native/`) + - React-Core/DevSupport (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) + - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) + - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) + - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)" + - react-native-restart (from `../node_modules/react-native-restart`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - react-native-simple-toast (from `../node_modules/react-native-simple-toast`) + - react-native-webview (from `../node_modules/react-native-webview`) + - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) + - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - React-rncore (from `../node_modules/react-native/ReactCommon`) + - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) + - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - RNCalendarEvents (from `../node_modules/react-native-calendar-events`) + - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" + - "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)" + - RNDeviceInfo (from `../node_modules/react-native-device-info`) + - RNDevMenu (from `../node_modules/react-native-dev-menu`) + - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - RNLocalize (from `../node_modules/react-native-localize`) + - RNScreens (from `../node_modules/react-native-screens`) + - RNSVG (from `../node_modules/react-native-svg`) + - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + +SPEC REPOS: + trunk: + - CocoaAsyncSocket + - Flipper + - Flipper-Boost-iOSX + - Flipper-DoubleConversion + - Flipper-Fmt + - Flipper-Folly + - Flipper-Glog + - Flipper-PeerTalk + - FlipperKit + - fmt + - libevent + - OpenSSL-Universal + - SocketRocket + - Toast + - YogaKit + +EXTERNAL SOURCES: + boost: + :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + DoubleConversion: + :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + FBLazyVector: + :path: "../node_modules/react-native/Libraries/FBLazyVector" + FBReactNativeSpec: + :path: "../node_modules/react-native/React/FBReactNativeSpec" + glog: + :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + hermes-engine: + :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :tag: hermes-2023-08-07-RNv0.72.4-813b2def12bc9df02654b3e3653ae4a68d0572e0 + RCT-Folly: + :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTRequired: + :path: "../node_modules/react-native/Libraries/RCTRequired" + RCTTypeSafety: + :path: "../node_modules/react-native/Libraries/TypeSafety" + React: + :path: "../node_modules/react-native/" + React-callinvoker: + :path: "../node_modules/react-native/ReactCommon/callinvoker" + React-Codegen: + :path: build/generated/ios + React-Core: + :path: "../node_modules/react-native/" + React-CoreModules: + :path: "../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-debug: + :path: "../node_modules/react-native/ReactCommon/react/debug" + React-hermes: + :path: "../node_modules/react-native/ReactCommon/hermes" + React-jsi: + :path: "../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../node_modules/react-native/ReactCommon/jsinspector" + React-logger: + :path: "../node_modules/react-native/ReactCommon/logger" + react-native-cookies: + :path: "../node_modules/@react-native-cookies/cookies" + react-native-restart: + :path: "../node_modules/react-native-restart" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" + react-native-simple-toast: + :path: "../node_modules/react-native-simple-toast" + react-native-webview: + :path: "../node_modules/react-native-webview" + React-NativeModulesApple: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + React-perflogger: + :path: "../node_modules/react-native/ReactCommon/reactperflogger" + React-RCTActionSheet: + :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../node_modules/react-native/Libraries/NativeAnimation" + React-RCTAppDelegate: + :path: "../node_modules/react-native/Libraries/AppDelegate" + React-RCTBlob: + :path: "../node_modules/react-native/Libraries/Blob" + React-RCTImage: + :path: "../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../node_modules/react-native/Libraries/Network" + React-RCTSettings: + :path: "../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../node_modules/react-native/Libraries/Vibration" + React-rncore: + :path: "../node_modules/react-native/ReactCommon" + React-runtimeexecutor: + :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + React-runtimescheduler: + :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + React-utils: + :path: "../node_modules/react-native/ReactCommon/react/utils" + ReactCommon: + :path: "../node_modules/react-native/ReactCommon" + RNCalendarEvents: + :path: "../node_modules/react-native-calendar-events" + RNCAsyncStorage: + :path: "../node_modules/@react-native-async-storage/async-storage" + RNDateTimePicker: + :path: "../node_modules/@react-native-community/datetimepicker" + RNDeviceInfo: + :path: "../node_modules/react-native-device-info" + RNDevMenu: + :path: "../node_modules/react-native-dev-menu" + RNGestureHandler: + :path: "../node_modules/react-native-gesture-handler" + RNLocalize: + :path: "../node_modules/react-native-localize" + RNScreens: + :path: "../node_modules/react-native-screens" + RNSVG: + :path: "../node_modules/react-native-svg" + Yoga: + :path: "../node_modules/react-native/ReactCommon/yoga" + +SPEC CHECKSUMS: + boost: 57d2868c099736d80fcd648bf211b4431e51a558 + CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 + DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 + FBLazyVector: 71803c074f6325f10b5ec891c443b6bbabef0ca7 + FBReactNativeSpec: 448e08a759d29a96e15725ae532445bf4343567c + Flipper: 6edb735e6c3e332975d1b17956bcc584eccf5818 + Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c + Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 + Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b + Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 + Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 + Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 + FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6 + fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 + glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b + hermes-engine: f6cf92a471053245614d9d8097736f6337d5b86c + libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 + OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c + RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 + RCTRequired: df81ab637d35fac9e6eb94611cfd20f0feb05455 + RCTTypeSafety: 4636e4a36c7c2df332bda6d59b19b41c443d4287 + React: e0cc5197a804031a6c53fb38483c3485fcb9d6f3 + React-callinvoker: 1a635856fe0c3d8b13fccd4ed7e76283b99b0868 + React-Codegen: 78d61f981cccc68a771a598f71621cb7db14b04c + React-Core: 252f8e9ca5a4e91af9b9be58670846d662b1c49f + React-CoreModules: f8b9e91fac7bd5d18729ce961a4978c70b5031cc + React-cxxreact: 70284b32dcd367439d7dae84d9f72660544181b5 + React-debug: ee33d7ba43766d9b10b32561527b57ccfbcb6bd1 + React-hermes: 91f97ea2669dc5847e1f26c243aaad913319c570 + React-jsi: bd68b7779746014f01ea72d1b738809e132d7f1e + React-jsiexecutor: ff70a72027dea5cc7d71cfcc6fad7f599f63987a + React-jsinspector: aef73cbd43b70675f572214d10fa438c89bf11ba + React-logger: 2e4aee3e11b3ec4fa6cfd8004610bbb3b8d6cca4 + react-native-cookies: f54fcded06bb0cda05c11d86788020b43528a26c + react-native-restart: 7595693413fe3ca15893702f2c8306c62a708162 + react-native-safe-area-context: 7aa8e6d9d0f3100a820efb1a98af68aa747f9284 + react-native-simple-toast: 0c7d14bcad288b5b83ae4b0eea65651b4ca829b0 + react-native-webview: 669ae162965f629a8d6a4bdd3b99a304d36ef1f2 + React-NativeModulesApple: 797bc6078d566eef3fb3f74127e6e1d2e945a15f + React-perflogger: cd8886513f68e1c135a1e79d20575c6489641597 + React-RCTActionSheet: 726d2615ca62a77ce3e2c13d87f65379cdc73498 + React-RCTAnimation: 8f2716b881c37c64858e4ecee0f58bfa57ff9afd + React-RCTAppDelegate: d4a213f29e81682f6b9c7d22f62a2ccab6d125ae + React-RCTBlob: dfaa933231c3497915bbcc9d98fcff7b6b60582c + React-RCTImage: 747e3d7b656a67470f9c234baedb8d41bbc4e745 + React-RCTLinking: 148332b5b0396b280b05534f7d168e560a3bbd5f + React-RCTNetwork: 1d818121a8e678f064de663a6db7aaefc099e53c + React-RCTSettings: 4b95d26ebc88bfd3b6535b2d7904914ff88dbfc2 + React-RCTText: ce4499e4f2d8f85dc4b93ff0559313a016c4f3e2 + React-RCTVibration: 45372e61b35e96d16893540958d156675afbeb63 + React-rncore: a79d1cb3d6c01b358a8aa0b31ccc04ab5f0dbebc + React-runtimeexecutor: 7e31e2bc6d0ecc83d4ba05eadc98401007abc10c + React-runtimescheduler: cc32add98c45c5df18436a6a52a7e1f6edec102c + React-utils: 7a9918a1ffdd39aba67835d42386f592ea3f8e76 + ReactCommon: 91ece8350ebb3dd2be9cef662abd78b6948233c0 + RNCalendarEvents: 7e65eb4a94f53c1744d1e275f7fafcfaa619f7a3 + RNCAsyncStorage: c913ede1fa163a71cea118ed4670bbaaa4b511bb + RNDateTimePicker: ccd988deb223cbb2e669e157ec576c2c6217128c + RNDeviceInfo: bf8a32acbcb875f568217285d1793b0e8588c974 + RNDevMenu: 72807568fe4188bd4c40ce32675d82434b43c45d + RNGestureHandler: 38aa38413896620338948fbb5c90579a7b1c3fde + RNLocalize: dbea38dcb344bf80ff18a1757b1becf11f70cae4 + RNScreens: 85d3880b52d34db7b8eeebe2f1a0e807c05e69fa + RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396 + SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 + Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + Yoga: 86fed2e4d425ee4c6eab3813ba1791101ee153c6 + YogaKit: f782866e155069a2cca2517aafea43200b01fd5a + +PODFILE CHECKSUM: 65fac31507ce363c84c5ab1cb333c7f711468d6a + +COCOAPODS: 1.12.1 diff --git a/apps/skolplattformen-app-new/ios/app.xcodeproj/project.pbxproj b/apps/skolplattformen-app-new/ios/app.xcodeproj/project.pbxproj new file mode 100644 index 000000000..fc5367360 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app.xcodeproj/project.pbxproj @@ -0,0 +1,721 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 00E356F31AD99517003FC87E /* appTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* appTests.m */; }; + 0C80B921A6F3F58F76C31292 /* libPods-app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-app.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 7699B88040F8A987B510C191 /* libPods-app-appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-app-appTests.a */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = app; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00E356EE1AD99517003FC87E /* appTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = appTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* appTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = appTests.m; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = app.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = app/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = app/AppDelegate.mm; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = app/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = app/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = app/main.m; sourceTree = ""; }; + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-app-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B4392A12AC88292D35C810B /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = ""; }; + 5B7EB9410499542E8C5724F5 /* Pods-app-appTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.debug.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.debug.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = app/LaunchScreen.storyboard; sourceTree = ""; }; + 89C6BE57DB24E9ADA2F236DE /* Pods-app-appTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app-appTests.release.xcconfig"; path = "Target Support Files/Pods-app-appTests/Pods-app-appTests.release.xcconfig"; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7699B88040F8A987B510C191 /* libPods-app-appTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-app.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00E356EF1AD99517003FC87E /* appTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* appTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = appTests; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* app */ = { + isa = PBXGroup; + children = ( + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.mm */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = app; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-app.a */, + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-app-appTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* app */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* appTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* app.app */, + 00E356EE1AD99517003FC87E /* appTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-app.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-app.release.xcconfig */, + 5B7EB9410499542E8C5724F5 /* Pods-app-appTests.debug.xcconfig */, + 89C6BE57DB24E9ADA2F236DE /* Pods-app-appTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* appTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "appTests" */; + buildPhases = ( + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */, + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = appTests; + productName = appTests; + productReference = 00E356EE1AD99517003FC87E /* appTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* app */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "app" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + FD10A7F022414F080027D42C /* Start Packager */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = app; + productName = app; + productReference = 13B07F961A680F5B00A75B9A /* app.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* app */, + 00E356ED1AD99517003FC87E /* appTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-app-appTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-app-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app-appTests/Pods-app-appTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + FD10A7F022414F080027D42C /* Start Packager */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Start Packager"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* appTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* app */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-app-appTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = appTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/app.app/app"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-app-appTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = appTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/app.app/app"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-app.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = app/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = app; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-app.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = app/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = app; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = "$(inherited)"; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + "-Wl -ld_classic ", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = "$(inherited)"; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + "-Wl -ld_classic ", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "appTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "app" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/apps/skolplattformen-app-new/ios/app.xcworkspace/contents.xcworkspacedata b/apps/skolplattformen-app-new/ios/app.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..b83e63c38 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/apps/skolplattformen-app-new/ios/app/AppDelegate.h b/apps/skolplattformen-app-new/ios/app/AppDelegate.h new file mode 100644 index 000000000..5d2808256 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : RCTAppDelegate + +@end diff --git a/apps/skolplattformen-app-new/ios/app/AppDelegate.mm b/apps/skolplattformen-app-new/ios/app/AppDelegate.mm new file mode 100644 index 000000000..50ce18d8b --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app/AppDelegate.mm @@ -0,0 +1,26 @@ +#import "AppDelegate.h" + +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @"app"; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = @{}; + + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +@end diff --git a/apps/skolplattformen-app-new/ios/app/Images.xcassets/AppIcon.appiconset/Contents.json b/apps/skolplattformen-app-new/ios/app/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..81213230d --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/skolplattformen-app-new/ios/app/Images.xcassets/Contents.json b/apps/skolplattformen-app-new/ios/app/Images.xcassets/Contents.json new file mode 100644 index 000000000..2d92bd53f --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/apps/skolplattformen-app-new/ios/app/Info.plist b/apps/skolplattformen-app-new/ios/app/Info.plist new file mode 100644 index 000000000..a3f8d6b76 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app/Info.plist @@ -0,0 +1,55 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + app + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/apps/skolplattformen-app-new/ios/app/LaunchScreen.storyboard b/apps/skolplattformen-app-new/ios/app/LaunchScreen.storyboard new file mode 100644 index 000000000..61f6b47aa --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/skolplattformen-app-new/ios/app/main.m b/apps/skolplattformen-app-new/ios/app/main.m new file mode 100644 index 000000000..d645c7246 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/app/main.m @@ -0,0 +1,10 @@ +#import + +#import "AppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/apps/skolplattformen-app-new/ios/appTests/Info.plist b/apps/skolplattformen-app-new/ios/appTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/appTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/apps/skolplattformen-app-new/ios/appTests/appTests.m b/apps/skolplattformen-app-new/ios/appTests/appTests.m new file mode 100644 index 000000000..bc0d3a085 --- /dev/null +++ b/apps/skolplattformen-app-new/ios/appTests/appTests.m @@ -0,0 +1,66 @@ +#import +#import + +#import +#import + +#define TIMEOUT_SECONDS 600 +#define TEXT_TO_LOOK_FOR @"Welcome to React" + +@interface appTests : XCTestCase + +@end + +@implementation appTests + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +- (void)testRendersWelcomeScreen +{ + UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + + __block NSString *redboxError = nil; +#ifdef DEBUG + RCTSetLogFunction( + ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + if (level >= RCTLogLevelError) { + redboxError = message; + } + }); +#endif + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + + foundElement = [self findSubviewInView:vc.view + matching:^BOOL(UIView *view) { + if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + return NO; + }]; + } + +#ifdef DEBUG + RCTSetLogFunction(RCTDefaultLogFunction); +#endif + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); +} + +@end diff --git a/apps/skolplattformen-app-new/jest.config.js b/apps/skolplattformen-app-new/jest.config.js new file mode 100644 index 000000000..c2d9d8fcd --- /dev/null +++ b/apps/skolplattformen-app-new/jest.config.js @@ -0,0 +1,16 @@ +module.exports = { + preset: 'react-native', + moduleFileExtensions: ['ts', 'js', 'html', 'tsx', 'jsx'], + setupFilesAfterEnv: ['/test-setup.ts'], + transform: { + // '\\.(js|ts|tsx)$': require.resolve('react-native/jest/preprocessor.js'), + '^.+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp)$': require.resolve( + 'react-native/jest/assetFileTransformer.js' + ), + }, + transformIgnorePatterns: [ + // 'node_modules/(?!(@react-native|react-native|@ronradtke/react-native-markdown-display|react-native-webview|react-native-calendar-events|react-native-simple-toast|react-native-modal-datetime-picker|@react-native-community/datetimepicker)/)', + 'node_modules/(?!(@react-native|react-native|@ronradtke/react-native-markdown-display|react-native-webview|react-native-calendar-events|react-native-simple-toast|react-native-modal-datetime-picker|@react-native-community/datetimepicker|@ui-kitten)/)', + ], + testEnvironment: 'jsdom', +} diff --git a/apps/skolplattformen-app-new/library-extractor.js b/apps/skolplattformen-app-new/library-extractor.js new file mode 100644 index 000000000..f504c8cca --- /dev/null +++ b/apps/skolplattformen-app-new/library-extractor.js @@ -0,0 +1,28 @@ +// Filters the output from 'react-native-oss-license'. + +const fs = require('fs').promises +const packageJson = require('./package.json') +const rnLicenses = require('./licenses-oss.json') + +/** + * TOOD: Make this a bit more testable + */ +async function run() { + try { + const dependencies = Object.keys(packageJson.dependencies) + + const result = rnLicenses.filter((pkg) => { + return dependencies.find((name) => pkg.libraryName === name) + }) + + await fs.writeFile( + './libraries.json', + JSON.stringify(result, null, 2), + 'utf-8' + ) + } catch (e) { + console.error(e) + } +} + +run() diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/__mocks__/@react-native-cookies/cookies.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/__mocks__/@react-native-cookies/cookies.ts new file mode 100644 index 000000000..7ce777bc7 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/__mocks__/@react-native-cookies/cookies.ts @@ -0,0 +1,81 @@ +import { CookieJar, Cookie as TCookie } from 'tough-cookie' + +export interface Cookie { + name: string + value: string + path?: string + domain?: string + version?: string + expires?: string + secure?: boolean + httpOnly?: boolean +} + +export interface Cookies { + [key: string]: Cookie +} + +export interface CookieManagerStatic { + set(url: string, cookie: Cookie, useWebKit?: boolean): Promise + setFromResponse(url: string, cookie: string): Promise + + get(url: string, useWebKit?: boolean): Promise + + clearAll(useWebKit?: boolean): Promise +} + +const convertTtoC = (cookie: string | TCookie): Cookie => { + if (typeof cookie === 'string') { + return convertTtoC(TCookie.parse(cookie) as TCookie) + } + return { + name: cookie.key, + value: cookie.value, + domain: cookie.domain || undefined, + expires: + cookie.expires === 'Infinity' ? undefined : cookie.expires.toUTCString(), + httpOnly: cookie.httpOnly || undefined, + path: cookie.path || undefined, + secure: cookie.secure, + } +} +const convertCtoT = (cookie: Cookie): TCookie => + new TCookie({ + key: cookie.name, + value: cookie.value, + domain: cookie.domain, + expires: cookie.expires ? new Date(cookie.expires) : undefined, + httpOnly: cookie.httpOnly || false, + path: cookie.path, + secure: cookie.secure || false, + }) +const convertCookies = (cookies: TCookie[]): Cookies => + cookies.reduce( + (map, cookie) => ({ + ...map, + [cookie.key]: convertTtoC(cookie), + }), + {} as Cookies + ) + +const jar = new CookieJar() +const CookieManager: CookieManagerStatic = { + clearAll: async () => { + await jar.removeAllCookies() + return true + }, + get: async (url) => { + const cookies = await jar.getCookies(url) + return convertCookies(cookies) + }, + set: async (url, cookie) => { + await jar.setCookie(convertCtoT(cookie), url) + return true + }, + setFromResponse: async (url, cookie) => { + await jar.setCookie(cookie, url) + return true + }, +} + +export default CookieManager diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/apiHjarntorget.test.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/apiHjarntorget.test.ts new file mode 100644 index 000000000..c0aa31ed2 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/apiHjarntorget.test.ts @@ -0,0 +1,288 @@ +import { wrapToughCookie } from '../../api/lib' +import { CookieJar } from 'tough-cookie' +import { ApiHjarntorget } from './apiHjarntorget' + +const setupSuccessfullLoginInitiation = (fetcherMock: jest.Mock) => { + // 'begin-login' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + url: 'some url with url encoded at the end?return=hello', + }) + ) + + // 'init-shibboleth-login' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + url: 'some url with url encoded at the end?Target=hello', + }) + ) + + // 'init-bankId' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + text: jest.fn().mockReturnValue( + Promise.resolve(` + + + + + + `) + ), + }) + ) + + // 'pick-mvghost' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + url: 'some url to a mvghost', + }) + ) + + // 'start-bankId' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + url: 'some base url to a mvghost to use when polling status', + }) + ) +} + +const setupSuccessfullBankIdLogin = (fetcherMock: jest.Mock) => { + // 'poll-bankid-status' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + json: jest.fn().mockReturnValue( + Promise.resolve({ + infotext: '', + location: 'an url to go to confirm the login', + }) + ), + }) + ) + + // 'confirm-signature-redirect' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + text: jest.fn().mockReturnValue( + Promise.resolve(` + + + + + + `) + ), + }) + ) + + // 'authgbg-saml-login' + fetcherMock.mockReturnValueOnce( + Promise.resolve({ + text: jest.fn().mockReturnValue( + Promise.resolve(` + + + + + + `) + ), + }) + ) + + // 'hjarntorget-saml-login' + fetcherMock.mockReturnValueOnce(Promise.resolve({ status: 200 })) +} + +describe('api', () => { + let fetcherMock: jest.Mock + let api: ApiHjarntorget + + beforeEach(() => { + const fetcher = jest.fn() + fetcherMock = fetcher as jest.Mock + + const cookieManager = wrapToughCookie(new CookieJar()) + cookieManager.clearAll() + api = new ApiHjarntorget(jest.fn(), cookieManager) + api.replaceFetcher(fetcher) + }) + it('works', () => { + expect(1 + 1).toBe(2) + }) + // describe('#login', () => { + // it('goes through single sing-on steps', async (done) => { + // setupSuccessfullLoginInitiation(fetcherMock) + // setupSuccessfullBankIdLogin(fetcherMock) + // const personalNumber = 'my personal number' + + // const loginComplete = new Promise((resolve, reject) => { + // api.on('login', () => done()) + // }); + // await api.login(personalNumber) + // }) + // it('checker emits PENDING', async (done) => { + // // 'poll-bankid-status' + // fetcherMock.mockReturnValueOnce(Promise.resolve({ + // json: jest.fn().mockReturnValue(Promise.resolve({ + // infotext: "some prompt to do signing in app", + // location: "" + // })) + // })) + + // const status = checkStatus(fetcherMock, "some url") + // status.on('PENDING', () => { + // status.cancel() + // done() + // }) + // }) + // it('checker emits ERROR', async (done) => { + // // 'poll-bankid-status' + // fetcherMock.mockReturnValueOnce(Promise.resolve({ + // json: jest.fn().mockReturnValue(Promise.resolve({ + // infotext: "some prompt to do signing in app", + // location: "url with error in the name" + // })) + // })) + + // const status = checkStatus(fetcherMock, "some url") + // status.on('ERROR', () => { + // status.cancel() + // done() + // }) + // }) + // it('checker emits ERROR when an exception occurs', async (done) => { + // // 'poll-bankid-status' + // fetcherMock.mockReturnValueOnce(Promise.resolve({ + // json: jest.fn().mockReturnValue(Promise.resolve({ + // infotext: undefined, + // location: undefined + // })) + // })) + + // const status = checkStatus(fetcherMock, "some url") + // status.on('ERROR', () => { + // status.cancel() + // done() + // }) + // }) + // it('remembers used personal number', async (done) => { + // setupSuccessfullLoginInitiation(fetcherMock) + // setupSuccessfullBankIdLogin(fetcherMock) + // const personalNumber = 'my personal number' + // await api.login(personalNumber) + // api.on('login', () => { + // expect(api.getPersonalNumber()).toEqual(personalNumber) + // done() + // }) + // }) + // it('forgets used personal number if sign in is unsuccessful', async (done) => { + // setupSuccessfullLoginInitiation(fetcherMock) + // // 'poll-bankid-status' + // fetcherMock.mockReturnValueOnce(Promise.resolve({ + // json: jest.fn().mockReturnValue(Promise.resolve({ + // infotext: "", + // location: "an url to go to confirm the login" + // })) + // })) + // // 'confirm-signature-redirect' + // fetcherMock.mockReturnValueOnce(Promise.resolve({ + // text: Promise.resolve("some error occured") + // })) + + // const personalNumber = 'my personal number' + // const status = await api.login(personalNumber) + + // status.on('ERROR', () => { + // expect(api.getPersonalNumber()).toEqual(undefined) + // done() + // }) + // }) + + // // TODO: Possibly rewrite the mocking so we mock the responses more properly, + // // that way it would be possible to implement a throwIfNotOk wrapper for the + // // fetch calls. + // // it('throws error on external api error', async () => { + // // const personalNumber = 'my personal number' + // // try { + // // await api.login(personalNumber) + // // } catch (error: any) { + // // expect(error.message).toEqual(expect.stringContaining('Server Error')) + // // } + // // }) + // }) + // describe('#logout', () => { + // // it('clears session', async () => { + // // await api.logout() + // // const session = await api.getSession('') + // // expect(session).toEqual({ + // // headers: { + // // cookie: '', + // // }, + // // }) + // // }) + // it('emits logout event', async () => { + // const listener = jest.fn() + // api.on('logout', listener) + // await api.logout() + // expect(listener).toHaveBeenCalled() + // }) + // it('sets .isLoggedIn', async () => { + // api.isLoggedIn = true + // await api.logout() + // expect(api.isLoggedIn).toBe(false) + // }) + // it('forgets personalNumber', async () => { + // // eslint-disable-next-line @typescript-eslint/no-explicit-any + // (api as any).personalNumber = 'my personal number' + // api.isLoggedIn = true + + // await api.logout() + + // expect(api.getPersonalNumber()).toEqual(undefined) + // }) + // }) + /* + describe('fake', () => { + it('sets fake mode for the correct pnr:s', async () => { + let status + + status = await api.login('121212121212') + expect(status.token).toEqual('fake') + + status = await api.login('201212121212') + expect(status.token).toEqual('fake') + + status = await api.login('1212121212') + expect(status.token).toEqual('fake') + }) + it('delivers fake data', async (done) => { + api.on('login', async () => { + const user = await api.getUser() + expect(user).toEqual({ + firstName: 'Namn', + lastName: 'Namnsson', + isAuthenticated: true, + personalNumber: "195001182046", + }) + + const children = await api.getChildren() + expect(children).toHaveLength(2) + + const calendar1 = await api.getCalendar(children[0]) + expect(calendar1).toHaveLength(20) + const calendar2 = await api.getCalendar(children[1]) + expect(calendar2).toHaveLength(18) + + const skola24Children = await api.getSkola24Children() + expect(skola24Children).toHaveLength(1) + + const timetable = await api.getTimetable(skola24Children[0], 2021, 15, 'sv') + expect(timetable).toHaveLength(32) + + done() + }) + await api.login('121212121212') + }) + })*/ +}) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/apiHjarntorget.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/apiHjarntorget.ts new file mode 100644 index 000000000..c661ea15f --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/apiHjarntorget.ts @@ -0,0 +1,620 @@ +import { + Api, + CalendarItem, + Classmate, + CookieManager, + EtjanstChild, + Fetch, + Fetcher, + FetcherOptions, + FrejaLoginStatusChecker, + LoginStatusChecker, + MenuItem, + NewsItem, + Notification, + ScheduleItem, + SchoolContact, + Skola24Child, + Teacher, + TimetableEntry, + toMarkdown, + URLSearchParams, + User, + wrap, +} from '../../api/lib' +import { EventEmitter } from 'events' +import { decode } from 'he' +import { DateTime, FixedOffsetZone } from 'luxon' +import * as html from 'node-html-parser' +import { fakeFetcher } from './fake/fakeFetcher' +import { checkStatus, DummyStatusChecker } from './loginStatus' +import { extractMvghostRequestBody, parseCalendarItem } from './parse/parsers' +import { + beginBankIdUrl, + beginLoginUrl, + calendarEventUrl, + calendarsUrl, + currentUserUrl, + fullImageUrl, + hjarntorgetEventsUrl, + hjarntorgetUrl, + infoUrl, + initBankIdUrl, + lessonsUrl, + membersWithRoleUrl, + mvghostUrl, + myChildrenUrl, + rolesInEventUrl, + shibbolethLoginUrl, + shibbolethLoginUrlBase, + verifyUrlBase, + wallMessagesUrl, +} from './routes' +import parse from '../../curriculum/src' + +function getDateOfISOWeek(week: number, year: number) { + const simple = new Date(year, 0, 1 + (week - 1) * 7) + const dow = simple.getDay() + const isoWeekStart = simple + if (dow <= 4) { + isoWeekStart.setDate(simple.getDate() - simple.getDay() + 1) + } else { + isoWeekStart.setDate(simple.getDate() + 8 - simple.getDay()) + } + return isoWeekStart +} + +export class ApiHjarntorget extends EventEmitter implements Api { + private fetch: Fetcher + private realFetcher: Fetcher + + private personalNumber?: string + + private cookieManager: CookieManager + + public isLoggedIn = false + + private _isFake = false + + public set isFake(fake: boolean) { + this._isFake = fake + if (this._isFake) { + this.fetch = fakeFetcher + } else { + this.fetch = this.realFetcher + } + } + + public get isFake() { + return this._isFake + } + + constructor( + fetch: Fetch, + cookieManager: CookieManager, + options?: FetcherOptions + ) { + super() + this.fetch = wrap(fetch, options) + this.realFetcher = this.fetch + this.cookieManager = cookieManager + } + + public replaceFetcher(fetcher: Fetcher) { + this.fetch = fetcher + } + + async getSchedule( + child: EtjanstChild, + from: DateTime, + to: DateTime + ): Promise<(CalendarItem & ScheduleItem)[]> { + const lessonParams = { + forUser: child.id, + startDateIso: from.toISODate(), + endDateIso: to.toISODate(), + } + const lessonsResponse = await this.fetch( + `lessons-${lessonParams.forUser}`, + lessonsUrl(lessonParams) + ) + const lessonsResponseJson: any[] = await lessonsResponse.json() + + return lessonsResponseJson.map((l) => { + const start = DateTime.fromMillis(l.startDate.ts, { + zone: FixedOffsetZone.instance(l.startDate.timezoneOffsetMinutes), + }) + const end = DateTime.fromMillis(l.endDate.ts, { + zone: FixedOffsetZone.instance(l.endDate.timezoneOffsetMinutes), + }) + return { + id: l.id, + title: l.title, + description: l.note, + location: l.location, + startDate: start.toISO(), + endDate: end.toISO(), + oneDayEvent: false, + allDayEvent: false, + } + }) + } + + getPersonalNumber(): string | undefined { + return this.personalNumber + } + + public async getSessionHeaders( + url: string + ): Promise<{ [index: string]: string }> { + const cookie = await this.cookieManager.getCookieString(url) + return { + cookie, + } + } + + async setSessionCookie(sessionCookie: string): Promise { + this.cookieManager.setCookieString(sessionCookie, hjarntorgetUrl) + + const user = await this.getUser() + if (!user.isAuthenticated) { + throw new Error('Session cookie is expired') + } + + this.isLoggedIn = true + this.emit('login') + } + + async getUser(): Promise { + console.log('fetching user') + const currentUserResponse = await this.fetch('current-user', currentUserUrl) + if (currentUserResponse.status !== 200) { + return { isAuthenticated: false } + } + + const retrivedUser = await currentUserResponse.json() + return { ...retrivedUser, isAuthenticated: true } + } + + async getChildren(): Promise<(Skola24Child & EtjanstChild)[]> { + if (!this.isLoggedIn) { + throw new Error('Not logged in...') + } + console.log('fetching children') + + const myChildrenResponse = await this.fetch('my-children', myChildrenUrl) + const myChildrenResponseJson: any[] = await myChildrenResponse.json() + + return myChildrenResponseJson.map( + (c) => + ({ + id: c.id, + sdsId: c.id, + personGuid: c.id, + firstName: c.firstName, + lastName: c.lastName, + name: `${c.firstName} ${c.lastName}`, + } as Skola24Child & EtjanstChild) + ) + } + + async getCalendar(child: EtjanstChild): Promise { + const childEventsAndMembers = + await this.getChildEventsWithAssociatedMembers(child) + + // This fetches the calendars search page on Hjärntorget. + // It is used (at least at one school) for homework schedule + // The Id for the "event" that the calendar belongs to is not the same as the ones + // fetched using the API... So we match them by name :/ + const calendarsResponse = await this.fetch('calendars', calendarsUrl) + const calendarsResponseText = await calendarsResponse.text() + const calendarsDoc = html.parse(decode(calendarsResponseText)) + const calendarCheckboxes = Array.from( + calendarsDoc.querySelectorAll('.calendarPageContainer input.checkbox') + ) + + let calendarItems: CalendarItem[] = [] + for (let i = 0; i < calendarCheckboxes.length; i++) { + const calendarId = calendarCheckboxes[i].getAttribute('value') || '' + + const today = DateTime.fromJSDate(new Date()) + const start = today.toISODate() + const end = today.plus({ days: 30 }).toISODate() + const calendarResponse = await this.fetch( + `calendar-${calendarId}`, + calendarEventUrl(calendarId, start, end) + ) + const calendarResponseText = await calendarResponse.text() + const calendarDoc = html.parse(decode(calendarResponseText)) + + const calendarRows = Array.from( + calendarDoc.querySelectorAll('.default-table tr') + ) + if (!calendarRows.length) { + continue + } + + calendarRows.shift() + const eventName = calendarRows.shift()?.textContent + if (childEventsAndMembers.some((e) => e.name === eventName)) { + const items: CalendarItem[] = calendarRows.map(parseCalendarItem) + + calendarItems = calendarItems.concat(items) + } + } + + return calendarItems + } + + getClassmates(_child: EtjanstChild): Promise { + // TODO: We could get this from the events a child is associated with... + if (!this.isLoggedIn) { + throw new Error('Not logged in...') + } + return Promise.resolve([]) + } + + public async getTeachers(_child: EtjanstChild): Promise { + if (!this.isLoggedIn) { + throw new Error('Not logged in...') + } + return Promise.resolve([]) + } + + public async getSchoolContacts( + _child: EtjanstChild + ): Promise { + if (!this.isLoggedIn) { + throw new Error('Not logged in...') + } + return Promise.resolve([]) + } + + async getNews(_child: EtjanstChild): Promise { + if (!this.isLoggedIn) { + throw new Error('Not logged in...') + } + + const children = await this.getChildren() + const eventsAndMembersForChildren = + await this.getEventsWithAssociatedMembersForChildren(children) + const membersInChildensEvents = eventsAndMembersForChildren.reduce( + (acc, e) => acc.concat(e.eventMembers), + [] as any[] + ) + + const wallMessagesResponse = await this.fetch( + 'wall-events', + wallMessagesUrl + ) + const wallMessagesResponseJson: any[] = await wallMessagesResponse.json() + const nonChildSpecificMessages = wallMessagesResponseJson + .filter( + (message) => + // Ignore "Alarm" messages from the calendar + message.creator.id !== '__system$virtual$calendar__' && + // Only include messages that can not reliably be associated with one of the children + !membersInChildensEvents.some( + (member) => member.id === message.creator.id + ) + ) + .map((message) => { + const createdDate = new Date(message.created.ts) + const body = message.body as string + const trimmedBody = body.trim() + const firstNewline = trimmedBody.indexOf('\n') + const title = + trimmedBody.substring(0, firstNewline).trim() || message.title + const intro = trimmedBody.substring(firstNewline).trim() + return { + id: message.id, + author: + message.creator && + `${message.creator.firstName} ${message.creator.lastName}`, + header: title, + intro: intro, + body: body, + published: createdDate.toISOString(), + modified: createdDate.toISOString(), + fullImageUrl: + message.creator && fullImageUrl(message.creator.imagePath), + timestamp: message.created.ts, + } + }) + + const infoResponse = await this.fetch('info', infoUrl) + const infoResponseJson: any[] = await infoResponse.json() + // TODO: Filter out read messages? + const officialInfoMessages = infoResponseJson.map((i) => { + const body = html.parse(decode(i.body || '')) + const bodyText = toMarkdown(i.body) + + const introText = body.innerText || '' + const publishedDate = new Date(i.created.ts) + + return { + id: i.id, + author: i.creator && `${i.creator.firstName} ${i.creator.lastName}`, + header: i.title, + intro: introText, + body: bodyText, + published: publishedDate.toISOString(), + modified: publishedDate.toISOString(), + fullImageUrl: i.creator && fullImageUrl(i.creator.imagePath), + timestamp: i.created.ts, + } + }) + + const newsMessages = officialInfoMessages.concat(nonChildSpecificMessages) + newsMessages.sort((a, b) => b.timestamp - a.timestamp) + return newsMessages + } + + async getNewsDetails(_child: EtjanstChild, item: NewsItem): Promise { + return { ...item } + } + + getMenu(_child: EtjanstChild): Promise { + if (!this.isLoggedIn) { + throw new Error('Not logged in...') + } + // Have not found this available on hjärntorget. Perhaps do a mapping to https://www.skolmaten.se/ ? + return Promise.resolve([]) + } + + async getChildEventsWithAssociatedMembers(child: EtjanstChild) { + return this.getEventsWithAssociatedMembersForChildren([child]) + } + + async getEventsWithAssociatedMembersForChildren(children: EtjanstChild[]) { + const hjarntorgetEventsResponse = await this.fetch( + 'events', + hjarntorgetEventsUrl + ) + const hjarntorgetEventsResponseJson: any[] = + await hjarntorgetEventsResponse.json() + const membersInEvents = await Promise.all( + hjarntorgetEventsResponseJson + .filter((e) => e.state === 'ONGOING') + .map(async (e) => { + const eventId = e.id as number + + const rolesInEvenResponse = await this.fetch( + `roles-in-event-${eventId}`, + rolesInEventUrl(eventId) + ) + const rolesInEvenResponseJson: any[] = + await rolesInEvenResponse.json() + + const eventMembers = await Promise.all( + rolesInEvenResponseJson.map(async (r) => { + const roleId = r.id + const membersWithRoleResponse = await this.fetch( + `event-role-members-${eventId}-${roleId}`, + membersWithRoleUrl(eventId, roleId) + ) + const membersWithRoleResponseJson: any[] = + await membersWithRoleResponse.json() + return membersWithRoleResponseJson + }) + ) + return { + eventId, + name: e.name as string, + eventMembers: ([] as any[]).concat(...eventMembers), + } + }) + ) + + return membersInEvents.filter((e) => + e.eventMembers.find((p) => children.some((c) => c.id === p.id)) + ) + } + + async getNotifications(child: EtjanstChild): Promise { + const childEventsAndMembers = + await this.getChildEventsWithAssociatedMembers(child) + const membersInChildsEvents = childEventsAndMembers.reduce( + (acc, e) => acc.concat(e.eventMembers), + [] as any[] + ) + + const wallMessagesResponse = await this.fetch( + 'wall-events', + wallMessagesUrl + ) + const wallMessagesResponseJson: any[] = await wallMessagesResponse.json() + return wallMessagesResponseJson + .filter((message) => + membersInChildsEvents.find((member) => member.id === message.creator.id) + ) + .map((message) => { + const createdDate = new Date(message.created.ts) + return { + id: message.id, + sender: + message.creator && + `${message.creator.firstName} ${message.creator.lastName}`, + dateCreated: createdDate.toISOString(), + message: message.body, + url: message.url, + category: message.title, + type: message.type, + dateModified: createdDate.toISOString(), + } + }) + } + + async getSkola24Children(): Promise { + if (!this.isLoggedIn) { + throw new Error('Not logged in...') + } + return [] + } + + async getTimetable( + child: Skola24Child, + week: number, + year: number, + _lang: string + ): Promise { + const startDate = DateTime.fromJSDate(getDateOfISOWeek(week, year)) + const endDate = startDate.plus({ days: 7 }) + + const lessonParams = { + forUser: child.personGuid!, // This is a bit of a hack due to how we map things... + startDateIso: startDate.toISODate(), + endDateIso: endDate.toISODate(), + } + const lessonsResponse = await this.fetch( + `lessons-${lessonParams.forUser}`, + lessonsUrl(lessonParams) + ) + const lessonsResponseJson: any[] = await lessonsResponse.json() + + return lessonsResponseJson.map((l) => { + const start = DateTime.fromMillis(l.startDate.ts, { + zone: FixedOffsetZone.instance(l.startDate.timezoneOffsetMinutes), + }) + const end = DateTime.fromMillis(l.endDate.ts, { + zone: FixedOffsetZone.instance(l.endDate.timezoneOffsetMinutes), + }) + return { + ...parse(l.title, _lang), + id: l.id, + teacher: l.bookedTeacherNames && l.bookedTeacherNames[0], + location: l.location, + timeStart: start.toISOTime().substring(0, 5), + timeEnd: end.toISOTime().substring(0, 5), + dayOfWeek: start.toJSDate().getDay(), + blockName: l.title, + dateStart: start.toISODate(), + dateEnd: end.toISODate(), + } as TimetableEntry + }) + } + + async logout(): Promise { + this.isLoggedIn = false + this.personalNumber = undefined + this.cookieManager.clearAll() + this.emit('logout') + } + + public async login(personalNumber?: string): Promise { + // short circut the bank-id login if in fake mode + if (personalNumber !== undefined && personalNumber.endsWith('1212121212')) { + return this.fakeMode() + } + + this.isFake = false + + console.log('initiating login to hjarntorget') + const beginLoginRedirectResponse = await this.fetch( + 'begin-login', + beginLoginUrl, + { + redirect: 'follow', + } + ) + + if ((beginLoginRedirectResponse as any).url.endsWith('startPage.do')) { + // already logged in! + const emitter = new DummyStatusChecker() + setTimeout(() => { + this.isLoggedIn = true + emitter.emit('OK') + this.emit('login') + }, 50) + return emitter as LoginStatusChecker + } + + console.log('prepping??? shibboleth') + const shibbolethLoginResponse = await this.fetch( + 'init-shibboleth-login', + shibbolethLoginUrl( + shibbolethLoginUrlBase((beginLoginRedirectResponse as any).url) + ), + { + redirect: 'follow', + } + ) + + const shibbolethRedirectUrl = (shibbolethLoginResponse as any).url + console.log('initiating bankid...') + const initBankIdResponse = await this.fetch( + 'init-bankId', + initBankIdUrl(shibbolethRedirectUrl), + { + redirect: 'follow', + } + ) + + const initBankIdResponseText = await initBankIdResponse.text() + const mvghostRequestBody = extractMvghostRequestBody(initBankIdResponseText) + + console.log('picking auth server???') + const mvghostResponse = await this.fetch('pick-mvghost', mvghostUrl, { + redirect: 'follow', + method: 'POST', + body: mvghostRequestBody, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }) + + console.log('start bankid sign in') + // We may get redirected to some other subdomain i.e. not 'm00-mg-local': + // https://mNN-mg-local.idp.funktionstjanster.se/mg-local/auth/ccp11/grp/other + + const ssnBody = new URLSearchParams({ ssn: personalNumber }).toString() + const beginBankIdResponse = await this.fetch( + 'start-bankId', + beginBankIdUrl((mvghostResponse as any).url), + { + redirect: 'follow', + method: 'POST', + body: ssnBody, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + } + ) + + console.log('start polling') + const statusChecker = checkStatus( + this.fetch, + verifyUrlBase((beginBankIdResponse as any).url) + ) + + statusChecker.on('OK', async () => { + // setting these similar to how the sthlm api does it + // not sure if it is needed or if the cookies are enough for fetching all info... + this.isLoggedIn = true + this.personalNumber = personalNumber + this.emit('login') + }) + statusChecker.on('ERROR', () => { + this.personalNumber = undefined + }) + + return statusChecker + } + + private async fakeMode(): Promise { + this.isFake = true + + setTimeout(() => { + this.isLoggedIn = true + this.emit('login') + }, 50) + + const emitter: any = new EventEmitter() + emitter.token = 'fake' + return emitter + } + + async loginFreja(): Promise { + throw new Error('Not implemented...') + } +} diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/calendars.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/calendars.ts new file mode 100644 index 000000000..257aed5a8 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/calendars.ts @@ -0,0 +1,43 @@ +import { Response } from '../../../api/lib' +/* eslint-disable no-useless-escape */ +export const calendars = () => + ({ + url: 'https://hjarntorget.goteborg.se/pp/system/calendar/cal_events.jsp', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + text: () => + Promise.resolve( + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nThe PING PONG Calendar\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t
\n\t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n\t\n\n\t\n\n\n\n\t\t\n\n\t\t
\n\t\t\t\n\t\t\t
\n\t\t\t\t

Make a selection

\n\n\t\t\t\t

Here you get an overview of your calendars. Choose from which calendars you wish to see events. Choose if you want to search for a word. Click Show to see the result.

\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
Show calendar events for the checked calendars
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\n\n
\n\n\n\n
removed checkbox
\n\n\n\n
removed checkbox
\n\n\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t
Group the events per calendar\n\t\t\t\t\t\t\t\t\t
Don\'t group\n\t\t\t\t\t\t\t\t\t
From - to:\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
Search for
\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t
\n\t\t\t
\n\n\t\t\t

Calendar events

\n\n\t\t\t\t\n\t\t\t\t

\n\t\t\t\t\t No events was found \n\t\t\t\t\t\n\t\t\t\t

\n\t\t\t\t\n\n\t\t\t
\n\t\t
\n\t
\n\n\n\n\n' + ), + } as any as Response) + +export const calendar_14241345 = () => + ({ + url: 'https://hjarntorget.goteborg.se/pp/system/calendar/cal_events.jsp?order_by=start_date&show_cal_ids=14241345&mode=separate&filter_start_date=2021-11-09&filter_end_date=2021-12-09&search_for=', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: null, + ok: true, + text: () => { + const now = new Date() + const dateYearMonth = `${now.getFullYear()}-${now.getMonth() + 1}` + const nextMonthDate = new Date(now.getFullYear(), now.getMonth() + 1, 1) // Should roll over to new year... + const nextMonth = `${nextMonthDate.getFullYear()}-${ + nextMonthDate.getMonth() + 1 + }` + const result = ` + \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nThe PING PONG Calendar\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t
\n\t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n\t\n\n\t\n\n\n\n\t\t\n\n\t\t
\n\t\t\t\n\t\t\t
\n\t\t\t\t

Make a selection

\n\n\t\t\t\t

Here you get an overview of your calendars. Choose from which calendars you wish to see events. Choose if you want to search for a word. Click Show to see the result.

\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
Show calendar events for the checked calendars
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\n\n
removed checkbox
\"\"
\n\n\n\n
removed checkbox
\"\"
\n\n\n\n
removed checkbox
\"\"
\n\n\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t
Group the events per calendar\n\t\t\t\t\t\t\t\t\t
Don't group\n\t\t\t\t\t\t\t\t\t
From - to:\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
Search for
\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t
\n\t\t\t
\n\n\t\t\t

Calendar events

\n\n\t\t\t\t\n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\n\t\t\t\t\t\t\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\t\t\tTitle\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tDates\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tTimes\n\n\t\t\t\t\t\t\t
138JÄTS Provschema år 8
\"\"
\nProv/komplettering franska ${dateYearMonth}-0113:00-14:00
\"\"
\nTyska läxförhör${dateYearMonth}-0113:00-13:30\"The
\"\"
\nLäxa i franska${dateYearMonth}-0309:40-10:20\"The
\"\"
\nSpanskaprov Repasamos 1- 4${dateYearMonth}-0310:00-11:00
\"\"
\nTyska läxförhör${dateYearMonth}-0813:00-13:30\"The
\"\"
\nLäxa i franska${dateYearMonth}-1009:40-10:20\"The
\"\"
\nDeadline engelska - Postcard from Great Britain${dateYearMonth}-1115:00-16:00\"The
\"\"
\nLäxa engelska${dateYearMonth}-1408:00-09:00\"The
\"\"
\nTyska läxförhör${dateYearMonth}-1513:00-13:30\"The
\"\"
\nLäxa i franska${dateYearMonth}-1709:40-10:20\"The
\"\"
\nLäxa engelska${dateYearMonth}-1908:00-09:00\"The
\"\"
\nProv franska åk 7${dateYearMonth}-2012:00-13:00
\"\"
\nLäxa i franska${dateYearMonth}-2209:40-10:20\"The
\"\"
\nLäxa engelska${nextMonth}-0108:00-09:00\"The
\n\n\t\t\t\t\n\n\t\t\t
\n\t\t
\n\t
\n\n\n\n\n + ` + return Promise.resolve(result) + }, + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/current-user.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/current-user.ts new file mode 100644 index 000000000..fd5f0efca --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/current-user.ts @@ -0,0 +1,21 @@ +export const currentUser = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/core/current-user', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve({ + id: '889911_goteborgsstad', + firstName: 'TOLV', + lastName: 'TOLVAN', + email: null, + online: true, + imagePath: '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/event-role-members.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/event-role-members.ts new file mode 100644 index 000000000..14123340a --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/event-role-members.ts @@ -0,0 +1,242 @@ +export const eventRoleMembers21 = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/event-members/members-having-role?eventId=21&roleId=821', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: '__system$virtual$calendar__', + firstName: 'Kalendern', + lastName: 'i PING PONG', + email: null, + online: false, + imagePath: '/pp/lookAndFeel/skins/default/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + // Klass: 8B + id: '133700_goteborgsstad', + firstName: 'Azra', + lastName: 'Göransson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + ]), + } as any as Response) + +export const eventRoleMembers14 = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/event-members/members-having-role?eventId=14&roleId=821', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + // Klass: 8B + id: '133700_goteborgsstad', + firstName: 'Azra', + lastName: 'Göransson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '362119_goteborgsstad', + firstName: 'Elina', + lastName: 'Cocolis', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '999999_goteborgsstad', + firstName: 'Sanne', + lastName: 'Berggren', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '168925_goteborgsstad', + firstName: 'Teddy', + lastName: 'Karlsson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '494949_goteborgsstad', + firstName: 'Fideli', + lastName: 'Sundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + ]), + } as any as Response) + +export const eventRoleMembers18 = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/event-members/members-having-role?eventId=18&roleId=821', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: '776655_goteborgsstad', + firstName: 'Walid', + lastName: 'Söderström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '388601_goteborgsstad', + firstName: 'Rosa', + lastName: 'Fredriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '654654_goteborgsstad', + firstName: 'Moses', + lastName: 'Johansson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '1313131_goteborgsstad', + firstName: 'Haris', + lastName: 'Jonsson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '887766_goteborgsstad', + firstName: 'Neo', + lastName: 'Lundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + // Klass: 5A + id: '123456_goteborgsstad', + firstName: 'Jon', + lastName: 'Göransson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + ]), + } as any as Response) + +export const eventRoleMembers24 = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/event-members/members-having-role?eventId=24&roleId=821', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: '393939_goteborgsstad', + firstName: 'Malik Maria', + lastName: 'Henriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '444444_goteborgsstad', + firstName: 'Idas', + lastName: 'Svensson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '818181_goteborgsstad', + firstName: 'Nadja', + lastName: 'Ekström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + id: '919191_goteborgsstad', + firstName: 'Karim', + lastName: 'Fakir', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + // Klass: Förskola + id: '133737_goteborgsstad', + firstName: 'Havin', + lastName: 'Göransson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + ]), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/events.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/events.ts new file mode 100644 index 000000000..60e01b2fd --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/events.ts @@ -0,0 +1,38 @@ +export const events = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/events/events-sorted-by-name?offset=0&limit=100', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: 18, + name: '138JÄTS 21/22 5A', + url: 'https://hjarntorget.goteborg.se/o/apiAccessWithKey.do?forwardUrl=%2FlaunchCourse.do%3Fid%3D12', + state: 'ONGOING', + }, + { + id: 14, + name: '138JÄTS 21/22 8B', + url: 'https://hjarntorget.goteborg.se/o/apiAccessWithKey.do?forwardUrl=%2FlaunchCourse.do%3Fid%3D14', + state: 'ONGOING', + }, + { + id: 21, + name: '138JÄTS Provschema år 8', + url: 'https://hjarntorget.goteborg.se/o/apiAccessWithKey.do?forwardUrl=%2FlaunchCourse.do%3Fid%3D21', + state: 'ONGOING', + }, + { + id: 24, + name: '139SS27F Södra Bangatan förskola', + url: 'https://hjarntorget.goteborg.se/o/apiAccessWithKey.do?forwardUrl=%2FlaunchCourse.do%3Fid%3D24', + state: 'ONGOING', + }, + ]), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/fakeFetcher.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/fakeFetcher.ts new file mode 100644 index 000000000..65a58eec9 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/fakeFetcher.ts @@ -0,0 +1,53 @@ +import { Fetcher, Response } from '../../../api/lib' +import { calendars, calendar_14241345 } from './calendars' +import { currentUser } from './current-user' +import { events } from './events' +import { + lessons_123456_goteborgsstad, + lessons_133700_goteborgsstad, + lessons_133737_goteborgsstad, +} from './lessons' +import { myChildren } from './my-children' +import { wallEvents } from './wall-events' +import { information } from './information' +import { genericRolesInEvent } from './roles-in-event' +import { + eventRoleMembers14, + eventRoleMembers18, + eventRoleMembers21, + eventRoleMembers24, +} from './event-role-members' + +const fetchMappings: { [name: string]: () => Response } = { + 'current-user': currentUser, + events: events, + 'my-children': myChildren, + 'wall-events': wallEvents, + 'lessons-133700_goteborgsstad': lessons_133700_goteborgsstad, + 'lessons-133737_goteborgsstad': lessons_133737_goteborgsstad, + 'lessons-123456_goteborgsstad': lessons_123456_goteborgsstad, + info: information, + 'roles-in-event-14': genericRolesInEvent, + 'roles-in-event-18': genericRolesInEvent, + 'roles-in-event-21': genericRolesInEvent, + 'roles-in-event-24': genericRolesInEvent, + 'event-role-members-14-821': eventRoleMembers14, + 'event-role-members-18-821': eventRoleMembers18, + 'event-role-members-21-821': eventRoleMembers21, + 'event-role-members-24-821': eventRoleMembers24, + calendars: calendars, + 'calendar-14241345': calendar_14241345, +} + +export const fakeFetcher: Fetcher = ( + name: string, + _url: string, + _init?: any +): Promise => { + const responder = + fetchMappings[name] ?? + (() => { + throw new Error('Request not faked for name: ' + name) + }) + return Promise.resolve(responder()) +} diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/information.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/information.ts new file mode 100644 index 000000000..c073d1c0f --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/information.ts @@ -0,0 +1,117 @@ +export const information = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/information/messages-by-date-desc?messageStatus=CURRENT&offset=0&limit=10&language=en', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: 3276034, + title: 'Nu får du och ditt barn tillgång till Polyglutt hemma', + body: '

Nu får alla barn som går i kommunal förskola i Göteborg tillgång till bilderboksappen Polyglutt hemifrån! Det innebär att du som vårdnadshavare och barn kan ta del av ett bibliotek av böcker på både svenska och 60 andra språk, inklusive TAKK och teckenspråk via telefon eller läsplatta.

\r\n

Polyglutt är en app med bilderböcker som fungerar som ett verktyg för att arbeta med språkutveckling och litteratur i förskolan och hemma.

\r\n

Polyglutt Home Access är en tjänst som innebär att alla barn som går i kommunal förskola i Göteborg får tillgång till ett bibliotek av böcker på både svenska och 60 andra språk, inklusive TAKK och teckenspråk hemifrån. Varje förskola kan också skapa egna bokhyllor med boktips i appen som du och ditt barn kan läsa hemma.

\r\n

Tjänsten fungerar på iPad, Androidplattor och i mobilen.

\r\n

Vill du veta mer om tjänsten, kontakta pedagogerna på ditt barns förskola.

', + creator: { + id: '501747_goteborgsstad', + firstName: 'Information Digitalisering', + lastName: 'Innovation', + email: + 'information.digitaliseringochinnovation@forskola.goteborg.se', + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + recipientGroups: [ + { + id: 1121821, + name: 'DL Göteborg Vhavare förskolor', + }, + ], + created: { + ts: 1629970713111, + timezoneOffsetMinutes: 120, + }, + attachments: [], + readByUser: false, + archivedByUser: false, + }, + { + id: 3270718, + title: 'Information från grundskoleförvaltningen', + body: '

Till vårdnadshavare med barn på Göteborgs Stads grundskolor och grundsärskolor.

\r\n

Spridningen av covid-19 har ökat. Därför är det viktigt att alla hjälper till att minska spridningen av smitta.

\r\n

Vi fortsätter hålla avstånd

\r\n
    \r\n
  • Om du vill ha kontakt med någon på ditt barns skola vill vi gärna att du ringer eller skickar e-post.
  • \r\n
  • Lämna och hämta ditt barn utomhus på skolgården.
  • \r\n
  • En del möten som skolan har kommer att vara digitala.
  • \r\n
  • Uppmuntra ditt barn att promenera till och från skolan för att minska trängseln i kollektivtrafiken.
  • \r\n
\r\n

Detta gäller när ditt barn är sjukt

\r\n
    \r\n
  • Barn som bara är lite sjuka, som till exempel är snuviga eller har ont i halsen, ska stanna hemma.
  • \r\n
  • Berätta alltid för skolan om ditt barn har konstaterad covid-19.
  • \r\n
\r\n

Här hittar du mer information om vad som gäller när ditt barn är sjukt.

\r\n

Om ditt barn har varit på resa utomlands

\r\n

Folkhälsomyndigheten rekommenderar alla som har varit i länder utanför Norden att ta ett test för covid-19 när de kommer tillbaka Sverige. Detta gäller oavsett om man har symtom eller inte.

\r\n

Läs mer på Krisinformation.se om vad som gäller för resor från olika länder:
Utrikesresor och att vistas utomlands - Krisinformation.se

\r\n

Undervisning på skolan

\r\n

Från och med höstterminen 2021 har alla skolor undervisning på plats i skolan. Detta gäller även för årskurs 7-9.

\r\n

För förskoleklass till och med årskurs 9 finns det fortfarande möjlighet att få undervisning på distans om:

\r\n
    \r\n
  • Många av de som jobbar på skolan är frånvarande på grund av covid-19 och det inte går att ha undervisning i skolan.
  • \r\n
  • Det är stor spridningen av covid-19 bland elever och medarbetare.
  • \r\n
\r\n

Nytt test för covid-19 på skolorna

\r\n

Inom kort börjar Västra Götalandsregionen med ett nytt test för covid-19 riktat mot elever.  Om ditt barn har haft nära kontakt med en person på skolan som har konstaterad covid-19 får ni med ett paket hem med ett test. 

\r\n

Du som vårdnadshavare hjälper ditt barn att ta testet. Testet lämnar du som vårdnadshavare sedan till en utvald vårdcentral.

\r\n

Om ditt barn ska ta ett test får du mer information från ditt barns skola om hur testet går till och vilken vårdcentral du ska lämna det till.

\r\n

Kontakt

\r\n

Har du frågor eller funderingar kontaktar du ditt barns skola.

\r\n

Läs mer om covid-19 och vad som gäller för grundskoleförvaltningen.

\r\n

 

', + creator: { + id: '486497_goteborgsstad', + firstName: 'Grundskola', + lastName: 'Informerar', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + recipientGroups: [ + { + id: 4925595, + name: 'DL Göteborg Grundskola Vhavare Alla', + }, + { + id: 4525636, + name: 'Grundskola - informationskonto', + }, + { + id: 4925600, + name: 'DL Göteborg Grundsärskola Vhavare Alla', + }, + ], + created: { + ts: 1629096850743, + timezoneOffsetMinutes: 120, + }, + attachments: [ + { + id: 67888219, + name: 'Om ditt barn är sjukt eller borta från skolan_information till vårdnadshavare_uppdaterad 13 augusti 2021.pdf', + size: 70466, + }, + ], + readByUser: false, + archivedByUser: false, + }, + { + id: 2982365, + title: 'Nya regler för skolplacering i förskoleklass och grundskola', + body: '

Grundskolenämnden har beslutat om nya regler för skolplacering i förskoleklass och grundskola. Reglerna ska stärka elevernas rätt till en skola nära hemmet och börjar gälla 1 januari 2021.

\r\n

Du kan läsa mer på sidan Nya regler för skolplacering i förskoleklass och grundskola

\r\n

Om du har frågor kan du kontakta grundskoleförvaltningen på telefon: 031-365 09 60 eller e-post: grundskola@grundskola.goteborg.se

\r\n

Observera att detta meddelande inte går att svara på. 

\r\n

 

', + creator: { + id: '486497_goteborgsstad', + firstName: 'Grundskola', + lastName: 'Informerar', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + recipientGroups: [ + { + id: 4925595, + name: 'DL Göteborg Grundskola Vhavare Alla', + }, + { + id: 4525636, + name: 'Grundskola - informationskonto', + }, + ], + created: { + ts: 1603974943027, + timezoneOffsetMinutes: 60, + }, + attachments: [], + readByUser: false, + archivedByUser: false, + }, + ]), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/lessons.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/lessons.ts new file mode 100644 index 000000000..76c514ab8 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/lessons.ts @@ -0,0 +1,437 @@ +// TODO: fix the startDate/endDate of all lessons +export const lessons_133700_goteborgsstad = () => { + const baseTime = 1636357800000 + const baseDate = new Date(baseTime) + const today = new Date() + const currentHour = today.getHours() + today.setHours(baseDate.getHours()) + today.setMinutes(baseDate.getMinutes()) + today.setSeconds(0) + + let offset = Math.abs(baseTime - today.getTime()) + const weekDay = today.getDay() + + if (weekDay == 6 || (weekDay == 5 && currentHour >= 18)) { + offset = offset + 2 * 86400000 + } + if (weekDay == 0) { + offset = offset + 86400000 + } + if (weekDay > 0 && weekDay < 6 && currentHour >= 18) { + offset = offset + 86400000 + } + + return { + url: 'https://hjarntorget.goteborg.se/api/schema/lessons?forUser=133700_goteborgsstad&startDateIso=2021-11-01&endDateIso=2021-11-08', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: '36080472:1', + title: 'HKK', + location: 'A402', + calendars: ['138JÄTS 21/22 8B/HKK'], + startDate: { + ts: offset + 1636357800000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636360500000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Noel Nyström (NNM)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080497:1', + title: 'BL', + location: 'B260', + calendars: ['138JÄTS 21/22 8B/BL'], + startDate: { + ts: offset + 1636361700000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636365000000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Joseph Ekström (JHE)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '37164864:1', + title: 'IDH', + location: 'IDH Ute', + calendars: ['138JÄTS 21/22 8B/IDH'], + startDate: { + ts: offset + 1636365600000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636369800000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Katja Fransson (KAF)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080557:1', + title: 'LUNCH', + location: '-', + calendars: ['138JÄTS 21/22 8B'], + startDate: { + ts: offset + 1636370700000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636372800000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: [], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080576:1', + title: 'EN', + location: 'A402', + calendars: ['138JÄTS 21/22 8B/EN'], + startDate: { + ts: offset + 1636372800000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636376400000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Henrietta Fransson (HAF)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080591:1', + title: 'MA', + location: 'A402', + calendars: ['138JÄTS 21/22 8B/MA'], + startDate: { + ts: offset + 1636377000000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636380600000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Amin Månsson (ANM)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + ]), + } as any as Response +} + +export const lessons_123456_goteborgsstad = () => { + const baseTime = 1636357800000 + const baseDate = new Date(baseTime) + const today = new Date() + const currentHour = today.getHours() + today.setHours(baseDate.getHours()) + today.setMinutes(baseDate.getMinutes()) + today.setSeconds(0) + + let offset = Math.abs(baseTime - today.getTime()) + const weekDay = today.getDay() + + if (weekDay == 6 || (weekDay == 5 && currentHour >= 18)) { + offset = offset + 2 * 86400000 + } + if (weekDay == 0) { + offset = offset + 86400000 + } + if (weekDay > 0 && weekDay < 6 && currentHour >= 18) { + offset = offset + 86400000 + } + + return { + url: 'https://hjarntorget.goteborg.se/api/schema/lessons?forUser=123456_goteborgsstad&startDateIso=2021-11-01&endDateIso=2021-11-08', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => [ + { + id: '36080454:1', + title: 'EV', + location: 'P18', + calendars: ['138JÄTS 21/22 5A'], + startDate: { + ts: offset + 1636355400000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636357500000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Petra Modin (PMO)', 'Joakim Ness (JNE)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080467:1', + title: 'MENT', + location: 'P18', + calendars: ['138JÄTS 21/22 5A'], + startDate: { + ts: offset + 1636357500000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636358100000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Petra Modin (PMO)', 'Joakim Ness (JNE)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080474:1', + title: 'EN', + location: 'P18', + calendars: ['138JÄTS 21/22 5A'], + startDate: { + ts: offset + 1636358400000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636362000000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Petra Modin (PMO)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080502:1', + title: 'SV', + location: 'P18', + calendars: ['138JÄTS 21/22 5A'], + startDate: { + ts: offset + 1636362900000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636366500000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Joakim Ness (JNE)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080529:1', + title: 'LUNCH', + location: '-', + calendars: ['138JÄTS 21/22 5A'], + startDate: { + ts: offset + 1636366500000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636368300000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: [], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080545:1', + title: 'MA', + location: 'P18', + calendars: ['138JÄTS 21/22 5A'], + startDate: { + ts: offset + 1636369200000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636372800000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Ali Gupta (AGU)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + { + id: '36080578:1', + title: 'NO', + location: 'P18', + calendars: ['138JÄTS 21/22 5A'], + startDate: { + ts: offset + 1636373400000, + timezoneOffsetMinutes: 60, + }, + endDate: { + ts: offset + 1636376400000, + timezoneOffsetMinutes: 60, + }, + ownPlannings: null, + teacherPlannings: null, + teacherAndStudentPlannings: null, + ownGeneralPlannings: null, + teacherGeneralPlannings: null, + teacherAndStudentGeneralPlannings: null, + bookedResourceNames: [], + bookedTeacherNames: ['Ali Gupta (AGU)'], + hasTest: false, + hasHomework: false, + hasAssignment: false, + url: null, + note: '', + }, + ], + } as any as Response +} + +export const lessons_133737_goteborgsstad = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/schema/lessons?forUser=133737_goteborgsstad&startDateIso=2021-11-01&endDateIso=2021-11-08', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => Promise.resolve([] as any[]), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/my-children.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/my-children.ts new file mode 100644 index 000000000..2669d1506 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/my-children.ts @@ -0,0 +1,47 @@ +export const myChildren = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/person/children', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + // Klass: Förskola + id: '133737_goteborgsstad', + firstName: 'Havin', + lastName: 'Göransson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + // Klass: 8B + id: '133700_goteborgsstad', + firstName: 'Azra', + lastName: 'Göransson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + { + // Klass: 5A + id: '123456_goteborgsstad', + firstName: 'Jon', + lastName: 'Göransson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + ]), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/roles-in-event.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/roles-in-event.ts new file mode 100644 index 000000000..4daabb0bf --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/roles-in-event.ts @@ -0,0 +1,18 @@ +export const genericRolesInEvent = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/event-members/roles?eventId=XXX&language=en', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: 821, + name: 'SINGLE ROLE', + }, + ]), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/wall-events.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/wall-events.ts new file mode 100644 index 000000000..447a3f44b --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/fake/wall-events.ts @@ -0,0 +1,1139 @@ +export const wallEvents = () => + ({ + url: 'https://hjarntorget.goteborg.se/api/wall/events?language=en&limit=500', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + cookie: 'REMOVED', + }, + status: 200, + statusText: '200', + json: () => + Promise.resolve([ + { + id: 12312312, + type: 'PIM_SENT', + intId: 27817023, + eventId: null, + eventName: null, + created: { + ts: 1635946042792, + timezoneOffsetMinutes: 60, + }, + creator: { + id: '494949_goteborgsstad', + firstName: 'Fideli', + lastName: 'Sundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Uppdaterade matriser - Engelska\n\nHej,\r Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Fideli Sundström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27817023&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 123123133, + type: 'PIM_SENT', + intId: 112233, + eventId: null, + eventName: null, + created: { + ts: 1635707596339, + timezoneOffsetMinutes: 60, + }, + creator: { + id: '1313131_goteborgsstad', + firstName: 'Haris', + lastName: 'Jonsson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Föräldramöte \n\nHej alla föräldrar! \r\nDen Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Haris Jonsson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=112233&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 123123, + type: 'PIM_SENT', + intId: 445566, + eventId: null, + eventName: null, + created: { + ts: 1635539349363, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '494949_goteborgsstad', + firstName: 'Fideli', + lastName: 'Sundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Veckobrev vecka 43\n\nHej på er,\n Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Fideli Sundström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=445566&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 33060728, + type: 'PIM_SENT', + intId: 27784844, + eventId: null, + eventName: null, + created: { + ts: 1635433031919, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '887766_goteborgsstad', + firstName: 'Neo', + lastName: 'Lundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Schemabrytande dag fredag 29/10\n\nHej!\n Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Neo Lundström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27784844&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 33060544, + type: 'PIM_SENT', + intId: 27784728, + eventId: null, + eventName: null, + created: { + ts: 1635432357047, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '776655_goteborgsstad', + firstName: 'Walid', + lastName: 'Söderström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Info mattematik\n\nHej! Här kommer lite Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Walid Söderström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27784728&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 33060526, + type: 'PIM_SENT', + intId: 27784714, + eventId: null, + eventName: null, + created: { + ts: 1635432262110, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '393939_goteborgsstad', + firstName: 'Malik Maria', + lastName: 'Henriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Förändrade Covid-19 restriktioner den 1/11\n Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Malik Maria Henriksson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27784714&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 1231232, + type: 'PIM_SENT', + intId: 666777, + eventId: null, + eventName: null, + created: { + ts: 1635423440616, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '444444_goteborgsstad', + firstName: 'Idas', + lastName: 'Svensson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Klädbyte\n\nHej! Här kommer lite sen Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Idas Svensson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=666777&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 33038976, + type: 'PIM_SENT', + intId: 27767727, + eventId: null, + eventName: null, + created: { + ts: 1635343618117, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '388601_goteborgsstad', + firstName: 'Rosa', + lastName: 'Fredriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Info: Teater i klassrummet \n\nHej, Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Rosa Fredriksson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27767727&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 33026905, + type: 'PIM_SENT', + intId: 27758800, + eventId: null, + eventName: null, + created: { + ts: 1635320813305, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '393939_goteborgsstad', + firstName: 'Malik Maria', + lastName: 'Henriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Inbjudan till digitalt föräldramöte\n\nHej!\r Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Malik Maria Henriksson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27758800&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 33000399, + type: 'PIM_SENT', + intId: 27737280, + eventId: null, + eventName: null, + created: { + ts: 1635191359954, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '1313131_goteborgsstad', + firstName: 'Haris', + lastName: 'Jonsson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Aktiviteten guls blogg är uppdaterad\n\nKlicka på Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Haris Jonsson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27737280&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32989753, + type: 'PIM_SENT', + intId: 27728754, + eventId: null, + eventName: null, + created: { + ts: 1635158030341, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '776655_goteborgsstad', + firstName: 'Walid', + lastName: 'Söderström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Veckobrev\n\nHej!\r\n\r\nDen Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Walid Söderström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27728754&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32974490, + type: 'PIM_SENT', + intId: 27716539, + eventId: null, + eventName: null, + created: { + ts: 1635061518818, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '__system$virtual$calendar__', + firstName: 'Kalendern', + lastName: 'i PING PONG', + email: null, + online: false, + imagePath: '/pp/lookAndFeel/skins/default/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Alarm från kalendern!\n\n2021-10-27 Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Kalendern i PING PONG', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27716539&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32971325, + type: 'PIM_SENT', + intId: 27714073, + eventId: null, + eventName: null, + created: { + ts: 1634917402164, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '393939_goteborgsstad', + firstName: 'Malik Maria', + lastName: 'Henriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Information om Rs-virus och om jul och Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Malik Maria Henriksson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27714073&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32967200, + type: 'PIM_SENT', + intId: 27711059, + eventId: null, + eventName: null, + created: { + ts: 1634903242904, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '362119_goteborgsstad', + firstName: 'Elina', + lastName: 'Cocolis', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Veckobrev v. 42\n\nHej!\r Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Elina Cocolis', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27711059&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32921663, + type: 'PIM_SENT', + intId: 27675194, + eventId: null, + eventName: null, + created: { + ts: 1634722320717, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '654654_goteborgsstad', + firstName: 'Moses', + lastName: 'Johansson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Information om vaccination Covid 19 \n\n\r Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Katarina Krokström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27675194&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32885504, + type: 'PIM_SENT', + intId: 27646298, + eventId: null, + eventName: null, + created: { + ts: 1634562692304, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '494949_goteborgsstad', + firstName: 'Fideli', + lastName: 'Sundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Klargörande gällande tillgång till classroom för föräldrar \n Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Fideli Sundström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27646298&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32883748, + type: 'PIM_SENT', + intId: 27645002, + eventId: null, + eventName: null, + created: { + ts: 1634559012123, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '776655_goteborgsstad', + firstName: 'Walid', + lastName: 'Söderström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Veckobrev\n\nHej!\r\nNu har jobbat Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Walid Söderström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27645002&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32866619, + type: 'PIM_SENT', + intId: 27630980, + eventId: null, + eventName: null, + created: { + ts: 1634369141552, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '818181_goteborgsstad', + firstName: 'Nadja', + lastName: 'Ekström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Nytt blogginlägg Södra Bangatan förskola stänger kl 16 mån Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Nadja Ekström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27630980&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32865172, + type: 'PIM_SENT', + intId: 27629801, + eventId: null, + eventName: null, + created: { + ts: 1634306923490, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '388601_goteborgsstad', + firstName: 'Rosa', + lastName: 'Fredriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Veckobrev (v.41)\n\nHej, \r Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Rosa Fredriksson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27629801&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32850672, + type: 'PIM_SENT', + intId: 27618230, + eventId: null, + eventName: null, + created: { + ts: 1634271404561, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '818181_goteborgsstad', + firstName: 'Nadja', + lastName: 'Ekström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Lägg in nytt schema snarast!\n\nHej Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Nadja Ekström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27618230&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32847588, + type: 'PIM_SENT', + intId: 27615823, + eventId: null, + eventName: null, + created: { + ts: 1634222507832, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '887766_goteborgsstad', + firstName: 'Neo', + lastName: 'Lundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Länk till föräldramöte\n\nHär är länken till Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Neo Lundström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27615823&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32846324, + type: 'PIM_SENT', + intId: 27614784, + eventId: null, + eventName: null, + created: { + ts: 1634218630977, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '393939_goteborgsstad', + firstName: 'Malik Maria', + lastName: 'Henriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Kort information från förskolan\n\nHej!\r Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Malik Maria Henriksson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27614784&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32827306, + type: 'PIM_SENT', + intId: 27599759, + eventId: null, + eventName: null, + created: { + ts: 1634133056730, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '654654_goteborgsstad', + firstName: 'Moses', + lastName: 'Johansson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Information om vaccination Covid 19 \n\n\r Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Moses Johansson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27599759&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32808563, + type: 'PIM_SENT', + intId: 27584917, + eventId: null, + eventName: null, + created: { + ts: 1634045704615, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '654654_goteborgsstad', + firstName: 'Moses', + lastName: 'Johansson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Erbjudande om ABC-föräldrakurs\n\nHej vårdnadshavare F Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Katarina Krokström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27584917&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32805895, + type: 'PIM_SENT', + intId: 27582958, + eventId: null, + eventName: null, + created: { + ts: 1634039816865, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '999999_goteborgsstad', + firstName: 'Sanne', + lastName: 'Berggren', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Utvecklingssamtal v. 42 & v. 43 Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Sanne Berggren', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27582958&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32788940, + type: 'PIM_SENT', + intId: 27569652, + eventId: null, + eventName: null, + created: { + ts: 1633959214453, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '168925_goteborgsstad', + firstName: 'Teddy', + lastName: 'Karlsson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'No-prov v.42.\n\nHejsan!\n Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Teddy Karlsson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27569652&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 11223344, + type: 'PIM_SENT', + intId: 4949494, + eventId: null, + eventName: null, + created: { + ts: 1633952791428, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '776655_goteborgsstad', + firstName: 'Walid', + lastName: 'Söderström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Veckobrev\n\nHej!\r\n\r\nVi Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Walid Söderström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=4949494&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [ + { + fileId: 68860163, + width: 1413, + height: 774, + }, + { + fileId: 68860164, + width: 1400, + height: 761, + }, + ], + videos: [], + unread: false, + }, + { + id: 32780295, + type: 'PIM_SENT', + intId: 27562530, + eventId: null, + eventName: null, + created: { + ts: 1633939225240, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '__system$virtual$calendar__', + firstName: 'Kalendern', + lastName: 'i PING PONG', + email: null, + online: false, + imagePath: '/pp/lookAndFeel/skins/default/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Alarm från kalendern!\n\n2021-10-12 Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Kalendern i PING PONG', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27562530&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32773706, + type: 'PIM_SENT', + intId: 27556897, + eventId: null, + eventName: null, + created: { + ts: 1633890789600, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '1313131_goteborgsstad', + firstName: 'Haris', + lastName: 'Jonsson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Aktiviteten rosas blogg är uppdaterad\n\nKlicka på Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Haris Jonsson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27556897&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 67676767, + type: 'PIM_SENT', + intId: 525252, + eventId: null, + eventName: null, + created: { + ts: 1633701687774, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '919191_goteborgsstad', + firstName: 'Karim', + lastName: 'Fakir', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Veckobrev v. 40\n\nHej\r\n Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Karim Fakir', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=525252&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32751305, + type: 'PIM_SENT', + intId: 969696, + eventId: null, + eventName: null, + created: { + ts: 1633621344421, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '818181_goteborgsstad', + firstName: 'Nadja', + lastName: 'Ekström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Nytt blogginlägg för förra veckan....\n\nhttps Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Nadja Ekström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=969696&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32750570, + type: 'PIM_SENT', + intId: 27539459, + eventId: null, + eventName: null, + created: { + ts: 1633618458315, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '887766_goteborgsstad', + firstName: 'Neo', + lastName: 'Lundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Inbjudan föräldramöte åk 7, tors 14/10 Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Neo Lundström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27539459&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32748594, + type: 'PIM_SENT', + intId: 27538060, + eventId: null, + eventName: null, + created: { + ts: 1633612340812, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '887766_goteborgsstad', + firstName: 'Neo', + lastName: 'Lundström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: '7C: Fredag 8/10 börjar matten 9 Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Neo Lundström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27538060&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 7917197, + type: 'PIM_SENT', + intId: 971971, + eventId: null, + eventName: null, + created: { + ts: 1633608467229, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '393939_goteborgsstad', + firstName: 'Malik Maria', + lastName: 'Henriksson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Påminnelse om Hämta/Lämna uppdateringen\n\nHej!\n Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Malik Maria Henriksson', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=971971&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32726984, + type: 'PIM_SENT', + intId: 27520912, + eventId: null, + eventName: null, + created: { + ts: 1633519169842, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '776655_goteborgsstad', + firstName: 'Walid', + lastName: 'Söderström', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Ordet\n\nHej igen!\r\nKlassen har Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Walid Söderström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27520912&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + { + id: 32713989, + type: 'PIM_SENT', + intId: 27510300, + eventId: null, + eventName: null, + created: { + ts: 1633444717085, + timezoneOffsetMinutes: 120, + }, + creator: { + id: '654654_goteborgsstad', + firstName: 'Moses', + lastName: 'Johansson', + email: null, + online: false, + imagePath: + '/pp/lookAndFeel/skins/hjarntorget/icons/monalisa_large.png', + extraInfoInCatalog: '', + }, + title: 'PIM from PING PONG', + body: 'Information från grundskoleförvaltningen-rekommendationer för att minska spridningen Löksås ipsum räv jäst har tre nu om, mjuka träutensilierna olika hans dag inom bra gamla, att oss kan sista erfarenheter olika. Vidsträckt själv upprätthållande så groda smultron nya år regn mjuka strand upprätthållande som rot erfarenheter, blivit brunsås dag kanske sjö miljoner ta söka räv blivit vemod rännil. Björnbär strand sjö inom icke i det, faktor denna verkligen av trevnadens, så tre miljoner för helt.', + attribute1: 'Katarina Krokström', + attribute2: null, + url: 'https://hjarntorget.goteborg.se/pimShowInboxMessage.do?id=27510300&linkOrigin=wall', + onclick: null, + anonymous: false, + images: [], + videos: [], + unread: false, + }, + ]), + } as any as Response) diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/features.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/features.ts new file mode 100644 index 000000000..f1f39dde9 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/features.ts @@ -0,0 +1,8 @@ +import { Features } from '../../api/lib' + +export const features: Features = { + LOGIN_BANK_ID_SAME_DEVICE_WITHOUT_ID: false, + LOGIN_FREJA_EID: false, + FOOD_MENU: false, + CLASS_LIST: false, +} diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/index.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/index.ts new file mode 100644 index 000000000..c98383e80 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/index.ts @@ -0,0 +1,25 @@ +import { + Api, + Fetch, + FetcherOptions, + RNCookieManager, + ToughCookieJar, + wrapReactNativeCookieManager, + wrapToughCookie, +} from '../../api/lib' +import { ApiHjarntorget } from './apiHjarntorget' +export { features } from './features' + +const init = ( + fetchImpl: Fetch, + cookieManagerImpl: RNCookieManager | ToughCookieJar, + options?: FetcherOptions +): Api => { + // prettier-ignore + const cookieManager = ((cookieManagerImpl as RNCookieManager).get) + ? wrapReactNativeCookieManager(cookieManagerImpl as RNCookieManager) + : wrapToughCookie(cookieManagerImpl as ToughCookieJar); + return new ApiHjarntorget(fetchImpl as any, cookieManager, options) +} + +export default init diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/loginStatus.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/loginStatus.ts new file mode 100644 index 000000000..b4ec3dfc0 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/loginStatus.ts @@ -0,0 +1,135 @@ +import { Fetcher, LoginStatusChecker } from '../../api/lib' +import { EventEmitter } from 'events' +import { + extractAuthGbgLoginRequestBody, + extractHjarntorgetSAMLLogin, +} from './parse/parsers' +import { + authGbgLoginUrl, + hjarntorgetSAMLLoginUrl, + pollStatusUrl, +} from './routes' + +export class HjarntorgetChecker + extends EventEmitter + implements LoginStatusChecker +{ + private fetcher: Fetcher + + private basePollingUrl: string + + public token: string + + private cancelled = false + + constructor(fetcher: Fetcher, basePollingUrl: string) { + super() + this.token = '' // not used, but needed for compatability with the LoginStatusChecker + this.fetcher = fetcher + this.basePollingUrl = basePollingUrl + + this.check() + } + + async check(): Promise { + try { + console.log('polling bankid signature') + // https://mNN-mg-local.idp.funktionstjanster.se/mg-local/auth/ccp11/grp/pollstatus + + const pollStatusResponse = await this.fetcher( + 'poll-bankid-status', + pollStatusUrl(this.basePollingUrl) + ) + console.log('poll-bankid-status') + const pollStatusResponseJson = await pollStatusResponse.json() + + const keepPolling = pollStatusResponseJson.infotext !== '' + const isError = pollStatusResponseJson.location.indexOf('error') >= 0 + if (!keepPolling && !isError) { + console.log('bankid successfull! follow to location...') + // follow response location to get back to auth.goteborg.se + // r.location is something like: + // 'https://mNN-mg-local.idp.funktionstjanster.se/mg-local/auth/ccp11/grp/signature' + const signatureResponse = await this.fetcher( + 'confirm-signature-redirect', + pollStatusResponseJson.location, + { + redirect: 'follow', + } + ) + if (!signatureResponse.ok) { + throw new Error('Bad signature response') + } + const signatureResponseText = await signatureResponse.text() + const authGbgLoginBody = extractAuthGbgLoginRequestBody( + signatureResponseText + ) + + console.log('authGbg saml login') + const authGbgLoginResponse = await this.fetcher( + 'authgbg-saml-login', + authGbgLoginUrl, + { + redirect: 'follow', + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: authGbgLoginBody, + } + ) + if (!authGbgLoginResponse.ok) { + throw new Error('Bad augGbgLogin response') + } + const authGbgLoginResponseText = await authGbgLoginResponse.text() + const hjarntorgetSAMLLoginBody = extractHjarntorgetSAMLLogin( + authGbgLoginResponseText + ) + + console.log('hjarntorget saml login') + const hjarntorgetSAMLLoginResponse = await this.fetcher( + 'hjarntorget-saml-login', + hjarntorgetSAMLLoginUrl, + { + method: 'POST', + redirect: 'follow', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: hjarntorgetSAMLLoginBody, + } + ) + if (!hjarntorgetSAMLLoginResponse.ok) { + throw new Error('Bad hjarntorgetSAMLLogin response') + } + // TODO: add more checks above between calls to see if everything is actually 'OK'... + this.emit('OK') + } else if (isError) { + console.log('polling error') + this.emit('ERROR') + } else if (!this.cancelled && keepPolling) { + console.log('keep on polling...') + this.emit('PENDING') + setTimeout(() => this.check(), 3000) + } + } catch (er) { + console.log('Error validating login to Hjärntorget', er) + this.emit('ERROR') + } + } + + async cancel(): Promise { + this.cancelled = true + } +} + +export const checkStatus = ( + fetch: Fetcher, + basePollingUrl: string +): LoginStatusChecker => new HjarntorgetChecker(fetch, basePollingUrl) + +export class DummyStatusChecker + extends EventEmitter + implements LoginStatusChecker +{ + token = '' + async cancel(): Promise { + // do nothing + } +} diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/missingtypes.d.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/missingtypes.d.ts new file mode 100644 index 000000000..0334e2034 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/missingtypes.d.ts @@ -0,0 +1 @@ +declare module 'h2m' diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/parse/parsers.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/parse/parsers.ts new file mode 100644 index 000000000..b9e338814 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/parse/parsers.ts @@ -0,0 +1,79 @@ +import * as html from 'node-html-parser' +import { decode } from 'he' + +// TODO: Move this into the parse folder and convert it to follow the pattern of other parsers (include tests). + +export const extractInputField = (sought: string, attrs: string[]) => { + // there must be a better way to do this... + const s = attrs.find((e) => e.indexOf(sought) >= 0) || '' + const v = s.substring(s.indexOf('value="') + 'value="'.length) + return v.substring(0, v.length - 2) +} + +export function extractMvghostRequestBody(initBankIdResponseText: string) { + const doc = html.parse(decode(initBankIdResponseText)) + const inputAttrs = doc + .querySelectorAll('input') + .map((i) => (i as any).rawAttrs) + const relayState = extractInputField('RelayState', inputAttrs) + const samlRequest = extractInputField('SAMLRequest', inputAttrs) + const mvghostRequestBody = `RelayState=${encodeURIComponent( + relayState + )}&SAMLRequest=${encodeURIComponent(samlRequest)}` + + return mvghostRequestBody +} + +export function extractHjarntorgetSAMLLogin(authGbgLoginResponseText: string) { + const authGbgLoginDoc = html.parse(decode(authGbgLoginResponseText)) + const inputAttrs = authGbgLoginDoc + .querySelectorAll('input') + .map((i) => (i as any).rawAttrs) + const RelayStateText = extractInputField('RelayState', inputAttrs) + const SAMLResponseText = extractInputField('SAMLResponse', inputAttrs) + + return `SAMLResponse=${encodeURIComponent( + SAMLResponseText || '' + )}&RelayState=${encodeURIComponent(RelayStateText || '')}` +} + +export function extractAuthGbgLoginRequestBody(signatureResponseText: string) { + const signatureResponseDoc = html.parse(decode(signatureResponseText)) + const signatureResponseTextAreas = + signatureResponseDoc.querySelectorAll('textarea') + const SAMLResponseElem = signatureResponseTextAreas.find((ta) => { + const nameAttr = ta.getAttribute('name') + return nameAttr === 'SAMLResponse' + }) + const SAMLResponseText = SAMLResponseElem?.rawText + const RelayStateElem = signatureResponseTextAreas.find((ta) => { + const nameAttr = ta.getAttribute('name') + return nameAttr === 'RelayState' + }) + const RelayStateText = RelayStateElem?.rawText + const authGbgLoginBody = `SAMLResponse=${encodeURIComponent( + SAMLResponseText || '' + )}&RelayState=${encodeURIComponent(RelayStateText || '')}` + return authGbgLoginBody +} + +export const parseCalendarItem = ( + x: html.HTMLElement +): { id: number; title: string; startDate: string; endDate: string } => { + const info = Array.from(x.querySelectorAll('a')) + // TODO: the identifier is realy on this format: '\d+:\d+' currently we only take the first part so Id will clash between items + const id = + info[0] + .getAttribute('onClick') + ?.replace(new RegExp("return viewEvent\\('(\\d+).+"), '$1') || NaN + const day = info[1].textContent + const timeSpan = info[2].textContent + const [startTime, endTime] = timeSpan.replace('.', ':').split('-') + + return { + id: +id, + title: info[0].textContent, + startDate: `${day} ${startTime}`, + endDate: `${day} ${endTime}`, + } +} diff --git a/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/routes.ts b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/routes.ts new file mode 100644 index 000000000..d23d1dcfa --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-hjarntorget/lib/routes.ts @@ -0,0 +1,83 @@ +export const lessonsUrl = (lessonParams: { + forUser: string + startDateIso: string + endDateIso: string +}) => { + const urlEncodedParams = new URLSearchParams(lessonParams).toString() + return `https://hjarntorget.goteborg.se/api/schema/lessons?${urlEncodedParams}` +} +export const hjarntorgetUrl = 'https://hjarntorget.goteborg.se' +export const currentUserUrl = + 'https://hjarntorget.goteborg.se/api/core/current-user' +export const myChildrenUrl = + 'https://hjarntorget.goteborg.se/api/person/children' +export const infoUrl = + 'https://hjarntorget.goteborg.se/api/information/messages-by-date-desc?messageStatus=CURRENT&offset=0&limit=10&language=en' +export const fullImageUrl = (imagePath: string) => hjarntorgetUrl + imagePath +export const infoSetReadUrl = (item: { id: string }) => + `https://hjarntorget.goteborg.se/api/information/set-message-read?messageId=${item.id}` +export const hjarntorgetEventsUrl = + 'https://hjarntorget.goteborg.se/api/events/events-sorted-by-name?offset=0&limit=100' +export const rolesInEventUrl = (eventId: number) => + `https://hjarntorget.goteborg.se/api/event-members/roles?eventId=${eventId}&language=en` +export const membersWithRoleUrl = (eventId: number, roleId: string) => + `https://hjarntorget.goteborg.se/api/event-members/members-having-role?eventId=${eventId}&roleId=${roleId}` +export const wallMessagesUrl = + 'https://hjarntorget.goteborg.se/api/wall/events?language=en&limit=500' +export const beginLoginUrl = 'https://hjarntorget.goteborg.se' +export const calendarsUrl = + 'https://hjarntorget.goteborg.se/pp/system/calendar/cal_events.jsp' +export const calendarEventUrl = ( + calendarId: string, + startDate: string, + endDate: string +) => + `${calendarsUrl}?order_by=start_date&show_cal_ids=${calendarId}&mode=separate&filter_start_date=${startDate}&filter_end_date=${endDate}&search_for=` + +export const shibbolethLoginUrlBase = (beginLoginRedirectUrl: string) => { + const returnUrlStart = + beginLoginRedirectUrl.indexOf('return=') + 'return='.length + return decodeURIComponent(beginLoginRedirectUrl.substring(returnUrlStart)) +} + +export const shibbolethLoginUrl = (returnUrl: string) => { + return `${returnUrl}&entityID=${encodeURIComponent( + 'https://auth.goteborg.se/FIM/sps/HjarntorgetEID/saml20' + )}` +} + +export const initBankIdUrl = (shibbolethRedirectUrl: any) => { + const targetParamIndex = + shibbolethRedirectUrl.indexOf('Target=') + 'Target='.length + const targetParam = decodeURIComponent( + shibbolethRedirectUrl.substring(targetParamIndex) + ) + const initBankIdUrl = + 'https://auth.goteborg.se/FIM/sps/BankID/saml20/logininitial?' + const initBankIdParams = + `ITFIM_WAYF_IDP=${encodeURIComponent( + 'https://m00-mg-local.idp.funktionstjanster.se/samlv2/idp/metadata/0/34' + )}` + + '&submit=Mobilt+BankID' + + '&ResponseBinding=HTTPPost' + + '&RequestBinding=HTTPPost' + + `&Target=${encodeURIComponent(targetParam)}` + return initBankIdUrl + initBankIdParams +} + +export const mvghostUrl = + 'https://m00-mg-local.idp.funktionstjanster.se/samlv2/idp/req/0/34?mgvhostparam=0' + +export const beginBankIdUrl = (beingBankIdUrlBase: string) => + `${beingBankIdUrlBase}/ssn` + +export const verifyUrlBase = (verifyUrl: string) => + verifyUrl.substring(0, verifyUrl.length - 'verify'.length) + +export const pollStatusUrl = (basePollingUrl: string) => + `${basePollingUrl}pollstatus` + +export const authGbgLoginUrl = + 'https://auth.goteborg.se/FIM/sps/BankID/saml20/login' +export const hjarntorgetSAMLLoginUrl = + 'https://hjarntorget.goteborg.se/Shibboleth.sso/SAML2/POST' diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/@react-native-cookies/cookies.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/@react-native-cookies/cookies.ts new file mode 100644 index 000000000..7ce777bc7 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/@react-native-cookies/cookies.ts @@ -0,0 +1,81 @@ +import { CookieJar, Cookie as TCookie } from 'tough-cookie' + +export interface Cookie { + name: string + value: string + path?: string + domain?: string + version?: string + expires?: string + secure?: boolean + httpOnly?: boolean +} + +export interface Cookies { + [key: string]: Cookie +} + +export interface CookieManagerStatic { + set(url: string, cookie: Cookie, useWebKit?: boolean): Promise + setFromResponse(url: string, cookie: string): Promise + + get(url: string, useWebKit?: boolean): Promise + + clearAll(useWebKit?: boolean): Promise +} + +const convertTtoC = (cookie: string | TCookie): Cookie => { + if (typeof cookie === 'string') { + return convertTtoC(TCookie.parse(cookie) as TCookie) + } + return { + name: cookie.key, + value: cookie.value, + domain: cookie.domain || undefined, + expires: + cookie.expires === 'Infinity' ? undefined : cookie.expires.toUTCString(), + httpOnly: cookie.httpOnly || undefined, + path: cookie.path || undefined, + secure: cookie.secure, + } +} +const convertCtoT = (cookie: Cookie): TCookie => + new TCookie({ + key: cookie.name, + value: cookie.value, + domain: cookie.domain, + expires: cookie.expires ? new Date(cookie.expires) : undefined, + httpOnly: cookie.httpOnly || false, + path: cookie.path, + secure: cookie.secure || false, + }) +const convertCookies = (cookies: TCookie[]): Cookies => + cookies.reduce( + (map, cookie) => ({ + ...map, + [cookie.key]: convertTtoC(cookie), + }), + {} as Cookies + ) + +const jar = new CookieJar() +const CookieManager: CookieManagerStatic = { + clearAll: async () => { + await jar.removeAllCookies() + return true + }, + get: async (url) => { + const cookies = await jar.getCookies(url) + return convertCookies(cookies) + }, + set: async (url, cookie) => { + await jar.setCookie(convertCtoT(cookie), url) + return true + }, + setFromResponse: async (url, cookie) => { + await jar.setCookie(cookie, url) + return true + }, +} + +export default CookieManager diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/__snapshots__/routes.test.ts.snap b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/__snapshots__/routes.test.ts.snap new file mode 100644 index 000000000..055cf5f7d --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/__snapshots__/routes.test.ts.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`handles route calender 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/Calender/GetSchoolCalender?childId=123&rowLimit=50"`; + +exports[`handles route children 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/GetChildren"`; + +exports[`handles route classmates 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/contacts/GetStudentsByClass?studentId=123"`; + +exports[`handles route image 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/NewsBanner?url=https://example.com/img.png"`; + +exports[`handles route login with personal number 1`] = `"https://login003.stockholm.se/NECSadcmbid/authenticate/NECSadcmbid?TYPE=33554433&REALMOID=06-42f40edd-0c5b-4dbc-b714-1be1e907f2de&GUID=1&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2fmbid%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvaGVt&initialize=bankid&personalNumber=201701012393&_=1618404258782"`; + +exports[`handles route login without personal number 1`] = `"https://login003.stockholm.se/NECSadcmbid/authenticate/NECSadcmbid?TYPE=33554433&REALMOID=06-42f40edd-0c5b-4dbc-b714-1be1e907f2de&GUID=1&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2fmbid%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvaGVt&initialize=bankid&_=1618404258782"`; + +exports[`handles route menuChoice 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/Matsedel/GetMatsedelChoice?childId=123"`; + +exports[`handles route menuList 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/Matsedel/GetMatsedelList?childId=123"`; + +exports[`handles route menuRss 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/Matsedel/GetMatsedelRSS?childId=123"`; + +exports[`handles route news 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/News/GetNewsArchive?bannerImageLimit=5000&childId=123"`; + +exports[`handles route newsDetails 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/News/GetNewsArticle?newsItemId=321&childId=123"`; + +exports[`handles route notifications 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/notifications/getnotifications?childId=123"`; + +exports[`handles route schedule 1`] = `"https://etjanst.stockholm.se/vardnadshavare/inloggad2/Calender/GetSchema?childId=123&startDate=2021-01-01&endDate=2021-01-01"`; + +exports[`handles route user 1`] = `"https://etjanst.stockholm.se/vardnadshavare/base/getuserdata"`; diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/api.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/api.test.ts new file mode 100644 index 000000000..647d52257 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/api.test.ts @@ -0,0 +1,211 @@ +import init from '..' +import { ApiSkolplattformen } from '../api' +import { Fetch, Headers, Response } from '../../../api/lib' +import CookieManager from '@react-native-cookies/cookies' + +jest.mock('@react-native-cookies/cookies') + +describe('api', () => { + let fetch: jest.Mocked + let response: jest.Mocked + let headers: jest.Mocked + let api: ApiSkolplattformen + beforeEach(() => { + headers = { get: jest.fn() } + response = { + json: jest.fn(), + text: jest.fn(), + ok: true, + status: 200, + statusText: 'ok', + headers, + } + fetch = jest.fn().mockResolvedValue(response) + response.text.mockResolvedValue('') + CookieManager.clearAll() + api = init(fetch, CookieManager) as ApiSkolplattformen + }) + describe('#login', () => { + it('exposes token', async () => { + const data = { + token: '9462cf77-bde9-4029-bb41-e599f3094613', + order: '5fe57e4c-9ad2-4b52-b794-48adef2f6663', + } + response.json.mockResolvedValue(data) + + const personalNumber = 'my personal number' + const status = await api.login(personalNumber) + + expect(status.token).toEqual(data.token) + status.cancel() + }) + it('emits PENDING', (done) => { + const data = { + token: '9462cf77-bde9-4029-bb41-e599f3094613', + order: '5fe57e4c-9ad2-4b52-b794-48adef2f6663', + } + const pending = { state: 'PENDING' } + response.json.mockResolvedValue(data) + response.json.mockResolvedValue(pending) + + const personalNumber = 'my personal number' + api.login(personalNumber).then((status) => { + status.on('PENDING', async () => { + status.cancel() + done() + }) + }) + }) + it('retries on PENDING', (done) => { + const data = { + token: '9462cf77-bde9-4029-bb41-e599f3094613', + order: '5fe57e4c-9ad2-4b52-b794-48adef2f6663', + } + const pending = { state: 'PENDING' } + const ok = { state: 'OK' } + response.json.mockResolvedValue(data) + response.json.mockResolvedValueOnce(pending) + response.json.mockResolvedValueOnce(ok) + + const personalNumber = 'my personal number' + api.login(personalNumber).then((status) => { + status.on('OK', () => { + expect(fetch).toHaveBeenCalledTimes(3) + done() + }) + }) + }) + it('remembers used personal number', async () => { + const data = { + token: '9462cf77-bde9-4029-bb41-e599f3094613', + order: '5fe57e4c-9ad2-4b52-b794-48adef2f6663', + } + response.json.mockResolvedValue(data) + + const personalNumber = 'my personal number' + await api.login(personalNumber) + + expect(api.getPersonalNumber()).toEqual(personalNumber) + }) + it('forgets used personal number if sign in is unsuccessful', (done) => { + const data = { + token: '9462cf77-bde9-4029-bb41-e599f3094613', + order: '5fe57e4c-9ad2-4b52-b794-48adef2f6663', + } + const error = { state: 'ERROR' } + response.json.mockResolvedValue(data) + response.json.mockResolvedValue(error) + + const personalNumber = 'my personal number' + api.login(personalNumber).then((status) => { + status.on('ERROR', () => { + expect(api.getPersonalNumber()).toEqual(undefined) + done() + }) + }) + }) + it('throws error on external api error', async () => { + expect.hasAssertions() + + const data = '' + response.json.mockResolvedValue(data) + response.ok = false + response.status = 500 + response.statusText = 'Internal Server Error' + + const personalNumber = 'my personal number' + try { + await api.login(personalNumber) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + expect(error.message).toEqual(expect.stringContaining('Server Error')) + } + }) + }) + describe('#logout', () => { + it('clears session', async () => { + await api.logout() + const session = await api.getSession('') + expect(session).toEqual({ + headers: { + cookie: '', + }, + }) + }) + + it('emits logout event', async () => { + const listener = jest.fn() + api.on('logout', listener) + await api.logout() + expect(listener).toHaveBeenCalled() + }) + it('sets .isLoggedIn', async () => { + api.isLoggedIn = true + await api.logout() + expect(api.isLoggedIn).toBe(false) + }) + it('forgets personalNumber', async () => { + const data = { + token: '9462cf77-bde9-4029-bb41-e599f3094613', + order: '5fe57e4c-9ad2-4b52-b794-48adef2f6663', + } + response.json.mockResolvedValue(data) + + const pnr = 'my personal number' + await api.login(pnr) + api.isLoggedIn = true + + await api.logout() + + expect(api.getPersonalNumber()).toEqual(undefined) + }) + }) + describe('fake', () => { + it('sets fake mode for the correct pnr:s', async () => { + let status + + status = await api.login('121212121212') + expect(status.token).toEqual('fake') + + status = await api.login('201212121212') + expect(status.token).toEqual('fake') + + status = await api.login('1212121212') + expect(status.token).toEqual('fake') + }) + it('delivers fake data', (done) => { + api.on('login', async () => { + const user = await api.getUser() + expect(user).toEqual({ + firstName: 'Namn', + lastName: 'Namnsson', + isAuthenticated: true, + personalNumber: '195001182046', + }) + + const children = await api.getChildren() + expect(children).toHaveLength(2) + + const calendar1 = await api.getCalendar(children[0]) + expect(calendar1).toHaveLength(20) + const calendar2 = await api.getCalendar(children[1]) + expect(calendar2).toHaveLength(18) + + const skola24Children = await api.getSkola24Children() + expect(skola24Children).toHaveLength(1) + + const timetable = await api.getTimetable( + skola24Children[0], + 2021, + 15, + 'sv' + ) + expect(timetable).toHaveLength(32) + + done() + }) + + api.login('121212121212') + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/queueFetcher.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/queueFetcher.test.ts new file mode 100644 index 000000000..79143b089 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/queueFetcher.test.ts @@ -0,0 +1,64 @@ +import QueueFetcher from '../queue/queueFetcher' + +let sut: QueueFetcher +beforeEach(() => { + jest.useFakeTimers('legacy') + sut = new QueueFetcher(async () => '') +}) + +test('creates queues for each id', () => { + sut.fetch(async () => '', 'one') + sut.fetch(async () => '', 'two') + sut.fetch(async () => '', 'three') + + expect(sut.Queues).toHaveLength(3) +}) + +test('add same id to same queue', () => { + sut.fetch(async () => '', 'one') + sut.fetch(async () => '', 'one') + sut.fetch(async () => '', 'one') + + expect(sut.Queues).toHaveLength(1) + expect(sut.Queues[0].id).toEqual('one') +}) + +test('can run a task', async () => { + const func = async () => 'output' + const promise = sut.fetch(func, 'one') + + jest.runOnlyPendingTimers() + + const result = await promise + + expect(result).toEqual('output') +}) + +test('can run many tasks', async () => { + const promise1 = sut.fetch(async () => 'one', 'one') + const promise2 = sut.fetch(async () => 'two', 'two') + const promise3 = sut.fetch(async () => 'three', 'three') + + await sut.schedule() + await sut.schedule() + await sut.schedule() + + const result = await Promise.all([promise1, promise2, promise3]) + + expect(result).toEqual(['one', 'two', 'three']) +}) + +// test('sets up timer on fetch', () => { +// sut.fetch(async () => 'one', 'one'); + +// expect(setTimeout).toHaveBeenCalledTimes(1); +// }); + +test('sets up timer on fetch', () => { + const setTimeoutSpy = jest.spyOn(global, 'setTimeout') + sut.fetch(async () => 'one', 'one') + expect(setTimeoutSpy).toHaveBeenCalledTimes(1) + + // Restore the original setTimeout function + setTimeoutSpy.mockRestore() +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/routes.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/routes.test.ts new file mode 100644 index 000000000..21ac72eeb --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/__tests__/routes.test.ts @@ -0,0 +1,22 @@ +import * as routes from '../routes' + +Date.now = jest.fn(() => 1618404258782) + +test.each([ + ['children', routes.children], + ['calender', routes.calendar('123')], + ['classmates', routes.classmates('123')], + ['user', routes.user], + ['news', routes.news('123')], + ['newsDetails', routes.newsDetails('123', '321')], + ['image', routes.image('https://example.com/img.png')], + ['notifications', routes.notifications('123')], + ['menuRss', routes.menuRss('123')], + ['menuList', routes.menuList('123')], + ['menuChoice', routes.menuChoice('123')], + ['schedule', routes.schedule('123', '2021-01-01', '2021-01-01')], + ['login with personal number', routes.login('201701012393')], + ['login without personal number', routes.login()], +])('handles route %s', (_name, input) => { + expect(input).toMatchSnapshot() +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/api.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/api.ts new file mode 100644 index 000000000..e52eb66cb --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/api.ts @@ -0,0 +1,715 @@ +import { + Api, + AuthTicket, + CalendarItem, + Classmate, + CookieManager, + EtjanstChild, + Fetch, + Fetcher, + FetcherOptions, + FrejaLoginStatusChecker, + LoginStatusChecker, + MenuItem, + NewsItem, + Notification, + RequestInit, + Response, + ScheduleItem, + Skola24Child, + SSOSystem, + Teacher, + TimetableEntry, + SchoolContact, + URLSearchParams, + User, + wrap, +} from '../../api/lib' +import { Language } from '../../curriculum/src' +import { EventEmitter } from 'events' +import { decode } from 'he' +import { DateTime } from 'luxon' +import * as html from 'node-html-parser' +import * as fake from './fakeData' +import { checkStatus, DummyStatusChecker } from './loginStatusChecker' +import { checkStatus as checkFrejaStatus } from './frejaLoginStatusChecker' +import * as parse from './parse/index' +import queueFetcherWrapper from './queueFetcherWrapper' +import * as routes from './routes' + +const fakeResponse = (data: T): Promise => + new Promise((res) => setTimeout(() => res(data), 200 + Math.random() * 800)) + +const s24Init = { + headers: { + accept: 'application/json, text/javascript, */*; q=0.01', + referer: + 'https://fns.stockholm.se/ng/timetable/timetable-viewer/fns.stockholm.se/', + 'accept-language': 'en-US,en;q=0.9,sv;q=0.8', + 'cache-control': 'no-cache', + 'content-type': 'application/json', + pragma: 'no-cache', + host: 'fns.stockholm.se', + 'x-scope': '8a22163c-8662-4535-9050-bc5e1923df48', + }, +} + +interface SSOSystems { + [name: string]: boolean | undefined +} + +export class ApiSkolplattformen extends EventEmitter implements Api { + private fetch: Fetcher + + private personalNumber?: string + + private headers: any + + private cookieManager: CookieManager + + public isLoggedIn = false + + public isFake = false + + private authorizedSystems: SSOSystems = {} + + constructor( + fetch: Fetch, // typeof global.fetch, + cookieManager: CookieManager, + options?: FetcherOptions + ) { + super() + this.fetch = wrap(fetch, options) + this.cookieManager = cookieManager + this.headers = {} + } + + public getPersonalNumber(): string | undefined { + return this.personalNumber + } + + private getRequestInit(options: RequestInit = {}): RequestInit { + return { + ...options, + headers: { + ...this.headers, + ...options.headers, + }, + } + } + + public async getSessionHeaders( + url: string + ): Promise<{ [index: string]: string }> { + const init = this.getRequestInit() + const cookie = await this.cookieManager.getCookieString(url) + return { + ...init.headers, + cookie, + } + } + + public async getSession( + url: string, + options?: RequestInit + ): Promise { + const init = this.getRequestInit(options) + const cookie = await this.cookieManager.getCookieString(url) + return { + ...init, + headers: { + ...init.headers, + cookie, + }, + } + } + + private async clearSession(): Promise { + this.headers = {} + await this.cookieManager.clearAll() + } + + private addHeader(name: string, value: string): void { + this.headers[name] = value + } + + public async login(personalNumber?: string): Promise { + if (personalNumber !== undefined && personalNumber.endsWith('1212121212')) { + return this.fakeMode() + } + + this.isFake = false + + const ticketUrl = routes.login(personalNumber) + const ticketResponse = await this.fetch('auth-ticket', ticketUrl) + + if (!ticketResponse.ok) { + throw new Error( + `Server Error [${ticketResponse.status}] [${ticketResponse.statusText}] [${ticketUrl}]` + ) + } + + const ticket: AuthTicket = await ticketResponse.json() + + // login was initiated - store personal number + this.personalNumber = personalNumber + + const status = checkStatus(this.fetch, ticket) + status.on('OK', async () => { + await this.retrieveSessionCookie() + + const [user] = await Promise.all([ + this.getUser(), + this.retrieveXsrfToken(), + ]) + this.personalNumber = user.personalNumber + + this.isLoggedIn = true + this.emit('login') + }) + status.on('ERROR', () => { + this.personalNumber = undefined + }) + + return status + } + + public async loginFreja(): Promise { + await this.clearSession() + + const loginUrl = routes.frejaLogin + const loginResponse = await this.fetch('auth-ticket', loginUrl) + + // if (!ticketResponse.ok) { + // throw new Error( + // `Server Error [${ticketResponse.status}] [${ticketResponse.statusText}] [${ticketUrl}]` + // ) + // } + + const appSwitchUrl: string = await loginResponse.text() + const cleanAppSwitchUrl = this.cleanFrejaAppSwitchUrl(appSwitchUrl) + + console.log('getting freja login url: ' + cleanAppSwitchUrl) + + const checkStatusSession = await this.getSession(loginUrl, { + redirect: 'manual', + }) + + const status = checkFrejaStatus( + this.fetch, + cleanAppSwitchUrl, + checkStatusSession + ) + status.on('APPROVED', async () => { + await this.retrieveFrejaSessionCookie() + const [user] = await Promise.all([ + this.getUser(), + this.retrieveXsrfToken(), + ]) + this.personalNumber = user.personalNumber + + this.isLoggedIn = true + this.emit('login') + }) + + return status + } + + private cleanFrejaAppSwitchUrl(url: string): string { + const parts = url.split('&') + return parts[0] + } + + public async setSessionCookie(sessionCookie: string): Promise { + // Manually set cookie in this call and let the cookieManager + // handle it from here + // If we put it into the cookieManager manually, we get duplicate cookies + const url = routes.loginCookie + await this.fetch('login-cookie', url, { + headers: { + cookie: sessionCookie, + }, + redirect: 'manual', // Important! Turn off redirect following. We can get into a redirect loop without this. + }) + + const user = await this.getUser() + if (!user.isAuthenticated) { + throw new Error('Session cookie is expired') + } + + await this.retrieveXsrfToken() + + this.isLoggedIn = true + this.emit('login') + } + + private async retrieveSessionCookie(): Promise { + const url = routes.loginCookie + await this.fetch('login-cookie', url) + } + + private async retrieveFrejaSessionCookie(): Promise { + try { + const url = routes.frejaReturnUrl + await this.fetch('freja-login-return-url', url) + } catch (error) { + console.log(JSON.stringify(error)) + } + + try { + const url2 = routes.frejaLoginCookie + await this.fetch('freja-login-cookie', url2) + } catch (error2) { + console.log(JSON.stringify(error2)) + } + } + + private async retrieveXsrfToken(): Promise { + const url = routes.hemPage + const session = this.getRequestInit() + const response = await this.fetch('hemPage', url, session) + const text = await response.text() + const doc = html.parse(decode(text)) + const xsrfToken = + doc + .querySelector('input[name="__RequestVerificationToken"]') + ?.getAttribute('value') || '' + + this.addHeader('x-xsrf-token', xsrfToken) + } + + private async fakeMode(): Promise { + this.isFake = true + + setTimeout(() => { + this.isLoggedIn = true + this.emit('login') + }, 50) + + const emitter = new DummyStatusChecker() + emitter.token = 'fake' + return emitter + } + + public async getUser(): Promise { + if (this.isFake) { + return fakeResponse(fake.user()) + } + + const url = routes.user + const session = this.getRequestInit() + const response = await this.fetch('user', url, session) + const data = await response.json() + return parse.user(data) + } + + public async getChildren(): Promise { + if (this.isFake) { + return fakeResponse(fake.children()) + } + + const url = routes.children + const session = this.getRequestInit({ + headers: { + Accept: 'application/json;odata=verbose', + Host: 'etjanst.stockholm.se', + Referer: 'https://etjanst.stockholm.se/vardnadshavare/inloggad2/hem', + }, + }) + const response = await this.fetch('children', url, session) + + if (!response.ok) { + throw new Error( + `Server Error [${response.status}] [${response.statusText}] [${url}]` + ) + } + + const data = await response.json() + + const parsed = parse.children(data) + const useSpecialQueueModeForFSChildren = parsed.some((c) => + (c.status || '').includes('FS') + ) + + if (useSpecialQueueModeForFSChildren) { + this.fetch = queueFetcherWrapper(this.fetch, (childId) => + this.selectChildById(childId) + ) + } + + return parsed + } + + public async getCalendar(child: EtjanstChild): Promise { + if (this.isFake) { + return fakeResponse(fake.calendar(child)) + } + + const url = routes.calendar(child.id) + const session = this.getRequestInit() + const response = await this.fetch('calendar', url, session, child.id) + const data = await response.json() + return parse.calendar(data) + } + + public async getClassmates(child: EtjanstChild): Promise { + if (this.isFake) { + return fakeResponse(fake.classmates(child)) + } + + const url = routes.classmates(child.sdsId) + const session = this.getRequestInit() + const response = await this.fetch('classmates', url, session) + const data = await response.json() + return parse.classmates(data) + } + + public async getTeachers(child: EtjanstChild): Promise { + if (this.isFake) { + return fakeResponse(fake.teachers(child)) + } + + const session = this.getRequestInit() + + const schoolForms = (child.status || '').split(';') + let teachers: Teacher[] = [] + + for (let i = 0; i < schoolForms.length; i += 1) { + const url = routes.teachers(child.sdsId, schoolForms[i]) + + const response = await this.fetch( + `teachers_${schoolForms[i]}`, + url, + session + ) + + const data = await response.json() + teachers = [...teachers, ...parse.teachers(data)] + } + + return teachers + } + + public async getSchoolContacts( + child: EtjanstChild + ): Promise { + if (this.isFake) { + return fakeResponse(fake.schoolContacts(child)) + } + + const url = routes.schoolContacts(child.sdsId, child.schoolId || '') + const session = this.getRequestInit() + const response = await this.fetch('schoolContacts', url, session) + const data = await response.json() + return parse.schoolContacts(data) + } + + public async getSchedule( + child: EtjanstChild, + from: DateTime, + to: DateTime + ): Promise { + if (this.isFake) { + return fakeResponse(fake.schedule(child)) + } + + const url = routes.schedule(child.id, from.toISODate(), to.toISODate()) + const session = this.getRequestInit() + const response = await this.fetch('schedule', url, session) + const data = await response.json() + return parse.schedule(data) + } + + public async getNews(child: EtjanstChild): Promise { + if (this.isFake) { + return fakeResponse(fake.news(child)) + } + + const url = routes.news(child.id) + const session = this.getRequestInit() + const response = await this.fetch('news', url, session, child.id) + + this.CheckResponseForCorrectChildStatus(response, child) + + const data = await response.json() + return parse.news(data) + } + + private CheckResponseForCorrectChildStatus( + response: Response, + child: EtjanstChild + ) { + const setCookieResp = response.headers.get('Set-Cookie') + + if ( + child.status !== 'FS' && + setCookieResp && + setCookieResp.includes('Status=FS') + ) { + throw new Error('Wrong child in response') + } + } + + public async getNewsDetails( + child: EtjanstChild, + item: NewsItem + ): Promise { + if (this.isFake) { + return fakeResponse( + fake.news(child).find((ni) => ni.id === item.id) || { + id: '', + published: '', + } + ) + } + const url = routes.newsDetails(child.id, item.id) + const session = this.getRequestInit() + const response = await this.fetch(`news_${item.id}`, url, session, child.id) + + this.CheckResponseForCorrectChildStatus(response, child) + + const data = await response.json() + return parse.newsItemDetails(data) + } + + public async getMenu(child: EtjanstChild): Promise { + if (this.isFake) { + return fakeResponse(fake.menu(child).map(parse.menuItem)) + } + + const menuService = await this.getMenuChoice(child) + if (menuService === 'rss') { + const url = routes.menuRss(child.id) + const session = this.getRequestInit() + const response = await this.fetch('menu-rss', url, session, child.id) + + this.CheckResponseForCorrectChildStatus(response, child) + + const data = await response.json() + return parse.menu(data) + } + + const url = routes.menuList(child.id) + const session = this.getRequestInit() + const response = await this.fetch('menu-list', url, session, child.id) + + this.CheckResponseForCorrectChildStatus(response, child) + + const data = await response.json() + return parse.menuList(data) + } + + private async getMenuChoice(child: EtjanstChild): Promise { + const url = routes.menuChoice(child.id) + const session = this.getRequestInit() + const response = await this.fetch('menu-choice', url, session, child.id) + + this.CheckResponseForCorrectChildStatus(response, child) + + const data = await response.json() + const etjanstResponse = parse.etjanst(data) + return etjanstResponse + } + + public async getNotifications(child: EtjanstChild): Promise { + if (this.isFake) { + return fakeResponse(fake.notifications(child)) + } + + const url = routes.notifications(child.sdsId) + const session = this.getRequestInit() + const response = await this.fetch('notifications', url, session) + const data = await response.json() + return parse.notifications(data) + } + + private async readSAMLRequest(targetSystem: string): Promise { + const url = routes.ssoRequestUrl(targetSystem) + const session = this.getRequestInit({ + redirect: 'follow', + }) + const response = await this.fetch('samlRequest', url, session) + const text = await response.text() + const samlRequest = /name="SAMLRequest" value="(\S+)">/gm.exec( + text || '' + )?.[1] + if (!samlRequest) { + throw new Error('Could not parse SAML Request') + } else { + return samlRequest + } + } + + private async submitSAMLRequest(samlRequest: string): Promise { + const body = new URLSearchParams({ SAMLRequest: samlRequest }).toString() + const url = routes.ssoResponseUrl + const session = this.getRequestInit({ + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + }, + redirect: 'follow', + method: 'POST', + body, + }) + const response = await this.fetch('samlResponse', url, session) + const text = await response.text() + const samlResponse = /name="SAMLResponse" value="(\S+)">/gm.exec(text)?.[1] + if (!samlResponse) { + throw new Error('Could not parse SAML Response') + } else { + return samlResponse + } + } + + private async ssoAuthorize(targetSystem: SSOSystem): Promise { + if (this.authorizedSystems[targetSystem]) { + return '' + } + const samlRequest = await this.readSAMLRequest(targetSystem) + const samlResponse = await this.submitSAMLRequest(samlRequest) + + const body = new URLSearchParams({ SAMLResponse: samlResponse }).toString() + const url = routes.samlResponseUrl + const session = this.getRequestInit({ + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + }, + redirect: 'follow', + method: 'POST', + body, + }) + const response = await this.fetch('samlAuthorize', url, session) + const text = await response.text() + this.authorizedSystems[targetSystem] = true + return text + } + + public async getSkola24Children(): Promise { + if (this.isFake) { + return fakeResponse(fake.skola24Children()) + } + + await this.ssoAuthorize('TimetableViewer') + const body = { + getPersonalTimetablesRequest: { + hostName: 'fns.stockholm.se', + }, + } + const session = this.getRequestInit({ + ...s24Init, + body: JSON.stringify(body), + method: 'POST', + }) + + const url = routes.timetables + const response = await this.fetch('s24children', url, session) + const { + data: { + getPersonalTimetablesResponse: { childrenTimetables }, + }, + } = await response.json() + + return childrenTimetables as Skola24Child[] + } + + private async getRenderKey(): Promise { + const url = routes.renderKey + const session = this.getRequestInit(s24Init) + const response = await this.fetch('renderKey', url, session) + const { + data: { key }, + } = await response.json() + return key as string + } + + public async getTimetable( + child: Skola24Child, + week: number, + year: number, + lang: Language + ): Promise { + if (this.isFake) { + return fakeResponse(fake.timetable(child)) + } + + if (!child.timetableID) { + return new Array() + } + + const url = routes.timetable + const renderKey = await this.getRenderKey() + const params = { + blackAndWhite: false, + customerKey: '', + endDate: null, + height: 1063, + host: 'fns.stockholm.se', + periodText: '', + privateFreeTextMode: null, + privateSelectionMode: true, + renderKey, + scheduleDay: 0, + selection: child.personGuid, + selectionType: 5, + showHeader: false, + startDate: null, + unitGuid: child.unitGuid, + week, + width: 1227, + year, + } + const session = this.getRequestInit({ + ...s24Init, + method: 'POST', + body: JSON.stringify(params), + }) + const response = await this.fetch( + `timetable_${child.personGuid}_${year}_${week}`, + url, + session + ) + const json = await response.json() + + return parse.timetable(json, year, week, lang) + } + + public async selectChild(child: EtjanstChild): Promise { + const response = await this.selectChildById(child.id) + + const data = await response.json() + return parse.child(parse.etjanst(data)) + } + + private async selectChildById(childId: string) { + const requestInit = this.getRequestInit({ + method: 'POST', + headers: { + host: 'etjanst.stockholm.se', + accept: 'application/json, text/plain, */*', + 'accept-Encoding': 'gzip, deflate', + 'content-Type': 'application/json;charset=UTF-8', + origin: 'https://etjanst.stockholm.se', + referer: 'https://etjanst.stockholm.se/vardnadshavare/inloggad2/hem', + }, + body: JSON.stringify({ + id: childId, + }), + }) + + const response = await this.fetch( + 'selectChild', + routes.selectChild, + requestInit + ) + return response + } + + public async logout() { + this.isFake = false + this.personalNumber = undefined + this.isLoggedIn = false + this.authorizedSystems = {} + this.emit('logout') + await this.clearSession() + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/children.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/children.ts new file mode 100644 index 000000000..550bb2949 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/children.ts @@ -0,0 +1,29 @@ +import { EtjanstChild, Skola24Child } from '@skolplattformen/api' + +export const children = (): EtjanstChild[] => [ + { + name: 'Shanel Nilsson (elev)', + id: '39b59e-bf4b9f-f68ac25321-977218-bf0', + sdsId: '8e81a06-53f55fb-d1b93-f0e5b357ad0b7caaf1d36', + status: 'F;GR', + schoolId: '9e58434-8800-da59547-614bf0e-e09c015', + }, + { + name: 'Alan Nilsson (elev)', + id: 'eea96a-a3e045-caab589391-ed7d17-029', + sdsId: 'bc2d341-8d970cc-69526-43501c082aaa870d9fe99', + status: 'GR', + schoolId: '8e6b13b-3116-e66c39b-a4c3fa5-a1d72d9', + }, +] +export const skola24Children = (): Skola24Child[] => [ + { + firstName: 'Shanel', + lastName: 'Jonsson Nilsson', + personGuid: 'abc123', + schoolGuid: 'def456', + schoolID: 'Superskolan', + timetableID: 'jkl012', + unitGuid: 'mno345', + }, +] diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/classmates.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/classmates.ts new file mode 100644 index 000000000..a1fedba31 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/classmates.ts @@ -0,0 +1,452 @@ +import { Child, Classmate } from '@skolplattformen/api' +import { children } from './children' + +export const classmates = (child: Child): Classmate[] => + classmatesData.get(child.id) ?? [] + +const [child1, child2] = children() + +const classmatesData = new Map([ + [ + child1.id, + [ + { + sisId: 'd004a-98d965a-45174-d2894ca2-f74ebcb', + firstname: 'Darion', + lastname: 'Gustafsson', + guardians: [ + { + email: 'Mike_Svensson@example.net', + firstname: 'Tad', + lastname: 'Eriksson', + mobile: '07074791613', + address: 'Martinvägen 50', + }, + ], + className: '2B', + }, + { + sisId: '54075-284de06-5664c-750b7b13-520fb61', + firstname: 'Brock', + lastname: 'Andersson', + guardians: [ + { + email: 'Brad56@example.org', + firstname: 'Camren', + lastname: 'Eriksson', + mobile: '07075129297', + address: undefined, + }, + ], + className: '2B', + }, + { + sisId: 'c1fc7-285f95d-c0f37-ea48a297-281e985', + firstname: 'Eloy', + lastname: 'Karlsson', + guardians: [ + { + email: 'Samara.Larsson@example.net', + firstname: 'Ike', + lastname: 'Gustafsson', + mobile: '07077667407', + address: undefined, + }, + ], + className: '2B', + }, + { + sisId: '212e9-8a2609c-b29c1-97a32bd8-5f84645', + firstname: 'Kristina', + lastname: 'Eriksson', + guardians: [ + { + email: 'Doug57@example.com', + firstname: 'Rollin', + lastname: 'Olsson', + mobile: '07071720107', + address: 'Höckertsvägen 2', + }, + ], + className: '2B', + }, + { + sisId: '01d21-ebc6f8b-526f8-7cfba0ab-26b9956', + firstname: 'Cydney', + lastname: 'Larsson', + guardians: [ + { + email: 'Davon6@example.org', + firstname: 'Oleta', + lastname: 'Svensson', + mobile: '07079762186', + address: undefined, + }, + ], + className: '2B', + }, + { + sisId: 'a45bb-8a481af-0ad12-7bd1fa4c-1eed4b1', + firstname: 'Berneice', + lastname: 'Persson', + guardians: [ + { + email: 'Milford_Johansson72@example.com', + firstname: 'Arely', + lastname: 'Johansson', + mobile: '07071926019', + address: 'Roslinvägen 36', + }, + ], + className: '2B', + }, + { + sisId: '32f31-039fbed-9060b-2d857c46-e47177d', + firstname: 'Emory', + lastname: 'Svensson', + guardians: [ + { + email: 'Alfredo_Nilsson96@example.org', + firstname: 'Dolores', + lastname: 'Andersson', + mobile: '070752561937', + address: 'Börjesonsvägen 6', + }, + ], + className: '2B', + }, + { + sisId: 'c9d0a-28c371d-e7be2-9781386b-6841eb0', + firstname: 'Maryjane', + lastname: 'Eriksson', + guardians: [ + { + email: 'Eula_Olsson@example.net', + firstname: 'Wendy', + lastname: 'Andersson', + mobile: '07078513037', + address: undefined, + }, + { + email: 'Lesley_Persson45@example.org', + firstname: 'Erich', + lastname: 'Persson', + mobile: '070788191316', + address: undefined, + }, + ], + className: '2B', + }, + { + sisId: 'e0f51-3fbd0be-5a8c3-ded7bbed-1d655d5', + firstname: 'Rosendo', + lastname: 'Eriksson', + guardians: [ + { + email: 'Mitchell.Gustafsson84@example.org', + firstname: 'Mariam', + lastname: 'Johansson', + mobile: '07074537423', + address: 'Molinvägen 29', + }, + { + email: 'Rachelle_Olsson@example.net', + firstname: 'Shaniya', + lastname: 'Persson', + mobile: '070765878480', + address: 'Molinvägen 29', + }, + ], + className: '2B', + }, + { + sisId: '298c2-46a24d4-548b9-3d1f90ee-4fae0ab', + firstname: 'Sammy', + lastname: 'Persson', + guardians: [ + { + email: 'Gloria_Svensson@example.com', + firstname: 'Simeon', + lastname: 'Olsson', + mobile: '070753525610', + address: 'Börjesonsvägen 43', + }, + ], + className: '2B', + }, + { + sisId: 'e7628-09352ea-b5d19-1af845b7-63b3e08', + firstname: 'Abraham', + lastname: 'Svensson', + guardians: [ + { + email: 'Erica_Johansson40@example.net', + firstname: 'Carlotta', + lastname: 'Nilsson', + mobile: '070737951712', + address: 'Aroseniusvägen 27', + }, + { + email: 'Malcolm_Gustafsson55@example.org', + firstname: 'Ramon', + lastname: 'Persson', + mobile: '07070395626', + address: 'Aroseniusvägen 27', + }, + ], + className: '2B', + }, + { + sisId: 'ae315-4696438-b3db6-8f0a5b39-74e34bd', + firstname: 'Devante', + lastname: 'Olsson', + guardians: [ + { + email: 'Alf.Johansson39@example.com', + firstname: 'Schuyler', + lastname: 'Gustafsson', + mobile: '07070724289', + address: undefined, + }, + ], + className: '2B', + }, + { + sisId: '0d812-350f1d5-323aa-d5d93cdd-406e337', + firstname: 'Tyrell', + lastname: 'Eriksson', + guardians: [ + { + email: 'Brennon.Svensson@example.com', + firstname: 'Belle', + lastname: 'Nilsson', + mobile: '07070137347', + address: undefined, + }, + ], + className: '2B', + }, + ], + ], + [ + child2.id, + [ + { + sisId: '9ee9e-312233c-0df98-05fa5a65-a3787ec', + firstname: 'Raphael', + lastname: 'Olsson', + guardians: [ + { + email: 'Johan99@example.com', + firstname: 'Alessandra', + lastname: 'Svensson', + mobile: '070767120463', + address: 'Franklandsvägen 34', + }, + ], + className: '8C', + }, + { + sisId: 'd3a4b-16b53de-63c22-56d1ad24-4a64a2d', + firstname: 'Fanny', + lastname: 'Karlsson', + guardians: [ + { + email: 'Bernadette.Eriksson@example.org', + firstname: 'Bernadette', + lastname: 'Karlsson', + mobile: '070759877956', + address: undefined, + }, + { + email: 'Candice29@example.net', + firstname: 'Kelley', + lastname: 'Gustafsson', + mobile: '070748592035', + address: undefined, + }, + ], + className: '8C', + }, + { + sisId: '42bde-8fabd1c-7a00e-28aea88a-8481bac', + firstname: 'Jamie', + lastname: 'Persson', + guardians: [ + { + email: 'Louisa82@example.net', + firstname: 'Mose', + lastname: 'Larsson', + mobile: '07076548362', + address: undefined, + }, + ], + className: '8C', + }, + { + sisId: 'dad49-74308c8-83612-5eb7f3a5-e1c4047', + firstname: 'Iris', + lastname: 'Eriksson', + guardians: [ + { + email: 'Vaughn90@example.net', + firstname: 'Ezra', + lastname: 'Andersson', + mobile: '07078700165', + address: 'Björnsonsgatan 251 D Lgh 1503', + }, + { + email: 'Stephany_Svensson22@example.net', + firstname: 'Mia', + lastname: 'Larsson', + mobile: '070761752378', + address: 'Björnsonsgatan 251 D Lgh 1503', + }, + ], + className: '8C', + }, + { + sisId: 'b3425-ada6d70-d3acc-a49a12a6-8b3afdc', + firstname: 'Evans', + lastname: 'Nilsson', + guardians: [ + { + email: 'Terry_Svensson@example.com', + firstname: 'Christop', + lastname: 'Olsson', + mobile: '070767660094', + address: undefined, + }, + { + email: 'Johanna_Svensson30@example.org', + firstname: 'Madisen', + lastname: 'Johansson', + mobile: '07072269029', + address: undefined, + }, + ], + className: '8C', + }, + { + sisId: '67471-6c03979-9ef6e-bb2827c4-96d00d5', + firstname: 'Evy', + lastname: 'Larsson', + guardians: [ + { + email: 'Serenity.Gustafsson@example.net', + firstname: 'Toni', + lastname: 'Larsson', + mobile: '07075211567', + address: 'Roslinvägen 48', + }, + ], + className: '8C', + }, + { + sisId: 'f4040-516c4ed-34555-fd525183-6a2f666', + firstname: 'Maximillia', + lastname: 'Karlsson', + guardians: [ + { + email: 'Faustino.Andersson@example.com', + firstname: 'Eriberto', + lastname: 'Nilsson', + mobile: '07076024039', + address: 'Beckombergavägen 213 Lgh 1304', + }, + ], + className: '8C', + }, + { + sisId: 'a9494-75d8ca7-a5fd4-977eca3c-40edbc1', + firstname: 'Pia', + lastname: 'Karlsson', + guardians: [ + { + email: 'Arthur.Karlsson4@example.org', + firstname: 'Eldred', + lastname: 'Svensson', + mobile: '07077609534', + address: 'Börjesonsvägen 6', + }, + ], + className: '8C', + }, + { + sisId: '42a6d-3eaf407-fed01-4a9538de-b822503', + firstname: 'Logan', + lastname: 'Larsson', + guardians: [ + { + email: 'Blake4@example.org', + firstname: 'Jan', + lastname: 'Karlsson', + mobile: '070728715653', + address: 'Bällstavägen 162', + }, + ], + className: '8C', + }, + { + sisId: '9077d-c323c8d-d0d29-5690abfb-d348317', + firstname: 'Torun', + lastname: 'Eriksson', + guardians: [ + { + email: 'Blanca98@example.net', + firstname: 'Dallin', + lastname: 'Eriksson', + mobile: '070766214425', + address: 'Molinvägen 1', + }, + ], + className: '8C', + }, + { + sisId: '31c68-5b86667-0701d-6b7e2471-89e6df9', + firstname: 'Izabella', + lastname: 'Johansson', + guardians: [ + { + email: 'Elouise_Johansson25@example.org', + firstname: 'Jerrold', + lastname: 'Nilsson', + mobile: '07073789274', + address: 'Stobaeusvägen 11', + }, + ], + className: '8C', + }, + { + sisId: '1bb69-5f1c3a6-f0ea8-e1dbb608-2756a52', + firstname: 'Ella', + lastname: 'Persson', + guardians: [ + { + email: 'Shayna.Olsson54@example.net', + firstname: 'Onie', + lastname: 'Nilsson', + mobile: '07076957797', + address: undefined, + }, + ], + className: '8C', + }, + { + sisId: '348a7-2d0eccc-02981-a02ccb03-cb2a8f2', + firstname: 'Jaylen', + lastname: 'Larsson', + guardians: [ + { + email: 'Aileen_Andersson@example.net', + firstname: 'Tess', + lastname: 'Karlsson', + mobile: '070715315590', + address: 'Peringskiöldsvägen 64', + }, + ], + className: '8C', + }, + ], + ], +]) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/data.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/data.ts new file mode 100644 index 000000000..ce843710c --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/data.ts @@ -0,0 +1,500 @@ +import { fourDaysAgo, oneDayAgo } from './dates' + +import { + CalendarItem, + Child, + Notification, + ScheduleItem, + User, +} from '@skolplattformen/api' +import { oneDayForward, oneWeekForward, twoDaysForward } from './dates' + +const data: any = { + '39b59e-bf4b9f-f68ac25321-977218-bf0': { + calendar: [ + { + title: 'Terminslut', + id: 73, + description: null, + location: null, + startDate: '2020-12-18', + endDate: '2020-12-18', + allDay: true, + }, + { + title: 'Terminen börjar', + id: 74, + description: null, + location: null, + startDate: '2021-01-12', + endDate: '2021-01-12', + allDay: true, + }, + { + title: 'APT - fritids stänger 15:45', + id: 75, + description: null, + location: null, + startDate: '2021-01-21', + endDate: '2021-01-21', + allDay: true, + }, + { + title: 'Utvecklingsamtal', + id: 76, + description: null, + location: null, + startDate: '2021-02-04', + endDate: '2021-02-04', + allDay: true, + }, + { + title: 'Vänliga veckan', + id: 77, + description: null, + location: null, + startDate: '2021-02-08', + endDate: '2021-02-12', + allDay: true, + }, + { + title: 'Utvecklingsamtal', + id: 79, + description: null, + location: null, + startDate: '2021-02-09', + endDate: '2021-02-09', + allDay: true, + }, + { + title: 'Trygghetsdag', + id: 78, + description: null, + location: null, + startDate: '2021-02-12', + endDate: '2021-02-12', + allDay: true, + }, + { + title: 'APT fritids stänger 15:45', + id: 80, + description: null, + location: null, + startDate: '2021-02-25', + endDate: '2021-02-25', + allDay: true, + }, + { + title: 'Sportlov', + id: 81, + description: null, + location: null, + startDate: '2021-03-01', + endDate: '2021-03-05', + allDay: true, + }, + { + title: 'Studiedag', + id: 82, + description: null, + location: null, + startDate: oneWeekForward.startOf('day').toISODate(), + endDate: oneWeekForward.endOf('day').toISODate(), + allDay: true, + }, + { + title: 'APT - fritids stänger 15:45', + id: 83, + description: null, + location: null, + startDate: '2021-04-01', + endDate: '2021-04-01', + allDay: true, + }, + { + title: 'Långfredag', + id: 84, + description: null, + location: null, + startDate: '2021-04-02', + endDate: '2021-04-02', + allDay: true, + }, + { + title: 'Påsklov', + id: 85, + description: null, + location: null, + startDate: '2021-04-05', + endDate: '2021-04-09', + allDay: true, + }, + { + title: 'Föräldraråd', + id: 86, + description: null, + location: null, + startDate: '2021-04-20', + endDate: '2021-04-20', + allDay: true, + }, + { + title: 'Prao åk 8', + id: 97, + description: null, + location: null, + startDate: '2021-04-26', + endDate: '2021-05-12', + allDay: true, + }, + { + title: 'Kristi Himmelfärd', + id: 87, + description: null, + location: null, + startDate: '2021-05-13', + endDate: '2021-05-13', + allDay: true, + }, + { + title: 'Lov', + id: 88, + description: null, + location: null, + startDate: '2021-05-14', + endDate: '2021-05-14', + allDay: true, + }, + { + title: 'APT Fritids stänger 15:45', + id: 90, + description: null, + location: null, + startDate: '2021-05-20', + endDate: '2021-05-20', + allDay: true, + }, + { + title: 'Läsårsslut', + id: 91, + description: + "

 

", + location: null, + startDate: '2021-06-11', + endDate: '2021-06-11', + allDay: true, + }, + { + title: 'Fritids stängt', + id: 92, + description: + "

 

", + location: null, + startDate: '2021-06-14', + endDate: '2021-06-14', + allDay: true, + }, + ], + schedule: [ + { + title: 'Läsläxan tillbaka', + description: 'Ta med boken tillbaka till skolan', + location: '', + allDayEvent: false, + startDate: oneDayForward.startOf('day').toISO(), + endDate: oneDayForward.endOf('day').toISO(), + oneDayEvent: true, + } as ScheduleItem, + ], + notifications: [ + { + id: 'bfe19b-766db3-b38d99d321-bbed3d-506', + sender: 'Planering och Bedömning', + dateCreated: oneDayAgo.minus({ months: 6 }).toISO(), + dateModified: fourDaysAgo.toISO(), + message: 'Ett nytt inlägg i en lärlogg har skapats.', + url: 'https://www.breakit.se/artikel/21423/har-ar-it-bolaget-bakom-haveriet-pa-skolplattformen', + category: 'Lärlogg', + type: 'avisering', + }, + { + id: '9025f9-a1e685-d7c4668f09-e14bc5-0ab', + sender: 'Elevdokumentation', + dateCreated: '2020-12-10T14:31:29.966Z', + message: + 'Nu kan du ta del av ditt barns dokumentation av utvecklingssamtal', + url: 'https://www.breakit.se/artikel/21404/kodaren-slog-larm-nu-akutstoppas-skolplattformen-i-stockholm', + category: null, + type: 'webnotify', + }, + { + id: 'a24061-1c9a4e-83dc479d7c-f44fe9-376', + sender: 'Planering och Bedömning', + dateCreated: '2020-06-10T12:18:00.000Z', + message: 'Nu finns det en bedömning att titta på.', + url: 'https://www.svt.se/nyheter/lokalt/stockholm/skolplattformen-i-stockholm-beratta-om-era-erfarenheter', + category: 'Bedömning', + type: 'avisering', + }, + { + id: '79d65c-1f8240-35c94296ec-9f4bdc-cea', + sender: 'Planering och Bedömning', + dateCreated: '2020-03-24T14:28:00.000Z', + message: 'Nu finns det en bedömning att titta på.', + url: 'https://www.breakit.se/artikel/18120/skolplattformen-kostade-700-miljoner-strid-med-entreprenor-om-varumarket', + category: 'Bedömning', + type: 'avisering', + }, + { + id: '9c5b7b-52c16d-b9fc2e8248-e4de76-279', + sender: 'Planering och Bedömning', + dateCreated: '2020-03-24T13:48:00.000Z', + message: 'Nu finns det en bedömning att titta på.', + url: 'https://www.mitti.se/nyheter/forskolans-tur-att-fa-kritiserade-skolplattformen-app/lmsau!5338007/', + category: 'Bedömning', + type: 'avisering', + }, + ], + }, + 'eea96a-a3e045-caab589391-ed7d17-029': { + calendar: [ + { + title: 'Terminslut', + id: 73, + description: null, + location: null, + startDate: '2020-12-18', + endDate: '2020-12-18', + allDay: true, + }, + { + title: 'Terminen börjar', + id: 74, + description: null, + location: null, + startDate: '2021-01-12', + endDate: '2021-01-12', + allDay: true, + }, + { + title: 'APT - fritids stänger 15:45', + id: 75, + description: null, + location: null, + startDate: oneWeekForward.startOf('day').toISODate(), + endDate: oneWeekForward.endOf('day').toISODate(), + allDay: true, + }, + { + title: 'Utvecklingsamtal', + id: 76, + description: null, + location: null, + startDate: '2021-02-04', + endDate: '2021-02-04', + allDay: true, + }, + { + title: 'Vänliga veckan', + id: 77, + description: null, + location: null, + startDate: '2021-02-08', + endDate: '2021-02-12', + allDay: true, + }, + { + title: 'Utvecklingsamtal', + id: 79, + description: null, + location: null, + startDate: '2021-02-09', + endDate: '2021-02-09', + allDay: true, + }, + { + title: 'Trygghetsdag', + id: 78, + description: null, + location: null, + startDate: '2021-02-12', + endDate: '2021-02-12', + allDay: true, + }, + { + title: 'APT fritids stänger 15:45', + id: 80, + description: null, + location: null, + startDate: '2021-02-25', + endDate: '2021-02-25', + allDay: true, + }, + { + title: 'Sportlov', + id: 81, + description: null, + location: null, + startDate: '2021-03-01', + endDate: '2021-03-05', + allDay: true, + }, + { + title: 'Studiedag', + id: 82, + description: null, + location: null, + startDate: '2021-03-22', + endDate: '2021-03-22', + allDay: true, + }, + { + title: 'APT - fritids stänger 15:45', + id: 83, + description: null, + location: null, + startDate: '2021-04-01', + endDate: '2021-04-01', + allDay: true, + }, + { + title: 'Långfredag', + id: 84, + description: null, + location: null, + startDate: '2021-04-02', + endDate: '2021-04-02', + allDay: true, + }, + { + title: 'Påsklov', + id: 85, + description: null, + location: null, + startDate: '2021-04-05', + endDate: '2021-04-09', + allDay: true, + }, + { + title: 'Föräldraråd', + id: 86, + description: null, + location: null, + startDate: '2021-04-20', + endDate: '2021-04-20', + allDay: true, + }, + { + title: 'Prao åk 8', + id: 97, + description: null, + location: null, + startDate: '2021-04-26', + endDate: '2021-05-12', + allDay: true, + }, + { + title: 'Kristi Himmelfärd', + id: 87, + description: null, + location: null, + startDate: '2021-05-13', + endDate: '2021-05-13', + allDay: true, + }, + { + title: 'Lov', + id: 88, + description: null, + location: null, + startDate: '2021-05-14', + endDate: '2021-05-14', + allDay: true, + }, + { + title: 'APT Fritids stänger 15:45', + id: 90, + description: null, + location: null, + startDate: '2021-05-20', + endDate: '2021-05-20', + allDay: true, + }, + ], + schedule: [ + { + title: 'Läxförhör franska', + description: 'Läxförhör, glosor samt verben!', + location: 'Klassrummet', + allDayEvent: false, + startDate: twoDaysForward.startOf('day').toISO(), + endDate: twoDaysForward.endOf('day').toISO(), + oneDayEvent: false, + } as ScheduleItem, + ], + notifications: [ + { + id: 'e1b5bc-597fa8-5511794939-3614e1-615', + sender: 'Planering och Bedömning', + dateCreated: fourDaysAgo.toISO(), + dateModified: fourDaysAgo.toISO(), + message: 'Ett nytt inlägg i en lärlogg har skapats.', + url: 'https://www.mitti.se/nyheter/rekorddyr-skolplattform-kostar-258-miljoner-till/lmsao!5381301/', + category: 'Lärlogg', + messageType: 'avisering', + }, + { + id: '7dbc20-bfa1ac-e20171b865-82c1f7-f3c', + sender: 'Planering och Bedömning', + dateCreated: '2020-12-01T12:43:00.000Z', + message: 'Ett nytt inlägg i en lärlogg har skapats.', + url: 'https://computersweden.idg.se/2.2683/1.722561/lacka-skolplattformen-datainspektionen', + category: 'Lärlogg', + messageType: 'avisering', + }, + { + id: 'a6829b-ecf912-b71582e8fb-b6dc14-f60', + sender: 'Planering och Bedömning', + dateCreated: '2020-11-24T13:34:00.000Z', + message: 'Ett nytt inlägg i en lärlogg har skapats.', + url: 'https://www.dagensarena.se/redaktionen/en-systemkramare-ger-upp/', + category: 'Lärlogg', + messageType: 'avisering', + }, + { + id: '3cedb4-767d24-8ccd6ac3ac-c05cb7-a3a', + sender: 'Planering och Bedömning', + dateCreated: '2020-11-16T13:24:00.000Z', + message: 'Ett nytt inlägg i en lärlogg har skapats.', + url: 'https://www.breakit.se/artikel/27075/skolplattformen-kostade-1-miljard-att-bygga-nu-tvingas-stockholm-bota', + category: 'Lärlogg', + messageType: 'avisering', + }, + { + id: '6ace13-5f99da-d1d50ac7a6-4a6108-d8e', + sender: 'Planering och Bedömning', + dateCreated: '2020-11-12T13:27:00.000Z', + message: 'Ett nytt inlägg i en lärlogg har skapats.', + url: 'https://www.nyteknik.se/sakerhet/ygeman-om-datalackan-i-skolplattformen-det-ar-upprorande-6968853', + category: 'Lärlogg', + messageType: 'avisering', + }, + ], + }, +} + +export const user = (): User => ({ + personalNumber: '195001182046', // Test personal number from Skatteverket + firstName: 'Namn', + lastName: 'Namnsson', + isAuthenticated: true, +}) + +export const calendar = (child: Child): CalendarItem[] => + data[child.id].calendar + +export const schedule = (child: Child): ScheduleItem[] => + data[child.id].schedule + +export const notifications = (child: Child): Notification[] => + data[child.id].notifications diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/dates.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/dates.ts new file mode 100644 index 000000000..a9c0795ce --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/dates.ts @@ -0,0 +1,14 @@ +import { DateTime } from 'luxon' + +export const getDate = () => DateTime.now() +export const oneDayAgo = getDate().minus({ days: 1 }) +export const twoDaysAgo = getDate().minus({ days: 2 }) +export const fourDaysAgo = getDate().minus({ days: 4 }) +export const oneWeekAgo = getDate().minus({ weeks: 1 }) + +export const oneDayForward = getDate().plus({ days: 1 }) +export const twoDaysForward = getDate().plus({ days: 2 }) +export const fourDaysForward = getDate().plus({ days: 4 }) +export const oneWeekForward = getDate().plus({ weeks: 1 }) + +export const week = getDate().weekNumber.toString() diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/index.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/index.ts new file mode 100644 index 000000000..e42df62fa --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/index.ts @@ -0,0 +1,8 @@ +export * from './data' +export * from './children' +export * from './menu' +export * from './classmates' +export * from './teachers' +export * from './timetable' +export * from './schoolContacts' +export * from './news' diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/menu.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/menu.ts new file mode 100644 index 000000000..eb5c5c297 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/menu.ts @@ -0,0 +1,69 @@ +import { Child, MenuItem } from '@skolplattformen/api' +import { DateTime } from 'luxon' +import { children } from './children' + +export const menu = (child: Child): MenuItem[] => menuData.get(child.id) ?? [] + +const getDate = () => DateTime.now() +const week = getDate().weekNumber.toString() + +const [child1, child2] = children() + +const menuData = new Map([ + [ + child1.id, + [ + { + title: 'Måndag - Vecka ' + week, + description: 'Kebabgryta ris
Ratatouille med kikärter', + }, + { + title: 'Tisdag - Vecka ' + week, + description: 'Ost-broccolisås pasta Fusilli', + }, + { + title: 'Onsdag - Vecka ' + week, + description: 'Köttbullar potatis gräddsås lingon
Falafel', + }, + { + title: 'Torsdag - Vecka ' + week, + description: + 'Prinskorv potatis rödbetssallad +
Inlagd och senapssill', + }, + { + title: 'Fredag - Vecka ' + week, + description: + 'Avslutning Varmkorv bröd ketchup senap
( F-3 i matsalen från 10:30 )', + }, + ], + ], + [ + child2.id, + [ + { + title: 'Måndag - Vecka ' + week, + description: + 'Thailändsk kycklinggryta med kokosmjölk, rödcurry och jasminris
Thailänsk grönsaksgryta med kokosmjölk, rödcurry och jasminris', + }, + { + title: 'Tisdag - Vecka ' + week, + description: 'Örtomlett med potatis , medelhavsost och olivtapenad', + }, + { + title: 'Onsdag - Vecka ' + week, + description: + 'Spagetti med rökt kalkon , grädde, dijon och persilja
Spagetti med rostade bönor , grädde , dijon och persilja', + }, + { + title: 'Torsdag - Vecka ' + week, + description: + 'Panerad flundra med dansk remoulad och koktåotatis
morot och linsbiff med danska remoulad och koktpotatis', + }, + { + title: 'Fredag - Vecka ' + week, + description: + 'Texaschili på högrev med picklad rödlök och bulgur
Texaschili på svartabönor picklad rödlök och bulgur', + }, + ], + ], +]) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/news.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/news.ts new file mode 100644 index 000000000..a65c0c28f --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/news.ts @@ -0,0 +1,138 @@ +import { children } from './children' +import { Child, NewsItem } from '@skolplattformen/api' +import * as dates from './dates' + +export const news = (child: Child): NewsItem[] => newsData.get(child.id) ?? [] + +const [child1, child2] = children() + +const newsData = new Map([ + [ + child1.id, + [ + { + id: 'asdfasdfasdfw', + author: 'Vaktmästare Persson', + header: 'Brandsläckare!', + intro: 'Idag hade vi en incident med en brandsläckare.', + body: '## Information om brandsläckarincidenten\n\nHej, idag vid lunchtid utlöste en elev av misstag en pulverbrandsläckare i kapprummet. En del pulver yrde runt i rummet och under saneringen fick eleverna i angränsande klassrum vara i aulan istället för klassrummet.\n\nFlera elever var på plats i hallen när detta inträffade men utrymdes kort därefter. Pulvret är INTE hälsovådligt men kan ge upphov till halsirritation vid inandning.\n\nJag har pratat med berörda elever om det inträffade och uppmanat dem att ta hem kläder och tillhörigheter som fanns i kapprummet eftersom de troligen blivit dammiga. Vi rekommenderar att ni tvättar eller vädrar dessa.', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: + 'https://cdn.breakit.se/assets/article/6607f9b923edb6f85aa4417bab43c0f8.jpg?d=980x500', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.twoDaysAgo.toISO(), + modified: dates.twoDaysAgo.plus({ hours: 1 }).toISO(), + }, + { + id: 'asdfabbuasdfs', + author: 'Ada L.', + header: 'Bygg din egen app', + intro: 'Denna vecka bygger vi appar!', + body: '## Appar med öppen data \n\nDenna vecka har vi förmånen att få besök av några föräldrar som visar hur vi enkelt kan skapa appar som visar information ifrån öppna datakällor.\n\nEn fantastisk möjlighet att lära oss hur digitalisering skapar nya möjligheter i såväl skolan som arbetslivet.', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: + 'https://live.staticflickr.com/4063/4369776892_5cd42d27ba.jpg', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.oneWeekAgo.toISO(), + modified: dates.oneWeekAgo.toISO(), + }, + { + id: 'asdfasdfasdfs', + author: 'Magister Svensson', + header: 'Läxor vecka 6.', + intro: 'Alla elever måste göra sina läxor!', + body: '## Läxor vecka 6 \n\nFöljande läxor är obligatoriska:\n\n- Antikens historia\n- Svenska stormaktstiden\n- Statistik A\n- Flerdimensionell analys, del 1', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: + 'https://images.unsplash.com/photo-1629652487043-fb2825838f8c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2671&q=80', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.oneWeekAgo.toISO(), + modified: dates.oneWeekAgo.minus({ hours: 3 }).toISO(), + }, + ], + ], + + [ + child2.id, + [ + { + id: 'asdfasdfasdfa', + author: 'Rektor Gustavsson', + header: 'Välkommen till skolan!', + intro: + 'Hej alla barn och föräldrar och välkomna till Storskolan! Här kommer en del information som kan vara bra att känna till inför första dagen.', + body: '## Information till föräldrar \n\nSkolan börjar kl 08.00 och slutar 18.00. Kommer man sent eller blir sjuk så ska det anmälas via Skolplattformen. Se till så att dina barn har ätit frukost. Frukt är nyttigt! \n\n## Information till barn\n\nLek är tillåtet på rasterna men enbart på skolgården. Medtag ej egna leksaker. Tvätta händerna.', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: + 'https://timbro.se/app/uploads/2020/10/broman-skolplattformen-1280x752.jpg', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.oneWeekAgo.toISO(), + modified: dates.oneWeekAgo.toISO(), + }, + { + id: 'asdfabbuasdfs', + author: 'Ada L.', + header: 'App, App, App', + intro: 'Denna vecka bygger vi appar!', + body: '## Appar med öppen data \n\nDenna vecka har vi förmånen att få besök av några föräldrar som visar hur vi enkelt kan skapa appar som visar information ifrån öppna datakällor.\n\nEn fantastisk möjlighet att lära oss hur digitalisering skapar nya möjligheter i såväl skolan som arbetslivet.', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: + 'https://live.staticflickr.com/4063/4369776892_5cd42d27ba.jpg', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.fourDaysAgo.toISO(), + modified: dates.fourDaysAgo.plus({ minutes: 45 }).toISO(), + }, + { + id: 'asdfasdfasdfs', + author: 'Magister Svensson', + header: 'Läxor i veckan', + intro: 'Alla elever måste göra sina läxor!', + body: '## Läxor vecka 6 \n\nFöljande läxor är obligatoriska:\n\n- Antikens historia\n- Svenska stormaktstiden\n- Statistik A\n- Flerdimensionell analys, del 1', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: + 'https://images.unsplash.com/photo-1629652487043-fb2825838f8c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2671&q=80', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.oneWeekAgo.toISO(), + modified: dates.oneWeekAgo.toISO(), + }, + { + id: 'asdfasdfasdfd', + author: 'Information från Förskoleklass', + header: 'Vinteraktiviteter', + intro: + 'Vi kommer efter att förskoleklassen är slut arrangera olika vinteraktiviteter genom fridtidsverksamheten.', + body: '## Vänligen ta med hjälm, skridskor eller stjärtlapp.\n\n ![Bild](https://images.unsplash.com/photo-1495377701095-00261b767581?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=988&q=80)\n\n Alla barn måste ha hjälm på sig samt varma kläder. Vi kommer åka i backen bakom skolbyggnaden samt använda isen som spolats vid Mullsjöskolan. Personal kommer finnas på plats samt att vi erbjuda varm dryck, frukt och lek för de barn som ej har hjälm eller lämpligt åkdon.', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: 'https://unsplash.com/photos/yB_aiAWkm40', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.oneWeekAgo.minus({ weeks: 2 }).toISO(), + modified: dates.oneWeekAgo.minus({ weeks: 1 }).toISO(), + }, + { + id: 'asdfasdfasdfdsa', + author: 'Köket', + header: 'Ekologisk vecka i matsalen', + intro: 'Ekologiska veckan i matsalen vecka 11', + body: '## Vi kommer ha tema jorden i matsalen och servera ekologisk mat från hela världen med tema jorden. Detta för att belysa att man kan använda alla delar av råvaorna. Det kommer erbjudas rätter från alla världsdelar som är producerat för jordens bästa. Smaklig spis hälsar Gunnel i köket med personal.', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: 'https://unsplash.com/photos/7K17MvT8qBg', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.oneWeekAgo.minus({ weeks: 3 }).toISO(), + modified: dates.oneWeekAgo.minus({ days: 2 }).toISO(), + }, + { + id: 'asdfasdfasdfbvdsa', + author: 'Vaktmästaren', + header: 'Klotter i korridoren (igen)', + intro: + 'Ännu en gång har vi råka ut för skadegörelse i korridorerna vid åk 5', + body: '## Tyvärr har flera elever klottat på skåp och väggar vid åk5 skåpen. Detta är helt oacceptablet beteende och kostar skolan stora belopp att åtgärda. Vi ber alla föräldrar prata med sina barn om klotter samt att det var väldigt grovt spårkbruk. Personalen på skolan kommer att hålla extra uppsikt och vi har även pratat med en del av de inblandade eleverna i denna skadegörelse.\n\nPersonalen har även börjat forska på vad vissa av de skrivna orden betyder och Eva-Britt är förfasad över språkbruket samt vad de innebär. Bernt kommer att påbörja saneringen och återställningen av skadegörelsen samt vakta korridorerna nogrannare för att säkerställa att detta ej kommer ske igen.\n\n Klotter\n\nUPPDATERING: Det som är skrivet om Sara är inte sant! ', + imageUrl: '6607f9b923edb6f85aa4417bab43c0f8.jpg', + fullImageUrl: 'https://unsplash.com/photos/SkbEZ16VywM', + imageAltText: 'Nyhetsbild. Bildtext ej tillgänglig.', + published: dates.oneWeekAgo.minus({ weeks: 4 }).toISO(), + modified: dates.oneWeekAgo.minus({ weeks: 2 }).toISO(), + }, + ], + ], +]) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/schoolContacts.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/schoolContacts.ts new file mode 100644 index 000000000..fcedc29c3 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/schoolContacts.ts @@ -0,0 +1,52 @@ +import { SchoolContact, Child } from '@skolplattformen/api' +import { children } from './children' + +export const schoolContacts = (child: Child): SchoolContact[] => + schoolContactData.get(child.id) ?? [] + +const [child1, child2] = children() + +const schoolContactData = new Map([ + [ + child1.id, + [ + { + title: 'Expedition', + name: undefined, + phone: '508 000 00', + email: '', + schoolName: 'Vallaskolan', + className: '', + }, + { + title: 'Rektor', + name: 'Alvar Sträng', + phone: '08-50800001', + email: 'alvar.strang@edu.stockholm.se', + schoolName: '', + className: '', + }, + ], + ], + [ + child2.id, + [ + { + title: 'Expedition', + name: undefined, + phone: '508 000 00', + email: '', + schoolName: 'Vallaskolan', + className: '', + }, + { + title: 'Rektor', + name: 'Alvar Sträng', + phone: '08-50800001', + email: 'alvar.strang@edu.stockholm.se', + schoolName: '', + className: '', + }, + ], + ], +]) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/teachers.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/teachers.ts new file mode 100644 index 000000000..bcb612eed --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/teachers.ts @@ -0,0 +1,86 @@ +import { Teacher, Child } from '@skolplattformen/api' +import { children } from './children' + +export const teachers = (child: Child): Teacher[] => + teacherData.get(child.id) ?? [] + +const [child1, child2] = children() + +const teacherData = new Map([ + [ + child1.id, + [ + { + id: 15662220, + firstname: 'Cecilia', + sisId: '', + lastname: 'Test', + email: 'cecilia.test@edu.stockholm.se', + phoneWork: undefined, + active: true, + status: ' S', + timeTableAbbreviation: 'CTE', + }, + { + id: 15662221, + firstname: 'Anna', + lastname: 'Test', + sisId: '', + email: 'anna.test@edu.stockholm.se', + phoneWork: '08000000', + active: true, + status: ' GR', + timeTableAbbreviation: 'ATE', + }, + { + id: 15662221, + firstname: 'Greta', + lastname: 'Test', + sisId: '', + email: undefined, + phoneWork: '08000001', + active: true, + status: ' F', + timeTableAbbreviation: 'GTE', + }, + ], + ], + [ + child2.id, + [ + { + id: 15662220, + firstname: 'Cecilia', + sisId: '', + lastname: 'Test', + email: 'cecilia.test@edu.stockholm.se', + phoneWork: undefined, + active: true, + status: ' S', + timeTableAbbreviation: 'CTE', + }, + { + id: 15662221, + firstname: 'Anna', + lastname: 'Test', + sisId: '', + email: 'anna.test@edu.stockholm.se', + phoneWork: '08000000', + active: true, + status: ' GR', + timeTableAbbreviation: 'ATE', + }, + { + id: 15662221, + firstname: 'Greta', + lastname: 'Test', + sisId: '', + email: undefined, + phoneWork: '08000001', + active: true, + status: ' F', + timeTableAbbreviation: 'GTE', + }, + ], + ], +]) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/timetable.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/timetable.ts new file mode 100644 index 000000000..353f47316 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/fakeData/timetable.ts @@ -0,0 +1,466 @@ +import { Skola24Child, TimetableEntry } from '@skolplattformen/api' + +export const timetable = (child: Skola24Child): TimetableEntry[] => { + if (!child.personGuid || !child.unitGuid) { + return [] + } + return [ + { + id: 'N2FjMDc1NjYtZmM2Yy0wZDQyLTY3M2YtZWI5NGNiZDA3ZGU4', + code: 'Lunch', + name: 'Lunch', + category: '', + blockName: '', + dayOfWeek: 1, + location: 'Ö5', + teacher: '', + timeEnd: '12:05:00', + timeStart: '11:40:00', + dateStart: '2021-04-12T11:40:00.000+02:00', + dateEnd: '2021-04-12T12:05:00.000+02:00', + }, + { + id: 'ZTQ1NWE0N2EtNzAwOS0wZTAzLTQ1ZDYtNTA1NWI4Y2JhNDYw', + code: 'BL', + name: 'Bild', + category: '', + blockName: '', + dayOfWeek: 1, + location: '221', + teacher: 'CTe', + timeEnd: '11:35:00', + timeStart: '09:40:00', + dateStart: '2021-04-12T09:40:00.000+02:00', + dateEnd: '2021-04-12T11:35:00.000+02:00', + }, + { + id: 'YjAxODRmY2QtNTJjZS0wMDJlLTYxOGItYmFlNTVlNDgzZmVk', + code: 'NO', + name: 'Naturorienterande ämnen', + category: '', + comment: 'a)', + blockName: '', + dayOfWeek: 1, + location: '307', + teacher: 'TBo', + timeEnd: '13:30:00', + timeStart: '12:30:00', + dateStart: '2021-04-12T12:30:00.000+02:00', + dateEnd: '2021-04-12T13:30:00.000+02:00', + }, + { + id: 'MWRiZGI1NzgtYWIzNy0wYzMwLTVkMmEtMWFjNWRkMTRmOTdh', + code: 'IDH', + name: 'Idrott & hälsa', + category: '', + blockName: '', + dayOfWeek: 1, + location: '215', + teacher: 'ATe, GTe', + timeEnd: '15:45:00', + timeStart: '14:40:00', + dateStart: '2021-04-12T14:40:00.000+02:00', + dateEnd: '2021-04-12T15:45:00.000+02:00', + }, + { + id: 'MmZkZTZiMzMtMjdjMS0wZGIzLTUzYWYtZTg0Zjc1NDRlNzQw', + code: 'M2FR', + name: 'Franska', + category: 'Moderna språk, språkval', + blockName: '', + dayOfWeek: 1, + location: '304', + teacher: 'CTe,ATe', + timeEnd: '14:25:00', + timeStart: '13:40:00', + dateStart: '2021-04-12T13:40:00.000+02:00', + dateEnd: '2021-04-12T14:25:00.000+02:00', + }, + { + id: 'MzAxMzU3MWItZGM1Ny0wOGVhLTVkZjUtOGFkMGIyYTY2OTAx', + code: 'SO', + name: 'Samhällsorienterande ämnen', + category: '', + blockName: '', + dayOfWeek: 1, + location: '303', + teacher: 'HRr', + timeEnd: '09:25:00', + timeStart: '08:15:00', + dateStart: '2021-04-12T08:15:00.000+02:00', + dateEnd: '2021-04-12T09:25:00.000+02:00', + }, + { + id: 'NDY3MDY1MmYtOTIzYi0wZmQ0LTVlZGEtNGVhZDRkOTExNTgz', + code: 'M2FR', + name: 'Franska', + category: 'Moderna språk, språkval', + blockName: '', + dayOfWeek: 2, + location: '302,Fjärr asd asdasd asdad aasdds', + teacher: 'DNi', + timeEnd: '09:50:00', + timeStart: '09:05:00', + dateStart: '2021-04-13T09:05:00.000+02:00', + dateEnd: '2021-04-13T09:50:00.000+02:00', + }, + { + id: 'NmE4OTU1NmItYzM0ZS0wYTI1LTYzM2QtYzBiN2M4OTVmYTQ3', + code: 'EN', + name: 'Engelska', + category: '', + blockName: '', + dayOfWeek: 2, + location: 'Fjärr', + teacher: 'TPe', + timeEnd: '13:15:00', + timeStart: '12:30:00', + dateStart: '2021-04-13T12:30:00.000+02:00', + dateEnd: '2021-04-13T13:15:00.000+02:00', + }, + { + id: 'NDAxODRjOTctMmE5ZC0wMzdjLTY2NDMtODhlODEzOTQ3YTJh', + code: 'Lunch', + name: 'Lunch', + category: '', + blockName: '', + dayOfWeek: 2, + location: 'Fjärr', + teacher: '', + timeEnd: '12:05:00', + timeStart: '11:40:00', + dateStart: '2021-04-13T11:40:00.000+02:00', + dateEnd: '2021-04-13T12:05:00.000+02:00', + }, + { + id: 'ZTc4YTcyZTUtMDc0NS0wNDE0LTVjODctYjY0MzQ2MGM3MDll', + code: 'MA', + name: 'Matematik', + category: '', + blockName: '', + dayOfWeek: 2, + location: 'Fjärr', + teacher: 'CBr', + timeEnd: '11:20:00', + timeStart: '10:00:00', + dateStart: '2021-04-13T10:00:00.000+02:00', + dateEnd: '2021-04-13T11:20:00.000+02:00', + }, + { + id: 'MjRkMWE4YTItYTk5ZC0wYTFmLTVhMDgtMThiMmNhZDc1ZDUz', + code: 'MU', + name: 'Musik', + category: '', + blockName: '', + dayOfWeek: 2, + location: 'Fjärr', + teacher: 'KBj', + timeEnd: '14:15:00', + timeStart: '13:30:00', + dateStart: '2021-04-13T13:30:00.000+02:00', + dateEnd: '2021-04-13T14:15:00.000+02:00', + }, + { + id: 'NTU4ZTc4ZTctNDQyMy0wMjVkLTRiYzktZGUwYmFmYzk2YTlj', + code: 'EN', + name: 'Engelska', + category: '', + blockName: '', + dayOfWeek: 3, + location: '303', + teacher: 'TPe', + timeEnd: '09:55:00', + timeStart: '09:10:00', + dateStart: '2021-04-14T09:10:00.000+02:00', + dateEnd: '2021-04-14T09:55:00.000+02:00', + }, + { + id: 'NDUyNjIxODItYzFiOC0wOTFjLTYwODYtZDllZjZjN2QyYzA3', + code: 'SV', + name: 'Svenska', + category: '', + comment: 'a)', + blockName: '', + dayOfWeek: 3, + location: '303', + teacher: 'JCa', + timeEnd: '14:45:00', + timeStart: '14:00:00', + dateStart: '2021-04-14T14:00:00.000+02:00', + dateEnd: '2021-04-14T14:45:00.000+02:00', + }, + { + id: 'NDdkMGI0ZjItMjkxMC0wYWI1LTQ0YWMtNDY3NTdkZTE2Njg3', + code: 'SO', + name: 'Engelska', + category: 'Samhällsorienterande ämnen', + blockName: '', + dayOfWeek: 3, + location: '303', + teacher: 'HRr', + timeEnd: '11:00:00', + timeStart: '10:05:00', + dateStart: '2021-04-14T10:05:00.000+02:00', + dateEnd: '2021-04-14T11:00:00.000+02:00', + }, + { + id: 'ZTI2ZDgyNWUtM2ZlOS0wZDVmLTY5NTctNGYzZThjMTMxOTdh', + code: 'NO', + name: 'Naturorienterande ämnen', + category: '', + comment: 'a)', + blockName: '', + dayOfWeek: 3, + location: '307', + teacher: 'TBo', + timeEnd: '13:50:00', + timeStart: '12:50:00', + dateStart: '2021-04-14T12:50:00.000+02:00', + dateEnd: '2021-04-14T13:50:00.000+02:00', + }, + { + id: 'NzMxNjczNGMtMmZmZi0wM2YzLTU0ZjMtODdjOTAwYzIwNTUw', + code: 'Lunch', + name: 'Lunch', + category: '', + blockName: '', + dayOfWeek: 3, + location: 'Ö5', + teacher: '', + timeEnd: '12:40:00', + timeStart: '12:15:00', + dateStart: '2021-04-14T12:15:00.000+02:00', + dateEnd: '2021-04-14T12:40:00.000+02:00', + }, + { + id: 'MWRkZjhlZTktNTBmMC0wZjNhLTQ1OTgtMWJkOWM3MjI2NWQ4', + code: 'SV', + name: 'Svenska', + category: '', + blockName: '', + dayOfWeek: 3, + location: '303', + teacher: 'JCa', + timeEnd: '12:05:00', + timeStart: '11:20:00', + dateStart: '2021-04-14T11:20:00.000+02:00', + dateEnd: '2021-04-14T12:05:00.000+02:00', + }, + { + id: 'NzM2Mjc2ZTYtY2JlYy0wOTc1LTU1ZGYtNjMwZjhjZWVjNjgy', + code: 'MA', + name: 'Matematik', + category: '', + comment: 'a)', + blockName: '', + dayOfWeek: 3, + location: '307', + teacher: 'CBr', + timeEnd: '15:45:00', + timeStart: '15:00:00', + dateStart: '2021-04-14T15:00:00.000+02:00', + dateEnd: '2021-04-14T15:45:00.000+02:00', + }, + { + id: 'YWNlZmEzZjYtM2EwNC0wYWY3LTU1N2MtMDBlMTA4MDQzMzRl', + code: 'MU', + name: 'Musik', + category: '', + blockName: '', + dayOfWeek: 3, + location: '504', + teacher: 'KBj', + timeEnd: '09:00:00', + timeStart: '08:15:00', + dateStart: '2021-04-14T08:15:00.000+02:00', + dateEnd: '2021-04-14T09:00:00.000+02:00', + }, + { + id: 'NDc4MThmMDYtYmYxYi0wZDBkLTdhNmItZGVjMjY3OWY3MmYz', + code: 'IDH', + name: 'Idrott & Hälsa', + category: '', + blockName: '', + dayOfWeek: 4, + location: 'Fjärr', + teacher: 'AKö,CSv,HAl', + timeEnd: '15:45:00', + timeStart: '14:35:00', + dateStart: '2021-04-15T14:35:00.000+02:00', + dateEnd: '2021-04-15T15:45:00.000+02:00', + }, + { + id: 'ZjQyZjNkOWItYWMzZi0wYWRhLTQ3YzItNTZiNTJkOTRmY2Iy', + code: 'M2FR', + name: 'Franska', + category: 'Moderna språk, språkval', + blockName: '', + dayOfWeek: 4, + location: 'Fjärr', + teacher: 'DNi', + timeEnd: '11:55:00', + timeStart: '11:10:00', + dateStart: '2021-04-15T11:10:00.000+02:00', + dateEnd: '2021-04-15T11:55:00.000+02:00', + }, + { + id: 'YzQ2NWZlOWMtYzM3ZC0wYzBlLTQzNTQtODMyYmU3ODcxMDQ3', + code: 'MTID', + name: 'Mentorstid', + category: 'Diverse', + comment: 'Arbetslagsråd 6C', + blockName: '', + dayOfWeek: 4, + location: 'Fjärr', + teacher: 'JCa,CBr', + timeEnd: '10:00:00', + timeStart: '09:15:00', + dateStart: '2021-04-15T09:15:00.000+02:00', + dateEnd: '2021-04-15T10:00:00.000+02:00', + }, + { + id: 'YzMwMGY0YzAtNjhjNi0wYzY0LTU1MjctODg2MWQ4ZTRmZTI2', + code: 'MU', + name: 'Musik', + category: '', + blockName: '', + dayOfWeek: 4, + location: 'Fjärr', + teacher: 'KBj', + timeEnd: '10:55:00', + timeStart: '10:10:00', + dateStart: '2021-04-15T10:10:00.000+02:00', + dateEnd: '2021-04-15T10:55:00.000+02:00', + }, + { + id: 'ZDNlNTFhMGUtYWFlYy0wOGI0LTVlMGItOTc0MzFiZmIwODcx', + code: 'Lunch', + name: 'Lunch', + category: 'Diverse', + blockName: '', + dayOfWeek: 4, + location: 'Fjärr', + teacher: '', + timeEnd: '12:25:00', + timeStart: '12:00:00', + dateStart: '2021-04-15T12:00:00.000+02:00', + dateEnd: '2021-04-15T12:25:00.000+02:00', + }, + { + id: 'MDRiZWMyODMtNjEwZC0wZDYwLTRlOWItYTY1MjAwZTc0YTZm', + code: 'SO', + name: 'Samhällsorienterande ämnen', + category: '', + blockName: '', + dayOfWeek: 4, + location: 'Fjärr', + teacher: 'HRr', + timeEnd: '13:10:00', + timeStart: '12:35:00', + dateStart: '2021-04-15T12:35:00.000+02:00', + dateEnd: '2021-04-15T13:10:00.000+02:00', + }, + { + id: 'YTA0ZTA2NTktYTU5MS0wMTFmLTVlYWYtNWM1MTgxNDJlMDcy', + code: 'EN', + name: 'Engelska', + category: '', + comment: 'a)', + blockName: '', + dayOfWeek: 4, + location: 'Fjärr', + teacher: 'TPe', + timeEnd: '14:20:00', + timeStart: '13:35:00', + dateStart: '2021-04-15T13:35:00.000+02:00', + dateEnd: '2021-04-15T14:20:00.000+02:00', + }, + { + id: 'OGJhN2MxYTYtMDQ4NS0wNWNhLTUwZWEtZDQ5YzQyMzFhYzc5', + code: 'Lunch', + name: 'Lunch', + category: 'Diverse', + blockName: '', + dayOfWeek: 5, + location: 'Ö5', + teacher: '', + timeEnd: '12:05:00', + timeStart: '11:40:00', + dateStart: '2021-04-16T11:40:00.000+02:00', + dateEnd: '2021-04-16T12:05:00.000+02:00', + }, + { + id: 'ZmUwMGEwM2QtNTExMy0wODliLTY1ZGEtODM0YmRjNjc1NDIw', + code: 'MA', + name: 'Matematik', + category: '', + comment: 'a)', + blockName: '', + dayOfWeek: 5, + location: '303', + teacher: 'CBr', + timeEnd: '14:00:00', + timeStart: '13:15:00', + dateStart: '2021-04-16T13:15:00.000+02:00', + dateEnd: '2021-04-16T14:00:00.000+02:00', + }, + { + id: 'Y2IwYjYzZDEtODAxYi0wMTNjLTRjNDMtMDFlODgzMmY4MWEy', + code: 'MU', + name: 'Musik', + category: '', + comment: 'a)', + blockName: '', + dayOfWeek: 5, + location: '510', + teacher: 'KBj', + timeEnd: '13:05:00', + timeStart: '12:20:00', + dateStart: '2021-04-16T12:20:00.000+02:00', + dateEnd: '2021-04-16T13:05:00.000+02:00', + }, + { + id: 'N2JkMGFiOTYtMjI5OC0wMjZiLTc3OGEtN2JkN2Q4MDZkNTEy', + code: 'SL', + name: 'Slöjd', + category: '', + comment: 'tmtx)', + blockName: '', + dayOfWeek: 5, + location: '860', + teacher: 'EAl', + timeEnd: '15:10:00', + timeStart: '14:10:00', + dateStart: '2021-04-16T14:10:00.000+02:00', + dateEnd: '2021-04-16T15:10:00.000+02:00', + }, + { + id: 'NzkxMjE3MDctMWExNS0wN2RmLTQwMzQtNTEyZTczZjQyZTUw', + code: 'SV', + name: 'Svenska', + category: '', + blockName: '', + dayOfWeek: 5, + location: '303', + teacher: 'JCa', + timeEnd: '10:35:00', + timeStart: '09:20:00', + dateStart: '2021-04-16T09:20:00.000+02:00', + dateEnd: '2021-04-16T10:35:00.000+02:00', + }, + { + id: 'ZTU1ZDQxNzQtN2Q3Yy0wMDMxLTY2ZmYtZmIyNGM5MjM3ZTRj', + code: 'MA', + name: 'Matematik', + category: '', + blockName: '', + dayOfWeek: 5, + location: '303', + teacher: 'CBr', + timeEnd: '11:35:00', + timeStart: '10:40:00', + dateStart: '2021-04-16T10:40:00.000+02:00', + dateEnd: '2021-04-16T11:35:00.000+02:00', + }, + ] +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/features.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/features.ts new file mode 100644 index 000000000..4a09ede18 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/features.ts @@ -0,0 +1,8 @@ +import { Features } from '../../api/lib' + +export const features: Features = { + LOGIN_BANK_ID_SAME_DEVICE_WITHOUT_ID: true, + LOGIN_FREJA_EID: true, + FOOD_MENU: true, + CLASS_LIST: true, +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/frejaLoginStatusChecker.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/frejaLoginStatusChecker.ts new file mode 100644 index 000000000..f0410f09b --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/frejaLoginStatusChecker.ts @@ -0,0 +1,59 @@ +import { EventEmitter } from 'events' +import { frejaLoginStatus } from './routes' +import { + Fetcher, + FrejaLoginStatusChecker, + RequestInit, +} from '@skolplattformen/api' +export class FrejaChecker + extends EventEmitter + implements FrejaLoginStatusChecker +{ + public token: string + + private fetcher: Fetcher + private url: string + + private cancelled = false + + constructor(fetcher: Fetcher, token: string) { + super() + this.fetcher = fetcher + + this.token = token + this.url = frejaLoginStatus + this.check() + } + + async check(): Promise { + const response = await this.fetcher('freja-login-status', this.url) + let status = await response.text() + + // For Freja we recieve CANCELED (with one L) - BankId returns CANCELLED (with two L) + // To make the API consistent - we choose the same as BankId - two L + if (status === 'CANCELED') { + status = 'CANCELLED' + } + + console.debug(status) + this.emit(status) + if ( + !this.cancelled && + status !== 'APPROVED' && + status !== 'ERROR' && + status !== 'CANCELLED' + ) { + setTimeout(() => this.check(), 1000) + } + } + + async cancel(): Promise { + this.cancelled = true + } +} + +export const checkStatus = ( + fetch: Fetcher, + token: string, + _session: RequestInit +): FrejaLoginStatusChecker => new FrejaChecker(fetch, token) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/index.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/index.ts new file mode 100644 index 000000000..16aeb4d5a --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/index.ts @@ -0,0 +1,25 @@ +import { + Api, + Fetch, + FetcherOptions, + RNCookieManager, + ToughCookieJar, + wrapReactNativeCookieManager, + wrapToughCookie, +} from '../../api/lib/index' +import { ApiSkolplattformen } from './api' +export { features } from './features' + +const init = ( + fetchImpl: Fetch, + cookieManagerImpl: RNCookieManager | ToughCookieJar, + options?: FetcherOptions +): Api => { + // prettier-ignore + const cookieManager = ((cookieManagerImpl as RNCookieManager).get) + ? wrapReactNativeCookieManager(cookieManagerImpl as RNCookieManager) + : wrapToughCookie(cookieManagerImpl as ToughCookieJar); + return new ApiSkolplattformen(fetchImpl as any, cookieManager, options) +} + +export default init diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/loginStatus.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/loginStatus.ts new file mode 100644 index 000000000..4b1f9da7c --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/loginStatus.ts @@ -0,0 +1,62 @@ +import { EventEmitter } from 'events' +import { loginStatus } from './routes' +import { Fetcher, AuthTicket } from '@skolplattformen/api' + +/* +export enum LoginEvent { + OK = 'OK', + PENDING = 'PENDING', + ERROR = 'ERROR', + USER_SIGN = 'USER_SIGN', +} +*/ + +export interface LoginStatusChecker { + token: string + on: ( + event: 'OK' | 'PENDING' | 'ERROR' | 'USER_SIGN' | 'CANCELLED', + listener: (...args: any[]) => void + ) => LoginStatusChecker + cancel: () => Promise +} + +class Checker extends EventEmitter { + public token: string + + private fetcher: Fetcher + + private url: string + + private cancelled = false + + constructor(fetcher: Fetcher, ticket: AuthTicket) { + super() + this.fetcher = fetcher + this.url = loginStatus(ticket.order) + this.token = ticket.token + this.check() + } + + async check(): Promise { + const response = await this.fetcher('login-status', this.url) + const status = await response.text() + this.emit(status) + if ( + !this.cancelled && + status !== 'OK' && + status !== 'ERROR!' && + status !== 'CANCELLED' + ) { + setTimeout(() => this.check(), 1000) + } + } + + async cancel(): Promise { + this.cancelled = true + } +} + +export const checkStatus = ( + fetch: Fetcher, + ticket: AuthTicket +): LoginStatusChecker => new Checker(fetch, ticket) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/loginStatusChecker.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/loginStatusChecker.ts new file mode 100644 index 000000000..4ccf4b429 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/loginStatusChecker.ts @@ -0,0 +1,54 @@ +import { EventEmitter } from 'events' +import { loginStatus } from './routes' +import { AuthTicket, Fetcher, LoginStatusChecker } from '@skolplattformen/api' + +export class Checker extends EventEmitter implements LoginStatusChecker { + public token: string + + private fetcher: Fetcher + + private url: string + + private cancelled = false + + constructor(fetcher: Fetcher, ticket: AuthTicket) { + super() + this.fetcher = fetcher + this.url = loginStatus(ticket.order) + this.token = ticket.token + this.check() + } + + async check(): Promise { + const response = await this.fetcher('login-status', this.url) + const status = await response.json() + this.emit(status.state) + if ( + !this.cancelled && + status.state !== 'OK' && + status.state !== 'ERROR' && + status.state !== 'CANCELLED' + ) { + setTimeout(() => this.check(), 1000) + } + } + + async cancel(): Promise { + this.cancelled = true + } +} + +export const checkStatus = ( + fetch: Fetcher, + ticket: AuthTicket +): LoginStatusChecker => new Checker(fetch, ticket) + +export class DummyStatusChecker + extends EventEmitter + implements LoginStatusChecker +{ + token = '' + async cancel(): Promise { + // do nothing + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/missingtypes.d.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/missingtypes.d.ts new file mode 100644 index 000000000..0334e2034 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/missingtypes.d.ts @@ -0,0 +1 @@ +declare module 'h2m' diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/calendar.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/calendar.test.ts new file mode 100644 index 000000000..3556621a8 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/calendar.test.ts @@ -0,0 +1,74 @@ +import { EtjanstResponse } from '../' +import { calendar } from '../calendar' + +let response: EtjanstResponse + +beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + Title: 'Jullov', + Id: 29, + Description: 'hello', + Location: null, + EventDate: '2020-12-21', + EventDateTime: '09:00', + LongEventDateTime: '2020-12-21 09:00', + EndDate: '2021-01-08', + EndDateTime: '10:00', + LongEndDateTime: '2021-01-08 10:00', + EventDateDayNumber: '21', + EventDateMonthName: 'dec', + EventDateMonthFullName: 'december', + FullDateDescription: '2020-12-21 09:00 - 2021-01-08 10:00', + IsSameDay: false, + AllDayEvent: false, + ListId: null, + Mentor: null, + }, + { + Title: 'Utvecklingsdag, förskolorna är stängda', + Id: 5, + Description: null, + Location: null, + EventDate: '2021-05-28', + EventDateTime: '', + LongEventDateTime: '2021-05-28', + EndDate: '2021-05-28', + EndDateTime: '', + LongEndDateTime: '2021-05-28', + EventDateDayNumber: '28', + EventDateMonthName: 'maj', + EventDateMonthFullName: 'maj', + FullDateDescription: '2021-05-28 - 2021-05-28', + IsSameDay: true, + AllDayEvent: true, + ListId: null, + Mentor: null, + }, + ], + } +}) + +it('parses calendar correctly', () => { + const [firstEvent] = calendar(response) + + expect(firstEvent).toEqual({ + id: 29, + location: null, + title: 'Jullov', + description: 'hello', + startDate: '2020-12-21T08:00:00.000Z', + endDate: '2021-01-08T09:00:00.000Z', + allDay: false, + }) +}) + +it('parses start and end date without time', () => { + const [, secondEvent] = calendar(response) + + expect(secondEvent.startDate).toEqual('2021-05-27T22:00:00.000Z') + expect(secondEvent.endDate).toEqual('2021-05-27T22:00:00.000Z') +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/children.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/children.test.ts new file mode 100644 index 000000000..d685f59ac --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/children.test.ts @@ -0,0 +1,43 @@ +import { EtjanstResponse } from '../' +import { children } from '../children' + +let response: EtjanstResponse + +beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + Name: 'Some name', + Id: '42C3997E-D772-423F-9290-6FEEB3CB2DA7', + SDSId: '786E3393-F044-4660-9105-B444DEB289AA', + Status: 'GR', + UserType: 'Student', + SchoolId: 'DE2E1293-0F40-4B91-9D91-1E99355DC257', + SchoolName: null, + GroupId: null, + GroupName: null, + Classes: + 'VHsidan_0495CABC-77DB-41D7-824B-8B4D63E50D15;Section_AD1BB3B2-C1EE-4DFE-8209-CB6D42CE23D7;Section_0E67D0BF-594C-4C1B-9291-E753926DCD40;VHsidan_1C94EC54-9798-401C-B973-2454246D95DA', + isSameSDSId: false, + ResultUnitId: null, + ResultUnitName: null, + UnitId: null, + UnitName: null, + }, + ], + } +}) + +it('parses children correctly', () => { + expect(children(response)).toEqual([ + { + name: 'Some name', + id: '42C3997E-D772-423F-9290-6FEEB3CB2DA7', + sdsId: '786E3393-F044-4660-9105-B444DEB289AA', + schoolId: 'DE2E1293-0F40-4B91-9D91-1E99355DC257', + status: 'GR', + }, + ]) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/classmates.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/classmates.test.ts new file mode 100644 index 000000000..a86f1ad9b --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/classmates.test.ts @@ -0,0 +1,72 @@ +import { EtjanstResponse } from '../' +import { classmates } from '../classmates' + +let response: EtjanstResponse + +beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + ID: 0, + BATCH: null, + SIS_ID: '22F0CFC7-09C7-45DC-9388-AE9A9EA1356B', + USERNAME: null, + SCHOOL_SIS_ID: null, + EMAILADDRESS: null, + STATUS: null, + ERRORCODE: 0, + PRIMARY_SCHOOL_SIS_ID: null, + MENTOR_SIS_ID: null, + FIRSTNAME: 'Bo', + LASTNAME: 'Burström', + ACTIVE: false, + Guardians: [ + { + SOCIALNUMBER: null, + DISPLAYNAME: null, + FIRSTNAME: 'Allan', + LASTNAME: 'Fridell', + ADDRESS: 'Hult södregård', + CITY: null, + POCODE: null, + TELHOME: null, + TELMOBILE: '0690-6346216', + EMAILHOME: 'allan.fridell@mailinater.com', + SECTION_NAME: null, + SECTION_ID: null, + TERM_STARTDATE: null, + TERM_ENDDATE: null, + GROUPTYPE: null, + STUDENT_FIRSTNAME: null, + STUDENT_LASTNAME: null, + STUDENT_ID: null, + }, + ], + ClassName: '7C', + ClassId: 'B2BF465B-581B-43AC-9CA7-F11BB0ED4646', + }, + ], + } +}) + +it('parses class mates correctly', () => { + expect(classmates(response)).toEqual([ + { + sisId: '22F0CFC7-09C7-45DC-9388-AE9A9EA1356B', + firstname: 'Bo', + lastname: 'Burström', + className: '7C', + guardians: [ + { + firstname: 'Allan', + lastname: 'Fridell', + address: 'Hult södregård', + mobile: '0690-6346216', + email: 'allan.fridell@mailinater.com', + }, + ], + }, + ]) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/index.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/index.test.ts new file mode 100644 index 000000000..794370b6c --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/index.test.ts @@ -0,0 +1,32 @@ +import * as parse from '../' + +let response: parse.EtjanstResponse + +describe('etjanst', () => { + beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + Name: 'Some name', + }, + ], + } + }) + + it('returns data on success', () => { + expect(parse.etjanst(response)).toBeInstanceOf(Array) + }) + + it('throws error on Error', () => { + response.Success = false + response.Error = 'b0rk' + expect(() => parse.etjanst(response)).toThrowError('b0rk') + }) + + it('camelCases data keys', () => { + const parsed = parse.etjanst(response) + expect(parsed[0].name).toEqual(response.Data[0].Name) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/menu.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/menu.test.ts new file mode 100644 index 000000000..157d9b2f6 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/menu.test.ts @@ -0,0 +1,91 @@ +import { EtjanstResponse } from '../' +import { menu, menuList } from '../menu' + +let response: EtjanstResponse + +describe('menu', () => { + beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + Title: 'Måndag - Vecka 52', + Description: 'Körrfärsrätt .
Veg färs', + }, + ], + } + }) + it(' menu correctly', () => { + expect(menu(response)).toEqual([ + { + title: 'Måndag - Vecka 52', + description: 'Körrfärsrätt .\nVeg färs', + }, + ]) + }) +}) + +describe('menu-list', () => { + beforeEach(() => { + response = { + Success: true, + Error: null, + Data: { + SelectedWeek: 12, + Menus: [ + { + Week: '12', + Mon: 'Köttfärslimpa med sås och potatis', + Tue: 'Curryfisk med ris', + Wed: 'Tagliatelle med vegetarisk sås', + Thu: 'Chorizo med stuvad potatis', + Fri: 'Ört och vitlöksinbakad fisk, potatis', + }, + { + Week: '19', + Mon: 'FISKGRATÄNG WALEWSKA', + Tue: 'STEKT FLÄSK MED RAGGMUNK', + Wed: 'PENNEPASTA MED TONFISK', + Thu: 'KÖTTGRYTA MED POTATIS', + Fri: 'GRÖNSAKSGRATÄNG MED TZATZIKI', + }, + { + Week: '20', + Mon: 'SPAGHETTI SALMONE ', + Tue: 'STEKT FALUKORV MED SENAPSSÅS OCH POTATIS', + Wed: 'SOPPA MED RISONI OCH HEMBAKAT BRÖD', + Thu: 'PANERAD FISK MED SKAGEN OCH POTATIS', + Fri: 'TACOS', + }, + ], + }, + } + }) + it(' menu correctly', () => { + const result = menuList(response) + + expect(result).toEqual([ + { + title: 'Måndag - Vecka 12', + description: 'Köttfärslimpa med sås och potatis', + }, + { + title: 'Tisdag - Vecka 12', + description: 'Curryfisk med ris', + }, + { + title: 'Onsdag - Vecka 12', + description: 'Tagliatelle med vegetarisk sås', + }, + { + title: 'Torsdag - Vecka 12', + description: 'Chorizo med stuvad potatis', + }, + { + title: 'Fredag - Vecka 12', + description: 'Ört och vitlöksinbakad fisk, potatis', + }, + ]) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/news.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/news.test.ts new file mode 100644 index 000000000..a652de83a --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/news.test.ts @@ -0,0 +1,330 @@ +import { EtjanstResponse } from '../' +import { news, newsItemDetails } from '../news' + +let response: EtjanstResponse + +describe('news', () => { + describe('parsing', () => { + beforeEach(() => { + response = { + Success: true, + Error: null, + Data: { + CurrentChild: null, + NewsItems: [ + { + NewsId: 'news id', + SiteId: + 'elevstockholm.sharepoint.com,27892ACC-BA2E-4DEC-97B8-25F7098C3BF6,A239466A-9A52-42FF-8A3F-D94C342F2700', + NewsListId: '3EC323A1-EA16-4D24-84C8-DAA49E76F9F4', + NewsItemId: + 'elevstockholm.sharepoint.com,27892ACC-BA2E-4DEC-97B8-25F7098C3BF6,A239466A-9A52-42FF-8A3F-D94C342F2700_99', + Header: + 'Problemet med att se betyg i bild, slöjd och teknik löst!', + PublicationDate: '/Date(1608304542000)/', + PubDateSE: '18 december 2020 16:15', + ModifiedDate: '/Date(1608304680000)/', + ModDateSE: '18 december 2020 16:18', + Source: 'Livets hårda skolklasser', + Preamble: + 'Hej,Nu är problemet löst! Alla betyg syns som de ska.God jul!...', + BannerImageUrl: 'A703552D-DBF3-45B0-8E67-6E062105A0C5.jpeg', + BannerImageGuid: 'A703552D-DBF3-45B0-8E67-6E062105A0C5', + BannerImageListId: 'FFBE49E9-BDE1-4C75-BA0E-D98D4E2FCF21', + Body: '

Hej,

Nu är problemet löst! Alla betyg syns som de ska. 

God jul!

', + BodyNoHtml: null, + AuthorDisplayName: 'Eva-Lotta Rönnberg', + altText: 'Nyhetsbild. Bildtext ej tillgänglig.', + }, + ], + ViewGlobalTranslations: {}, + ViewLocalTranslations: {}, + Children: null, + Status: null, + GlobalTranslationIds: [ + 'InformationalHeader', + 'ContactUsMessageLabel', + 'Send', + 'RequiredFieldMessageInfo', + 'Sex', + 'Male', + 'Female', + 'SSN', + 'FirstName', + 'LastName', + 'Email', + 'Zip', + 'Address', + 'ValidationRequiredFieldMessage', + 'ValidationErrorMessage', + ], + LocalTranslationIds: ['IndexPageHeading1'], + }, + } + }) + it(' news items (except body) correctly', () => { + const [item] = news(response) + + expect(item.id).toEqual('news id') + expect(item.author).toEqual('Eva-Lotta Rönnberg') + expect(item.header).toEqual( + 'Problemet med att se betyg i bild, slöjd och teknik löst!' + ) + expect(item.imageUrl).toEqual('A703552D-DBF3-45B0-8E67-6E062105A0C5.jpeg') + expect(item.fullImageUrl).toEqual( + 'https://etjanst.stockholm.se/Vardnadshavare/inloggad2/NewsBanner?url=A703552D-DBF3-45B0-8E67-6E062105A0C5.jpeg' + ) + expect(item.imageAltText).toEqual('Nyhetsbild. Bildtext ej tillgänglig.') + expect(item.intro).toEqual( + 'Hej, Nu är problemet löst! Alla betyg syns som de ska. God jul!...' + ) + expect(item.modified).toEqual('2020-12-18T15:18:00.000Z') + expect(item.published).toEqual('2020-12-18T15:15:42.000Z') + }) + it(' body correctly', () => { + const [item] = news(response) + + const expected = + 'Hej, Nu är problemet löst! Alla betyg syns som de ska. God jul!' + const trimmed = (item.body || '') + .split('\n') + .map((t) => t.trim()) + .join(' ') + expect(trimmed).toEqual(expected) + }) + }) + describe('sorting', () => { + beforeEach(() => { + response = { + Success: true, + Error: null, + Data: { + CurrentChild: null, + NewsItems: [ + { + NewsId: 'news id', + SiteId: + 'elevstockholm.sharepoint.com,27892ACC-BA2E-4DEC-97B8-25F7098C3BF6,A239466A-9A52-42FF-8A3F-D94C342F2700', + NewsListId: '3EC323A1-EA16-4D24-84C8-DAA49E76F9F4', + NewsItemId: + 'elevstockholm.sharepoint.com,27892ACC-BA2E-4DEC-97B8-25F7098C3BF6,A239466A-9A52-42FF-8A3F-D94C342F2700_99', + Header: + 'Problemet med att se betyg i bild, slöjd och teknik löst!', + PublicationDate: '/Date(1608304542000)/', + PubDateSE: '18 december 2020 16:15', + ModifiedDate: '/Date(1608304680000)/', + ModDateSE: '18 december 2020 16:18', + Source: 'Livets hårda skolklasser', + Preamble: + 'Hej,Nu är problemet löst! Alla betyg syns som de ska.God jul!...', + BannerImageUrl: 'A703552D-DBF3-45B0-8E67-6E062105A0C5.jpeg', + BannerImageGuid: 'A703552D-DBF3-45B0-8E67-6E062105A0C5', + BannerImageListId: 'FFBE49E9-BDE1-4C75-BA0E-D98D4E2FCF21', + Body: '

Hej,

Nu är problemet löst! Alla betyg syns som de ska. 

God jul!

', + BodyNoHtml: null, + AuthorDisplayName: 'Eva-Lotta Rönnberg', + altText: 'Nyhetsbild. Bildtext ej tillgänglig.', + }, + { + NewsId: 'news id updated', + SiteId: + 'elevstockholm.sharepoint.com,27892ACC-BA2E-4DEC-97B8-25F7098C3BF6,A239466A-9A52-42FF-8A3F-D94C342F2700', + NewsListId: '3EC323A1-EA16-4D24-84C8-DAA49E76F9F4', + NewsItemId: + 'elevstockholm.sharepoint.com,27892ACC-BA2E-4DEC-97B8-25F7098C3BF6,A239466A-9A52-42FF-8A3F-D94C342F2700_99', + Header: + 'Problemet med att se betyg i bild, slöjd och teknik löst!', + PublicationDate: '/Date(1608304542000)/', + PubDateSE: '18 november 2021 16:15', + ModifiedDate: '/Date(1608304680000)/', + ModDateSE: '18 december 2020 16:18', + Source: 'Livets hårda skolklasser', + Preamble: + 'Hej,Nu är problemet löst! Alla betyg syns som de ska.God jul!...', + BannerImageUrl: 'A703552D-DBF3-45B0-8E67-6E062105A0C5.jpeg', + BannerImageGuid: 'A703552D-DBF3-45B0-8E67-6E062105A0C5', + BannerImageListId: 'FFBE49E9-BDE1-4C75-BA0E-D98D4E2FCF21', + Body: '

Hej,

Nu är problemet löst! Alla betyg syns som de ska. 

God jul!

', + BodyNoHtml: null, + AuthorDisplayName: 'Eva-Lotta Rönnberg', + altText: 'Nyhetsbild. Bildtext ej tillgänglig.', + }, + ], + ViewGlobalTranslations: {}, + ViewLocalTranslations: {}, + Children: null, + Status: null, + GlobalTranslationIds: [ + 'InformationalHeader', + 'ContactUsMessageLabel', + 'Send', + 'RequiredFieldMessageInfo', + 'Sex', + 'Male', + 'Female', + 'SSN', + 'FirstName', + 'LastName', + 'Email', + 'Zip', + 'Address', + 'ValidationRequiredFieldMessage', + 'ValidationErrorMessage', + ], + LocalTranslationIds: ['IndexPageHeading1'], + }, + } + }) + it('sorts by modified date desc', () => { + const [item] = news(response) + + expect(item.id).toEqual('news id updated') + }) + }) +}) + +describe('newsItem', () => { + beforeEach(() => { + response = { + Success: true, + Error: null, + Data: { + CurrentNewsItem: { + NewsId: '123', + SiteId: + 'elevstockholm.sharepoint.com,d112c398-71d4-468f-9a59-84d806751b08,3addab10-546a-4551-8076-72c9cd67f961', + NewsListId: '95df7d70-fbf0-470d-9926-e4e633f77f27', + NewsItemId: + 'elevstockholm.sharepoint.com,d112c398-71d4-468f-9a59-84d806751b08,3addab10-546a-4551-8076-72c9cd67f961_40', + Header: 'Avlusningsdagarna 5-7 februari 2021', + PublicationDate: '/Date(1612445471000)/', + PubDateSE: '4 februari 2021 14:31', + ModifiedDate: '/Date(1612445852000)/', + ModDateSE: '14 februari 2021 14:37', + Source: 'Södra Ängby skola', + Preamble: 'Kära vårdnadshavare!I helgen är det avlusningsdagar!', + BannerImageUrl: '123123.jpeg', + BannerImageGuid: '7a8142d9d9d54cf090e8457e4c629227', + BannerImageListId: 'a88c22e8-7094-4a71-b4fd-8792c62a7b4a', + Body: '

Kära vårdnadshavare!

I helgen är det avlusningsdagar! Ta tillfället i akt att luskamma ditt barn

Du finner all info du behöver på 1177 hemsida ​​​​​​​

Trevlig helg!

​​​​​​​

', + BodyNoHtml: null, + AuthorDisplayName: 'Tieto Evry', + altText: null, + OriginalSourceUrl: null, + }, + CurrentChild: null, + ViewGlobalTranslations: {}, + ViewLocalTranslations: {}, + Children: null, + Status: null, + GlobalTranslationIds: [ + 'InformationalHeader', + 'ContactUsMessageLabel', + 'Send', + 'RequiredFieldMessageInfo', + 'Sex', + 'Male', + 'Female', + 'SSN', + 'FirstName', + 'LastName', + 'Email', + 'Zip', + 'Address', + 'ValidationRequiredFieldMessage', + 'ValidationErrorMessage', + ], + LocalTranslationIds: ['IndexPageHeading1'], + }, + } + }) + + it(' news details (except body) correctly', () => { + const item = newsItemDetails(response) + + expect(item.id).toEqual('123') + expect(item.header).toEqual('Avlusningsdagarna 5-7 februari 2021') + expect(item.imageUrl).toEqual('123123.jpeg') + expect(item.intro).toEqual( + 'Kära vårdnadshavare! I helgen är det avlusningsdagar!' + ) + expect(item.published).toEqual('2021-02-04T13:31:11.000Z') + expect(item.modified).toEqual('2021-02-04T13:37:32.000Z') + expect(item.author).toEqual('Tieto Evry') + }) + + it(' body correctly', () => { + const item = newsItemDetails(response) + + const expected = + '[1177 hemsida](https://www.1177.se/sjukdomar--besvar/hud-har-och-naglar/harbotten-och-harsackar/huvudloss/)' + expect(item.body).toContain(expected) + expect(item.body).toContain(' **tillfället** ') + }) +}) + +describe('newsItem', () => { + beforeEach(() => { + response = { + Success: true, + Error: null, + Data: { + CurrentNewsItem: { + NewsId: '123', + SiteId: + 'elevstockholm.sharepoint.com,d112c398-71d4-468f-9a59-84d806751b08,3addab10-546a-4551-8076-72c9cd67f961', + NewsListId: '95df7d70-fbf0-470d-9926-e4e633f77f27', + NewsItemId: + 'elevstockholm.sharepoint.com,d112c398-71d4-468f-9a59-84d806751b08,3addab10-546a-4551-8076-72c9cd67f961_40', + Header: 'Avlusningsdagarna 5-7 februari 2021', + PublicationDate: '/Date(1612445471000)/', + PubDateSE: '4 februari 2021 14:31', + ModifiedDate: '/Date(1612445852000)/', + ModDateSE: '14 februari 2021 14:37', + Source: 'Södra Ängby skola', + Preamble: 'Kära vårdnadshavare!I helgen är det avlusningsdagar!', + BannerImageUrl: '123123.jpeg', + BannerImageGuid: '7a8142d9d9d54cf090e8457e4c629227', + BannerImageListId: 'a88c22e8-7094-4a71-b4fd-8792c62a7b4a', + Body: 'italic bold emphasis
strongnbsp ', + BodyNoHtml: null, + AuthorDisplayName: 'Tieto Evry', + altText: null, + OriginalSourceUrl: null, + }, + CurrentChild: null, + ViewGlobalTranslations: {}, + ViewLocalTranslations: {}, + Children: null, + Status: null, + GlobalTranslationIds: [ + 'InformationalHeader', + 'ContactUsMessageLabel', + 'Send', + 'RequiredFieldMessageInfo', + 'Sex', + 'Male', + 'Female', + 'SSN', + 'FirstName', + 'LastName', + 'Email', + 'Zip', + 'Address', + 'ValidationRequiredFieldMessage', + 'ValidationErrorMessage', + ], + LocalTranslationIds: ['IndexPageHeading1'], + }, + } + }) + it(' emphasizes correctly', () => { + const item = newsItemDetails(response) + + expect(item.body).toContain('*italic*') + expect(item.body).toContain('**bold**') + expect(item.body).toContain('*emphasis*') + expect(item.body).toContain('**strong**') + expect(item.body).toContain('**nbsp**') + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/notifications.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/notifications.test.ts new file mode 100644 index 000000000..567f7b30e --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/notifications.test.ts @@ -0,0 +1,64 @@ +import { EtjanstResponse } from '../' +import { notifications } from '../notifications' + +let response: EtjanstResponse + +beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + Notification: { + Messageid: 'E2E3A567-307F-4859-91BA-31B1F4522A7B', + Messagecorrelationid: 'BB54DC8E-BB02-49A5-9806-4A2433031AA7', + Message: + '{"messages":{"message":{"messageid":"E2E3A567-307F-4859-91BA-31B1F4522A7B","messagecorrelationid":"BB54DC8E-BB02-49A5-9806-4A2433031AA7","messagetext":"Betygen är publicerade.","messagesubject":"Betyg klara","messagetime":"2020-12-18T15:59:43.195","linkbackurl":"https://elevdokumentation.stockholm.se/loa3/gradesStudent.do","sender":{"name":"Elevdokumentation"},"recipient":{"recipient":"195709227283","role":"Guardian"},"messagetype":{"type":"webnotify"},"system":"Elevdokumentation","participant":"BB7DE89D-D714-4EB2-85CD-36F9991E7C34"}}}', + Readreceipt: false, + Recipient: '195709227283', + Id: 5880387, + DateCreated: '2020-12-18T15:59:46.34', + DateModified: '/Date(1608307186340)/', + Role: 'Guardian', + Participant: 'BB7DE89D-D714-4EB2-85CD-36F9991E7C34', + }, + NotificationMessage: { + Messages: { + Message: { + Messageid: 'E2E3A567-307F-4859-91BA-31B1F4522A7B', + Messagecorrelationid: 'BB54DC8E-BB02-49A5-9806-4A2433031AA7', + Messagetext: 'Betygen är publicerade.', + Messagetime: '/Date(1608303583195)/', + Linkbackurl: + 'https://elevdokumentation.stockholm.se/loa3/gradesStudent.do', + Category: null, + Sender: { Name: 'Elevdokumentation' }, + Recipient: { + RecipientRecipient: '195709227283', + Role: 'Guardian', + Schooltype: null, + }, + Messagetype: { Type: 'webnotify' }, + System: 'Elevdokumentation', + }, + }, + }, + }, + ], + } +}) + +it(' notifications correctly', () => { + expect(notifications(response)).toEqual([ + { + id: 'E2E3A567-307F-4859-91BA-31B1F4522A7B', + message: 'Betygen är publicerade.', + sender: 'Elevdokumentation', + url: 'https://elevdokumentation.stockholm.se/loa3/gradesStudent.do', + dateCreated: '2020-12-18T14:59:46.340Z', + dateModified: '2020-12-18T15:59:46.340Z', + category: null, + type: 'webnotify', + }, + ]) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/schedule.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/schedule.test.ts new file mode 100644 index 000000000..4f5633ac0 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/schedule.test.ts @@ -0,0 +1,47 @@ +import { EtjanstResponse } from '../' +import { schedule } from '../schedule' + +let response: EtjanstResponse + +beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + Title: 'Canceled: Julavslutning 8C', + Id: 0, + Description: 'Nåt kul', + Location: 'Lakritskolan', + EventDate: '2020-12-14', + EventDateTime: '14:10', + LongEventDateTime: '2020-12-14 14:10', + EndDate: '2020-12-14', + EndDateTime: '14:40', + LongEndDateTime: '2020-12-14 14:40', + EventDateDayNumber: '14', + EventDateMonthName: 'dec', + EventDateMonthFullName: 'december', + FullDateDescription: '2020-12-14 14:10 - 2020-12-14 14:40', + IsSameDay: true, + AllDayEvent: false, + ListId: null, + Mentor: null, + }, + ], + } +}) + +it('parses schedule correctly', () => { + expect(schedule(response)).toEqual([ + { + title: 'Canceled: Julavslutning 8C', + description: 'Nåt kul', + location: 'Lakritskolan', + startDate: '2020-12-14T13:10:00.000Z', + endDate: '2020-12-14T13:40:00.000Z', + oneDayEvent: true, + allDayEvent: false, + }, + ]) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/schoolContacts.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/schoolContacts.test.ts new file mode 100644 index 000000000..b2d5cdc28 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/schoolContacts.test.ts @@ -0,0 +1,50 @@ +import { EtjanstResponse } from '../' +import { schoolContacts } from '../schoolContacts' + +let response: EtjanstResponse + +beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + Title: 'Expedition', + Name: null, + Phone: '508 000 00', + Email: '', + SchoolName: 'Påhittade skolan', + ClassName: null, + }, + { + Title: 'Rektor', + Name: 'Andersson, Anna Bella Cecilia', + Phone: '08-508 000 00', + Email: 'anna.anderssonn@edu.stockholm.se', + SchoolName: null, + ClassName: null, + }, + ], + } +}) + +it('parses teachers correctly', () => { + expect(schoolContacts(response)).toEqual([ + { + title: 'Expedition', + name: null, + phone: '508 000 00', + email: '', + schoolName: 'Påhittade skolan', + className: null, + }, + { + title: 'Rektor', + name: 'Andersson, Anna Bella Cecilia', + phone: '08-508 000 00', + email: 'anna.anderssonn@edu.stockholm.se', + schoolName: null, + className: null, + }, + ]) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/teachers.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/teachers.test.ts new file mode 100644 index 000000000..cda0583b1 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/teachers.test.ts @@ -0,0 +1,68 @@ +import { EtjanstResponse } from '../' +import { teachers } from '../teachers' + +let response: EtjanstResponse + +beforeEach(() => { + response = { + Success: true, + Error: null, + Data: [ + { + ID: 156735, + BATCH: 'GR', + SIS_ID: 'F154239A-EA4A-4C6C-A112-0B9581132E3D', + USERNAME: 'anna.andersson', + SCHOOL_SIS_ID: 'DE2E1293-0F40-4B91-9D91-1E99355DC257', + EMAILADDRESS: null, + STATUS: ' GR', + ERRORCODE: 0, + FIRSTNAME: 'Anna', + LASTNAME: 'Andersson', + ACTIVE: true, + TELWORK: '08 508 0000000', + }, + { + ID: 156690, + BATCH: 'GR', + SIS_ID: '9EC59FCA-80AD-4774-AABD-427040207E33', + USERNAME: 'gunnar.grymm', + SCHOOL_SIS_ID: 'DE2E1293-0F40-4B91-9D91-1E99355DC257', + EMAILADDRESS: 'gunnar.grymm@edu.stockholm.se', + STATUS: ' F', + ERRORCODE: 0, + FIRSTNAME: 'Gunnar', + LASTNAME: 'Grymm', + ACTIVE: true, + TELWORK: null, + }, + ], + } +}) + +it('parses teachers correctly', () => { + expect(teachers(response)).toEqual([ + { + id: 156735, + sisId: 'F154239A-EA4A-4C6C-A112-0B9581132E3D', + firstname: 'Anna', + lastname: 'Andersson', + email: null, + phoneWork: '08 508 0000000', + active: true, + status: ' GR', + timeTableAbbreviation: 'AAN', + }, + { + id: 156690, + sisId: '9EC59FCA-80AD-4774-AABD-427040207E33', + firstname: 'Gunnar', + lastname: 'Grymm', + email: 'gunnar.grymm@edu.stockholm.se', + phoneWork: null, + active: true, + status: ' F', + timeTableAbbreviation: 'GGR', + }, + ]) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/timetable.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/timetable.test.ts new file mode 100644 index 000000000..4ab1511ff --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/timetable.test.ts @@ -0,0 +1,147 @@ +import { timetable, timetableEntry, TimetableResponse } from '../' + +let response: TimetableResponse + +describe('Timetable', () => { + beforeEach(() => { + response = { + error: null, + data: { + textList: [ + { + x: 11, + y: 64, + fColor: '#000000', + fontsize: 14, + text: '8:30', + bold: false, + italic: false, + id: 9, + parentId: 6, + type: 'ClockAxisBox', + }, + { + x: 11, + y: 125, + fColor: '#000000', + fontsize: 14, + text: '9:00', + bold: false, + italic: false, + id: 12, + parentId: 6, + type: 'ClockAxisBox', + }, + ], + boxList: [ + { + x: 0, + y: 950, + width: 1226, + height: 112, + bColor: '#FFFFFF', + fColor: '#FFFFFF', + id: 0, + parentId: null, + type: 'Footer', + lessonGuids: null, + }, + { + x: 56, + y: 0, + width: 223, + height: 34, + bColor: '#FFFFFF', + fColor: '#000000', + id: 1, + parentId: null, + type: 'HeadingDay', + lessonGuids: null, + }, + ], + lineList: [ + { + p1x: 51, + p1y: 34, + p2x: 56, + p2y: 34, + color: '#000000', + id: 7, + parentId: 6, + type: 'ClockAxisGradiation', + }, + { + p1x: 0, + p1y: 64, + p2x: 56, + p2y: 64, + color: '#000000', + id: 8, + parentId: 6, + type: 'ClockAxisGradiation', + }, + ], + lessonInfo: [ + { + guidId: 'N2FjMDc1NjYtZmM2Yy0wZDQyLTY3M2YtZWI5NGNiZDA3ZGU4', + texts: ['Lunch', '', 'Ö5'], + timeStart: '11:40:00', + timeEnd: '12:05:00', + dayOfWeekNumber: 1, + blockName: '', + }, + { + guidId: 'ZTQ1NWE0N2EtNzAwOS0wZTAzLTQ1ZDYtNTA1NWI4Y2JhNDYw', + texts: ['BL', 'KUr', '221'], + timeStart: '09:40:00', + timeEnd: '11:35:00', + dayOfWeekNumber: 1, + blockName: 'block', + }, + ], + }, + exception: null, + validation: [], + } + }) + describe('timetableEntry', () => { + it('parses basic timeTableEntry data correctly', () => { + const entry = timetableEntry(response.data.lessonInfo[1], 2021, 15, 'sv') + + expect(entry.id).toEqual( + 'ZTQ1NWE0N2EtNzAwOS0wZTAzLTQ1ZDYtNTA1NWI4Y2JhNDYw' + ) + expect(entry.code).toEqual('BL') + expect(entry.name).toEqual('Bild') + expect(entry.teacher).toEqual('KUr') + expect(entry.location).toEqual('221') + expect(entry.timeStart).toEqual('09:40:00') + expect(entry.timeEnd).toEqual('11:35:00') + expect(entry.dayOfWeek).toEqual(1) + expect(entry.blockName).toEqual('block') + }) + it('parses dates correctly', () => { + const entry = timetableEntry(response.data.lessonInfo[1], 2021, 15, 'sv') + + expect(entry.dateStart).toEqual('2021-04-12T09:40:00.000+02:00') + expect(entry.dateEnd).toEqual('2021-04-12T11:35:00.000+02:00') + }) + }) + describe('timetable', () => { + it('throws error', () => { + response.error = 'b0rk' + expect(() => timetable(response, 2021, 15, 'sv')).toThrow('b0rk') + }) + it('parses lessonInfo', () => { + const table = timetable(response, 2021, 15, 'sv') + + expect(table).toHaveLength(2) + expect(table[0].id).toEqual( + 'N2FjMDc1NjYtZmM2Yy0wZDQyLTY3M2YtZWI5NGNiZDA3ZGU4' + ) + expect(table[1].id).toEqual( + 'ZTQ1NWE0N2EtNzAwOS0wZTAzLTQ1ZDYtNTA1NWI4Y2JhNDYw' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/user.test.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/user.test.ts new file mode 100644 index 000000000..a8685f5ce --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/__tests__/user.test.ts @@ -0,0 +1,27 @@ +import { user } from '../user' + +let response: any + +beforeEach(() => { + response = { + socialSecurityNumber: '197106171635', + isAuthenticated: true, + userFirstName: 'Per-Ola', + userLastName: 'Assarsson', + userEmail: 'per-ola.assarsson@dodgit.com', + notificationId: + 'B026594053D44299AB64ED81990B49C04D32F635C9A3454A84030439BFDDEF04', + } +}) + +it('parses user correctly', () => { + expect(user(response)).toEqual({ + personalNumber: '197106171635', + firstName: 'Per-Ola', + lastName: 'Assarsson', + email: 'per-ola.assarsson@dodgit.com', + isAuthenticated: true, + notificationId: + 'B026594053D44299AB64ED81990B49C04D32F635C9A3454A84030439BFDDEF04', + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/calendar.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/calendar.ts new file mode 100644 index 000000000..1ac439e87 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/calendar.ts @@ -0,0 +1,23 @@ +import { etjanst } from './etjanst' +import { CalendarItem, parseDate } from '../../../api/lib' + +export const calendarItem = ({ + id, + title, + description, + location, + longEventDateTime, + longEndDateTime, + allDayEvent, +}: any): CalendarItem => ({ + id, + title, + description, + location, + allDay: allDayEvent, + startDate: parseDate(longEventDateTime), + endDate: parseDate(longEndDateTime), +}) + +export const calendar = (data: any): CalendarItem[] => + etjanst(data).map(calendarItem) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/children.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/children.ts new file mode 100644 index 000000000..98bcfe510 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/children.ts @@ -0,0 +1,12 @@ +import { Child } from '@skolplattformen/api' +import { etjanst } from './etjanst' + +export const child = ({ id, sdsId, name, status, schoolId }: any): Child => ({ + id, + sdsId, + name, + status, + schoolId, +}) + +export const children = (data: any): Child[] => etjanst(data).map(child) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/classmates.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/classmates.ts new file mode 100644 index 000000000..89d20416a --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/classmates.ts @@ -0,0 +1,33 @@ +import { Classmate, Guardian } from '../../../api/lib' +import { etjanst } from './etjanst' + +export const guardian = ({ + emailhome, + firstname, + lastname, + address, + telmobile, +}: any): Guardian => ({ + firstname, + lastname, + address, + mobile: telmobile, + email: emailhome, +}) + +export const classmate = ({ + sisId, + firstname, + lastname, + className, + guardians = [], +}: any): Classmate => ({ + sisId, + firstname, + lastname, + className, + guardians: guardians.map(guardian), +}) + +export const classmates = (data: any): Classmate[] => + etjanst(data).map(classmate) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/etjanst.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/etjanst.ts new file mode 100644 index 000000000..5c8f14e88 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/etjanst.ts @@ -0,0 +1,14 @@ +import camel from 'camelcase-keys' + +export interface EtjanstResponse { + Success: boolean + Error: string | null + Data: any | any[] +} + +export const etjanst = (response: EtjanstResponse): any | any[] => { + if (!response.Success) { + throw new Error(response.Error || '') + } + return camel(response.Data, { deep: true }) +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/index.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/index.ts new file mode 100644 index 000000000..092b94eba --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/index.ts @@ -0,0 +1,12 @@ +export * from './calendar' +export * from './children' +export * from './classmates' +export * from './etjanst' +export * from './menu' +export * from './news' +export * from './notifications' +export * from './schedule' +export * from './schoolContacts' +export * from './teachers' +export * from './timetable' +export * from './user' diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/menu.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/menu.ts new file mode 100644 index 000000000..0cd7b43a9 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/menu.ts @@ -0,0 +1,47 @@ +import { MenuItem, MenuList, toMarkdown } from '../../../../libs/api/lib' +import { etjanst } from './etjanst' + +export const menuItem = ({ title, description }: any): MenuItem => ({ + title, + description: toMarkdown(description), +}) + +export const menu = (data: any): MenuItem[] => etjanst(data).map(menuItem) + +export const menuList = (data: any): MenuItem[] => { + const etjanstData = etjanst(data) + const menuFS = etjanstData as MenuList + + const currentWeek = menuFS.menus.find( + (item) => menuFS.selectedWeek === Number.parseInt(item.week, 10) + ) + + if (!currentWeek) { + return [] + } + + const menuItemsFS = [ + { + title: `Måndag - Vecka ${currentWeek.week}`, + description: toMarkdown(currentWeek.mon), + }, + { + title: `Tisdag - Vecka ${currentWeek.week}`, + description: toMarkdown(currentWeek.tue), + }, + { + title: `Onsdag - Vecka ${currentWeek.week}`, + description: toMarkdown(currentWeek.wed), + }, + { + title: `Torsdag - Vecka ${currentWeek.week}`, + description: toMarkdown(currentWeek.thu), + }, + { + title: `Fredag - Vecka ${currentWeek.week}`, + description: toMarkdown(currentWeek.fri), + }, + ] + + return menuItemsFS +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/news.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/news.ts new file mode 100644 index 000000000..9cd5d3c7c --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/news.ts @@ -0,0 +1,49 @@ +import { NewsItem, parseDate, toMarkdown } from '../../../../libs/api/lib' +import { etjanst } from './etjanst' + +const IMAGE_HOST = + 'https://etjanst.stockholm.se/Vardnadshavare/inloggad2/NewsBanner?url=' + +export const newsItem = ({ + newsId, + header, + preamble, + body, + bannerImageUrl, + publicationDate, + modifiedDate, + authorDisplayName, + altText, +}: any): NewsItem => ({ + header, + published: parseDate(publicationDate) || '', + modified: parseDate(modifiedDate) || '', + id: newsId, + author: authorDisplayName, + intro: preamble.replace(/([!,.])(\w)/gi, '$1 $2'), + imageUrl: bannerImageUrl, + fullImageUrl: `${IMAGE_HOST}${bannerImageUrl}`, + imageAltText: altText, + body: toNonEmptyMarkdownString(body), +}) + +// Fixes https://github.com/kolplattformen/skolplattformen/issues/525 +const toNonEmptyMarkdownString = (str: string): string => { + const res = toMarkdown(str) + if (res?.length === 0) { + return ' ' + } + return res +} + +const newsSort = (item1: NewsItem, item2: NewsItem): number => { + const m1 = item1.modified || item1.published + const m2 = item2.modified || item2.published + return m1 && m2 && m1 < m2 ? 1 : -1 //! changed this +} + +export const news = (data: any): NewsItem[] => + etjanst(data).newsItems.map(newsItem).sort(newsSort) + +export const newsItemDetails = (data: any): NewsItem => + newsItem(etjanst(data).currentNewsItem) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/notifications.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/notifications.ts new file mode 100644 index 000000000..e1d6cd400 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/notifications.ts @@ -0,0 +1,38 @@ +import { parseDate, Notification } from '../../../../libs/api/lib' +import { etjanst } from './etjanst' + +export const notification = ({ + notification: { messageid, dateCreated, dateModified }, + notificationMessage: { + messages: { + message: { + category, + messagetext, + linkbackurl, + messagetype: { type }, + sender: { name }, + }, + }, + }, +}: any): Notification => ({ + id: messageid, + message: messagetext, + sender: name, + url: linkbackurl, + dateCreated: parseDate(dateCreated) || '', + dateModified: parseDate(dateModified) || '', + category, + type, +}) + +const notificationsSort = ( + item1: Notification, + item2: Notification +): number => { + const m1 = item1.dateModified || item1.dateCreated + const m2 = item2.dateModified || item2.dateCreated + return m1 < m2 ? 1 : -1 +} + +export const notifications = (data: any): Notification[] => + etjanst(data).map(notification).sort(notificationsSort) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/schedule.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/schedule.ts new file mode 100644 index 000000000..e73aa1305 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/schedule.ts @@ -0,0 +1,38 @@ +import { parseDate, ScheduleItem } from '../../../../libs/api/lib' +import { etjanst } from './etjanst' + +export const scheduleItem = ({ + title, + description, + location, + longEventDateTime, + longEndDateTime, + isSameDay, + allDayEvent, +}: any): ScheduleItem => ({ + title, + description, + location, + allDayEvent, + startDate: parseDate(longEventDateTime), + endDate: parseDate(longEndDateTime), + oneDayEvent: isSameDay, +}) + +export const schedule = (data: any): ScheduleItem[] => { + try { + const scheduleData = etjanst(data) + const mapped = scheduleData.map(scheduleItem) + return mapped + } catch (e) { + if (e instanceof Error) { + // If this happens the child has no schedule + // It is the same on the official web + // Instead of retrying and spamming errors - lets return en empty array + if (e.message === 'A task was canceled.') { + return new Array() + } + } + throw e + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/schoolContacts.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/schoolContacts.ts new file mode 100644 index 000000000..13d31085d --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/schoolContacts.ts @@ -0,0 +1,21 @@ +import { etjanst } from './etjanst' +import { SchoolContact } from '@skolplattformen/api' + +export const schoolContact = ({ + title, + name, + phone, + email, + schoolName, + className, +}: any): SchoolContact => ({ + title, + name, + phone, + email, + schoolName, + className, +}) + +export const schoolContacts = (data: any): SchoolContact[] => + etjanst(data).map(schoolContact) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/teachers.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/teachers.ts new file mode 100644 index 000000000..a4650f5be --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/teachers.ts @@ -0,0 +1,28 @@ +import { etjanst } from './etjanst' +import { Teacher } from '@skolplattformen/api' + +const abbreviate = (firstname?: string, lastname?: string): string => + `${firstname?.substr(0, 1)}${lastname?.substr(0, 2)}`.toUpperCase() + +export const teacher = ({ + id, + sisId, + firstname, + lastname, + emailaddress, + telwork, + active, + status, +}: any): Teacher => ({ + id, + sisId, + firstname, + lastname, + email: emailaddress, + phoneWork: telwork, + active, + status, + timeTableAbbreviation: abbreviate(firstname, lastname), +}) + +export const teachers = (data: any): Teacher[] => etjanst(data).map(teacher) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/timetable.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/timetable.ts new file mode 100644 index 000000000..3bc59a909 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/timetable.ts @@ -0,0 +1,95 @@ +import { TimetableEntry } from '@skolplattformen/api' +import parse, { Language } from '../../../curriculum/src' +import { DateTime } from 'luxon' + +const calculateDate = ( + year: number, + weekNumber: number, + weekday: number, + time: string +): string => { + const [hours, minutes, seconds] = time.split(':') + return DateTime.local() + .set({ + weekYear: year, + weekNumber, + weekday, + hour: parseInt(hours, 10), + minute: parseInt(minutes, 10), + second: parseInt(seconds, 10), + millisecond: 0, + }) + .toISO() as string +} + +interface TimetableResponseEntry { + guidId: string + texts: string[] + timeStart: string + timeEnd: string + dayOfWeekNumber: number + blockName: string +} +export interface TimetableResponse { + error: string | null + data: { + textList: any[] + boxList: any[] + lineList: any[] + lessonInfo: TimetableResponseEntry[] + } + exception: any + validation: any[] +} + +interface EntryParser { + ( + args: TimetableResponseEntry, + year: number, + week: number, + lang: Language + ): TimetableEntry +} +export const timetableEntry: EntryParser = ( + { + guidId, + texts: [code, teacher, location], + timeStart, + timeEnd, + dayOfWeekNumber, + blockName, + }, + year, + week, + lang +) => ({ + ...parse(code, lang), + id: guidId, + blockName, + dayOfWeek: dayOfWeekNumber, + location, + teacher, + timeEnd, + timeStart, + dateStart: calculateDate(year, week, dayOfWeekNumber, timeStart), + dateEnd: calculateDate(year, week, dayOfWeekNumber, timeEnd), +}) + +export const timetable = ( + response: TimetableResponse, + year: number, + week: number, + lang: Language +) => { + if (response.error) { + throw new Error(response.error) + } + + if (!response.data.lessonInfo) { + throw new Error('Empty lessonInfo received') + } + + return response.data.lessonInfo.map((entry) => + timetableEntry(entry, year, week, lang) + ) +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/user.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/user.ts new file mode 100644 index 000000000..e6de7a58e --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/parse/user.ts @@ -0,0 +1,17 @@ +import { User } from '@skolplattformen/api' + +export const user = ({ + socialSecurityNumber, + isAuthenticated, + userFirstName, + userLastName, + userEmail, + notificationId, +}: any): User => ({ + personalNumber: socialSecurityNumber, + firstName: userFirstName, + lastName: userLastName, + email: userEmail, + isAuthenticated, + notificationId, +}) diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/autoQueue.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/autoQueue.ts new file mode 100644 index 000000000..d81a25955 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/autoQueue.ts @@ -0,0 +1,103 @@ +import { Queue } from './queue' +import { QueueStatus } from './queueStatus' + +export default class AutoQueue extends Queue { + private runningTasks: number + + private maxConcurrentTasks: number + + private isPaused: boolean + + private queueStatus: QueueStatus + + constructor(maxConcurrentTasks = 1) { + super() + this.runningTasks = 0 + this.maxConcurrentTasks = maxConcurrentTasks + this.isPaused = false + this.queueStatus = new QueueStatus() + } + + public enqueue(action: () => Promise, autoDequeue = true): Promise { + return new Promise((resolve, reject) => { + super.enqueue({ action, resolve, reject }) + + if (autoDequeue) { + this.dequeue() + } + }) + } + + public async dequeue() { + if (this.runningTasks >= this.maxConcurrentTasks) { + return false + } + + if (this.isPaused) { + return false + } + + const item = super.dequeue() + + if (!item) { + return false + } + + try { + this.runningTasks += 1 + + const payload = await item.action(this) + + this.decreaseRunningTasks() + item.resolve(payload) + } catch (e) { + this.decreaseRunningTasks() + item.reject(e) + } finally { + this.dequeue() + } + + return true + } + + public pause() { + this.isPaused = true + } + + public async start() { + this.isPaused = false + + while (await this.dequeue()) { + // do nothing + } + } + + public get runningTaskCount() { + return this.runningTasks + } + + public getQueueStatus() { + return this.queueStatus + } + + public getQueueInfo() { + return { + itemsInQueue: this.size, + runningTasks: this.runningTasks, + isPaused: this.isPaused, + } + } + + private decreaseRunningTasks() { + this.runningTasks -= 1 + + if (this.runningTasks <= 0) { + this.runningTasks = 0 + this.queueStatus.emitIdleQueue() + } + + if (this.size === 0) { + this.queueStatus.emitEmptyQueue() + } + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queue.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queue.ts new file mode 100644 index 000000000..1ad7c48c8 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queue.ts @@ -0,0 +1,19 @@ +export class Queue { + private items: any[] + + constructor() { + this.items = [] + } + + enqueue(item: any) { + this.items.push(item) + } + + dequeue() { + return this.items.shift() + } + + get size() { + return this.items.length + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queueFetcher.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queueFetcher.ts new file mode 100644 index 000000000..2b47aa5cf --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queueFetcher.ts @@ -0,0 +1,177 @@ +import AutoQueue from './autoQueue' +import RoundRobinArray from './roundRobinArray' + +export interface QueueEntry { + id: string + queue: AutoQueue +} + +// function delay(time: any) { +// return new Promise(resolve => setTimeout(resolve, time)); +// } + +/** + * Put requests in queues where each childId gets its own queue + * The class takes care of calling the provided changeChildFunc + * before running the queue. + * Why? The external api uses state where the child must be selected + * before any calls to News etc can be done. + * + */ +export default class QueueFetcher { + private queues: RoundRobinArray + + private currentRunningQueue: QueueEntry | undefined + + private changeChildFunc: (childId: string) => Promise + + private lastChildId = '' + + private scheduleTimeout: any + + /** + * Set to true to console.log verbose information + * For debugging mostly + */ + verboseDebug = false + + /** + * Creates a new QueueFetcher + * @param changeChildFunc function that is called to change the current + * selected child on the server + */ + constructor(changeChildFunc: (childId: string) => Promise) { + this.changeChildFunc = changeChildFunc + this.queues = new RoundRobinArray(new Array()) + } + + /** + * Queues a fetch - it will be executed together with other calls that + * has the same id + * @param func function that creates the request to be done. Must be a function + * because a Promise is always created in the running state + * @param id the id (e.g. childId) that is used to group calls together + * @returns a Promise that resolves when the Promise created by the func is resolved + * (i.e. is dequeued and executed) + */ + public async fetch(func: () => Promise, id: string): Promise { + if (!this.queues.array.some((e) => e.id === id)) { + const newQueue = new AutoQueue(10) + this.queues.add({ id, queue: newQueue }) + } + + const queueEntry = this.queues.array.find((e) => e.id === id) + if (queueEntry === undefined) { + throw new Error(`No queue found for id: ${id}`) + } + const promise = queueEntry.queue.enqueue(func, false) + + if (this.scheduleTimeout === undefined || this.scheduleTimeout === null) { + this.scheduleTimeout = setTimeout(async () => this.schedule(), 0) + } + + return promise + } + + public get Queues() { + return this.queues.array + } + + /** + * Method to schedule next queue + * Public because we need it from unit-tests + */ + async schedule() { + // Debug print info for all queues + this.queues.array.forEach(({ id: childId, queue }) => + this.debug('Schedule: ', childId, '=>', queue.getQueueInfo()) + ) + + if (this.queues.size === 0) { + this.debug('No queues created yet') + return + } + + if (this.currentRunningQueue === undefined || this.queues.size === 1) { + this.debug('First run schedule or only one queue') + const firstQueue = this.queues.first + await this.runNext(firstQueue) + return + } + + const nextToRun = this.findNextQueueToRun() + + if (nextToRun === undefined) { + this.debug('Nothing to do right now') + this.scheduleTimeout = null + return + } + + if (nextToRun.id === this.currentRunningQueue.id) { + this.debug('Same queue as before was scheduled') + this.runNext(nextToRun) + return + } + + const { id: queueToPauseId, queue: queueToPause } = this.currentRunningQueue + this.debug('Queue to pause', queueToPauseId, queueToPause.getQueueInfo()) + + queueToPause.pause() + + if (queueToPause.runningTaskCount === 0) { + await this.runNext(nextToRun) + return + } + + this.debug('Queue is not idle, waiting for it ...') + + queueToPause.getQueueStatus().once('IDLE', async () => { + this.debug('Got IDLE from queue') + await this.runNext(nextToRun) + }) + } + + private async runNext(queueToRun: QueueEntry) { + const { id: childId, queue } = queueToRun + this.debug('About to run', childId, queue.getQueueInfo()) + + if (this.lastChildId === childId) { + this.debug('Child already selected, skipping select call') + } else { + this.debug('Initiating change child') + await this.changeChildFunc(childId) + this.lastChildId = childId + this.debug('Change child done') + } + + this.currentRunningQueue = queueToRun + + this.setupTimerForSchedule() + await queue.start() + } + + private setupTimerForSchedule() { + this.scheduleTimeout = setTimeout(async () => this.schedule(), 3000) + } + + private findNextQueueToRun(): QueueEntry | undefined { + // Iterate all queues and look for next queue with work to do + for (let i = 0; i < this.queues.size; i += 1) { + const { id: childId, queue } = this.queues.next() + + // If queue has items to execute, return it + if (queue.size > 0 || queue.runningTaskCount > 0) { + return { id: childId, queue } + } + } + + // Nothing more to do + return undefined + } + + private debug(message: any, ...args: any[]) { + if (this.verboseDebug) { + console.debug(message, ...args) + } + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queueStatus.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queueStatus.ts new file mode 100644 index 000000000..ae61871fe --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/queueStatus.ts @@ -0,0 +1,11 @@ +import { EventEmitter } from 'events' + +export class QueueStatus extends EventEmitter { + public emitEmptyQueue() { + this.emit('EMPTY') + } + + public emitIdleQueue() { + this.emit('IDLE') + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/roundRobinArray.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/roundRobinArray.ts new file mode 100644 index 000000000..963944a0e --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queue/roundRobinArray.ts @@ -0,0 +1,34 @@ +export default class RoundRobinArray { + index: any + + array: T[] + + constructor(array: Array, index?: number | undefined) { + this.index = index || 0 + + if (array === undefined || array === null) { + this.array = new Array() + } else if (!Array.isArray(array)) { + throw new Error('Expecting argument to RoundRound to be an Array') + } + + this.array = array + } + + next() { + this.index = (this.index + 1) % this.array.length + return this.array[this.index] + } + + add(item: T) { + this.array.push(item) + } + + get first() { + return this.array[0] + } + + get size() { + return this.array.length + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queueFetcherWrapper.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queueFetcherWrapper.ts new file mode 100644 index 000000000..fb9eec606 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/queueFetcherWrapper.ts @@ -0,0 +1,24 @@ +import QueueFetcher from './queue/queueFetcher' +import { Fetcher, RequestInit, Response } from '@skolplattformen/api' + +export default function queueFetcherWrapper( + fetch: Fetcher, + changeChildFunc: (childId: string) => Promise +): Fetcher { + const queue = new QueueFetcher(changeChildFunc) + queue.verboseDebug = false + + return async ( + name: string, + url: string, + init: RequestInit = { headers: {} }, + childId?: string + ): Promise => { + if (childId === undefined) { + return fetch(name, url, init) + } + + const p = queue.fetch(() => fetch(name, url, init), childId) + return p + } +} diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/routes.ts b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/routes.ts new file mode 100644 index 000000000..480fd5985 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/lib/routes.ts @@ -0,0 +1,106 @@ +// BankId +export const login = (personalNumber?: string) => { + const baseUrl = + 'https://login003.stockholm.se/NECSadcmbid/authenticate/NECSadcmbid?TYPE=33554433&REALMOID=06-42f40edd-0c5b-4dbc-b714-1be1e907f2de&GUID=1&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2fmbid%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvaGVt' + const optionalPersonalNumber = + personalNumber === undefined ? '' : `&personalNumber=${personalNumber}` + return `${baseUrl}&initialize=bankid${optionalPersonalNumber}&_=${Date.now()}` +} + +export const loginStatus = (order: string) => + `https://login003.stockholm.se/NECSadcmbid/authenticate/NECSadcmbid?TYPE=33554433&REALMOID=06-42f40edd-0c5b-4dbc-b714-1be1e907f2de&GUID=1&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2fmbid%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvaGVt&verifyorder=${order}&_=${Date.now()}` +export const loginCookie = + 'https://login003.stockholm.se/NECSadcmbid/authenticate/SiteMinderAuthADC?TYPE=33554433&REALMOID=06-42f40edd-0c5b-4dbc-b714-1be1e907f2de&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2fmbid%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvR2V0Q2hpbGRyZW4%3d' + +// Freja +export const frejaLogin = + 'https://login003.stockholm.se/NECSadcfreja/authenticate/NECSadcfreja?action=init&return_url=https%3A%2F%2Flogin003.stockholm.se%2FNECSadcfreja%2Fauthenticate%2FNECSadcfreja' +export const frejaLoginStatus = + 'https://login003.stockholm.se/NECSadcfreja/authenticate/NECSadcfreja?TYPE=33554433&REALMOID=06-89cf916c-9764-45fa-8690-eaf3fe9282bc&GUID=1&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2ffreja%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvaGVt&action=checkstatus' +export const frejaReturnUrl = + 'https://login003.stockholm.se/NECSadcfreja/authenticate/NECSadcfreja?TYPE=33554433&REALMOID=06-89cf916c-9764-45fa-8690-eaf3fe9282bc&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2ffreja%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvT3ZlcnNpa3Q%3d' +export const frejaLoginCookie = + 'https://login003.stockholm.se/NECSadcfreja/authenticate/SiteMinderAuthADCFREJA?TYPE=33554433&REALMOID=06-89cf916c-9764-45fa-8690-eaf3fe9282bc&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=IfNE0iMOtzq2TcxFADHylR6rkmFtwzoxRKh5nRMO9NBqIxHrc38jFyt56FASdxk1&TARGET=-SM-HTTPS%3a%2f%2flogin001%2estockholm%2ese%2fNECSadc%2ffreja%2fb64startpage%2ejsp%3fstartpage%3daHR0cHM6Ly9ldGphbnN0LnN0b2NraG9sbS5zZS92YXJkbmFkc2hhdmFyZS9pbmxvZ2dhZDIvT3ZlcnNpa3Q%3d' + +const urlLoggedIn = 'https://etjanst.stockholm.se/vardnadshavare/inloggad2' + +export const children = `${urlLoggedIn}/GetChildren` + +export const calendar = (childId: string) => + `${urlLoggedIn}/Calender/GetSchoolCalender?childId=${childId}&rowLimit=50` + +export const classmates = (childId: string) => + `${urlLoggedIn}/contacts/GetStudentsByClass?studentId=${childId}` + +export const teachers = (childId: string, schoolForm: string) => + `${urlLoggedIn}/contacts/GetTeachersByStudent?studentId=${childId}&schoolForm=${schoolForm}` + +export const schoolContacts = (childId: string, schoolId: string) => + `${urlLoggedIn}/contacts/GetSchoolContacts?schoolId=${schoolId}&studentId=${childId}&schoolForm=Klasslista` + +export const user = + 'https://etjanst.stockholm.se/vardnadshavare/base/getuserdata' + +export const news = (childId: string) => + `${urlLoggedIn}/News/GetNewsArchive?bannerImageLimit=5000&childId=${childId}` + +export const newsDetails = (childId: string, newsId: string) => + `${urlLoggedIn}/News/GetNewsArticle?newsItemId=${newsId}&childId=${childId}` + +export const image = (url: string) => `${urlLoggedIn}/NewsBanner?url=${url}` + +export const notifications = (childId: string) => + `${urlLoggedIn}/notifications/getnotifications?childId=${childId}` + +export const menuRss = (childId: string) => + `${urlLoggedIn}/Matsedel/GetMatsedelRSS?childId=${childId}` + +export const menuList = (childId: string) => + `${urlLoggedIn}/Matsedel/GetMatsedelList?childId=${childId}` + +export const menuChoice = (childId: string) => + `${urlLoggedIn}/Matsedel/GetMatsedelChoice?childId=${childId}` + +export const schedule = (childId: string, fromDate: string, endDate: string) => + `${urlLoggedIn}/Calender/GetSchema?childId=${childId}&startDate=${fromDate}&endDate=${endDate}` + +export const cdn = 'https://etjanst.stockholm.se/vardnadshavare/base/cdn' + +export const auth = 'https://etjanst.stockholm.se/vardnadshavare/base/auth' + +export const startBundle = + 'https://etjanst.stockholm.se/vardnadshavare/bundles/start' + +export const hemPage = + 'https://etjanst.stockholm.se/vardnadshavare/inloggad2/hem' + +export const navigationControllerScript = + 'https://etjanst.stockholm.se/vardnadshavare/bundles/navigationController' + +export const baseEtjanst = 'https://etjanst.stockholm.se' + +export const childcontrollerScript = `https://etjanst.stockholm.se/vardnadshavare/bundles/childcontroller?v=${Date.now()}` + +export const createItemConfig = + 'https://raw.githubusercontent.com/kolplattformen/embedded-api/main/config.json' + +// Skola24 +export const ssoRequestUrl = (targetSystem: string) => + `https://fnsservicesso1.stockholm.se/sso-ng/saml-2.0/authenticate?customer=https://login001.stockholm.se&targetsystem=${targetSystem}` + +export const ssoResponseUrl = + 'https://login001.stockholm.se/affwebservices/public/saml2sso' +export const samlResponseUrl = + 'https://fnsservicesso1.stockholm.se/sso-ng/saml-2.0/response' + +export const timetables = + 'https://fns.stockholm.se/ng/api/services/skola24/get/personal/timetables' +export const renderKey = + 'https://fns.stockholm.se/ng/api/get/timetable/render/key' +export const timetable = 'https://fns.stockholm.se/ng/api/render/timetable' + +export const topologyConfigUrl = + 'https://fantomenkrypto.vercel.app/api/getConfig' + +export const selectChild = + 'https://etjanst.stockholm.se/vardnadshavare/inloggad2/SelectChild' diff --git a/apps/skolplattformen-app-new/libs/api-skolplattformen/run.js b/apps/skolplattformen-app-new/libs/api-skolplattformen/run.js new file mode 100644 index 000000000..230ffe338 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api-skolplattformen/run.js @@ -0,0 +1,160 @@ +function requestLogger(httpModule) { + var original = httpModule.request + httpModule.request = function (options, callback) { + console.log('-----------------------------------------------') + console.log( + options.href || options.proto + '://' + options.host + options.path, + options.method + ) + console.log(options.headers) + console.log('-----------------------------------------------') + return original(options, callback) + } +} + +requestLogger(require('http')) +requestLogger(require('https')) + +const { DateTime } = require('luxon') +const nodeFetch = require('node-fetch') +const { CookieJar } = require('tough-cookie') +const fetchCookie = require('fetch-cookie/node-fetch') +const { writeFile } = require('fs/promises') +const path = require('path') +const fs = require('fs') +const { inspect } = require('util') + +const init = require('./dist/api-skolplattformen-app/lib').default + +const [, , personalNumber] = process.argv + +if (!personalNumber) { + console.error( + 'You must pass in a valid personal number, eg `node run 197001011111`' + ) + process.exit(1) +} + +function ensureDirectoryExistence(filePath) { + var dirname = path.dirname(filePath) + if (fs.existsSync(dirname)) { + return true + } + ensureDirectoryExistence(dirname) + fs.mkdirSync(dirname) +} + +const record = async (info, data) => { + const name = info.error ? `${info.name}_error` : info.name + const filename = `./record/${name}.json` + ensureDirectoryExistence(filename) + const content = { + url: info.url, + headers: info.headers, + status: info.status, + statusText: info.statusText, + } + if (data) { + switch (info.type) { + case 'json': + content.json = data + break + case 'text': + content.text = data + break + case 'blob': { + const buffer = await data.arrayBuffer() + // eslint-disable-next-line no-undef + content.blob = Buffer.from(buffer).toString('base64') + break + } + } + } else if (info.error) { + const { message, stack } = info.error + content.error = { + message, + stack, + } + } + await writeFile(filename, JSON.stringify(content, null, 2)) +} + +async function run() { + const cookieJar = new CookieJar() + const fetch = fetchCookie(nodeFetch, cookieJar) + + try { + const api = init(fetch, cookieJar, { record }) + const status = await api.login(personalNumber) + status.on('PENDING', () => console.log('PENDING')) + status.on('USER_SIGN', () => console.log('USER_SIGN')) + status.on('ERROR', () => console.error('ERROR')) + status.on('OK', () => console.log('OK')) + status.on('CANCELLED', () => { + console.log('User cancelled login') + process.exit(0) + }) + + api.on('login', async () => { + console.log('Logged in') + + // console.log('user') + // const user = await api.getUser() + // console.log(user) + + console.log('children') + const children = await api.getChildren() + console.log(children) + + console.log('calendar') + const calendar = await api.getCalendar(children[0]) + console.log(calendar) + /* + console.log('classmates') + const classmates = await api.getClassmates(children[0]) + console.log(classmates) + + console.log('schedule') + const schedule = await api.getSchedule(children[0], DateTime.local(), DateTime.local().plus({ week: 1 })) + console.log(schedule) + + console.log('news') + const news = await api.getNews(children[0]) +*/ + /* console.log('news details') + const newsItems = await Promise.all( + news.map((newsItem) => + api.getNewsDetails(children[0], newsItem) + .catch((err) => { console.error(newsItem.id, err) }) + ) + ) + console.log(newsItems) */ + + /* console.log('menu') + const menu = await api.getMenu(children[0]) + console.log(menu) */ + + // console.log('notifications') + // const notifications = await api.getNotifications(children[0]) + // console.log(notifications) + + const skola24children = await api.getSkola24Children() + console.log(skola24children) + + console.log('timetable') + const timetable = await api.getTimetable(skola24children[0], 15, 2021) + console.log(inspect(timetable, false, 1000, true)) + + await api.logout() + }) + + api.on('logout', () => { + console.log('Logged out') + process.exit(0) + }) + } catch (err) { + console.error(err) + } +} + +run() diff --git a/apps/skolplattformen-app-new/libs/api/lib/URLSearchParams.ts b/apps/skolplattformen-app-new/libs/api/lib/URLSearchParams.ts new file mode 100644 index 000000000..3258c9bf1 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/URLSearchParams.ts @@ -0,0 +1,152 @@ +export class URLSearchParams { + private dict: { [key: string]: string[] } = {} + + constructor(search: string | string[] | any | URLSearchParams = '') { + if (search instanceof URLSearchParams) { + this.dict = this.parseToDict(search.toString()) + } else { + this.dict = this.parseToDict(search) + } + } + + /** + * Appends a specified key/value pair as a new search parameter + */ + public append(name: string, value: string): void { + this.appendTo(this.dict, name, value) + } + + /** + * Deletes this give search parameter, and its associated value, from the list of all search parameters + */ + public delete(name: string): void { + delete this.dict[name] + } + + /** + * Returns the first value associated to the given search parameter + */ + get(name: string): string | null { + return name in this.dict ? this.dict[name][0] : null + } + + /** + * Returns all the values association with a given parameter + */ + getAll(name: string): string[] { + return name in this.dict ? this.dict[name].slice(0) : [] + } + + /** + * Test if the search parameter exists + */ + has(name: string): boolean { + return name in this.dict + } + + /** + * Sets the value associated to a given search parameter to + * the given value. If there were several values, delete the others. + */ + set(name: string, value: string): void { + this.dict[name] = [value] + } + + /** + * Returns a string containing a query string suitable for use in a URL + */ + toString(): string { + return Object.entries(this.dict) + .map(([key, value]) => `${key}=${this.encode(value)}`) + .join('&') + } + + /** + * + */ + parseToDict(search: string | string[] | any): any { + const dict = {} + + if (typeof search === 'object') { + // if 'search' is an array, treat it as a sequence + if (Array.isArray(search)) { + for (let i = 0; i < search.length; i++) { + const item = search[i] + if (Array.isArray(item) && item.length === 2) { + this.appendTo(dict, item[0], item[1]) + } else { + throw new TypeError( + "Failed to construct 'URLSearchParams': Sequence initalizer must only contain pair elements" + ) + } + } + } else { + Object.entries(search).forEach(([key, value]) => + this.appendTo(dict, key, value) + ) + } + } else { + // remove 1st ? + if (search.indexOf('?') === 0) { + search = search.slice(1) + } + + const pairs = search.split('&') + for (let j = 0; j < pairs.length; j++) { + const value = pairs[j] + const index = value.indexOf('=') + if (index > -1) { + this.appendTo( + dict, + this.decode(value.slice(0, index)), + this.decode(value.slice(index + 1)) + ) + } else if (value) { + this.appendTo(dict, this.decode(value), '') + } + } + } + + return dict + } + + appendTo(dict: any, name: string, value: string | (() => void) | any): void { + const val = + typeof value === 'string' + ? value + : value !== null && + value !== undefined && + typeof value.toString === 'function' + ? value.toString() + : JSON.stringify(value) + + if (name in dict) { + dict[name].push(value) + } else { + dict[name] = [val] + } + } + + decode(str: string): string { + return str + .replace(/[ +]/g, '%20') + .replace(/(%[a-f0-9]{2})+/gi, (match) => decodeURIComponent(match)) + } + + encode(str: string[]): string { + const replace: { [key: string]: string } = { + '!': '%21', + "'": '%27', + '(': '%28', + ')': '%29', + '~': '%7E', + '%20': '+', + '%00': '\x00', + } + return encodeURIComponent(str.join(',')).replace( + // eslint-disable-next-line no-useless-escape + /[!'\(\)~]|%20|%00/g, + (match) => replace[match] || '' + ) + } +} diff --git a/apps/skolplattformen-app-new/libs/api/lib/__tests__/cookies.test.ts b/apps/skolplattformen-app-new/libs/api/lib/__tests__/cookies.test.ts new file mode 100644 index 000000000..d37af8edf --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/__tests__/cookies.test.ts @@ -0,0 +1,331 @@ +import { + deserialize, + serialize, + wrapToughCookie, + wrapReactNativeCookieManager, +} from '../cookies' +import { Cookie, CookieManager } from '../types' +import { CookieJar } from 'tough-cookie' +import RNCookieManager from '@react-native-cookies/cookies' + +describe('CookieManager', () => { + describe('deserialize', () => { + it('deserializes cookies with only name and value', () => { + const cookieStr = 'foo=bar' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + it('deserializes cookies with Expires', () => { + const cookieStr = 'foo=bar; Expires=Tue, 09 Mar 2021 08:27:48 GMT' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + expires: 'Tue, 09 Mar 2021 08:27:48 GMT', + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + it('deserializes cookies with Domain', () => { + const cookieStr = 'foo=bar; Domain=.stockholm.se' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + domain: '.stockholm.se', + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + it('deserializes cookies with Path', () => { + const cookieStr = 'foo=bar; Path=/' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + path: '/', + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + it('deserializes cookies with Secure', () => { + const cookieStr = 'foo=bar; Secure' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + secure: true, + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + it('deserializes cookies with HttpOnly', () => { + const cookieStr = 'foo=bar; HttpOnly' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + httpOnly: true, + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + it('deserializes cookies with HTTPOnly', () => { + const cookieStr = 'foo=bar; HTTPOnly' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + httpOnly: true, + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + it('deserializes cookies with all properties', () => { + const cookieStr = + 'foo=bar; Expires=Tue, 09 Mar 2021 08:27:48 GMT; Domain=.stockholm.se; Path=/; Secure; HTTPOnly' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + expires: 'Tue, 09 Mar 2021 08:27:48 GMT', + domain: '.stockholm.se', + path: '/', + secure: true, + httpOnly: true, + } + + expect(deserialize(cookieStr)).toEqual(cookie) + }) + }) + describe('serialize', () => { + it('serializes cookies with only name and value', () => { + const cookieStr = 'foo=bar' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + } + + expect(serialize(cookie)).toEqual(cookieStr) + }) + it('serializes cookies with Expires', () => { + const cookieStr = 'foo=bar; Expires=Tue, 09 Mar 2021 08:27:48 GMT' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + expires: 'Tue, 09 Mar 2021 08:27:48 GMT', + } + + expect(serialize(cookie)).toEqual(cookieStr) + }) + it('serializes cookies with Domain', () => { + const cookieStr = 'foo=bar; Domain=.stockholm.se' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + domain: '.stockholm.se', + } + + expect(serialize(cookie)).toEqual(cookieStr) + }) + it('serializes cookies with Path', () => { + const cookieStr = 'foo=bar; Path=/' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + path: '/', + } + + expect(serialize(cookie)).toEqual(cookieStr) + }) + it('serializes cookies with Secure', () => { + const cookieStr = 'foo=bar; Secure' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + secure: true, + } + + expect(serialize(cookie)).toEqual(cookieStr) + }) + it('serializes cookies with HttpOnly', () => { + const cookieStr = 'foo=bar; HttpOnly' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + httpOnly: true, + } + + expect(serialize(cookie)).toEqual(cookieStr) + }) + it('serializes cookies with all properties', () => { + const cookieStr = + 'foo=bar; Expires=Tue, 09 Mar 2021 08:27:48 GMT; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + expires: 'Tue, 09 Mar 2021 08:27:48 GMT', + domain: '.stockholm.se', + path: '/', + secure: true, + httpOnly: true, + } + + expect(serialize(cookie)).toEqual(cookieStr) + }) + }) + describe('wrap', () => { + describe('tough cookie', () => { + let jar: CookieJar + let manager: CookieManager + beforeEach(() => { + jar = new CookieJar() + manager = wrapToughCookie(jar) + }) + it('handles getCookieString', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + + await jar.setCookie(cookieStr, url) + const storedCookies = await manager.getCookieString( + 'https://foo.stockholm.se/bar/baz' + ) + expect(storedCookies).toEqual('foo=bar') + }) + it('handles getCookies', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + domain: 'stockholm.se', + path: '/', + secure: true, + httpOnly: true, + } + + await jar.setCookie(cookieStr, url) + const storedCookies = await manager.getCookies( + 'https://foo.stockholm.se/bar/baz' + ) + + expect(storedCookies).toHaveLength(1) + expect(storedCookies[0]).toEqual(cookie) + }) + it('handles setCookie', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + domain: 'stockholm.se', + path: '/', + secure: true, + httpOnly: true, + } + + await manager.setCookie(cookie, url) + + const cookies = await jar.getCookieString(url) + expect(cookies).toEqual('foo=bar') + }) + it('handles setCookieString', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + + await manager.setCookieString(cookieStr, url) + + const cookies = await jar.getCookieString(url) + expect(cookies).toEqual('foo=bar') + }) + it('handles clearAll', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + + await manager.setCookieString(cookieStr, url) + await manager.clearAll() + const cookies = await jar.getCookieString(url) + + expect(cookies).toEqual('') + }) + }) + describe('@react-native-cookies/cookies', () => { + let manager: CookieManager + beforeEach(async () => { + await RNCookieManager.clearAll() + manager = wrapReactNativeCookieManager(RNCookieManager) + }) + it('handles getCookieString', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + + await RNCookieManager.setFromResponse(url, cookieStr) + const storedCookies = await manager.getCookieString( + 'https://foo.stockholm.se/bar/baz' + ) + expect(storedCookies).toEqual('foo=bar') + }) + it('handles getCookies', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + domain: 'stockholm.se', + path: '/', + secure: true, + httpOnly: true, + } + + await RNCookieManager.setFromResponse(url, cookieStr) + const storedCookies = await manager.getCookies( + 'https://foo.stockholm.se/bar/baz' + ) + + expect(storedCookies).toHaveLength(1) + expect(storedCookies[0]).toEqual(cookie) + }) + it('handles setCookie', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookie: Cookie = { + name: 'foo', + value: 'bar', + domain: 'stockholm.se', + path: '/', + secure: true, + httpOnly: true, + } + + await manager.setCookie(cookie, url) + const cookies = await RNCookieManager.get(url) + + expect(cookies).toHaveProperty('foo') + expect(cookies.foo.value).toEqual('bar') + }) + it('handles setCookieString', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + + await manager.setCookieString(cookieStr, url) + const cookies = await RNCookieManager.get(url) + + expect(cookies).toHaveProperty('foo') + expect(cookies.foo.value).toEqual('bar') + }) + it('handles clearAll', async () => { + const url = 'https://etjanster.stockholm.se/' + const cookieStr = + 'foo=bar; Domain=.stockholm.se; Path=/; Secure; HttpOnly' + + await manager.setCookieString(cookieStr, url) + await manager.clearAll() + const cookies = await RNCookieManager.get(url) + + expect(cookies).toEqual({}) + }) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api/lib/__tests__/fetcher.test.ts b/apps/skolplattformen-app-new/libs/api/lib/__tests__/fetcher.test.ts new file mode 100644 index 000000000..2c437742e --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/__tests__/fetcher.test.ts @@ -0,0 +1,84 @@ +import wrap, { CallInfo, Fetcher, Recorder } from '../fetcher' +import { Fetch, Headers, Response } from '../types' + +const Blob = require('node-blob') +Blob.prototype.arrayBuffer = async function () { + return this.buffer.buffer +} + +describe('fetcher', () => { + let fetch: jest.Mocked + let response: jest.Mocked + let headers: jest.Mocked + let fetcher: Fetcher + beforeEach(() => { + headers = { get: jest.fn() } + response = { + ok: true, + status: 200, + statusText: 'ok', + json: jest.fn(), + text: jest.fn(), + headers, + } + fetch = jest.fn().mockResolvedValue(response) + fetcher = wrap(fetch) + }) + it('calls fetch', async () => { + await fetcher('foo', '/') + expect(fetch).toHaveBeenCalledWith('/', expect.any(Object)) + }) + it('json returns the result', async () => { + const data = { foo: 'bar' } + response.json.mockResolvedValue(data) + + const res = await fetcher('foo', '/') + const result = await res.json() + + expect(result).toEqual(data) + }) + it('text returns the result', async () => { + const data = 'Hello World!' + response.text.mockResolvedValue(data) + + const res = await fetcher('foo', '/') + const result = await res.text() + + expect(result).toEqual(data) + }) + describe('record', () => { + let recorder: Recorder + let expectedInfo: CallInfo + beforeEach(() => { + recorder = jest.fn().mockResolvedValue(undefined) + fetcher = wrap(fetch, { record: recorder }) + expectedInfo = { + name: 'foo', + type: '', + url: '/', + headers: expect.any(Object), + status: 200, + statusText: 'ok', + } + }) + it('records with the correct parameters for json', async () => { + response.json.mockResolvedValue({}) + + await (await fetcher('foo', '/')).json() + + expectedInfo.type = 'json' + const expectedData = {} + expect(recorder).toHaveBeenCalledWith(expectedInfo, expectedData) + }) + it('records with the correct parameters for text', async () => { + response.text.mockResolvedValue('Hello') + + await (await fetcher('foo', '/')).text() + + expectedInfo.type = 'text' + + const expectedData = 'Hello' + expect(recorder).toHaveBeenCalledWith(expectedInfo, expectedData) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api/lib/__tests__/parseHtml.test.ts b/apps/skolplattformen-app-new/libs/api/lib/__tests__/parseHtml.test.ts new file mode 100644 index 000000000..7d439e42a --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/__tests__/parseHtml.test.ts @@ -0,0 +1,141 @@ +import { clean, toMarkdown } from '../parseHtml' + +describe('parseHtml', () => { + describe('clean', () => { + it('cleans tag content', () => { + const html = ` +
+ Hello + World +  !  +
` + + const expected = ` +
+ Hello + World + ! +
` + + expect(clean(html)).toEqual(expected) + }) + it('handles missing html', () => { + expect(() => clean()).not.toThrow() + }) + it('handles links with spaces', () => { + const html = ` + ` + const expected = ` +
+ Hello + Hello +
` + + expect(clean(html)).toEqual(expected) + }) + it('handles breaks in ', () => { + const html = 'Uppdatering 2021-02-08
' + const expected = 'Uppdatering 2021-02-08' + + expect(clean(html)).toEqual(expected) + }) + }) + describe('toMarkdown', () => { + it('turns html into Markdown', () => { + const html = `
+

Hello

+ World +
    +
  • Foo
  • +
+ link + + + + + + + + + + + +
left 1right 1
left 2right 2
+
` + const expected = `# Hello +**World** +- Foo + +[link](#) + +|left 1|right 1| +|--------|--------| +|left 2|right 2|` + + expect(toMarkdown(html)).toEqual(expected) + }) + it('handles real data', () => { + const html = + '\u003cdiv data-sp-rte=""\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eHej,\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eNu är det dags för vattenballongkrig \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e12/2-21 till om med tisdag 16/2-21.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eAlla knep är tillåtna. \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cb\u003eDet blir kul.\u003c/b\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eKolla in Reddit\u0026#58; \u003ca href="https\u0026#58;//reddit.com/water-balloons/where-to-buy/" data-cke-saved-href="https\u0026#58;//reddit.com/water-balloons/where-to-buy/"\u003ehttps\u0026#58;//reddit.com/water-balloons/where-to-buy/\u003c/a\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e...och här\u0026#58; \u003ca href="https\u0026#58;//reddit.com/splash-wars/" data-cke-saved-href="https\u0026#58;//reddit.com/splash-wars/"\u003ehttps\u0026#58;//reddit.com/splash-wars/\u003c/a\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003ch2\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eOm att vara hemma vid symtom\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eÄven HackerNews är bra.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003ca href="https\u0026#58;//wnews.ycombinator.com/" data-cke-saved-href="https\u0026#58;//wnews.ycombinator.com/"\u003ehttps\u0026#58;//wnews.ycombinator.com/\u003c/a\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eVi fortsätter också att\u0026#58;\u003c/span\u003e\u003c/span\u003e\u0026#160;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cul\u003e\u003cli style="margin-left\u0026#58;32px;"\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003ehålla avstånd.\u003c/span\u003e\u003c/span\u003e\u0026#160;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style="margin-left\u0026#58;32px;"\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eha flera digitala möten.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style="margin-left\u0026#58;32px;"\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003etvätta händerna.\u003c/span\u003e\u003c/span\u003e\u0026#160;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style="margin-left\u0026#58;32px;"\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eundvika kollektivtrafik om det är möjligt.\u003c/span\u003e\u003c/span\u003e\u0026#160;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cul\u003e\u003cli style="margin-left\u0026#58;32px;"\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003estanna hemma även när man bara känner sig lite sjuk.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style="margin-left\u0026#58;32px;"\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003evädra ofta\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eTa hand om er!\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cb\u003eHa kul tillsammans, på avstånd.\u003c/b\u003e\u0026#160; \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eStort tack för ert samarbete! \u0026#160;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eVänligen, \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003erektorfnamn rektorenamn, rektor\u0026#160; \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cb\u003eVid frågor, kontakta oss gärna\u0026#58; \u003c/b\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cb\u003e\u003cspan\u003eSkolledning\u003c/span\u003e\u003c/b\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003erektorfnamn rektorenamn rektor\u0026#58; \u003c/span\u003e\u003ca href="mailto\u0026#58;rektorfnamn.rektorenamn@edu.stockholm.se" data-cke-saved-href="mailto\u0026#58;rektorfnamn.rektorenamn@edu.stockholm.se"\u003e\u003cspan\u003erektorfnamn.rektorenamn@edu.stockholm.se\u003c/span\u003e\u003c/a\u003e \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003ebrektorfnamn brektorenamn, bitr. rektor\u0026#58; \u003c/span\u003e\u003ca href="mailto\u0026#58;brektorfnamn.u.brektorenamn@edu.stockholm.se" data-cke-saved-href="mailto\u0026#58;brektorfnamn.u.brektorenamn@edu.stockholm.se"\u003e\u003cspan\u003ebrektorfnamn.u.brektorenamn@edu.stockholm.se\u003c/span\u003e\u003c/a\u003e \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eb2rektorfnamn b2rektorenamn bitr. rektor\u0026#58; \u003c/span\u003e\u003ca href="mailto\u0026#58;b2rektorfnamn.b2rektorenamn@edu.stockholm.se" data-cke-saved-href="mailto\u0026#58;b2rektorfnamn.b2rektorenamn@edu.stockholm.se"\u003e\u003cspan\u003eb2rektorfnamn.b2rektorenamn@edu.stockholm.se\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cb\u003e\u003cspan\u003eSkolhälsan\u003c/span\u003e\u003c/b\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eb2rektorfnamn skolskstenamn skolsköterska\u0026#58; \u003c/span\u003e\u003ca href="mailto\u0026#58;b2rektorfnamn.skolskstenamn@edu.stockholm.se" data-cke-saved-href="mailto\u0026#58;b2rektorfnamn.skolskstenamn@edu.stockholm.se"\u003e\u003cspan\u003eb2rektorfnamn.skolskstenamn@edu.stockholm.se\u003c/span\u003e\u003c/a\u003e \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003cspan\u003e\u003cspan\u003eStort tack för ert samarbete!\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cdiv data-sp-rte=""\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003c/div\u003e' + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const nbsp = String.fromCharCode(160) + const expected = `Hej, + +Nu är det dags för vattenballongkrig 12/2-21 till om med tisdag 16/2-21. + +Alla knep är tillåtna. + +**Det blir kul.** + +Kolla in Reddit: [https://reddit.com/water-balloons/where-to-buy/](https://reddit.com/water-balloons/where-to-buy/) + +...och här: [https://reddit.com/splash-wars/](https://reddit.com/splash-wars/) +## Om att vara hemma vid symtom + +Även HackerNews är bra. + +[https://wnews.ycombinator.com/](https://wnews.ycombinator.com/) + +Vi fortsätter också att: + +- hålla avstånd. +- ha flera digitala möten. +- tvätta händerna. +- undvika kollektivtrafik om det är möjligt. + +- stanna hemma även när man bara känner sig lite sjuk. +- vädra ofta + +Ta hand om er! + +**Ha kul tillsammans, på avstånd.** + +Stort tack för ert samarbete! + +Vänligen, + +rektorfnamn rektorenamn, rektor + +**Vid frågor, kontakta oss gärna:** + +**Skolledning** + +rektorfnamn rektorenamn rektor: [rektorfnamn.rektorenamn@edu.stockholm.se](mailto:rektorfnamn.rektorenamn@edu.stockholm.se) + +brektorfnamn brektorenamn, bitr. rektor: [brektorfnamn.u.brektorenamn@edu.stockholm.se](mailto:brektorfnamn.u.brektorenamn@edu.stockholm.se) + +b2rektorfnamn b2rektorenamn bitr. rektor: [b2rektorfnamn.b2rektorenamn@edu.stockholm.se](mailto:b2rektorfnamn.b2rektorenamn@edu.stockholm.se) + +**Skolhälsan** + +b2rektorfnamn skolskstenamn skolsköterska: [b2rektorfnamn.skolskstenamn@edu.stockholm.se](mailto:b2rektorfnamn.skolskstenamn@edu.stockholm.se) + +Stort tack för ert samarbete!` + + expect(toMarkdown(html)).toEqual(expected) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/api/lib/api.ts b/apps/skolplattformen-app-new/libs/api/lib/api.ts new file mode 100644 index 000000000..077f445b2 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/api.ts @@ -0,0 +1,51 @@ +import { Language } from '../../curriculum/src' +import { EventEmitter } from 'events' +import { DateTime } from 'luxon' +import { LoginStatusChecker, FrejaLoginStatusChecker } from './loginStatus' +import { + CalendarItem, + Classmate, + MenuItem, + NewsItem, + Notification, + User, + Skola24Child, + EtjanstChild, + TimetableEntry, + ScheduleItem, + SchoolContact, + Teacher, +} from './types' + +export interface Api extends EventEmitter { + isFake: boolean + isLoggedIn: boolean + getPersonalNumber(): string | undefined + login(personalNumber?: string): Promise + loginFreja(): Promise + setSessionCookie(sessionCookie: string): Promise + getSessionHeaders(url: string): Promise<{ [index: string]: string }> + getUser(): Promise + getChildren(): Promise + getCalendar(child: EtjanstChild): Promise + getClassmates(child: EtjanstChild): Promise + getNews(child: EtjanstChild): Promise + getNewsDetails(child: EtjanstChild, item: NewsItem): Promise + getMenu(child: EtjanstChild): Promise + getNotifications(child: EtjanstChild): Promise + getTeachers(child: EtjanstChild): Promise + getSchedule( + child: EtjanstChild, + from: DateTime, + to: DateTime + ): Promise + getSchoolContacts(child: EtjanstChild): Promise + getSkola24Children(): Promise + getTimetable( + child: Skola24Child, + week: number, + year: number, + lang: Language + ): Promise + logout(): Promise +} diff --git a/apps/skolplattformen-app-new/libs/api/lib/cookies.ts b/apps/skolplattformen-app-new/libs/api/lib/cookies.ts new file mode 100644 index 000000000..185327df1 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/cookies.ts @@ -0,0 +1,118 @@ +import { camelCase, pascalCase } from 'change-case' +import { Cookie, CookieManager } from './types' + +interface IndexableCookie extends Cookie { + [key: string]: string | boolean | undefined +} +interface Serializer { + (cookie: Cookie): string +} +interface Deserializer { + (cookieString: string): Cookie +} +export const serialize: Serializer = (cookie) => { + const ic = cookie + const tokens = [`${ic.name}=${ic.value}`] + + const keyVals = ['expires', 'domain', 'path'] + keyVals + .filter((key) => ic[key]) + .forEach((key) => { + tokens.push(`${pascalCase(key)}=${ic[key]}`) + }) + + const bools = ['secure', 'httpOnly'] + bools + .filter((key) => ic[key]) + .forEach((key) => { + tokens.push(pascalCase(key)) + }) + + return tokens.join('; ') +} +export const deserialize: Deserializer = (cookieString) => { + const [nameVal, ...others] = cookieString + .split(';') + .map((token) => token.trim()) + const [name, value] = nameVal.split('=') + + const cookie: Cookie = { + name, + value, + } + + others + .map((keyVal) => keyVal.split('=')) + .forEach(([key, val]) => { + const prop = camelCase(key) + + switch (prop) { + case 'expires': + case 'domain': + case 'path': + cookie[prop] = val + break + case 'secure': + case 'httpOnly': + cookie[prop] = true + break + } + }) + + return cookie +} + +interface ToughCookie { + toString: () => string +} +export interface ToughCookieJar { + getCookieString: (url: string) => Promise + getCookies: (url: string) => Promise + setCookie: (cookie: string, url: string) => Promise + removeAllCookies: () => Promise +} +export const wrapToughCookie = (jar: ToughCookieJar): CookieManager => ({ + getCookieString: (url) => jar.getCookieString(url), + getCookies: async (url) => { + const cookies = await jar.getCookies(url) + return cookies.map((cookie) => deserialize(cookie.toString())) + }, + setCookie: async (cookie, url) => { + await jar.setCookie(serialize(cookie), url) + }, + setCookieString: async (cookieString, url) => { + await jar.setCookie(cookieString, url) + }, + clearAll: () => jar.removeAllCookies(), +}) + +interface RNCookies { + [key: string]: Cookie +} +export interface RNCookieManager { + set(url: string, cookie: Cookie, useWebKit?: boolean): Promise + setFromResponse(url: string, cookie: string): Promise + get(url: string, useWebKit?: boolean): Promise + clearAll(useWebKit?: boolean): Promise +} +export const wrapReactNativeCookieManager = ( + rnc: RNCookieManager +): CookieManager => ({ + clearAll: () => rnc.clearAll().then(), + getCookieString: async (url) => { + const cookies = await rnc.get(url) + return Object.values(cookies) + .map((c) => `${c.name}=${c.value}`) + .join('; ') + }, + getCookies: async (url) => { + const cookies = await rnc.get(url) + return Object.values(cookies) + }, + setCookie: async (cookie, url) => { + await rnc.setFromResponse(url, serialize(cookie)) + }, + setCookieString: async (cookieString, url) => { + await rnc.setFromResponse(url, cookieString) + }, +}) diff --git a/apps/skolplattformen-app-new/libs/api/lib/features.ts b/apps/skolplattformen-app-new/libs/api/lib/features.ts new file mode 100644 index 000000000..9c1ed1fd4 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/features.ts @@ -0,0 +1,8 @@ +export interface Features { + LOGIN_BANK_ID_SAME_DEVICE_WITHOUT_ID: boolean + LOGIN_FREJA_EID: boolean + FOOD_MENU: boolean + CLASS_LIST: boolean +} + +export type FeatureType = keyof Features diff --git a/apps/skolplattformen-app-new/libs/api/lib/fetcher.ts b/apps/skolplattformen-app-new/libs/api/lib/fetcher.ts new file mode 100644 index 000000000..cec71c18d --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/fetcher.ts @@ -0,0 +1,89 @@ +import { Response, Fetch, RequestInit } from './types' + +export interface CallInfo extends RequestInit { + name: string + type: string + url: string + status: number + statusText: string + error?: Error +} + +export interface FetcherOptions { + record?: ( + info: CallInfo, + data: string | Blob | ArrayBuffer | any + ) => Promise +} + +export interface Fetcher { + ( + name: string, + url: string, + init?: RequestInit, + childId?: string + ): Promise +} + +export interface Recorder { + (info: CallInfo, data: string | Blob | ArrayBuffer | any): Promise +} + +const record = async ( + name: string, + url: string, + init: RequestInit | undefined, + type: string, + options: FetcherOptions, + response: Response, + data: string | ArrayBuffer | Blob | any +): Promise => { + if (!options.record) { + return + } + const info: CallInfo = { + ...(init || {}), + name, + url, + type, + status: response.status, + statusText: response.statusText, + } + await options.record(info, data) +} + +export default function wrap( + fetch: Fetch, + options: FetcherOptions = {} +): Fetcher { + return async ( + name: string, + url: string, + init: RequestInit = { headers: {} } + ): Promise => { + const config = { + ...init, + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + ...init.headers, + }, + } + const response = await fetch(url, config) + + const wrapMethod = (res: Response, methodName: string): void => { + // @ts-ignore + const original = res[methodName].bind(res) + // @ts-ignore + res[methodName] = async (...args) => { + const result = await original(...args) + await record(name, url, config, methodName, options, response, result) + return result + } + } + wrapMethod(response, 'json') + wrapMethod(response, 'text') + + return response + } +} diff --git a/apps/skolplattformen-app-new/libs/api/lib/index.ts b/apps/skolplattformen-app-new/libs/api/lib/index.ts new file mode 100644 index 000000000..3eb1ccb35 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/index.ts @@ -0,0 +1,14 @@ +import wrap from './fetcher' + +export { toMarkdown } from './parseHtml' +export * from './types' +export type { LoginStatusChecker, FrejaLoginStatusChecker } from './loginStatus' +export type { Api } from './api' +export type { FetcherOptions, Fetcher } from './fetcher' +export { wrapReactNativeCookieManager, wrapToughCookie } from './cookies' +export type { RNCookieManager, ToughCookieJar } from './cookies' +export { URLSearchParams } from './URLSearchParams' + +export { wrap } +export type { FeatureType, Features } from './features' +export * from './utils/dateHandling' diff --git a/apps/skolplattformen-app-new/libs/api/lib/loginStatus.ts b/apps/skolplattformen-app-new/libs/api/lib/loginStatus.ts new file mode 100644 index 000000000..dcccb0508 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/loginStatus.ts @@ -0,0 +1,34 @@ +/* +export enum LoginEvent { + OK = 'OK', + PENDING = 'PENDING', + ERROR = 'ERROR', + USER_SIGN = 'USER_SIGN', +} +*/ + +export interface LoginStatusChecker { + token: string + on: ( + event: 'OK' | 'PENDING' | 'ERROR' | 'USER_SIGN' | 'CANCELLED', + listener: (...args: any[]) => void + ) => LoginStatusChecker + cancel: () => Promise +} + +export interface FrejaLoginStatusChecker { + token: string + on: ( + event: + | 'APPROVED' + | 'STARTED' + | 'UNKNOWN' + | 'DELIVERED_TO_MOBILE' + | 'CANCELLED' + | 'EXPIRED' + | 'RP_CANCELED' + | 'ERROR', + listener: (...args: any[]) => void + ) => FrejaLoginStatusChecker + cancel: () => Promise +} diff --git a/apps/skolplattformen-app-new/libs/api/lib/missingtypes.d.ts b/apps/skolplattformen-app-new/libs/api/lib/missingtypes.d.ts new file mode 100644 index 000000000..0334e2034 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/missingtypes.d.ts @@ -0,0 +1 @@ +declare module 'h2m' diff --git a/apps/skolplattformen-app-new/libs/api/lib/parseHtml.ts b/apps/skolplattformen-app-new/libs/api/lib/parseHtml.ts new file mode 100644 index 000000000..94de97bb8 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/parseHtml.ts @@ -0,0 +1,116 @@ +import h2m from 'h2m' +import { decode } from 'he' +import { htmlDecode } from 'js-htmlencode' +import { HTMLElement, parse, TextNode } from 'node-html-parser' + +const noChildren = ['strong', 'b', 'em', 'i', 'u', 's'] +const trimNodes = [...noChildren, 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'a'] +const cleanText = (node: TextNode, parentType: string): TextNode => { + const text = + parentType && trimNodes.includes(parentType.toLowerCase()) + ? node.rawText.trim() + : node.rawText + return new TextNode(text) +} + +const deepClean = (node: HTMLElement): HTMLElement => { + const attributes = Object.entries(node.attributes) + .map(([key, val]) => { + if (key === 'href' && val) { + val = val.replace(/ /g, '%20') + } + return `${key}="${val}"` + }) + .join(' ') + const cleaned = new HTMLElement(node.tagName, {}, attributes, node.parentNode) + node.childNodes.forEach((childNode) => { + if (childNode instanceof HTMLElement) { + if (node.tagName && noChildren.includes(node.tagName.toLowerCase())) { + cleaned.childNodes.push( + cleanText(new TextNode(childNode.innerText), node.tagName) + ) + } else { + cleaned.childNodes.push(deepClean(childNode)) + } + } else if (childNode instanceof TextNode) { + cleaned.childNodes.push(cleanText(childNode, node.tagName)) + } + }) + return cleaned +} + +const rearrangeWhitespace = (html = ''): string => { + let content = html + .replace(/]*>/gm, '') + .split('') + .join('') + .replace(/]*>/gm, '') + .split('') + .join('') + .split(' ') + .join('&nbsp;') + + // FIXME: Make a loop that doesn't break linting + trimNodes.forEach((trimNode) => { + content = content.split(`<${trimNode}> `).join(` <${trimNode}>`) + content = content.split(` `).join(` `) + content = content.split(`<${trimNode}>&nbsp;`).join(` <${trimNode}>`) + content = content.split(`&nbsp;`).join(` `) + }) + + trimNodes.forEach((trimNode) => { + content = content.split(`<${trimNode}> `).join(` <${trimNode}>`) + content = content.split(` `).join(` `) + content = content.split(`<${trimNode}>&nbsp;`).join(` <${trimNode}>`) + content = content.split(`&nbsp;`).join(` `) + }) + trimNodes.forEach((trimNode) => { + content = content.split(`<${trimNode}> `).join(` <${trimNode}>`) + content = content.split(` `).join(` `) + content = content.split(`<${trimNode}>&nbsp;`).join(` <${trimNode}>`) + content = content.split(`&nbsp;`).join(` `) + }) + trimNodes.forEach((trimNode) => { + content = content.split(`<${trimNode}> `).join(` <${trimNode}>`) + content = content.split(` `).join(` `) + content = content.split(`<${trimNode}>&nbsp;`).join(` <${trimNode}>`) + content = content.split(`&nbsp;`).join(` `) + }) + + return content +} + +export const clean = (html = ''): string => + deepClean(parse(decode(html))).outerHTML + +interface Node { + name: string + attrs: { [key: string]: string } + isInPreNode: boolean + md: string +} +const converter = 'MarkdownExtra' +const overides = { + a: (node: Node) => `[${node.md}](${node.attrs.href})`, + img: (node: Node) => `![${node.attrs.title || ''}](${node.attrs.src})`, + i: (node: Node) => `*${node.md}*`, + b: (node: Node) => `**${node.md}**`, + h1: (node: Node) => `# ${node.md}\n`, + h2: (node: Node) => `## ${node.md}\n`, + h3: (node: Node) => `### ${node.md}\n`, + h4: (node: Node) => `#### ${node.md}\n`, + h5: (node: Node) => `##### ${node.md}\n`, + h6: (node: Node) => `###### ${node.md}\n`, +} + +export const toMarkdown = (html?: string): string => { + if (html?.length == 0) { + return '' + } + + const rearranged = rearrangeWhitespace(html) + const trimmed = clean(rearranged) + const markdown = h2m(trimmed, { overides, converter }) + const decoded = htmlDecode(markdown) + return decoded +} diff --git a/apps/skolplattformen-app-new/libs/api/lib/types.ts b/apps/skolplattformen-app-new/libs/api/lib/types.ts new file mode 100644 index 000000000..03cd4ac08 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/types.ts @@ -0,0 +1,234 @@ +import { Subject } from '../../curriculum/src' + +export interface Cookie { + name: string + value: string + path?: string + domain?: string + version?: string + expires?: string + secure?: boolean + httpOnly?: boolean +} + +export interface CookieManager { + setCookie: (cookie: Cookie, url: string) => Promise + getCookies: (url: string) => Promise + setCookieString: (cookieString: string, url: string) => Promise + getCookieString: (url: string) => Promise + clearAll: () => Promise + removeAllCookies?: () => Promise +} + +export interface Headers { + get(name: string): string | null +} + +export interface Response { + headers: Headers + ok: boolean + status: number + statusText: string + text: () => Promise + json: () => Promise +} + +export interface AuthTicket { + order: string + token: string +} + +/** + * @export + * @interface CalendarItem + */ +export interface CalendarItem { + id: number + title: string + description?: string + location?: string + startDate?: string + endDate?: string + allDay?: boolean +} + +/** + * @export + * @interface Child + */ +export interface EtjanstChild { + id: string + /** + *

Special ID used to access certain subsystems

+ * @type {string} + * @memberof Child + */ + sdsId: string + name: string + /** + *

F - förskola, GR - grundskola?

+ * @type {string} + * @memberof Child + */ + status?: string + schoolId?: string +} + +export interface Child extends EtjanstChild, Skola24Child {} + +/** + * @export + * @interface Classmate + */ +export interface Classmate { + sisId: string + className?: string + firstname: string + lastname: string + guardians: Guardian[] +} + +export interface Fetch { + (url: string, init?: RequestInit): Promise +} + +/** + * @export + * @interface Guardian + */ +export interface Guardian { + email?: string + firstname: string + lastname: string + mobile?: string + address?: string +} + +/** + *

A news item from the school, for example a weekly news letter

+ * @export + * @interface NewsItem + */ +export interface NewsItem { + id: string + author?: string + header?: string + intro?: string + body?: string + published: string | null // null added for fakeData news.ts to not have type error + modified?: string | null // null added for fakeData news.ts to not have type error + imageUrl?: string + fullImageUrl?: string + imageAltText?: string +} + +/** + * @export + * @interface Notification + */ +export interface Notification { + id: string + sender: string + dateCreated: string + dateModified: string + message: string + url: string + category: string | null + type: string +} + +export interface RequestInit { + headers?: any + method?: string + body?: string + /** + * Set to `manual` to extract redirect headers, `error` to reject redirect */ + redirect?: string +} + +/** + * @export + * @interface ScheduleItem + */ +export interface ScheduleItem { + title: string + description?: string + location?: string + startDate?: string + endDate?: string + oneDayEvent: boolean + allDayEvent: boolean +} + +export interface MenuItem { + title: string + description: string +} + +export interface MenuList { + selectedWeek: number + menus: MenuListItem[] +} + +export interface MenuListItem { + week: string + mon: string + tue: string + wed: string + thu: string + fri: string +} + +export interface User { + personalNumber?: string + isAuthenticated?: boolean + firstName?: string + lastName?: string + email?: string | null + notificationId?: string +} + +export interface Skola24Child { + schoolGuid?: string + unitGuid?: string + schoolID?: string + timetableID?: string + personGuid?: string + firstName?: string + lastName?: string +} + +export type SSOSystem = 'TimetableViewer' + +export interface TimetableEntry extends Subject { + id: string + teacher: string + location: string + timeStart: string + timeEnd: string + dayOfWeek: number + blockName: string + dateStart: string + dateEnd: string +} + +export interface Teacher { + id: number + sisId: string + firstname: string + lastname: string + email?: string + phoneWork?: string + active: boolean + status: string + timeTableAbbreviation: string +} + +export interface SchoolContact { + title?: string + name?: string + phone?: string + email?: string + schoolName: string + className: string +} diff --git a/apps/skolplattformen-app-new/libs/api/lib/utils/__tests__/dateHandling.test.ts b/apps/skolplattformen-app-new/libs/api/lib/utils/__tests__/dateHandling.test.ts new file mode 100644 index 000000000..a90d15094 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/utils/__tests__/dateHandling.test.ts @@ -0,0 +1,16 @@ +import { parseDate } from '../dateHandling' + +test.each([ + ['2020-12-21 09:00', '2020-12-21T08:00:00.000Z'], + ['2021-05-28', '2021-05-27T22:00:00.000Z'], + ['2 oktober 2020', '2020-10-01T22:00:00.000Z'], + ['12 oktober 2020', '2020-10-11T22:00:00.000Z'], + ['5 oktober 2020 11:34', '2020-10-05T09:34:00.000Z'], + ['15 oktober 2020 11:34', '2020-10-15T09:34:00.000Z'], + ['2020-12-18T15:59:46.34', '2020-12-18T14:59:46.340Z'], + ['2020-12-18T15:59:46.340Z', '2020-12-18T15:59:46.340Z'], + ['/Date(1637935089877)/', '2021-11-26T13:58:09.877Z'], + ['This is an invalid date', undefined], +])('handles date parsing of %s', (input, expected) => { + expect(parseDate(input)).toEqual(expected) +}) diff --git a/apps/skolplattformen-app-new/libs/api/lib/utils/dateHandling.ts b/apps/skolplattformen-app-new/libs/api/lib/utils/dateHandling.ts new file mode 100644 index 000000000..417b81259 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/api/lib/utils/dateHandling.ts @@ -0,0 +1,60 @@ +import { DateTime } from 'luxon' + +const options = { + locale: 'sv', +} + +const toISOString = (date: DateTime) => date.toUTC().toISO() +const aspNetJsonRegex = /^\/?Date\((-?\d+)/i + +export const parseDate = (input?: string): string | undefined => { + if (!input) { + return undefined + } + + // First try and parse old Aps.Net format + // \/Date(1612525846000)\/ + // where the numbers are milliseconds from Epoc + const matched = aspNetJsonRegex.exec(input) + if (matched !== null) { + const millisecondsSinceEpoc = parseInt(matched[1], 10) + const date = DateTime.fromMillis(millisecondsSinceEpoc) + return toISOString(date) + } + + const dateParse = (format: string) => + DateTime.fromFormat(input, format, options) + + const dateISO = DateTime.fromISO(input) + + if (dateISO.isValid) { + return toISOString(dateISO) + } + + const dateAndTime = dateParse('yyyy-MM-dd HH:mm') + + if (dateAndTime.isValid) { + return toISOString(dateAndTime) + } + + const onlyDate = dateParse('yyyy-MM-dd') + + if (onlyDate.isValid) { + return toISOString(onlyDate) + } + + const dateLongForm = dateParse('d MMMM yyyy') + + if (dateLongForm.isValid) { + return toISOString(dateLongForm) + } + + const dateTimeLongForm = dateParse('d MMMM yyyy HH:mm') + + if (dateTimeLongForm.isValid) { + return toISOString(dateTimeLongForm) + } + + // Explicit return to satisfy ESLint + return undefined +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/__tests__/index.test.ts b/apps/skolplattformen-app-new/libs/curriculum/src/__tests__/index.test.ts new file mode 100644 index 000000000..9d7a195c4 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/__tests__/index.test.ts @@ -0,0 +1,1079 @@ +import parse from '..' + +describe('parse', () => { + it('Diverse', () => { + expect(parse('Lunch')).toEqual({ + code: 'Lunch', + category: 'Diverse', + name: 'Lunch', + }) + expect(parse('Prandium')).toEqual({ + code: 'Prandium', + category: 'Diverse', + name: 'Lunch', + }) + expect(parse('MTID')).toEqual({ + code: 'MTID', + category: 'Diverse', + name: 'Mentorstid', + }) + }) + it('Ämnesområden', () => { + expect(parse('BL')).toEqual({ code: 'BL', category: '', name: 'Bild' }) + expect(parse('EN')).toEqual({ code: 'EN', category: '', name: 'Engelska' }) + expect(parse('HKK')).toEqual({ + code: 'HKK', + category: '', + name: 'Hem & Konsumentkunskap', + }) + expect(parse('IDH')).toEqual({ + code: 'IDH', + category: '', + name: 'Idrott & Hälsa', + }) + expect(parse('MA')).toEqual({ code: 'MA', category: '', name: 'Matematik' }) + expect(parse('MU')).toEqual({ code: 'MU', category: '', name: 'Musik' }) + expect(parse('NO')).toEqual({ + code: 'NO', + category: '', + name: 'Naturorienterande ämnen', + }) + expect(parse('BI')).toEqual({ code: 'BI', category: '', name: 'Biologi' }) + expect(parse('FY')).toEqual({ code: 'FY', category: '', name: 'Fysik' }) + expect(parse('KE')).toEqual({ code: 'KE', category: '', name: 'Kemi' }) + expect(parse('SO')).toEqual({ + code: 'SO', + category: '', + name: 'Samhällsorienterande ämnen', + }) + expect(parse('GE')).toEqual({ code: 'GE', category: '', name: 'Geografi' }) + expect(parse('HI')).toEqual({ code: 'HI', category: '', name: 'Historia' }) + expect(parse('RE')).toEqual({ + code: 'RE', + category: '', + name: 'Religionskunskap', + }) + expect(parse('SH')).toEqual({ + code: 'SH', + category: '', + name: 'Samhällskunskap', + }) + expect(parse('SL')).toEqual({ code: 'SL', category: '', name: 'Slöjd' }) + expect(parse('SV')).toEqual({ code: 'SV', category: '', name: 'Svenska' }) + expect(parse('SVA')).toEqual({ + code: 'SVA', + category: '', + name: 'Svenska som andraspråk', + }) + expect(parse('TN')).toEqual({ + code: 'TN', + category: '', + name: 'Teckenspråk', + }) + expect(parse('TK')).toEqual({ code: 'TK', category: '', name: 'Teknik' }) + expect(parse('DA')).toEqual({ + code: 'DA', + category: '', + name: 'Förberedande dansarutbildning', + }) + expect(parse('JU')).toEqual({ + code: 'JU', + category: '', + name: 'Judiska studier', + }) + expect(parse('ES')).toEqual({ + code: 'ES', + category: '', + name: 'Estetisk verksamhet', + }) + }) + it('Träningsskolans ämnesområden', () => { + expect(parse('KOM')).toEqual({ + code: 'KOM', + category: 'Träningsskolan', + name: 'Kommunikation', + }) + expect(parse('MOT')).toEqual({ + code: 'MOT', + category: 'Träningsskolan', + name: 'Motorik', + }) + expect(parse('VAA')).toEqual({ + code: 'VAA', + category: 'Träningsskolan', + name: 'Vardagsaktiviteter', + }) + expect(parse('VEU')).toEqual({ + code: 'VEU', + category: 'Träningsskolan', + name: 'Verklighetsuppfattning', + }) + }) + it('Moderna språk, elevens val', () => { + expect(parse('M1SP')).toEqual({ + code: 'M1SP', + category: 'Moderna språk, elevens val', + name: 'Spanska', + }) + expect(parse('M1FR')).toEqual({ + code: 'M1FR', + category: 'Moderna språk, elevens val', + name: 'Franska', + }) + expect(parse('M1TY')).toEqual({ + code: 'M1TY', + category: 'Moderna språk, elevens val', + name: 'Tyska', + }) + expect(parse('M1DAN')).toEqual({ + code: 'M1DAN', + category: 'Moderna språk, elevens val', + name: 'Danska', + }) + expect(parse('M1FI')).toEqual({ + code: 'M1FI', + category: 'Moderna språk, elevens val', + name: 'Finska', + }) + expect(parse('M1HEB')).toEqual({ + code: 'M1HEB', + category: 'Moderna språk, elevens val', + name: 'Hebreiska', + }) + expect(parse('M1IT')).toEqual({ + code: 'M1IT', + category: 'Moderna språk, elevens val', + name: 'Italienska', + }) + expect(parse('M1JAP')).toEqual({ + code: 'M1JAP', + category: 'Moderna språk, elevens val', + name: 'Japanska', + }) + expect(parse('M1KI')).toEqual({ + code: 'M1KI', + category: 'Moderna språk, elevens val', + name: 'Kinesiska', + }) + expect(parse('M1PO')).toEqual({ + code: 'M1PO', + category: 'Moderna språk, elevens val', + name: 'Portugisiska', + }) + expect(parse('M1RY')).toEqual({ + code: 'M1RY', + category: 'Moderna språk, elevens val', + name: 'Ryska', + }) + expect(parse('M1SAM')).toEqual({ + code: 'M1SAM', + category: 'Moderna språk, elevens val', + name: 'Samiska', + }) + expect(parse('M1SVA')).toEqual({ + code: 'M1SVA', + category: 'Moderna språk, elevens val', + name: 'Svenska som andraspråk', + }) + expect(parse('M1TN')).toEqual({ + code: 'M1TN', + category: 'Moderna språk, elevens val', + name: 'Teckenspråk', + }) + }) + it('Moderna språk, språkval', () => { + expect(parse('M2SP')).toEqual({ + code: 'M2SP', + category: 'Moderna språk, språkval', + name: 'Spanska', + }) + expect(parse('M2FR')).toEqual({ + code: 'M2FR', + category: 'Moderna språk, språkval', + name: 'Franska', + }) + expect(parse('M2TY')).toEqual({ + code: 'M2TY', + category: 'Moderna språk, språkval', + name: 'Tyska', + }) + expect(parse('M2DAN')).toEqual({ + code: 'M2DAN', + category: 'Moderna språk, språkval', + name: 'Danska', + }) + expect(parse('M2FI')).toEqual({ + code: 'M2FI', + category: 'Moderna språk, språkval', + name: 'Finska', + }) + expect(parse('M2HEB')).toEqual({ + code: 'M2HEB', + category: 'Moderna språk, språkval', + name: 'Hebreiska', + }) + expect(parse('M2IT')).toEqual({ + code: 'M2IT', + category: 'Moderna språk, språkval', + name: 'Italienska', + }) + expect(parse('M2JAP')).toEqual({ + code: 'M2JAP', + category: 'Moderna språk, språkval', + name: 'Japanska', + }) + expect(parse('M2KI')).toEqual({ + code: 'M2KI', + category: 'Moderna språk, språkval', + name: 'Kinesiska', + }) + expect(parse('M2PO')).toEqual({ + code: 'M2PO', + category: 'Moderna språk, språkval', + name: 'Portugisiska', + }) + expect(parse('M2RY')).toEqual({ + code: 'M2RY', + category: 'Moderna språk, språkval', + name: 'Ryska', + }) + expect(parse('M2SAM')).toEqual({ + code: 'M2SAM', + category: 'Moderna språk, språkval', + name: 'Samiska', + }) + expect(parse('M2SVA')).toEqual({ + code: 'M2SVA', + category: 'Moderna språk, språkval', + name: 'Svenska som andraspråk', + }) + expect(parse('M2TN')).toEqual({ + code: 'M2TN', + category: 'Moderna språk, språkval', + name: 'Teckenspråk', + }) + }) + it('Alt moderna språk, språkval', () => { + expect(parse('ASSVEN')).toEqual({ + code: 'ASSVEN', + category: 'Alt moderna språk, språkval', + name: 'Engelska', + }) + expect(parse('ASSVSV')).toEqual({ + code: 'ASSVSV', + category: 'Alt moderna språk, språkval', + name: 'Svenska', + }) + }) + it('Modersmål', () => { + expect(parse('MLACE')).toEqual({ + code: 'MLACE', + category: 'Modersmål', + name: 'Acehnesiska', + }) + expect(parse('MLACH')).toEqual({ + code: 'MLACH', + category: 'Modersmål', + name: 'Acholi', + }) + expect(parse('MLAAR')).toEqual({ + code: 'MLAAR', + category: 'Modersmål', + name: 'Afar, Danakil', + }) + expect(parse('MLAFR')).toEqual({ + code: 'MLAFR', + category: 'Modersmål', + name: 'Afrikaans', + }) + expect(parse('MLAKA')).toEqual({ + code: 'MLAKA', + category: 'Modersmål', + name: 'Akan', + }) + expect(parse('MLSQI')).toEqual({ + code: 'MLSQI', + category: 'Modersmål', + name: 'Albanska', + }) + expect(parse('MLAMH')).toEqual({ + code: 'MLAMH', + category: 'Modersmål', + name: 'Amhariska', + }) + expect(parse('MLARA')).toEqual({ + code: 'MLARA', + category: 'Modersmål', + name: 'Arabiska', + }) + expect(parse('MLHYE')).toEqual({ + code: 'MLHYE', + category: 'Modersmål', + name: 'Armeniska', + }) + expect(parse('MLAII')).toEqual({ + code: 'MLAII', + category: 'Modersmål', + name: 'Assyriska, Nyarameiska', + }) + expect(parse('MLAYM')).toEqual({ + code: 'MLAYM', + category: 'Modersmål', + name: 'Aymara', + }) + expect(parse('MLAZE')).toEqual({ + code: 'MLAZE', + category: 'Modersmål', + name: 'Azerbadjanska', + }) + expect(parse('MLBAL')).toEqual({ + code: 'MLBAL', + category: 'Modersmål', + name: 'Baluchiska', + }) + expect(parse('MLBAM')).toEqual({ + code: 'MLBAM', + category: 'Modersmål', + name: 'Bambara', + }) + expect(parse('MLBAI')).toEqual({ + code: 'MLBAI', + category: 'Modersmål', + name: 'Bamileke', + }) + expect(parse('MLEUS')).toEqual({ + code: 'MLEUS', + category: 'Modersmål', + name: 'Baskiska', + }) + expect(parse('MLBEM')).toEqual({ + code: 'MLBEM', + category: 'Modersmål', + name: 'Bemba', + }) + expect(parse('MLBEN')).toEqual({ + code: 'MLBEN', + category: 'Modersmål', + name: 'Bengaliska', + }) + expect(parse('MLBER')).toEqual({ + code: 'MLBER', + category: 'Modersmål', + name: 'Berbiska', + }) + expect(parse('MLBIL')).toEqual({ + code: 'MLBIL', + category: 'Modersmål', + name: 'Bile', + }) + expect(parse('MLBYN')).toEqual({ + code: 'MLBYN', + category: 'Modersmål', + name: 'Bilen, Bilein, Bileno, Bilin', + }) + expect(parse('MLBOS')).toEqual({ + code: 'MLBOS', + category: 'Modersmål', + name: 'Bosniska', + }) + expect(parse('MLBUL')).toEqual({ + code: 'MLBUL', + category: 'Modersmål', + name: 'Bulgariska', + }) + expect(parse('MLMYA')).toEqual({ + code: 'MLMYA', + category: 'Modersmål', + name: 'Burmesiska', + }) + expect(parse('MLBOS')).toEqual({ + code: 'MLBOS', + category: 'Modersmål', + name: 'Bosniska', + }) + expect(parse('MLCEB')).toEqual({ + code: 'MLCEB', + category: 'Modersmål', + name: 'Cebuanska, Binisaya, Sebuano, Sugbuanon, Sugbuhanon, Visayan', + }) + expect(parse('MLDAN')).toEqual({ + code: 'MLDAN', + category: 'Modersmål', + name: 'Danska', + }) + expect(parse('MLDAR')).toEqual({ + code: 'MLDAR', + category: 'Modersmål', + name: 'Darginska, Dargi, Dargin, Dargintsy, Khiurkilinskii, Uslar', + }) + expect(parse('MLPRS')).toEqual({ + code: 'MLPRS', + category: 'Modersmål', + name: 'Dari, Parsi, Persian', + }) + expect(parse('MLDMQ')).toEqual({ + code: 'MLDMQ', + category: 'Modersmål', + name: 'Dimli', + }) + expect(parse('MLDIV')).toEqual({ + code: 'MLDIV', + category: 'Modersmål', + name: 'Divehi', + }) + expect(parse('MLENG')).toEqual({ + code: 'MLENG', + category: 'Modersmål', + name: 'Engelska', + }) + expect(parse('MLEST')).toEqual({ + code: 'MLEST', + category: 'Modersmål', + name: 'Estniska', + }) + expect(parse('MLEWE')).toEqual({ + code: 'MLEWE', + category: 'Modersmål', + name: 'Ewe', + }) + expect(parse('MLFIJ')).toEqual({ + code: 'MLFIJ', + category: 'Modersmål', + name: 'Fijianska', + }) + expect(parse('MLFIN')).toEqual({ + code: 'MLFIN', + category: 'Modersmål', + name: 'Finska', + }) + expect(parse('MLVLS')).toEqual({ + code: 'MLVLS', + category: 'Modersmål', + name: 'Flamländska', + }) + expect(parse('MLFRA')).toEqual({ + code: 'MLFRA', + category: 'Modersmål', + name: 'Franska', + }) + expect(parse('MLFAO')).toEqual({ + code: 'MLFAO', + category: 'Modersmål', + name: 'Färöiska', + }) + expect(parse('MLGAA')).toEqual({ + code: 'MLGAA', + category: 'Modersmål', + name: 'Ga', + }) + expect(parse('MLKAT')).toEqual({ + code: 'MLKAT', + category: 'Modersmål', + name: 'Georgiska', + }) + expect(parse('MLGRE')).toEqual({ + code: 'MLGRE', + category: 'Modersmål', + name: 'Grekiska', + }) + expect(parse('MLKAL')).toEqual({ + code: 'MLKAL', + category: 'Modersmål', + name: 'Grönländska', + }) + expect(parse('MLGUJ')).toEqual({ + code: 'MLGUJ', + category: 'Modersmål', + name: 'Gujarati', + }) + expect(parse('MLHEB')).toEqual({ + code: 'MLHEB', + category: 'Modersmål', + name: 'Hebreiska', + }) + expect(parse('MLHIN')).toEqual({ + code: 'MLHIN', + category: 'Modersmål', + name: 'Hindi', + }) + expect(parse('MLIBO')).toEqual({ + code: 'MLIBO', + category: 'Modersmål', + name: 'Ibo', + }) + expect(parse('MLIND')).toEqual({ + code: 'MLIND', + category: 'Modersmål', + name: 'Indonesiska', + }) + expect(parse('MLISL')).toEqual({ + code: 'MLISL', + category: 'Modersmål', + name: 'Isländska', + }) + expect(parse('MLITA')).toEqual({ + code: 'MLITA', + category: 'Modersmål', + name: 'Italienska', + }) + expect(parse('MLJPN')).toEqual({ + code: 'MLJPN', + category: 'Modersmål', + name: 'Japanska', + }) + expect(parse('MLYID')).toEqual({ + code: 'MLYID', + category: 'Modersmål', + name: 'Jiddisch', + }) + expect(parse('MLKAM')).toEqual({ + code: 'MLKAM', + category: 'Modersmål', + name: 'Kamba', + }) + expect(parse('MLKHM')).toEqual({ + code: 'MLKHM', + category: 'Modersmål', + name: 'Khmer', + }) + expect(parse('MLKAN')).toEqual({ + code: 'MLKAN', + category: 'Modersmål', + name: 'Kannada', + }) + expect(parse('MLKAR')).toEqual({ + code: 'MLKAR', + category: 'Modersmål', + name: 'Karenska', + }) + expect(parse('MLCAT')).toEqual({ + code: 'MLCAT', + category: 'Modersmål', + name: 'Katalanska', + }) + expect(parse('MLKAZ')).toEqual({ + code: 'MLKAZ', + category: 'Modersmål', + name: 'Kazakiska', + }) + expect(parse('MLKIK')).toEqual({ + code: 'MLKIK', + category: 'Modersmål', + name: 'Kikuyu', + }) + expect(parse('MLZHO')).toEqual({ + code: 'MLZHO', + category: 'Modersmål', + name: 'Kinesiska', + }) + expect(parse('MLCMN')).toEqual({ + code: 'MLCMN', + category: 'Modersmål', + name: 'Kinesiska, Mandarin', + }) + expect(parse('MLHAK')).toEqual({ + code: 'MLHAK', + category: 'Modersmål', + name: 'Kinesiska, Hakka', + }) + expect(parse('MLYUE')).toEqual({ + code: 'MLYUE', + category: 'Modersmål', + name: 'Kinesiska, Kantonesiska', + }) + expect(parse('MLNAN')).toEqual({ + code: 'MLNAN', + category: 'Modersmål', + name: 'Kinesiska, Min Nan', + }) + expect(parse('MLKIN')).toEqual({ + code: 'MLKIN', + category: 'Modersmål', + name: 'Kinyarwanda', + }) + expect(parse('MLKIR')).toEqual({ + code: 'MLKIR', + category: 'Modersmål', + name: 'Kirgisiska', + }) + expect(parse('MLRUN')).toEqual({ + code: 'MLRUN', + category: 'Modersmål', + name: 'Kirundi', + }) + expect(parse('MLKON')).toEqual({ + code: 'MLKON', + category: 'Modersmål', + name: 'Kongo', + }) + expect(parse('MLKOR')).toEqual({ + code: 'MLKOR', + category: 'Modersmål', + name: 'Koreanska', + }) + expect(parse('MLROP')).toEqual({ + code: 'MLROP', + category: 'Modersmål', + name: 'Kreolska', + }) + expect(parse('MLHRV')).toEqual({ + code: 'MLHRV', + category: 'Modersmål', + name: 'Kroatiska', + }) + expect(parse('MLKRO')).toEqual({ + code: 'MLKRO', + category: 'Modersmål', + name: 'Kru', + }) + expect(parse('MLKUR')).toEqual({ + code: 'MLKUR', + category: 'Modersmål', + name: 'Kurdiska', + }) + expect(parse('MLCKB')).toEqual({ + code: 'MLCKB', + category: 'Modersmål', + name: 'Kurdiska, centr.', + }) + expect(parse('MLKMR')).toEqual({ + code: 'MLKMR', + category: 'Modersmål', + name: 'Kurdiska, norra', + }) + expect(parse('MLSDH')).toEqual({ + code: 'MLSDH', + category: 'Modersmål', + name: 'Kurdiska, södra', + }) + expect(parse('MLLAO')).toEqual({ + code: 'MLLAO', + category: 'Modersmål', + name: 'Laotiska', + }) + expect(parse('MLLAV')).toEqual({ + code: 'MLLAV', + category: 'Modersmål', + name: 'Lettiska', + }) + expect(parse('MLLMA')).toEqual({ + code: 'MLLMA', + category: 'Modersmål', + name: 'Limba', + }) + expect(parse('MLLIN')).toEqual({ + code: 'MLLIN', + category: 'Modersmål', + name: 'Lingala', + }) + expect(parse('MLLIT')).toEqual({ + code: 'MLLIT', + category: 'Modersmål', + name: 'Litauiska', + }) + expect(parse('MLLUG')).toEqual({ + code: 'MLLUG', + category: 'Modersmål', + name: 'Luganda/Ganda', + }) + expect(parse('MLLUO')).toEqual({ + code: 'MLLUO', + category: 'Modersmål', + name: 'Luo', + }) + expect(parse('MLMKD')).toEqual({ + code: 'MLMKD', + category: 'Modersmål', + name: 'Makedonska', + }) + expect(parse('MLMLG')).toEqual({ + code: 'MLMLG', + category: 'Modersmål', + name: 'Malagaskiska', + }) + expect(parse('MLMSA')).toEqual({ + code: 'MLMSA', + category: 'Modersmål', + name: 'Malajiska', + }) + expect(parse('MLMAL')).toEqual({ + code: 'MLMAL', + category: 'Modersmål', + name: 'Malayalami', + }) + expect(parse('MLMLT')).toEqual({ + code: 'MLMLT', + category: 'Modersmål', + name: 'Maltesiska', + }) + expect(parse('MLMNK')).toEqual({ + code: 'MLMNK', + category: 'Modersmål', + name: 'Mandinka', + }) + expect(parse('MLMRI')).toEqual({ + code: 'MLMRI', + category: 'Modersmål', + name: 'Maori', + }) + expect(parse('MLMAR')).toEqual({ + code: 'MLMAR', + category: 'Modersmål', + name: 'Marathi', + }) + expect(parse('MLMYX')).toEqual({ + code: 'MLMYX', + category: 'Modersmål', + name: 'Masaaba, Gisu, Gugisu, Lumasaaba, Masaba', + }) + expect(parse('MLFIT')).toEqual({ + code: 'MLFIT', + category: 'Modersmål', + name: 'Meänkieli', + }) + expect(parse('MLMON')).toEqual({ + code: 'MLMON', + category: 'Modersmål', + name: 'Mongoliska', + }) + expect(parse('MLNLD')).toEqual({ + code: 'MLNLD', + category: 'Modersmål', + name: 'Nederländska', + }) + expect(parse('MLNEP')).toEqual({ + code: 'MLNEP', + category: 'Modersmål', + name: 'Nepalesiska', + }) + expect(parse('MLNOR')).toEqual({ + code: 'MLNOR', + category: 'Modersmål', + name: 'Norska', + }) + expect(parse('MLNYA')).toEqual({ + code: 'MLNYA', + category: 'Modersmål', + name: 'Nyanja', + }) + expect(parse('MLORM')).toEqual({ + code: 'MLORM', + category: 'Modersmål', + name: 'Oromo', + }) + expect(parse('MLPUS')).toEqual({ + code: 'MLPUS', + category: 'Modersmål', + name: 'Pashto', + }) + expect(parse('MLPTN')).toEqual({ + code: 'MLPTN', + category: 'Modersmål', + name: 'Patani', + }) + expect(parse('MLFAS')).toEqual({ + code: 'MLFAS', + category: 'Modersmål', + name: 'Persiska', + }) + expect(parse('MLPOL')).toEqual({ + code: 'MLPOL', + category: 'Modersmål', + name: 'Polska', + }) + expect(parse('MLPOR')).toEqual({ + code: 'MLPOR', + category: 'Modersmål', + name: 'Portugisiska', + }) + expect(parse('MLPAN')).toEqual({ + code: 'MLPAN', + category: 'Modersmål', + name: 'Punjabi', + }) + expect(parse('MLROM')).toEqual({ + code: 'MLROM', + category: 'Modersmål', + name: 'Romani', + }) + expect(parse('MLRMC')).toEqual({ + code: 'MLRMC', + category: 'Modersmål', + name: 'Romani, Karpaterna', + }) + expect(parse('MLRML')).toEqual({ + code: 'MLRML', + category: 'Modersmål', + name: 'Romani, Baltisk', + }) + expect(parse('MLRMN')).toEqual({ + code: 'MLRMN', + category: 'Modersmål', + name: 'Romani, Arli', + }) + expect(parse('MLRMF')).toEqual({ + code: 'MLRMF', + category: 'Modersmål', + name: 'Romani, Kalé', + }) + expect(parse('MLRMO')).toEqual({ + code: 'MLRMO', + category: 'Modersmål', + name: 'Romani, Sinti', + }) + expect(parse('MLRMU')).toEqual({ + code: 'MLRMU', + category: 'Modersmål', + name: 'Romani, Tavringer', + }) + expect(parse('MLRMY')).toEqual({ + code: 'MLRMY', + category: 'Modersmål', + name: 'Romani, Lovari, Kalderari', + }) + expect(parse('MLRON')).toEqual({ + code: 'MLRON', + category: 'Modersmål', + name: 'Rumänska', + }) + expect(parse('MLRUS')).toEqual({ + code: 'MLRUS', + category: 'Modersmål', + name: 'Ryska', + }) + expect(parse('MLSSY')).toEqual({ + code: 'MLSSY', + category: 'Modersmål', + name: 'Saho', + }) + expect(parse('MLNSM')).toEqual({ + code: 'MLNSM', + category: 'Modersmål', + name: 'Samiska, (norra)', + }) + expect(parse('MLSMI')).toEqual({ + code: 'MLSMI', + category: 'Modersmål', + name: 'Samiska', + }) + expect(parse('MLSMJ')).toEqual({ + code: 'MLSMJ', + category: 'Modersmål', + name: 'Samiska, Lulesamiska', + }) + expect(parse('MLSJE')).toEqual({ + code: 'MLSJE', + category: 'Modersmål', + name: 'Samiska, Pitesamiska', + }) + expect(parse('MLSMA')).toEqual({ + code: 'MLSMA', + category: 'Modersmål', + name: 'Samiska, Sydsamiska', + }) + expect(parse('MLSJU')).toEqual({ + code: 'MLSJU', + category: 'Modersmål', + name: 'Samiska, Umesamiska', + }) + expect(parse('MLSMO')).toEqual({ + code: 'MLSMO', + category: 'Modersmål', + name: 'Samoanska', + }) + expect(parse('MLSRP')).toEqual({ + code: 'MLSRP', + category: 'Modersmål', + name: 'Serbiska', + }) + expect(parse('MLHBS')).toEqual({ + code: 'MLHBS', + category: 'Modersmål', + name: 'Serbokroatiska', + }) + expect(parse('MLSOT')).toEqual({ + code: 'MLSOT', + category: 'Modersmål', + name: 'Sydsotho', + }) + expect(parse('MLSNA')).toEqual({ + code: 'MLSNA', + category: 'Modersmål', + name: 'Shona', + }) + expect(parse('MLSIN')).toEqual({ + code: 'MLSIN', + category: 'Modersmål', + name: 'Singalesiska', + }) + expect(parse('MLSLK')).toEqual({ + code: 'MLSLK', + category: 'Modersmål', + name: 'Slovakiska', + }) + expect(parse('MLSLV')).toEqual({ + code: 'MLSLV', + category: 'Modersmål', + name: 'Slovenska', + }) + expect(parse('MLSOM')).toEqual({ + code: 'MLSOM', + category: 'Modersmål', + name: 'Somaliska', + }) + expect(parse('MLSPA')).toEqual({ + code: 'MLSPA', + category: 'Modersmål', + name: 'Spanska', + }) + expect(parse('MLSWA')).toEqual({ + code: 'MLSWA', + category: 'Modersmål', + name: 'Swahili', + }) + expect(parse('MLSYC')).toEqual({ + code: 'MLSYC', + category: 'Modersmål', + name: 'Syrianska/assyriska, suryaya, suryoyo', + }) + expect(parse('MLSYR')).toEqual({ + code: 'MLSYR', + category: 'Modersmål', + name: 'Syriska', + }) + expect(parse('MLTRU')).toEqual({ + code: 'MLTRU', + category: 'Modersmål', + name: 'Syriska, Turoyo', + }) + expect(parse('MLTLG')).toEqual({ + code: 'MLTLG', + category: 'Modersmål', + name: 'Tagalog', + }) + expect(parse('MLTAM')).toEqual({ + code: 'MLTAM', + category: 'Modersmål', + name: 'Tamil', + }) + expect(parse('MLTAT')).toEqual({ + code: 'MLTAT', + category: 'Modersmål', + name: 'Tatariska', + }) + expect(parse('MLTEL')).toEqual({ + code: 'MLTEL', + category: 'Modersmål', + name: 'Telugu', + }) + expect(parse('MLTHA')).toEqual({ + code: 'MLTHA', + category: 'Modersmål', + name: 'Thai', + }) + expect(parse('MLTIB')).toEqual({ + code: 'MLTIB', + category: 'Modersmål', + name: 'Tibetanska', + }) + expect(parse('MLTIG')).toEqual({ + code: 'MLTIG', + category: 'Modersmål', + name: 'Tigre', + }) + expect(parse('MLTIR')).toEqual({ + code: 'MLTIR', + category: 'Modersmål', + name: 'Tigrinja', + }) + expect(parse('MLCES')).toEqual({ + code: 'MLCES', + category: 'Modersmål', + name: 'Tjeckiska', + }) + expect(parse('MLTON')).toEqual({ + code: 'MLTON', + category: 'Modersmål', + name: 'Tonganska', + }) + expect(parse('MLTSN')).toEqual({ + code: 'MLTSN', + category: 'Modersmål', + name: 'Tswana', + }) + expect(parse('MLTUR')).toEqual({ + code: 'MLTUR', + category: 'Modersmål', + name: 'Turkiska', + }) + expect(parse('MLDEU')).toEqual({ + code: 'MLDEU', + category: 'Modersmål', + name: 'Tyska', + }) + expect(parse('MLUIG')).toEqual({ + code: 'MLUIG', + category: 'Modersmål', + name: 'Uiguriska', + }) + expect(parse('MLUKR')).toEqual({ + code: 'MLUKR', + category: 'Modersmål', + name: 'Ukrainska', + }) + expect(parse('MLHUN')).toEqual({ + code: 'MLHUN', + category: 'Modersmål', + name: 'Ungerska', + }) + expect(parse('MLURD')).toEqual({ + code: 'MLURD', + category: 'Modersmål', + name: 'Urdu', + }) + expect(parse('MLUZB')).toEqual({ + code: 'MLUZB', + category: 'Modersmål', + name: 'Uzbekiska', + }) + expect(parse('MLVIE')).toEqual({ + code: 'MLVIE', + category: 'Modersmål', + name: 'Vietnamesiska', + }) + expect(parse('MLWOL')).toEqual({ + code: 'MLWOL', + category: 'Modersmål', + name: 'Wolof', + }) + expect(parse('MLYOR')).toEqual({ + code: 'MLYOR', + category: 'Modersmål', + name: 'Yoruba', + }) + expect(parse('MLZUL')).toEqual({ + code: 'MLZUL', + category: 'Modersmål', + name: 'Zulu', + }) + expect(parse('MLSPK')).toEqual({ + code: 'MLSPK', + category: 'Modersmål', + name: 'Övriga språk', + }) + }) + it('handles comments', () => { + expect(parse('NO a)')).toEqual({ + code: 'NO', + category: '', + name: 'Naturorienterande ämnen', + comment: 'a)', + }) + expect(parse('MTID Arbetslagsråd 7C')).toEqual({ + code: 'MTID', + category: 'Diverse', + name: 'Mentorstid', + comment: 'Arbetslagsråd 7C', + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/index.ts b/apps/skolplattformen-app-new/libs/curriculum/src/index.ts new file mode 100644 index 000000000..6af538336 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/index.ts @@ -0,0 +1,114 @@ +import translate, { Language, Translation } from './translations' +export type { Language } from './translations' + +export interface Subject { + code: string + category: string + name: string + comment?: string +} + +type Parser = (translation: Translation, code: string) => Subject | null +const parseSubject: Parser = ({ subjects }, code) => { + if (!subjects[code]) { + return null + } + + return { + code, + category: '', + name: subjects[code] as string, + } +} + +const parseTrainingSubject: Parser = ( + { categories, traningsskolaSubjects }, + code +) => { + if (!traningsskolaSubjects[code]) { + return null + } + + return { + code, + category: categories.trainingSchool, + name: traningsskolaSubjects[code] as string, + } +} + +const parseLanguage: Parser = ({ categories, languages }, code) => { + if (!code.startsWith('M1') && !code.startsWith('M2')) { + return null + } + const category = `${categories.modernLanguages}, ${ + code.startsWith('M1') + ? categories.modernLanguagesA1 + : categories.modernLanguagesA2 + }` + const language = code.substr(2) + + return { + code, + category, + name: languages[language] || categories.unknown, + } +} + +const parseAltLanguage: Parser = ({ categories, languages }, code) => { + if (!code.startsWith('ASSV')) { + return null + } + const language = code.substr(4) + + return { + code, + category: categories.modernLanguagesAlt, + name: languages[language] || categories.unknown, + } +} + +const parseNativeLanguage: Parser = ({ categories, languages }, code) => { + if (!code.startsWith('ML')) { + return null + } + const language = code.substr(2) + + return { + code, + category: categories.motherTounge, + name: languages[language] || categories.unknown, + } +} + +const parseMisc: Parser = ({ categories, misc }, code) => { + if (!misc[code.toUpperCase()]) { + return null + } + + return { + code, + category: categories.misc, + name: misc[code.toUpperCase()] as string, + } +} + +const parse = (code: string, lang: Language = 'sv'): Subject => { + const translation = translate(lang) + const [subjectCode, ...rest] = code.split(' ') + const result: Subject = parseSubject(translation, subjectCode) || + parseTrainingSubject(translation, subjectCode) || + parseLanguage(translation, subjectCode) || + parseAltLanguage(translation, subjectCode) || + parseNativeLanguage(translation, subjectCode) || + parseMisc(translation, subjectCode) || { + code: subjectCode, + category: translation.categories.unknown, + name: subjectCode, + } + if (rest.length) { + result.comment = rest.join(' ').trim() + } + return result +} + +export default parse diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/de.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/de.json new file mode 100644 index 000000000..b6c54c556 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/de.json @@ -0,0 +1,29 @@ +{ + "subjects": { + "TN": "Zei­chen­spra­che", + "SVA": "Schwedisch als Fremdsprache", + "SV": "Schwedisch", + "SL": "Werken", + "SH": "Staats­bür­ger­kun­de", + "RE": "Re­li­gi­on", + "HI": "Geschichte", + "GE": "Geografie", + "NO": "Naturwissenschaften", + "SO": "Gesellschaftslehre", + "KE": "Chemie", + "FY": "Physik", + "BI": "Biologie", + "MU": "Musik", + "MA": "Mathematik", + "IDH": "Sport und Gesundheit", + "HKK": "Hauswirtschaft", + "EN": "Englisch", + "BL": "Kunst", + "TK": "Technik" + }, + "misc": { + "PRANDIUM": "Mittagspause", + "LUNCH": "Mittagspause", + "RAST": "Pause" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/en.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/en.json new file mode 100644 index 000000000..b68629966 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/en.json @@ -0,0 +1,225 @@ +{ + "subjects": { + "BL": "Art", + "EN": "English", + "HKK": "Home and consumer studies", + "IDH": "Physical education and health", + "MA": "Mathematics", + "MU": "Music", + "NO": "Science studies", + "BI": "Biology", + "FY": "Physics", + "KE": "Chemistry", + "SO": "Social study subjects", + "GE": "Geography", + "HI": "History", + "RE": "Religion", + "SH": "Civics", + "SL": "Crafts", + "SV": "Swedish", + "SVA": "Swedish as a second language", + "TN": "Sign language", + "TK": "Technology", + "DA": "Preparatory dancing studies", + "JU": "Jewish studies", + "ES": "Aesthetics" + }, + "traningsskolaSubjects": { + "KOM": "Communication", + "MOT": "Physical coordination", + "VAA": "Everyday activities", + "VEU": "Perception" + }, + "specialLanguages": { + "EN": "English", + "FR": "French", + "FI": "Finnish", + "IT": "Italian", + "JAP": "Japanese", + "KI": "Chinese", + "PO": "Portugese", + "RY": "Russian", + "SAM": "Sami", + "SP": "Spanish", + "SV": "Swedish", + "SVA": "Swedish as a second language", + "TN": "Sign language", + "TY": "German" + }, + "languages": { + "ACE": "Acehnese", + "ACH": "Acholi", + "AAR": "Afar, Danakil", + "AFR": "Afrikaans", + "AKA": "Akan, Asante, Fante", + "SQI": "Albanian", + "AMH": "Amharic", + "ARA": "Arabic", + "HYE": "Armenian", + "AII": "Assyric, Neo-Aramaic", + "AYM": "Aymara", + "AZE": "Azerbaijani", + "BAL": "Baluchi, Baloci, Baluci, Makrani", + "BAM": "Bambara", + "BAI": "Bamileke", + "EUS": "Baskiska", + "BEM": "Bemba, Chibemba, Chiwemba, Ichibemba, Wemba", + "BEN": "Bengali", + "BER": "Berber", + "BIL": "Bile", + "BYN": "Bilen, Bilein, Bileno, Bilin", + "BOS": "Bosnian", + "BUL": "Bulgarian", + "MYA": "Burmese", + "CEB": "Cebuan, Binisaya, Sebuano, Sugbuanon, Sugbuhanon, Visayan", + "DAN": "Danish", + "DAR": "Dargin, Dargi, Dargin, Dargintsy, Khiurkilinskii, Uslar", + "PRS": "Dari, Parsi, Persian", + "DMQ": "Dimli", + "DIV": "Divehi", + "ENG": "English", + "EST": "Estonian", + "EWE": "Ewe", + "FIJ": "Fijian", + "FIN": "Finnish", + "VLS": "Flemish", + "FRA": "French", + "FAO": "Faroese", + "GAA": "Ga", + "KAT": "Georgian", + "GRE": "Greek", + "KAL": "Greenlandic", + "GUJ": "Gujarati", + "HEB": "Hebrew", + "HIN": "Hindi", + "IBO": "Ibo", + "IND": "Indonesian", + "ISL": "Icelandic", + "ITA": "Italian", + "JPN": "Japanese", + "YID": "Yiddish", + "KAM": "Kamba, Kekamba, Kikamba", + "KHM": "Khmer", + "KAN": "Kannada", + "KAR": "Karen", + "CAT": "Catalan", + "KAZ": "Kazakh", + "KIK": "Kikuyu", + "ZHO": "Chinese", + "CMN": "Chinese, Mandarin", + "HAK": "Chinese, Hakka", + "YUE": "Chinese, Cantonese", + "NAN": "Chinese, Min Nan", + "KIN": "Kinyarwanda", + "KIR": "Kyrgyz", + "RUN": "Kirundi", + "KON": "Kongo", + "KOR": "Korean", + "ROP": "Creole", + "HRV": "Croatian", + "KRO": "Kru", + "KUR": "Kurdish", + "CKB": "Kurdish, centr.", + "KMR": "Kurdish, north", + "SDH": "Kurdish, south", + "LAO": "Laotian", + "LAV": "Latvian", + "LMA": "Limba", + "LIN": "Lingala", + "LIT": "Lithuanian", + "LUG": "Luganda/Ganda", + "LUO": "Luo", + "MKD": "Macedonian", + "MLG": "Malagaskiska", + "MSA": "Malagasy", + "MAL": "Malayalami", + "MLT": "Maltese", + "MNK": "Mandinka", + "MRI": "Maori", + "MAR": "Marathi", + "MYX": "Masaaba, Gisu, Gugisu, Lumasaaba, Masaba", + "FIT": "Meänkieli", + "MON": "Mongolian", + "NLD": "Dutch", + "NEP": "Nepalese", + "NOR": "Norwegian", + "NYA": "Nyanja", + "ORM": "Oromo", + "PUS": "Pashto", + "PTN": "Patani", + "FAS": "Persian", + "POL": "Polish", + "POR": "Portuguese", + "PAN": "Punjabi", + "ROM": "Romani", + "RMC": "Romani, Carpathians", + "RML": "Romani, Baltic", + "RMN": "Romani, Arli", + "RMF": "Romani, Kalé", + "RMO": "Romani, Sinti", + "RMU": "Romani, Tavringer", + "RMY": "Romani, Lovari, Kalderari", + "RON": "Romanian", + "RUS": "Russian", + "SSY": "Saho", + "NSM": "Sami, (northern)", + "SMI": "Sami", + "SMJ": "Sami, Lule Sami", + "SJE": "Sami, Pite Sami", + "SMA": "Sami, Syd Sami", + "SJU": "Sami, Ume Sami", + "SMO": "Samoan", + "SRP": "Serbian", + "HBS": "Serbo-Croatian", + "SOT": "Sesotho, Sisutho, Souto, Suthu, Suto", + "SNA": "Shona", + "SIN": "Sinhalese", + "SLK": "Slovak", + "SLV": "Slovenian", + "SOM": "Somali", + "SPA": "Spanish", + "SWA": "Swahili", + "SYC": "Syrian/Assyrian, suryaya, suryoyo", + "SYR": "Syrian", + "TRU": "Syrian, Turoyo", + "TLG": "Tagalog", + "TAM": "Tamil", + "TAT": "Tatar", + "TEL": "Telugu", + "THA": "Thai", + "TIB": "Tibetan", + "TIG": "Tigre", + "TIR": "Tigrinya", + "CES": "Czech", + "TON": "Tongan", + "TSN": "Tswana, Setswana", + "TUR": "Turkish", + "DEU": "German", + "UIG": "Uighur", + "UKR": "Ukrainian", + "HUN": "Hungarian", + "URD": "Urdu", + "UZB": "Uzbek", + "VIE": "Vietnamese", + "WOL": "Wolof", + "YOR": "Yoruba, Yariba, Yooba", + "ZUL": "Zulu", + "SPK": "Other language" + }, + "categories": { + "trainingSchool": "Compulsory school for children with severe learning disabilities", + "modernLanguages": "Modern languages", + "modernLanguagesA1": "CEFR min. A1+", + "modernLanguagesA2": "CEFR min. A2", + "modernLanguagesAlt": "Alt modern language, CEFR min. A2", + "motherTounge": "Mother tongue tuition", + "unknown": "Unknown", + "misc": "Miscellaneous" + }, + "misc": { + "LUNCH": "Lunch", + "PRANDIUM": "Lunch", + "MTID": "Mentor time", + "RAST": "Break" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/es.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/es.json new file mode 100644 index 000000000..05a0dc6cf --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/es.json @@ -0,0 +1,41 @@ +{ + "specialLanguages": { + "SV": "Sueco", + "SP": "Español", + "SAM": "Sami", + "RY": "Ruso", + "PO": "Portugués", + "KI": "Chino", + "JAP": "Japonés", + "IT": "Italiano", + "FI": "Finlandés", + "FR": "Francés", + "EN": "Inglés" + }, + "traningsskolaSubjects": { + "VAA": "Actividades cotidianas", + "KOM": "Comunicación" + }, + "subjects": { + "ES": "Estética", + "DA": "Estudios preparatorios de baile", + "TK": "Tecnología", + "TN": "Lenguaje de signos", + "SVA": "Sueco como segunda lengua", + "SV": "Sueco", + "SL": "Artesanía", + "SH": "Educación cívica", + "RE": "Religión", + "HI": "Historia", + "GE": "Geografía", + "KE": "Química", + "FY": "Física", + "BI": "Biología", + "NO": "Ciencias Naturales", + "MU": "Música", + "MA": "Matemáticas", + "IDH": "Salud y educación física", + "HKK": "Estudios sobre el hogar y el consumidor", + "EN": "inglés" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/fr.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/fr.json new file mode 100644 index 000000000..6e964f431 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/fr.json @@ -0,0 +1,78 @@ +{ + "languages": { + "VIE": "Vietnamien", + "UZB": "Ouzbek", + "URD": "Ourdou", + "HUN": "Hongrois", + "UKR": "Ukrainien", + "UIG": "Ouïghour", + "ZUL": "Zoulou", + "YOR": "Yorouba", + "WOL": "Wolof", + "SPK": "Autre langue", + "SQI": "Albanais" + }, + "categories": { + "trainingSchool": "École obligatoire pour les enfants souffrant de graves difficultés d'apprentissage", + "motherTounge": "Cours de langue maternelle", + "modernLanguagesAlt": "Langue moderne Alt, CECR min. A2", + "modernLanguagesA2": "CECR min. A2", + "modernLanguagesA1": "CECR min. A1+", + "modernLanguages": "Langues modernes", + "misc": "Divers", + "unknown": "Inconnu" + }, + "misc": { + "RAST": "Pause", + "MTID": "Tutorat", + "PRANDIUM": "Déjeuner", + "LUNCH": "Déjeuner" + }, + "specialLanguages": { + "TY": "Allemand", + "TN": "Langue des signes", + "SVA": "Suédois comme deuxième langue", + "SV": "Suédois", + "SP": "Espagnol", + "SAM": "Same", + "RY": "Russe", + "PO": "Portugais", + "KI": "Chinois", + "JAP": "Japonais", + "IT": "Italien", + "FI": "Finnois", + "FR": "Français", + "EN": "Anglais" + }, + "traningsskolaSubjects": { + "VEU": "Perception", + "VAA": "Activités quotidiennes", + "MOT": "Coordination physique", + "KOM": "Communication" + }, + "subjects": { + "ES": "Esthétique", + "JU": "Études juives", + "DA": "Études préparatoires de danse", + "TK": "Technologie", + "TN": "Langue des signes", + "SVA": "Suédois comme deuxième langue", + "SV": "Suédois", + "SL": "Travaux manuels", + "SH": "Éducation civique", + "RE": "Religion", + "HI": "Histoire", + "GE": "Géographie", + "SO": "Sujets d'étude sociale", + "KE": "Chimie", + "FY": "Physique", + "BI": "Biologie", + "NO": "Études scientifiques", + "MU": "Musique", + "MA": "Mathématiques", + "IDH": "Éducation physique et santé", + "HKK": "Études économiques et domestiques", + "EN": "Anglais", + "BL": "Art" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/index.ts b/apps/skolplattformen-app-new/libs/curriculum/src/translations/index.ts new file mode 100644 index 000000000..ee336f922 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/index.ts @@ -0,0 +1,58 @@ +import merge from 'deepmerge' + +type Repo = Record +export interface Translation { + subjects: Repo + traningsskolaSubjects: Repo + languages: Repo + categories: Repo + misc: Repo +} +interface RawTranslation extends Translation { + specialLanguages: Repo +} + +const translations: Translations = { + sv: require('./sv.json'), + de: require('./de.json'), + en: require('./en.json'), + es: require('./es.json'), + fr: require('./fr.json'), + it: require('./it.json'), + ja: require('./ja.json'), + la: require('./la.json'), + nb_NO: require('./nb_NO.json'), + pl: require('./pl.json'), + pt: require('./pt.json'), + th: require('./th.json'), + uk: require('./uk.json'), + zh_Hans: require('./zh_Hans.json'), +} +const languageList: string[] = Object.keys(translations) +export type Language = (typeof languageList)[number] +type Translations = Record + +const translate = (lang: Language): Translation => { + const selectedLanguage = languageList.includes(lang) ? lang : languageList[0] + const { + subjects, + traningsskolaSubjects, + specialLanguages, + languages, + categories, + misc, + } = merge(translations.sv, translations[selectedLanguage]) + + return { + subjects, + traningsskolaSubjects, + categories, + misc, + languages: { + ...specialLanguages, + ...languages, + }, + } +} + +export default translate diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/it.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/it.json new file mode 100644 index 000000000..34f0d3cb9 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/it.json @@ -0,0 +1,51 @@ +{ + "misc": { + "PRANDIUM": "Pranzo", + "LUNCH": "Pranzo" + }, + "categories": { + "unknown": "Sconosciuta", + "motherTounge": "Madre lingua" + }, + "languages": { + "ITA": "Italiano", + "FRA": "Francese", + "TUR": "Turco", + "SPA": "Spagnolo", + "RUS": "Russo", + "POR": "Portogese", + "NOR": "Norvegese", + "KOR": "Coreano", + "ZHO": "Cinese", + "JPN": "Giapponese", + "ENG": "Inglese", + "DAN": "Danese", + "FIN": "Finlandese" + }, + "specialLanguages": { + "SVA": "Svedese come secondo lingua", + "SV": "Svedese", + "SP": "Spangnolo", + "IT": "Italiano", + "FR": "Francese", + "EN": "Inglese" + }, + "subjects": { + "TK": "Tecnologia", + "SVA": "Svedese come seconda lingua", + "SV": "Svedese", + "RE": "Religione", + "HI": "Storia", + "GE": "Geografia", + "KE": "Chimica", + "FY": "Fisica", + "BI": "Biologia", + "NO": "Scienze", + "MU": "Musica", + "MA": "Matematica", + "IDH": "Ed. fisica", + "HKK": "Cuchina", + "EN": "Inglese", + "BL": "Artistica" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/ja.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/ja.json new file mode 100644 index 000000000..36c12def9 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/ja.json @@ -0,0 +1,75 @@ +{ + "subjects": { + "SV": "スウェーデン語", + "MA": "数学", + "MU": "音楽", + "SVA": "第二言語としてスウェーデン語", + "IDH": "体育と健康", + "BI": "生物学", + "FY": "物理学", + "KE": "化学", + "EN": "英語学", + "GE": "地理学", + "HI": "歴史学", + "RE": "宗教学", + "SO": "社会科学", + "BL": "芸術学", + "NO": "自然科学", + "SH": "社会学" + }, + "languages": { + "KAL": "グリーンランド語", + "SLV": "スロベニア語", + "ARA": "アラビア語", + "AZE": "アゼルバイジャン語", + "BOS": "ボスニア語", + "MYA": "ビルマ語", + "DAN": "デンマーク語", + "ENG": "英語学", + "EST": "エストニア語", + "FIN": "フィンランド語", + "FRA": "フランス語", + "GRE": "ギリシャ語", + "HIN": "ヒンディー語", + "IND": "インドネシア語", + "ISL": "アイスランド語", + "JPN": "日本語", + "CAT": "カタロニア語", + "ZHO": "中国語", + "CMN": "北京語", + "YUE": "広東語", + "KOR": "韓国語", + "HRV": "クロアチア語", + "LAV": "ラトビア語", + "LIT": "リトアニア語", + "MKD": "マケドニア語", + "MLT": "マルタ語", + "POL": "ポーランド語", + "POR": "ポルトガル語", + "RON": "ルーマニア語", + "RUS": "ロシア語", + "SOM": "ソマリア語", + "SPA": "スペイン語", + "SRP": "セルビア語", + "HUN": "ハンガリー語", + "THA": "タイ語", + "CES": "チェコ語", + "TUR": "トルコ語", + "DEU": "ドイツ語", + "UKR": "ウクライナ語", + "BEN": "ベンガル語", + "BUL": "ブルガリア語", + "FIJ": "フィジー語", + "NEP": "ネパール語", + "NOR": "ノルウェー語", + "SLK": "スロバキア語", + "KAT": "ジョージア語", + "HEB": "ヘブライ語", + "ITA": "イタリア語", + "MRI": "マオリ語" + }, + "misc": { + "LUNCH": "昼休み", + "RAST": "休憩" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/la.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/la.json new file mode 100644 index 000000000..e8d6e71ff --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/la.json @@ -0,0 +1,63 @@ +{ + "languages": { + "AZE": "Lingua atropatenica", + "AYM": "Lingua aymara", + "AII": "Lingua Assyriae", + "HYE": "Lingua armeniaca", + "ARA": "Lingua arabica", + "AMH": "Lingua amharica", + "SQI": "Lingua albanica", + "AKA": "Lingua acanica", + "AFR": "Lingua batava capitensis", + "AAR": "Lingua afarica", + "ACH": "Lingua acholica", + "ACE": "Lingua acehnesiana" + }, + "specialLanguages": { + "TY": "Lingua germanica", + "TN": "Lingua gesticulationum", + "SVA": "Lingua suecica extranea", + "SV": "Lingua suecica", + "SP": "Lingua hispanica", + "SAM": "Lingua samica", + "RY": "Lingua russica", + "PO": "Lingua lusitanica", + "KI": "Lingua sinica", + "JAP": "Lingua iaponica", + "IT": "Lingua italica", + "FI": "Lingua finnica", + "FR": "Lingua francogallica", + "EN": "Lingua anglica" + }, + "traningsskolaSubjects": { + "VEU": "Perceptio", + "VAA": "Actiones vulgares", + "MOT": "Coordinatio corporalis", + "KOM": "Communicatio" + }, + "subjects": { + "ES": "Opera formosa", + "JU": "Studia iudaea", + "DA": "Studia praeparatoria saltatoria", + "TK": "Technologia", + "TN": "Lingua gesticulationum", + "SVA": "Lingua suecica extranea", + "SV": "Lingua suecica", + "SL": "Artes practicae", + "SH": "Scientia civilis", + "RE": "Scientia religiosa", + "HI": "Historia", + "GE": "Geographia", + "SO": "Scientiae rei publicae", + "KE": "Chemia", + "FY": "Physica", + "BI": "Biologia", + "HKK": "Scientia domi emptorisque", + "NO": "Scientia naturalis", + "MU": "Musica", + "MA": "Mathematica", + "IDH": "Exercitium sanitasque", + "EN": "Lingua anglica", + "BL": "Ars" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/nb_NO.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/nb_NO.json new file mode 100644 index 000000000..c1e9bcb57 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/nb_NO.json @@ -0,0 +1,76 @@ +{ + "languages": { + "POR": "Portugisisk", + "POL": "Polsk", + "JPN": "Japansk", + "ITA": "Italiensk", + "ISL": "Islandsk", + "IND": "Indonesisk", + "SPK": "Annet språk", + "FRA": "Fransk", + "DEU": "Tysk" + }, + "traningsskolaSubjects": { + "VAA": "Hverdagsaktiviteter", + "KOM": "Kommunikasjon", + "VEU": "Virkelighetsoppfatning", + "MOT": "Motorikk" + }, + "subjects": { + "ES": "Estetisk virksomhet", + "NO": "Naturfag", + "HKK": "Heimkunnskap", + "JU": "Jødiske studier", + "SO": "Samfunnsfag", + "SH": "Samfunnslære", + "KE": "Kjemi", + "IDH": "Idrett og helse", + "SL": "Sløyd", + "DA": "Forberedende dansestudie", + "TK": "Teknologi", + "TN": "Tegnspråk", + "SVA": "Svensk som andrespråk", + "SV": "Svensk", + "RE": "Religion", + "HI": "Historie", + "GE": "Geografi", + "FY": "Fysikk", + "BI": "Biologi", + "MU": "Musikk", + "MA": "Matematikk", + "EN": "Engelsk", + "BL": "Kunst" + }, + "misc": { + "PRANDIUM": "Lunsj", + "LUNCH": "Lunsj", + "RAST": "Pause", + "MTID": "Mentortid" + }, + "categories": { + "misc": "Ymse", + "unknown": "Ukjent", + "modernLanguages": "Moderne språk", + "motherTounge": "Morsmålsopplæring", + "modernLanguagesAlt": "Alt moderne språk, språkvalg", + "modernLanguagesA2": "Språkvalg", + "modernLanguagesA1": "Elevens valg", + "trainingSchool": "Grunnskole for elever med lærevansker" + }, + "specialLanguages": { + "TY": "Tysk", + "TN": "Tegnspråk", + "SVA": "Svensk som andrespråk", + "SV": "Svensk", + "SP": "Spansk", + "SAM": "Samisk", + "RY": "Russisk", + "PO": "Portugisisk", + "KI": "Kinesisk", + "JAP": "Japansk", + "IT": "Italiensk", + "FI": "Finsk", + "FR": "Fransk", + "EN": "Engelsk" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/pl.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/pl.json new file mode 100644 index 000000000..f7bdae517 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/pl.json @@ -0,0 +1,225 @@ +{ + "languages": { + "MAL": "Malayalami", + "MSA": "Język malgaski", + "MKD": "Język macedoński", + "LUO": "Luo", + "LUG": "Luganda/Ganda", + "LIT": "Język litewski", + "LIN": "Język lingala", + "LMA": "Limba", + "LAV": "Język łotewski", + "LAO": "Język laotański", + "SDH": "Kurdyjski, południowy", + "KMR": "Kurdyjski, północny", + "CKB": "Kurdyjski, centrowy.", + "KUR": "Język kurdyjski", + "HRV": "Język chorwacki", + "ROP": "Kreolski", + "KOR": "Język koreański", + "KIR": "Język kirgiski", + "NAN": "Chiński, Min Nan", + "YUE": "Chiński, kantoński", + "HAK": "Chiński, hakka", + "CMN": "Język chiński, mandaryński", + "ZHO": "Język chiński", + "KAZ": "Język kazachski", + "CAT": "Język kataloński", + "KAR": "Język kareński", + "KAN": "Język kannada", + "KHM": "Język khmerski", + "YID": "Język jidisz", + "JPN": "Język japoński", + "ITA": "Język włoski", + "ISL": "Język islandzki", + "IND": "Język indonezyjski", + "HIN": "Język hindi", + "HEB": "Język hebrajski", + "GUJ": "Język gujarati", + "KAL": "Język grenlandzki", + "GRE": "Język grecki", + "KAT": "Język gruziński", + "GAA": "Język ga", + "FAO": "Język farerski", + "FRA": "Język francuski", + "VLS": "Język flamandzki", + "FIN": "Język fiński", + "FIJ": "Język fidżyjski", + "EST": "Język estoński", + "ENG": "Język angielski", + "PRS": "Dari, Parsi, perski", + "DAN": "Język duński", + "MYA": "Język birmański", + "TIG": "Język tigre", + "TIB": "Język tybetański", + "THA": "Język tajski", + "TEL": "Język telugu", + "TAT": "Język tatarski", + "TAM": "Język tamilski", + "TLG": "Język tagalski", + "TRU": "Syryjski, Turoyo", + "SYR": "Język syryjski", + "SYC": "Syryjski/Asyryjski, suryaya, suryoyo", + "SWA": "Język suahili", + "SPA": "Język hiszpański", + "SOM": "Język somalijski", + "SLV": "Język słoweński", + "SLK": "Język słowacki", + "SIN": "Język cejloński", + "SNA": "Shona", + "SOT": "Sesotho, Sisutho, Souto, Suthu, Suto", + "HBS": "Język serbsko-chorwacki", + "SRP": "Język serbski", + "SMO": "Język samoański", + "SJU": "Język ume", + "SMA": "Język południowosaamski", + "SJE": "Język saamski pite", + "SMJ": "Język lule", + "SMI": "Język saamski", + "NSM": "Język północnosaamski", + "SSY": "Język saho", + "RUS": "Język rosyjski", + "RON": "Język rumuński", + "RMY": "Romani, Lovari, Kalderari", + "RMU": "Romani, Tavringer", + "RMO": "Romani, Sinti", + "RMF": "Romani, Kalé", + "RMN": "Romani, Arli", + "RML": "Romani, Baltic", + "RMC": "Romani, Karpaty", + "ROM": "Romani", + "PAN": "Język pendżabski", + "POR": "Język portugalski", + "POL": "Język polski", + "FAS": "Język perski", + "PTN": "Patani", + "PUS": "Język paszto", + "ORM": "Język oromo", + "NYA": "Język nyanja", + "NOR": "Język norweski", + "NEP": "Język nepalski", + "NLD": "Język holenderski", + "MON": "Język mongolski", + "FIT": "Meänkieli", + "MYX": "Masaaba, Gisu, Gugisu, Lumasaaba, Masaba", + "MAR": "Marathi", + "MRI": "Język maoryjski", + "MNK": "Język mandinka", + "MLT": "Język maltański", + "BUL": "Język bułgarski", + "BOS": "Język bośniacki", + "BER": "Język berberyjski", + "BEN": "Język bengalski", + "BAM": "Język bambara", + "AZE": "Język azerski", + "ARA": "Język arabski", + "AMH": "Język amharski", + "SQI": "Język albański", + "AFR": "Język afrikaans", + "ACH": "Język akoli", + "YOR": "Yoruba, Yariba, Yooba", + "TSN": "Tswana, Setswana", + "TON": "Język tongan", + "DAR": "Darginska, Dargi, Dargin, Dargintsy, Khiurkilinskii, Uslar", + "AYM": "Ajmarski", + "MLG": "Malagaskiska", + "KRO": "Kru", + "KON": "Kongo", + "RUN": "Kirundi", + "KIN": "Kinyarwanda", + "KIK": "Kikuyu", + "KAM": "Kamba, Kekamba, Kikamba", + "IBO": "Ibo", + "EWE": "Ewe", + "DIV": "Divehi", + "DMQ": "Dimli", + "CEB": "Cebuanska, Binisaya, Sebuano, Sugbuanon, Sugbuhanon, Visayan", + "BYN": "Bilen, Bilein, Bileno, Bilin", + "BIL": "Bile", + "BEM": "Bemba, Chibemba, Chiwemba, Ichibemba, Wemba", + "EUS": "Język baskijski", + "BAI": "Język bamileke", + "BAL": "Baluchi, Baloci, Baluci, Makrani", + "AII": "Assyriska, Nyarameiska", + "HYE": "Język ormiański", + "AKA": "Akan, Asante, Fante", + "AAR": "Afar, Danakil", + "ACE": "Acehnesiska", + "SPK": "Inne języki", + "ZUL": "Język zulu", + "WOL": "Język wolof", + "VIE": "Język wietnamski", + "UZB": "Język uzbecki", + "URD": "Język urdu", + "HUN": "Język węgierski", + "UKR": "Język ukraiński", + "UIG": "Język ujgurski", + "DEU": "Język niemiecki", + "TUR": "Język turecki", + "CES": "Język czeski", + "TIR": "Język tigrinia" + }, + "specialLanguages": { + "TY": "Język niemiecki", + "TN": "Język migowy", + "SVA": "Szwedzki jako drugi język", + "SV": "Język szwedzki", + "SP": "Język hiszpański", + "SAM": "Język saamski", + "RY": "Język rosyjski", + "PO": "Język portugalski", + "KI": "Język chiński", + "JAP": "Język japoński", + "IT": "Język włoski", + "FI": "Język fiński", + "FR": "Język francuski", + "EN": "Język angielski" + }, + "traningsskolaSubjects": { + "MOT": "Motoryka", + "KOM": "Komunikacja", + "VAA": "Codzienne czynności", + "VEU": "Postrzeganie rzeczywistości" + }, + "subjects": { + "TK": "Technika", + "TN": "Język migowy", + "SVA": "Szwedzki jako drugi język", + "SV": "Język szwedzki", + "RE": "Religioznawstwo", + "HI": "Historia", + "GE": "Geografia", + "KE": "Chemia", + "FY": "Fizyka", + "BI": "Biologia", + "MU": "Muzyka", + "MA": "Matematyka", + "IDH": "Wychowanie fizyczne", + "EN": "Język angielski", + "BL": "Zajęcia plastyczne", + "ES": "Estetyka", + "DA": "Przygotowawcze studia taneczne", + "SL": "Rzemieślnictwo", + "SH": "Wiedza o społeczeństwie", + "SO": "Przedmioty społeczne", + "NO": "Nauki ścisłe", + "HKK": "Wiedza o domu i konsumentach", + "JU": "Judaistyka" + }, + "categories": { + "trainingSchool": "Szkoła obowiązkowa dla dzieci ze znacznymi trudnościami w nauce", + "misc": "Różne", + "unknown": "Nieznany", + "motherTounge": "Język ojczysty", + "modernLanguagesAlt": "Alternatywny język nowożytny, CEFR min. A2", + "modernLanguagesA2": "språkval", + "modernLanguagesA1": "elevens val", + "modernLanguages": "Języki nowożytne" + }, + "misc": { + "LUNCH": "Lunch", + "MTID": "Czas z mentorem", + "PRANDIUM": "Lunch", + "RAST": "Przerwa" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/pt.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/pt.json new file mode 100644 index 000000000..3d80896f5 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/pt.json @@ -0,0 +1,131 @@ +{ + "subjects": { + "HKK": "Estudos domésticos e de consumo", + "BL": "Arte", + "EN": "Inglês", + "MA": "Matemática", + "MU": "Música", + "BI": "Biologia", + "FY": "Física", + "GE": "Geografia", + "NO": "Estudos científicos", + "KE": "Química", + "SO": "Temas de estudos sociais", + "IDH": "Educação física e saúde", + "TN": "Linguagem gestual", + "ES": "Estética", + "HI": "História", + "RE": "Religião", + "SH": "Educação cívica", + "SL": "Trabalhos manuais", + "SV": "Sueco", + "DA": "Estudos preparatórios de dança", + "JU": "Estudos judaicos", + "SVA": "Sueco como segunda língua", + "TK": "Tecnologia" + }, + "traningsskolaSubjects": { + "VAA": "Atividades diárias", + "VEU": "Percepção", + "KOM": "Comunicação", + "MOT": "Coordenação física" + }, + "languages": { + "KMR": "Curdo, norte", + "HUN": "Húngaro", + "BUL": "Búlgaro", + "ISL": "Islandês", + "KOR": "Coreano", + "SDH": "Curdo, sul", + "LIT": "Lituano", + "CKB": "Curdo, central", + "AMH": "Amárico", + "HYE": "Arménio", + "AYM": "Aimará", + "MYA": "Birmanês", + "DAN": "Dinamarquês", + "VLS": "Flamengo", + "HEB": "Hebraico", + "ITA": "Italiano", + "CAT": "Catalão", + "KUR": "Curdo", + "MLT": "Maltês", + "NOR": "Norueguês", + "RON": "Romeno", + "TIB": "Tibetano", + "UKR": "Ucraniano", + "AFR": "Africâner", + "SQI": "Albanês", + "BOS": "Bósnio", + "EST": "Estoniano", + "FIJ": "Fijiano", + "FIN": "Finlandês", + "FRA": "Francês", + "KAT": "Georgiano", + "GRE": "Grego", + "GUJ": "Gujarati", + "IND": "Indonésio", + "YID": "Iídiche", + "KAZ": "Cazaque", + "ZHO": "Chinês", + "NAN": "Chinês, min nan", + "ROP": "Crioulo", + "HRV": "Croata", + "FAS": "Persa", + "POR": "Português", + "RUS": "Russo", + "SLK": "Eslovaco", + "ARA": "Árabe", + "JPN": "Japonês", + "YUE": "Chinês, cantonês", + "LAV": "Letão", + "DEU": "Alemão", + "VIE": "Vietnamita", + "CMN": "Chinês, mandarim", + "MKD": "Macedónio", + "LAO": "Laociano", + "NLD": "Holandês", + "NEP": "Nepalês", + "HBS": "Servo-croata", + "SLV": "Esloveno", + "SPA": "Espanhol", + "CES": "Checo", + "TUR": "Turco", + "SPK": "Outro idioma", + "ACE": "Acenésico", + "ACH": "Acoli", + "AAR": "Afar, Danakil", + "AII": "Assírico, Novo arameico", + "AZE": "Azerbaijano", + "BEN": "Bengalês", + "BER": "Berbere" + }, + "specialLanguages": { + "SVA": "O sueco como segunda língua", + "EN": "Inglês", + "FR": "Francês", + "IT": "Italiano", + "SV": "Sueco", + "PO": "Português", + "RY": "Russo", + "SAM": "Sami", + "SP": "Espanhol", + "TN": "Linguagem gestual", + "TY": "Alemão", + "FI": "Finlandês", + "JAP": "Japonês", + "KI": "Chinês" + }, + "categories": { + "trainingSchool": "Escola obrigatória para crianças com graves dificuldades de aprendizagem", + "modernLanguages": "Idiomas modernos", + "unknown": "Desconhecido", + "misc": "Diversos" + }, + "misc": { + "RAST": "Intervalo", + "MTID": "Tempo do mentor", + "LUNCH": "Almoço", + "PRANDIUM": "Almoço" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/sv.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/sv.json new file mode 100644 index 000000000..fa415eba8 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/sv.json @@ -0,0 +1,225 @@ +{ + "subjects": { + "BL": "Bild", + "EN": "Engelska", + "HKK": "Hem & Konsumentkunskap", + "IDH": "Idrott & Hälsa", + "MA": "Matematik", + "MU": "Musik", + "NO": "Naturorienterande ämnen", + "BI": "Biologi", + "FY": "Fysik", + "KE": "Kemi", + "SO": "Samhällsorienterande ämnen", + "GE": "Geografi", + "HI": "Historia", + "RE": "Religionskunskap", + "SH": "Samhällskunskap", + "SL": "Slöjd", + "SV": "Svenska", + "SVA": "Svenska som andraspråk", + "TN": "Teckenspråk", + "TK": "Teknik", + "DA": "Förberedande dansarutbildning", + "JU": "Judiska studier", + "ES": "Estetisk verksamhet" + }, + "traningsskolaSubjects": { + "KOM": "Kommunikation", + "MOT": "Motorik", + "VAA": "Vardagsaktiviteter", + "VEU": "Verklighetsuppfattning" + }, + "specialLanguages": { + "EN": "Engelska", + "FR": "Franska", + "FI": "Finska", + "IT": "Italienska", + "JAP": "Japanska", + "KI": "Kinesiska", + "PO": "Portugisiska", + "RY": "Ryska", + "SAM": "Samiska", + "SP": "Spanska", + "SV": "Svenska", + "SVA": "Svenska som andraspråk", + "TN": "Teckenspråk", + "TY": "Tyska" + }, + "languages": { + "ACE": "Acehnesiska", + "ACH": "Acholi", + "AAR": "Afar, Danakil", + "AFR": "Afrikaans", + "AKA": "Akan", + "SQI": "Albanska", + "AMH": "Amhariska", + "ARA": "Arabiska", + "HYE": "Armeniska", + "AII": "Assyriska, Nyarameiska", + "AYM": "Aymara", + "AZE": "Azerbadjanska", + "BAL": "Baluchiska", + "BAM": "Bambara", + "BAI": "Bamileke", + "EUS": "Baskiska", + "BEM": "Bemba", + "BEN": "Bengaliska", + "BER": "Berbiska", + "BIL": "Bile", + "BYN": "Bilen, Bilein, Bileno, Bilin", + "BOS": "Bosniska", + "BUL": "Bulgariska", + "MYA": "Burmesiska", + "CEB": "Cebuanska, Binisaya, Sebuano, Sugbuanon, Sugbuhanon, Visayan", + "DAN": "Danska", + "DAR": "Darginska, Dargi, Dargin, Dargintsy, Khiurkilinskii, Uslar", + "PRS": "Dari, Parsi, Persian", + "DMQ": "Dimli", + "DIV": "Divehi", + "ENG": "Engelska", + "EST": "Estniska", + "EWE": "Ewe", + "FIJ": "Fijianska", + "FIN": "Finska", + "VLS": "Flamländska", + "FRA": "Franska", + "FAO": "Färöiska", + "GAA": "Ga", + "KAT": "Georgiska", + "GRE": "Grekiska", + "KAL": "Grönländska", + "GUJ": "Gujarati", + "HEB": "Hebreiska", + "HIN": "Hindi", + "IBO": "Ibo", + "IND": "Indonesiska", + "ISL": "Isländska", + "ITA": "Italienska", + "JPN": "Japanska", + "YID": "Jiddisch", + "KAM": "Kamba", + "KHM": "Khmer", + "KAN": "Kannada", + "KAR": "Karenska", + "CAT": "Katalanska", + "KAZ": "Kazakiska", + "KIK": "Kikuyu", + "ZHO": "Kinesiska", + "CMN": "Kinesiska, Mandarin", + "HAK": "Kinesiska, Hakka", + "YUE": "Kinesiska, Kantonesiska", + "NAN": "Kinesiska, Min Nan", + "KIN": "Kinyarwanda", + "KIR": "Kirgisiska", + "RUN": "Kirundi", + "KON": "Kongo", + "KOR": "Koreanska", + "ROP": "Kreolska", + "HRV": "Kroatiska", + "KRO": "Kru", + "KUR": "Kurdiska", + "CKB": "Kurdiska, centr.", + "KMR": "Kurdiska, norra", + "SDH": "Kurdiska, södra", + "LAO": "Laotiska", + "LAV": "Lettiska", + "LMA": "Limba", + "LIN": "Lingala", + "LIT": "Litauiska", + "LUG": "Luganda/Ganda", + "LUO": "Luo", + "MKD": "Makedonska", + "MLG": "Malagaskiska", + "MSA": "Malajiska", + "MAL": "Malayalami", + "MLT": "Maltesiska", + "MNK": "Mandinka", + "MRI": "Maori", + "MAR": "Marathi", + "MYX": "Masaaba, Gisu, Gugisu, Lumasaaba, Masaba", + "FIT": "Meänkieli", + "MON": "Mongoliska", + "NLD": "Nederländska", + "NEP": "Nepalesiska", + "NOR": "Norska", + "NYA": "Nyanja", + "ORM": "Oromo", + "PUS": "Pashto", + "PTN": "Patani", + "FAS": "Persiska", + "POL": "Polska", + "POR": "Portugisiska", + "PAN": "Punjabi", + "ROM": "Romani", + "RMC": "Romani, Karpaterna", + "RML": "Romani, Baltisk", + "RMN": "Romani, Arli", + "RMF": "Romani, Kalé", + "RMO": "Romani, Sinti", + "RMU": "Romani, Tavringer", + "RMY": "Romani, Lovari, Kalderari", + "RON": "Rumänska", + "RUS": "Ryska", + "SSY": "Saho", + "NSM": "Samiska, (norra)", + "SMI": "Samiska", + "SMJ": "Samiska, Lulesamiska", + "SJE": "Samiska, Pitesamiska", + "SMA": "Samiska, Sydsamiska", + "SJU": "Samiska, Umesamiska", + "SMO": "Samoanska", + "SRP": "Serbiska", + "HBS": "Serbokroatiska", + "SOT": "Sydsotho", + "SNA": "Shona", + "SIN": "Singalesiska", + "SLK": "Slovakiska", + "SLV": "Slovenska", + "SOM": "Somaliska", + "SPA": "Spanska", + "SWA": "Swahili", + "SYC": "Syrianska/assyriska, suryaya, suryoyo", + "SYR": "Syriska", + "TRU": "Syriska, Turoyo", + "TLG": "Tagalog", + "TAM": "Tamil", + "TAT": "Tatariska", + "TEL": "Telugu", + "THA": "Thai", + "TIB": "Tibetanska", + "TIG": "Tigre", + "TIR": "Tigrinja", + "CES": "Tjeckiska", + "TON": "Tonganska", + "TSN": "Tswana", + "TUR": "Turkiska", + "DEU": "Tyska", + "UIG": "Uiguriska", + "UKR": "Ukrainska", + "HUN": "Ungerska", + "URD": "Urdu", + "UZB": "Uzbekiska", + "VIE": "Vietnamesiska", + "WOL": "Wolof", + "YOR": "Yoruba", + "ZUL": "Zulu", + "SPK": "Övriga språk" + }, + "categories": { + "trainingSchool": "Träningsskolan", + "modernLanguages": "Moderna språk", + "modernLanguagesA1": "elevens val", + "modernLanguagesA2": "språkval", + "modernLanguagesAlt": "Alt moderna språk, språkval", + "motherTounge": "Modersmål", + "unknown": "Okänd", + "misc": "Diverse" + }, + "misc": { + "LUNCH": "Lunch", + "PRANDIUM": "Lunch", + "MTID": "Mentorstid", + "RAST": "Rast" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/th.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/th.json new file mode 100644 index 000000000..5b86a5294 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/th.json @@ -0,0 +1,65 @@ +{ + "languages": { + "SQI": "ภาษาแอลเบเนีย", + "FRA": "ภาษาฝรั่งเศส", + "MYA": "ภาษาพม่า", + "AII": "ภาษาอัสซีเรีย", + "AAR": "ภาษา Afar ดานาคิล", + "AFR": "ภาษาแอฟริกัน", + "ACE": "ภาษาอาเจะห์", + "ACH": "ภาษาอโชลี", + "AKA": "ภาษาอะกัน", + "ARA": "ภาษาอารบ", + "HYE": "ภาษาอาร์เมเนีย", + "AYM": "ภาษาไอมารา", + "AZE": "ภาษาอาเซอร์ไบจัน", + "DAN": "ภาษาเดนมาร์ก", + "ENG": "ภาษาอังกฤษ", + "GRE": "ภาษากรีก", + "ITA": "ภาษาอิตาลี", + "JPN": "ภาษาญี่ปุ่น", + "ZHO": "ภาษาจีน", + "AMH": "ภาษาอัมฮาริก" + }, + "subjects": { + "BL": "ศิลปะศึกษา", + "EN": "ภาษาอังกฤษ", + "MA": "คณิตศาสตร์", + "NO": "วิทยาศาสตร์ธรรมชาติ", + "FY": "ฟิสิกส์", + "SO": "สังคมศึกษา", + "HI": "ประวัติศาสตร์", + "RE": "ศาสนา", + "SH": "หน้าที่พลเมืองศึกษา", + "SV": "ภาษาสวีเดน", + "IDH": "กีฬาและสุขภาพ", + "GE": "ภูมิศาสตร์", + "SL": "งานฝีมือ", + "SVA": "ภาษาสวีเดนเป็นภาษาที่สอง", + "TN": "ภาษามือ", + "TK": "เทคโนโลยี", + "ES": "สุนทรียภาพ", + "MU": "ดนตรี", + "KE": "เคมี", + "BI": "ชีววิทยา" + }, + "traningsskolaSubjects": { + "KOM": "การสื่อสาร" + }, + "specialLanguages": { + "EN": "ภาษาอังกฤษ", + "FR": "ภาษาฝรั่งเศส", + "FI": "ภาษาฟินแลนด์", + "IT": "ภาษาอิตาลี", + "JAP": "ภาษาญี่ปุ่น", + "KI": "ภาษาจีน", + "PO": "ภาษาโปรตุเกส", + "SP": "ภาษาสเปน", + "SV": "ภาษาสวีเดน", + "SVA": "ภาษาสวีเดนเป็นภาษาที่สอง", + "TN": "ภาษามือ", + "TY": "ภาษาเยอรมัน", + "RY": "ภาษารัสเซีย", + "SAM": "ภาษาซามิ" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/uk.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/uk.json new file mode 100644 index 000000000..82af681d3 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/uk.json @@ -0,0 +1,127 @@ +{ + "languages": { + "MON": "Монгольська", + "ROM": "Румуньська", + "SLV": "Словенська", + "SOM": "Сомалійська", + "SPA": "Іспанська", + "TAT": "Татарська", + "SPK": "Інша мова", + "SQI": "Албанська", + "ARA": "Арабська", + "AZE": "Азербайджанська", + "BEN": "Бенгальська", + "BOS": "Боснійська", + "BUL": "Болгарська", + "DAN": "Датська", + "ENG": "Англійська", + "EST": "Естонська", + "FIJ": "Фіджійська", + "FIN": "Фінська", + "VLS": "Фламандська", + "FRA": "Французська", + "HEB": "Іврит", + "HIN": "Хінді", + "IND": "Індонезійська", + "ISL": "Ісландська", + "ITA": "Італійська", + "JPN": "Японська", + "YID": "Ідіш", + "CAT": "Каталанська", + "ZHO": "Китайська", + "YUE": "Китайська, Кантонійська", + "HRV": "Хорватська", + "KUR": "Курдська", + "LAV": "Латвійська", + "LIT": "Литовська", + "MKD": "Македонська", + "MLT": "Мальтійська", + "AFR": "Південно-африканська", + "HYE": "Армянська", + "GRE": "Грецька", + "CMN": "Китайська, Мандаринська", + "NEP": "Непальська", + "NOR": "Норвезька", + "FAS": "Персійська", + "KAT": "Грузинська", + "KOR": "Корейська", + "POR": "Португальська", + "RON": "Румунська", + "NSM": "Самі", + "TIB": "Тібетська", + "KAL": "Гренладська", + "KAZ": "Казахська", + "KIR": "Киргизська", + "NLD": "Нідерландська", + "SMI": "Самі", + "POL": "Польська", + "DEU": "Німецька", + "RUS": "Російська", + "TUR": "Турецька", + "SRP": "Сербська", + "HBS": "Сербо-хорватська", + "SLK": "Словацька", + "SWA": "Суахілі", + "SYR": "Сирійська", + "THA": "Тайська", + "CES": "Чеська", + "UKR": "Українська", + "HUN": "Угорська", + "UZB": "Узбекська", + "VIE": "В'єтнамська" + }, + "categories": { + "modernLanguages": "Сучасні мови", + "modernLanguagesA1": "CEFR принаймні A1+", + "modernLanguagesA2": "CEFR принаймні A2", + "modernLanguagesAlt": "Інша сучасна мова, CEFR принаймні A2", + "unknown": "Невідома", + "misc": "Різне" + }, + "misc": { + "RAST": "Перерва", + "LUNCH": "Обід", + "PRANDIUM": "Обід" + }, + "subjects": { + "BL": "Мистецтво", + "MA": "Математика", + "MU": "Музика", + "NO": "Наука", + "FY": "Фізика", + "TN": "Мова жестів", + "ES": "Естетика", + "IDH": "Фізичне виховання", + "SV": "Шведська", + "TK": "Технології", + "EN": "Англійська", + "BI": "Біологія", + "KE": "Хімія", + "GE": "Географія", + "RE": "Релігія", + "HI": "Історія", + "SVA": "Шведська як друга мова" + }, + "traningsskolaSubjects": { + "VAA": "Щоденні справи", + "VEU": "Сприйняття", + "KOM": "Комунікації", + "MOT": "Фізична координація" + }, + "specialLanguages": { + "FR": "Французська", + "IT": "Італійська", + "KI": "Китайська", + "PO": "Португальська", + "RY": "Російська", + "SAM": "Мова Самі", + "SP": "Іспанська", + "TN": "Мова жестів", + "EN": "Англійська", + "JAP": "Японська", + "SVA": "Шведська як друга мова", + "TY": "Німецька", + "FI": "Фінська", + "SV": "Шведська" + } +} diff --git a/apps/skolplattformen-app-new/libs/curriculum/src/translations/zh_Hans.json b/apps/skolplattformen-app-new/libs/curriculum/src/translations/zh_Hans.json new file mode 100644 index 000000000..1da08a0a9 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/curriculum/src/translations/zh_Hans.json @@ -0,0 +1,71 @@ +{ + "subjects": { + "BL": "美术", + "HKK": "家庭和消费者研究", + "IDH": "体育与健康", + "MA": "数学", + "MU": "音乐", + "BI": "生物", + "FY": "物理", + "KE": "化学", + "SO": "社会研究项目", + "GE": "地理", + "HI": "历史", + "RE": "宗教学", + "SH": "公民学", + "SL": "手工课", + "SV": "瑞典语", + "SVA": "瑞典语(第二语言)", + "TN": "手语", + "TK": "技术", + "JU": "犹太学", + "ES": "美学", + "EN": "英语", + "NO": "科学研究", + "DA": "预备舞蹈研究" + }, + "traningsskolaSubjects": { + "MOT": "身体协调", + "VAA": "日常活动", + "VEU": "感知课", + "KOM": "传媒学" + }, + "specialLanguages": { + "EN": "英语", + "IT": "意大利语", + "JAP": "日语", + "KI": "汉语", + "PO": "葡萄牙语", + "SAM": "萨米语", + "SP": "西班牙语", + "SV": "瑞典语", + "SVA": "瑞典语(第二语言)", + "TN": "手语", + "TY": "德语", + "FR": "法语", + "RY": "俄语", + "FI": "芬兰语" + }, + "languages": { + "ACE": "亚齐语", + "ACH": "阿科利语", + "SPK": "其他语言", + "ZUL": "祖鲁语", + "TUR": "土耳其语", + "DEU": "德语", + "UIG": "维吾尔语", + "UKR": "乌克兰语", + "HUN": "匈牙利语", + "URD": "乌尔都语", + "UZB": "乌兹别克语", + "VIE": "越南语", + "WOL": "沃洛夫语", + "YOR": "约鲁巴语、雅里巴语、约巴语" + }, + "categories": { + "unknown": "未知", + "modernLanguages": "现代语言", + "trainingSchool": "重度学习障碍儿童义务教育学校", + "misc": "杂项" + } +} diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/@skolplattformen/embedded-api.js b/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/@skolplattformen/embedded-api.js new file mode 100644 index 000000000..109055b6d --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/@skolplattformen/embedded-api.js @@ -0,0 +1,32 @@ +import { EventEmitter } from 'events' + +const emitter = new EventEmitter() + +const createApi = () => ({ + emitter, + isLoggedIn: false, + login: jest.fn(), + logout: jest.fn(), + on: jest.fn().mockImplementation((...args) => emitter.on(...args)), + off: jest.fn().mockImplementation((...args) => emitter.off(...args)), + + getSession: jest.fn(), + getPersonalNumber: jest.fn(), + + getCalendar: jest.fn(), + getChildren: jest.fn(), + getSkola24Children: jest.fn(), + getClassmates: jest.fn(), + getMenu: jest.fn(), + getNews: jest.fn(), + getNewsDetails: jest.fn(), + getNotifications: jest.fn(), + getSchedule: jest.fn(), + getSchoolContacts: jest.fn(), + getTeachers: jest.fn(), + getTimetable: jest.fn(), + getUser: jest.fn(), +}) +const init = jest.fn().mockImplementation(() => createApi()) + +export default init diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/AsyncStorage.js b/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/AsyncStorage.js new file mode 100644 index 000000000..341904f44 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/AsyncStorage.js @@ -0,0 +1,27 @@ +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +export default (init = {}, delay = 0) => { + const cache = {} + Object.keys(init).forEach((key) => { + cache[key] = JSON.stringify(init[key]) + }) + const getItem = async (key) => { + await pause(delay) + return cache[key] || null + } + const setItem = async (key, val) => { + await pause(delay) + cache[key] = val + } + const clear = () => { + Object.keys(cache).forEach((key) => { + cache[key] = undefined + }) + } + return { + getItem, + setItem, + cache, + clear, + } +} diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/reporter.js b/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/reporter.js new file mode 100644 index 000000000..ae27bbdad --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__mocks__/reporter.js @@ -0,0 +1,6 @@ +const reporter = { + log: jest.fn().mockName('log'), + error: jest.fn().mockName('error'), +} + +export default reporter diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/childlists.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/childlists.test.js new file mode 100644 index 000000000..d5d002869 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/childlists.test.js @@ -0,0 +1,82 @@ +import { merge } from '../childlists' + +describe('childlists', () => { + describe('merge', () => { + it('works with empty skola24children list', () => { + const etjanstChildren = [ + { name: 'Uwe Übrink (elev)' }, + { name: 'Cassius Übrink (elev)' }, + ] + const skola24Children = [] + + const children = [ + { name: 'Uwe Übrink (elev)' }, + { name: 'Cassius Übrink (elev)' }, + ] + expect(merge(etjanstChildren, skola24Children)).toEqual(children) + }) + it('works with same length skola24children list', () => { + const etjanstChildren = [ + { name: 'Uwe Übrink (elev)' }, + { name: 'Cassius Übrink (elev)' }, + ] + const skola24Children = [ + { firstName: 'Uwe', lastName: 'Vredstein Übrink' }, + { firstName: 'Cassius', lastName: 'Vredstein Übrink' }, + ] + + const children = [ + { + name: 'Uwe Übrink (elev)', + firstName: 'Uwe', + lastName: 'Vredstein Übrink', + }, + { + name: 'Cassius Übrink (elev)', + firstName: 'Cassius', + lastName: 'Vredstein Übrink', + }, + ] + expect(merge(etjanstChildren, skola24Children)).toEqual(children) + }) + it('works with different length skola24children list', () => { + const etjanstChildren = [ + { name: 'Uwe Übrink (elev)' }, + { name: 'Cassius Übrink (elev)' }, + ] + const skola24Children = [ + { firstName: 'Uwe', lastName: 'Vredstein Übrink' }, + ] + + const children = [ + { + name: 'Uwe Übrink (elev)', + firstName: 'Uwe', + lastName: 'Vredstein Übrink', + }, + { name: 'Cassius Übrink (elev)' }, + ] + expect(merge(etjanstChildren, skola24Children)).toEqual(children) + }) + it('works with non matching skola24children list', () => { + const etjanstChildren = [ + { name: 'Uwe Übrink (elev)' }, + { name: 'Cassius Übrink (elev)' }, + ] + const skola24Children = [ + { firstName: 'Uwe', lastName: 'Vredstein Übrink' }, + { firstName: 'Rolph', lastName: 'Gögendorff Bröök' }, + ] + + const children = [ + { + name: 'Uwe Übrink (elev)', + firstName: 'Uwe', + lastName: 'Vredstein Übrink', + }, + { name: 'Cassius Übrink (elev)' }, + ] + expect(merge(etjanstChildren, skola24Children)).toEqual(children) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/context.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/context.test.js new file mode 100644 index 000000000..04ee74938 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/context.test.js @@ -0,0 +1,49 @@ +import React from 'react' +import { act, renderHook, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import init from '../__mocks__/@skolplattformen/embedded-api' +import { useApi } from '../context' + +describe('useApi()', () => { + let api + beforeEach(() => { + api = init() + }) + const wrapper = ({ children }) => ( + {children} + ) + + it('exposes api', () => { + const { result } = renderHook(() => useApi(), { wrapper }) + + expect(result.current.api).toBeTruthy() + }) + + it('exposes isLoggedIn', () => { + const { result } = renderHook(() => useApi(), { wrapper }) + + expect(result.current.isLoggedIn).toBe(false) + }) + + it('updates isLoggedIn', async () => { + const { result } = renderHook(() => useApi(), { + wrapper, + }) + await act(async () => { + api.isLoggedIn = true + api.emitter.emit('login') + }) + await waitFor(() => expect(result.current.isLoggedIn).toBe(true)) + }) + + it('updates isFake', async () => { + const { result } = renderHook(() => useApi(), { + wrapper, + }) + await act(async () => { + api.isFake = true + api.emitter.emit('login') + }) + await waitFor(() => expect(result.current.isFake).toBe(true)) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/fake.test.tsx b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/fake.test.tsx new file mode 100644 index 000000000..ba7d247b9 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/fake.test.tsx @@ -0,0 +1,142 @@ +import { renderHook, waitFor } from '@testing-library/react' +import React from 'react' +import { ApiProvider } from '../provider' +import { + useCalendar, + useClassmates, + useEtjanstChildren, + useMenu, + useNews, + useNotifications, + useSchedule, + useUser, +} from '../hooks' +import store from '../store' +import createStorage from '../__mocks__/AsyncStorage' + +const { default: init } = jest.requireActual( + '../../../api-skolplattformen/lib/index.ts' +) + +const wait = (ms: number) => new Promise((res) => setTimeout(res, ms)) + +describe('hooks with fake data', () => { + let api: any + let storage: any + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ) + beforeEach(async () => { + api = init( + () => { + // noop + }, + () => { + //noop + } + ) + await api.login('121212121212') + + storage = createStorage({}) + }) + it('does not use cache', async () => { + storage.cache.user = JSON.stringify({ user: 'cached' }) + + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => + expect(result.current.data).toEqual({ + firstName: 'Namn', + lastName: 'Namnsson', + isAuthenticated: true, + personalNumber: '195001182046', + }) + ) + }) + it('returns user', async () => { + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => + expect(result.current.data).toEqual({ + firstName: 'Namn', + lastName: 'Namnsson', + isAuthenticated: true, + personalNumber: '195001182046', + }) + ) + }) + it('returns child list', async () => { + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + await waitFor(() => expect(result.current.data).toHaveLength(2)) + }) + describe('data belonging to one child', () => { + let child: any + beforeEach(async () => { + ;[child] = await api.getChildren() + }) + it('returns calendar', async () => { + const { result } = renderHook(() => useCalendar(child), { wrapper }) + + await waitFor(() => expect(result.current.data.length).toBeGreaterThan(1)) + }) + it('returns classmates', async () => { + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + await waitFor(() => expect(result.current.data.length).toBeGreaterThan(1)) + }) + it('returns menu', async () => { + const { result } = renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.data.length).toBeGreaterThan(1)) + }) + it('returns news', async () => { + const { result } = renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.data.length).toBeGreaterThan(1)) + }) + it('returns notifications', async () => { + const { result } = renderHook(() => useNotifications(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.data.length).toBeGreaterThan(1)) + }) + it('returns schedule', async () => { + const from = '2021-01-01' + const to = '2021-01-08' + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + await waitFor(() => + // No fake schedule in embedded-api yet + expect(result.current.data.length).not.toBeGreaterThan(1) + ) + }) + }) + it('handles reloads', async () => { + store.dispatch({ type: 'CLEAR' } as any) // fixes test for invalid type + + const [child] = await api.getChildren() + + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + }) + + result.current.reload() + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/logout.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/logout.test.js new file mode 100644 index 000000000..aa9507d7a --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/logout.test.js @@ -0,0 +1,76 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useEtjanstChildren } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('logout - cleanup', () => { + let api + let storage + let response + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getChildren.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_etjanst_children': [{ id: 2 }], + }, + 2 + ) + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + + it('cleans up on logout', async () => { + act(() => { + api.isLoggedIn = true + api.isFake = false + }) + + renderHook(() => useEtjanstChildren(), { wrapper }) + act(() => { + api.isLoggedIn = false + api.emitter.emit('logout') + }) + + const { result: result1 } = renderHook(() => useEtjanstChildren(), { + wrapper, + }) + + await waitFor(() => { + expect(result1.current.data).toHaveLength(0) + }) + + act(() => { + api.isLoggedIn = true + api.emitter.emit('login') + }) + + const { result: result2 } = renderHook(() => useEtjanstChildren(), { + wrapper, + }) + + await waitFor(() => expect(result2.current.data).toHaveLength(1)) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/provider.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/provider.test.js new file mode 100644 index 000000000..771237744 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/provider.test.js @@ -0,0 +1,29 @@ +import React from 'react' +import { render } from '@testing-library/react' +import { ApiProvider } from '../provider' +import init from '../__mocks__/@skolplattformen/embedded-api' +import { useApi } from '../context' + +describe('ApiProvider', () => { + const Login = () => { + const { isLoggedIn } = useApi() + return ( +
+
{isLoggedIn ? 'y' : 'n'}
+
+ ) + } + let api + beforeEach(() => { + api = init() + }) + it('enables useApi()', () => { + const { getByTestId } = render( + + + + ) + + expect(getByTestId('isLoggedIn').textContent).toEqual('n') + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/provider.test.jsx b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/provider.test.jsx new file mode 100644 index 000000000..0574413e4 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/provider.test.jsx @@ -0,0 +1,29 @@ +import React from 'react' +import { render } from '@testing-library/react' +import { ApiProvider } from './provider' +import init from './__mocks__/@skolplattformen/embedded-api' +import { useApi } from './context' + +describe('ApiProvider', () => { + const Login = () => { + const { isLoggedIn } = useApi() + return ( +
+
{isLoggedIn ? 'y' : 'n'}
+
+ ) + } + let api + beforeEach(() => { + api = init() + }) + it('enables useApi()', () => { + const { getByTestId } = render( + + + + ) + + expect(getByTestId('isLoggedIn').textContent).toEqual('n') + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useCalendar.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useCalendar.test.js new file mode 100644 index 000000000..721aa0773 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useCalendar.test.js @@ -0,0 +1,208 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useCalendar } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useCalendar(child)', () => { + let api + let storage + let response + let child + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getCalendar.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_calendar_10': [{ id: 2 }], + }, + 2 + ) + child = { id: 10 } + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + + it('returns correct initial value', () => { + const { result } = renderHook(() => useCalendar(child), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => expect(api.getCalendar).toHaveBeenCalled()) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useCalendar(child), { wrapper }) + renderHook(() => useCalendar(child), { + wrapper, + }) + + renderHook(() => useCalendar(child), { wrapper }) + + renderHook(() => useCalendar(child), { wrapper }) + + const { result } = renderHook(() => useCalendar(child), { wrapper }) + await waitFor(() => { + expect(api.getCalendar).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('retrieves data from cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + + it('works when cache is empty', async () => { + storage.clear() + + api.isLoggedIn = true + const { result } = renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 1 }])) + }) + + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => + expect(storage.cache['123_calendar_10']).toEqual('[{"id":1}]') + ) + }) + + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useCalendar(child), { + wrapper, + }) + + // await pause(20); + await waitFor(() => + expect(storage.cache['123_calendar_10']).toEqual('[{"id":2}]') + ) + }) + + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getCalendar.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getCalendar.mockRejectedValueOnce(error) + api.getCalendar.mockRejectedValueOnce(error) + api.getCalendar.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getCalendar.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useCalendar(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting CALENDAR from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useChildList.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useChildList.test.js new file mode 100644 index 000000000..7928472b2 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useChildList.test.js @@ -0,0 +1,274 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useChildList } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' +import { etjanstChildren } from '../reducers' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useChildList()', () => { + let api + let storage + let echildrenCache + let skola24Cache + let echildrenResponse + let skola24Response + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + echildrenCache = [{ id: 2, name: 'Uwe Übrink (elev)' }] + skola24Cache = [ + { personGuid: '2', firstName: 'Uwe', lastName: 'Vredstein Übrink' }, + ] + + echildrenResponse = [{ id: 1, name: 'Uwe Übrink (elev)' }] + skola24Response = [ + { personGuid: '1', firstName: 'Uwe', lastName: 'Vredstein Übrink' }, + ] + + api = init() + api.getPersonalNumber.mockReturnValue('123') + + api.getChildren.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(echildrenResponse), 50) + }) + ) + api.getSkola24Children.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(skola24Response), 50) + }) + ) + storage = createStorage( + { + '123_etjanst_children': echildrenCache, + '123_skola24_children': skola24Cache, + }, + 2 + ) + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + + it('returns correct initial value', () => { + const { result } = renderHook(() => useChildList(), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useChildList(), { + wrapper, + }) + + await waitFor(() => { + expect(api.getChildren).toHaveBeenCalled() + expect(api.getSkola24Children).toHaveBeenCalled() + }) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useChildList(), { wrapper }) + renderHook(() => useChildList(), { + wrapper, + }) + + renderHook(() => useChildList(), { wrapper }) + + renderHook(() => useChildList(), { wrapper }) + + const { result } = renderHook(() => useChildList(), { wrapper }) + await waitFor(() => { + expect(api.getChildren).toHaveBeenCalledTimes(1) + expect(api.getSkola24Children).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useChildList(), { + wrapper, + }) + + await waitFor(() => + expect(result.current.data).toEqual([ + { + id: 2, + name: 'Uwe Übrink (elev)', + personGuid: '2', + firstName: 'Uwe', + lastName: 'Vredstein Übrink', + }, + ]) + ) + }) + + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useChildList(), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useChildList(), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useChildList(), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_etjanst_children']).toEqual( + JSON.stringify(echildrenResponse) + ) + expect(storage.cache['123_skola24_children']).toEqual( + JSON.stringify(skola24Response) + ) + }) + }) + + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + const { result } = renderHook(() => useChildList(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(storage.cache['123_etjanst_children']).toEqual( + JSON.stringify(echildrenCache) + ) + expect(storage.cache['123_skola24_children']).toEqual( + JSON.stringify(skola24Cache) + ) + }) + }) + + it.skip('retries if etjanst-api fails', async () => { + await act(async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getChildren.mockRejectedValueOnce(error) + + const { result, waitForNextUpdate } = renderHook(() => useChildList(), { + wrapper, + }) + + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual(echildrenCache) + + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([ + { + id: 1, + name: 'Uwe Übrink (elev)', + personGuid: '1', + firstName: 'Uwe', + lastName: 'Vredstein Übrink', + }, + ]) + }) + }) + + it.skip('gives up after 3 retries', async () => { + await act(async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getChildren.mockRejectedValueOnce(error) + api.getChildren.mockRejectedValueOnce(error) + api.getChildren.mockRejectedValueOnce(error) + + const { result, waitForNextUpdate } = renderHook(() => useChildList(), { + wrapper, + }) + + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual(echildrenCache) + + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + await waitForNextUpdate() + + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([ + { + id: 2, + name: 'Uwe Übrink (elev)', + personGuid: '1', + firstName: 'Uwe', + lastName: 'Vredstein Übrink', + }, + ]) + }) + }) + + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getChildren.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useChildList(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting ETJANST_CHILDREN from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useClassmates.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useClassmates.test.js new file mode 100644 index 000000000..5ce4c9d52 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useClassmates.test.js @@ -0,0 +1,176 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useClassmates } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useClassmates(child)', () => { + let api + let storage + let response + let child + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getClassmates.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_classmates_10': [{ id: 2 }], + }, + 2 + ) + child = { id: 10 } + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + + it('returns correct initial value', () => { + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useClassmates(child), { + wrapper, + }) + + await waitFor(() => expect(api.getClassmates).toHaveBeenCalled()) + }) + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useClassmates(child), { wrapper }) + renderHook(() => useClassmates(child), { + wrapper, + }) + + renderHook(() => useClassmates(child), { wrapper }) + + renderHook(() => useClassmates(child), { wrapper }) + + const { result } = renderHook(() => useClassmates(child), { wrapper }) + await waitFor(() => { + expect(api.getClassmates).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + }) + }) + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useClassmates(child), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_classmates_10']).toEqual('[{"id":1}]') + }) + }) + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useClassmates(child), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_classmates_10']).toEqual('[{"id":2}]') + }) + }) + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getClassmates.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getClassmates.mockRejectedValueOnce(error) + api.getClassmates.mockRejectedValueOnce(error) + api.getClassmates.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getClassmates.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useClassmates(child), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting CLASSMATES from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useEtjanstChildren.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useEtjanstChildren.test.js new file mode 100644 index 000000000..916df3c3d --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useEtjanstChildren.test.js @@ -0,0 +1,181 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useEtjanstChildren } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useEtjanstChildren()', () => { + let api + let storage + let response + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getChildren.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_etjanst_children': [{ id: 2 }], + }, + 2 + ) + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + it('returns correct initial value', () => { + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useEtjanstChildren(), { + wrapper, + }) + + await waitFor(() => expect(api.getChildren).toHaveBeenCalled()) + }) + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useEtjanstChildren(), { wrapper }) + renderHook(() => useEtjanstChildren(), { + wrapper, + }) + + renderHook(() => useEtjanstChildren(), { wrapper }) + + renderHook(() => useEtjanstChildren(), { wrapper }) + + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + await waitFor(() => { + expect(api.getChildren).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + }) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useEtjanstChildren(), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_etjanst_children']).toEqual('[{"id":1}]') + }) + }) + + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useEtjanstChildren(), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_etjanst_children']).toEqual('[{"id":2}]') + }) + }) + + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getChildren.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getChildren.mockRejectedValueOnce(error) + api.getChildren.mockRejectedValueOnce(error) + api.getChildren.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getChildren.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useEtjanstChildren(), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting ETJANST_CHILDREN from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useMenu.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useMenu.test.js new file mode 100644 index 000000000..6bfe2dca4 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useMenu.test.js @@ -0,0 +1,189 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useMenu } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useMenu(child)', () => { + let api + let storage + let response + let child + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getMenu.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_menu_10': [{ id: 2 }], + }, + 2 + ) + child = { id: 10 } + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + it('returns correct initial value', () => { + const { result } = renderHook(() => useMenu(child), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useMenu(child), { + wrapper, + }) + + expect(api.getMenu).toHaveBeenCalled() + }) + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useMenu(child), { wrapper }) + renderHook(() => useMenu(child), { + wrapper, + }) + + renderHook(() => useMenu(child), { wrapper }) + + renderHook(() => useMenu(child), { wrapper }) + + const { result } = renderHook(() => useMenu(child), { wrapper }) + await waitFor(() => { + expect(api.getMenu).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => + expect(storage.cache['123_menu_10']).toEqual('[{"id":1}]') + ) + }) + + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_menu_10']).toEqual('[{"id":2}]') + }) + }) + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getMenu.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getMenu.mockRejectedValueOnce(error) + api.getMenu.mockRejectedValueOnce(error) + api.getMenu.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getMenu.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useMenu(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting MENU from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNews.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNews.test.js new file mode 100644 index 000000000..fc5849090 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNews.test.js @@ -0,0 +1,194 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useNews } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useNews(child)', () => { + let api + let storage + let response + let child + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getNews.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_news_10': [{ id: 2 }], + }, + 2 + ) + child = { id: 10 } + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + + it('returns correct initial value', () => { + const { result } = renderHook(() => useNews(child), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => expect(api.getNews).toHaveBeenCalled()) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useNews(child), { wrapper }) + renderHook(() => useNews(child), { + wrapper, + }) + + renderHook(() => useNews(child), { wrapper }) + + renderHook(() => useNews(child), { wrapper }) + + const { result } = renderHook(() => useNews(child), { wrapper }) + await waitFor(() => { + expect(api.getNews).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result, waitForNextUpdate } = renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result, waitForNextUpdate } = renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => + expect(storage.cache['123_news_10']).toEqual('[{"id":1}]') + ) + }) + + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_news_10']).toEqual('[{"id":2}]') + }) + }) + + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNews.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNews.mockRejectedValueOnce(error) + api.getNews.mockRejectedValueOnce(error) + api.getNews.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNews.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNews(child), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting NEWS from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNewsDetails.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNewsDetails.test.js new file mode 100644 index 000000000..4e9699897 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNewsDetails.test.js @@ -0,0 +1,195 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useNewsDetails } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useNewsDetails(child, newsItem)', () => { + let api + let storage + let response + let cached + let child + let newsItem + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + cached = { id: '1337', modified: 'yesterday', body: 'rich and old' } + response = { id: '1337', modified: 'now', body: 'rich and new' } + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getNewsDetails.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_news_details_1337': { ...cached }, + }, + 2 + ) + child = { id: 10 } + newsItem = { id: '1337', modified: 'now', body: 'simple' } + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + + it('returns correct initial value', () => { + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + + expect(result.current.status).toEqual('pending') + }) + + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useNewsDetails(child, newsItem), { wrapper }) + + await waitFor(() => expect(api.getNewsDetails).toHaveBeenCalled()) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useNewsDetails(child, newsItem), { wrapper }) + renderHook(() => useNewsDetails(child, newsItem), { wrapper }) + + renderHook(() => useNewsDetails(child, newsItem), { wrapper }) + + renderHook(() => useNewsDetails(child, newsItem), { wrapper }) + + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + await waitFor(() => { + expect(api.getNewsDetails).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + + await waitFor(() => expect(result.current.data).toEqual(cached)) + }) + + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useNewsDetails(child, newsItem), { wrapper }) + + await waitFor(() => + expect(storage.cache['123_news_details_1337']).toEqual( + JSON.stringify(response) + ) + ) + }) + + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useNewsDetails(child, newsItem), { wrapper }) + + expect(storage.cache['123_news_details_1337']).toEqual( + JSON.stringify(cached) + ) + }) + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNewsDetails.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual({ ...cached }) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual({ ...response }) + }) + }) + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNewsDetails.mockRejectedValueOnce(error) + api.getNewsDetails.mockRejectedValueOnce(error) + api.getNewsDetails.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual({ ...cached }) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual({ ...cached }) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNewsDetails.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNewsDetails(child, newsItem), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting NEWS_DETAILS from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNotifications.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNotifications.test.js new file mode 100644 index 000000000..b823ac08e --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useNotifications.test.js @@ -0,0 +1,179 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useNotifications } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useNotifications(child)', () => { + let api + let storage + let response + let child + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getNotifications.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_notifications_10': [{ id: 2 }], + }, + 2 + ) + child = { id: 10 } + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + it('returns correct initial value', () => { + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useNotifications(child), { + wrapper, + }) + + await waitFor(() => expect(api.getNotifications).toHaveBeenCalled()) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useNotifications(child), { wrapper }) + renderHook(() => useNotifications(child), { + wrapper, + }) + + renderHook(() => useNotifications(child), { wrapper }) + + renderHook(() => useNotifications(child), { wrapper }) + + const { result } = renderHook(() => useNotifications(child), { wrapper }) + await waitFor(() => { + expect(api.getNotifications).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useNotifications(child), { + wrapper, + }) + + await waitFor(() => + expect(storage.cache['123_notifications_10']).toEqual('[{"id":1}]') + ) + }) + + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useNotifications(child), { + wrapper, + }) + + await waitFor(() => { + expect(storage.cache['123_notifications_10']).toEqual('[{"id":2}]') + }) + }) + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNotifications.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNotifications.mockRejectedValueOnce(error) + api.getNotifications.mockRejectedValueOnce(error) + api.getNotifications.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getNotifications.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useNotifications(child), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting NOTIFICATIONS from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useSchedule.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useSchedule.test.js new file mode 100644 index 000000000..62be6cd0a --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useSchedule.test.js @@ -0,0 +1,198 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useSchedule } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useSchedule(child, from, to)', () => { + let api + let storage + let response + let child + let from + let to + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getSchedule.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_schedule_10_2021-01-01_2021-01-08': [{ id: 2 }], + }, + 2 + ) + child = { id: 10 } + from = '2021-01-01' + to = '2021-01-08' + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + it('returns correct initial value', () => { + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + expect(result.current.status).toEqual('pending') + }) + + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useSchedule(child, from, to), { wrapper }) + + await waitFor(() => expect(api.getSchedule).toHaveBeenCalled()) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useSchedule(child, from, to), { wrapper }) + renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + renderHook(() => useSchedule(child, from, to), { wrapper }) + + renderHook(() => useSchedule(child, from, to), { wrapper }) + + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + await waitFor(() => { + expect(api.getSchedule).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result, waitForNextUpdate } = renderHook( + () => useSchedule(child, from, to), + { wrapper } + ) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useSchedule(child, from, to), { wrapper }) + + await waitFor(() => + expect(storage.cache['123_schedule_10_2021-01-01_2021-01-08']).toEqual( + '[{"id":1}]' + ) + ) + }) + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useSchedule(child, from, to), { wrapper }) + + await waitFor(() => { + expect(storage.cache['123_schedule_10_2021-01-01_2021-01-08']).toEqual( + '[{"id":2}]' + ) + }) + }) + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getSchedule.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getSchedule.mockRejectedValueOnce(error) + api.getSchedule.mockRejectedValueOnce(error) + api.getSchedule.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getSchedule.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useSchedule(child, from, to), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting SCHEDULE from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useSkola24Children.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useSkola24Children.test.js new file mode 100644 index 000000000..7a04967be --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useSkola24Children.test.js @@ -0,0 +1,189 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useSkola24Children } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useSkola24Children()', () => { + let api + let storage + let response + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ personGuid: '1' }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getSkola24Children.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_skola24_children': [{ personGuid: '2' }], + }, + 2 + ) + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + it('returns correct initial value', () => { + const { result } = renderHook(() => useSkola24Children(), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + + it('calls api', async () => { + api.isLoggedIn = true + const { waitForNextUpdate } = renderHook(() => useSkola24Children(), { + wrapper, + }) + + await waitFor(() => expect(api.getSkola24Children).toHaveBeenCalled()) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useSkola24Children(), { wrapper }) + renderHook(() => useSkola24Children(), { + wrapper, + }) + + renderHook(() => useSkola24Children(), { wrapper }) + + renderHook(() => useSkola24Children(), { wrapper }) + + const { result } = renderHook(() => useSkola24Children(), { wrapper }) + await waitFor(() => { + expect(api.getSkola24Children).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useSkola24Children(), { wrapper }) + + await waitFor(() => + expect(result.current.data).toEqual([{ personGuid: '2' }]) + ) + }) + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useSkola24Children(), { wrapper }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useSkola24Children(), { wrapper }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useSkola24Children(), { + wrapper, + }) + + await waitFor(() => + expect(storage.cache['123_skola24_children']).toEqual( + '[{"personGuid":"1"}]' + ) + ) + }) + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useSkola24Children(), { + wrapper, + }) + + await waitFor(() => + expect(storage.cache['123_skola24_children']).toEqual( + '[{"personGuid":"2"}]' + ) + ) + }) + + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getSkola24Children.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useSkola24Children(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ personGuid: '2' }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ personGuid: '1' }]) + }) + }) + + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getSkola24Children.mockRejectedValueOnce(error) + api.getSkola24Children.mockRejectedValueOnce(error) + api.getSkola24Children.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useSkola24Children(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ personGuid: '2' }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ personGuid: '2' }]) + }) + }) + + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getSkola24Children.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useSkola24Children(), { wrapper }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting SKOLA24_CHILDREN from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useTimetable.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useTimetable.test.js new file mode 100644 index 000000000..779a8e8d2 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useTimetable.test.js @@ -0,0 +1,193 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useTimetable } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useTimetable(child, week, year, lang)', () => { + let api + let storage + let response + let child + let week + let year + let lang + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = [{ id: 1 }] + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getTimetable.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_timetable_10_15_2021_sv': [{ id: 2 }], + }, + 2 + ) + child = { personGuid: '10' } + week = 15 + year = 2021 + lang = 'sv' + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + it('returns correct initial value', () => { + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + + expect(result.current.status).toEqual('pending') + }) + it('calls api', async () => { + api.isLoggedIn = true + renderHook(() => useTimetable(child, week, year, lang), { wrapper }) + + await waitFor(() => expect(api.getTimetable).toHaveBeenCalled()) + }) + + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useTimetable(child, week, year, lang), { wrapper }) + renderHook(() => useTimetable(child, week, year, lang), { wrapper }) + + renderHook(() => useTimetable(child, week, year, lang), { wrapper }) + + renderHook(() => useTimetable(child, week, year, lang), { wrapper }) + + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + await waitFor(() => { + expect(api.getTimetable).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + + it('calls cache', async () => { + api.isLoggedIn = true + + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + + await waitFor(() => expect(result.current.data).toEqual([{ id: 2 }])) + }) + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loading')) + }) + + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + + await waitFor(() => expect(result.current.status).toEqual('loaded')) + }) + + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useTimetable(child, week, year, lang), { wrapper }) + + await waitFor(() => { + expect(storage.cache['123_timetable_10_15_2021_sv']).toEqual('[{"id":1}]') + }) + }) + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useTimetable(child, week, year, lang), { wrapper }) + + await waitFor(() => + expect(storage.cache['123_timetable_10_15_2021_sv']).toEqual('[{"id":2}]') + ) + }) + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getTimetable.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual([{ id: 1 }]) + }) + }) + + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getTimetable.mockRejectedValueOnce(error) + api.getTimetable.mockRejectedValueOnce(error) + api.getTimetable.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual([{ id: 2 }]) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getTimetable.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useTimetable(child, week, year, lang), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting TIMETABLE from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useUser.test.js b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useUser.test.js new file mode 100644 index 000000000..b286647a6 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/__tests__/useUser.test.js @@ -0,0 +1,179 @@ +import React from 'react' +import { renderHook, act, waitFor } from '@testing-library/react' +import { ApiProvider } from '../provider' +import { useUser } from '../hooks' +import store from '../store' +import init from '../__mocks__/@skolplattformen/embedded-api' +import createStorage from '../__mocks__/AsyncStorage' +import reporter from '../__mocks__/reporter' + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) + +describe('useUser()', () => { + let api + let storage + let response + const wrapper = ({ children }) => ( + + {children} + + ) + beforeEach(() => { + response = { id: 1 } + api = init() + api.getPersonalNumber.mockReturnValue('123') + api.getUser.mockImplementation( + () => + new Promise((res) => { + setTimeout(() => res(response), 50) + }) + ) + storage = createStorage( + { + '123_user': { id: 2 }, + }, + 2 + ) + }) + afterEach(async () => { + await act(async () => { + await pause(70) + store.dispatch({ entity: 'ALL', type: 'CLEAR' }) + }) + }) + it('returns correct initial value', () => { + const { result } = renderHook(() => useUser(), { wrapper }) + + expect(result.current.status).toEqual('pending') + }) + it('calls api', async () => { + api.isLoggedIn = true + + await waitFor(() => { + renderHook(() => useUser(), { wrapper }) + }) + expect(api.getUser).toHaveBeenCalled() + }) + it('only calls api once', async () => { + api.isLoggedIn = true + renderHook(() => useUser(), { wrapper }) + + renderHook(() => useUser(), { wrapper }) + renderHook(() => useUser(), { wrapper }) + + const { result } = renderHook(() => useUser(), { wrapper }) + await waitFor(() => { + expect(api.getUser).toHaveBeenCalledTimes(1) + expect(result.current.status).toEqual('loaded') + }) + }) + it('calls cache', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.data).toEqual({ id: 2 }) + }) + }) + it('updates status to loading', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loading') + }) + }) + it('updates status to loaded', async () => { + api.isLoggedIn = true + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + }) + }) + it('stores in cache if not fake', async () => { + api.isLoggedIn = true + api.isFake = false + + renderHook(() => useUser(), { wrapper }) + + await waitFor(() => { + expect(storage.cache['123_user']).toEqual('{"id":1}') + }) + }) + it('does not store in cache if fake', async () => { + api.isLoggedIn = true + api.isFake = true + + renderHook(() => useUser(), { wrapper }) + + await waitFor(() => { + expect(storage.cache['123_user']).toEqual('{"id":2}') + }) + }) + it('retries if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getUser.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual({ id: 2 }) + }) + await waitFor(() => { + expect(result.current.status).toEqual('loaded') + expect(result.current.data).toEqual({ id: 1 }) + }) + }) + it('gives up after 3 retries', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getUser.mockRejectedValueOnce(error) + api.getUser.mockRejectedValueOnce(error) + api.getUser.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('loading') + expect(result.current.data).toEqual({ id: 2 }) + }) + await waitFor(() => { + expect(result.current.error).toEqual(error) + expect(result.current.status).toEqual('error') + expect(result.current.data).toEqual({ id: 2 }) + }) + }) + it('reports if api fails', async () => { + api.isLoggedIn = true + const error = new Error('fail') + api.getUser.mockRejectedValueOnce(error) + + const { result } = renderHook(() => useUser(), { + wrapper, + }) + + await waitFor(() => { + expect(result.current.error).toEqual(error) + + expect(reporter.error).toHaveBeenCalledWith( + error, + 'Error getting USER from API' + ) + }) + }) +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/actions.ts b/apps/skolplattformen-app-new/libs/hooks/src/actions.ts new file mode 100644 index 000000000..24c7ef55b --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/actions.ts @@ -0,0 +1,10 @@ +import { EntityAction, EntityName, ExtraActionProps } from './types' + +export const loadAction = ( + entity: EntityName, + extra: ExtraActionProps +): EntityAction => ({ + entity, + extra, + type: 'GET_FROM_API', +}) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/childlists.ts b/apps/skolplattformen-app-new/libs/hooks/src/childlists.ts new file mode 100644 index 000000000..31a3c1465 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/childlists.ts @@ -0,0 +1,17 @@ +import { Child, EtjanstChild, Skola24Child } from '../../api/lib' + +export const merge = ( + etjanstChildren: EtjanstChild[], + skola24Children: Skola24Child[] +): Child[] => + etjanstChildren.map((etjanstChild) => { + const skola24Child: Skola24Child = + skola24Children.find( + (s24c) => s24c.firstName && etjanstChild.name.startsWith(s24c.firstName) + ) || {} + const child: Child = { + ...etjanstChild, + ...skola24Child, + } + return child + }) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/context.ts b/apps/skolplattformen-app-new/libs/hooks/src/context.ts new file mode 100644 index 000000000..6c7beb69d --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/context.ts @@ -0,0 +1,6 @@ +import { createContext, useContext } from 'react' +import { IApiContext } from './types' + +export const ApiContext = createContext({} as IApiContext) + +export const useApi = () => useContext(ApiContext) diff --git a/apps/skolplattformen-app-new/libs/hooks/src/hooks.ts b/apps/skolplattformen-app-new/libs/hooks/src/hooks.ts new file mode 100644 index 000000000..583d809e8 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/hooks.ts @@ -0,0 +1,304 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import { + Api, + CalendarItem, + Child, + Classmate, + EtjanstChild, + MenuItem, + NewsItem, + Notification, + ScheduleItem, + SchoolContact, + Skola24Child, + Teacher, + TimetableEntry, + User, +} from '../../api/lib' +import { Language } from '@skolplattformen/curriculum' +import { DateTime } from 'luxon' +import { useEffect, useState } from 'react' +import { useDispatch } from 'react-redux' +import { loadAction } from './actions' +import { merge } from './childlists' +import { useApi } from './context' +import store from './store' +import { + ApiCall, + EntityHookResult, + EntityMap, + EntityName, + EntityStoreRootState, + ExtraActionProps, +} from './types' + +interface StoreSelector { + (state: EntityStoreRootState): EntityMap +} + +const hook = ( + entityName: EntityName, + key: string, + defaultValue: T, + selector: StoreSelector, + apiCaller: (api: Api) => ApiCall +): EntityHookResult => { + const { api, isLoggedIn, reporter, storage } = useApi() + + const getState = (): EntityStoreRootState => + store.getState() as unknown as EntityStoreRootState + const select = (storeState: EntityStoreRootState) => { + const stateMap = selector(storeState) || {} + const state = stateMap[key] || { status: 'pending', data: defaultValue } + return state + } + const initialState = select(getState()) + const [state, setState] = useState(initialState) + const dispatch = useDispatch() + + const load = (force = false) => { + if ( + isLoggedIn && + state.status !== 'loading' && + ((force && !api.isFake) || state.status === 'pending') + ) { + const extra: ExtraActionProps = { + key, + defaultValue, + apiCall: apiCaller(api), + retries: 0, + } + + // Only use cache when not in fake mode + if (!api.isFake) { + const pnr = api.getPersonalNumber() + + // Only get from cache first time + if (state.status === 'pending') { + extra.getFromCache = () => storage.getItem(`${pnr}_${key}`) + } + extra.saveToCache = (value: string) => + storage.setItem(`${pnr}_${key}`, value) + } + const action = loadAction(entityName, extra) + dispatch(action) + } + } + useEffect(() => { + load() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isLoggedIn]) + + let mounted: boolean + useEffect(() => { + // eslint-disable-next-line react-hooks/exhaustive-deps + mounted = true + return () => { + mounted = false + } + }, []) + + const listener = () => { + if (!mounted) { + return + } + + const newState = select(getState()) + if ( + newState.status !== state.status || + newState.data !== state.data || + newState.error !== state.error + ) { + setState(newState) + + if (newState.error) { + const description = `Error getting ${entityName} from API` + reporter.error && reporter.error(newState.error, description) + } + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(() => store.subscribe(listener), []) + + return { + ...state, + reload: () => load(true), + } +} + +export const useEtjanstChildren = () => + hook( + 'ETJANST_CHILDREN', + 'etjanst_children', + [], + (s) => s.etjanstChildren, + (api) => () => api.getChildren() + ) + +export const useSkola24Children = () => + hook( + 'SKOLA24_CHILDREN', + 'skola24_children', + [], + (s) => s.skola24Children, + (api) => () => api.getSkola24Children() + ) + +export const useCalendar = (child: Child) => + hook( + 'CALENDAR', + `calendar_${child.id}`, + [], + (s) => s.calendar, + (api) => () => api.getCalendar(child) + ) + +export const useClassmates = (child: Child) => + hook( + 'CLASSMATES', + `classmates_${child.id}`, + [], + (s) => s.classmates, + (api) => () => api.getClassmates(child) + ) + +export const useMenu = (child: Child) => + hook( + 'MENU', + `menu_${child.id}`, + [], + (s) => s.menu, + (api) => () => api.getMenu(child) + ) + +export const useNews = (child: Child) => + hook( + 'NEWS', + `news_${child.id}`, + [], + (s) => s.news, + (api) => () => api.getNews(child) + ) + +export const useNewsDetails = (child: Child, news: NewsItem) => + hook( + 'NEWS_DETAILS', + `news_details_${news.id}`, + news, + (s) => s.newsDetails, + (api) => () => api.getNewsDetails(child, news) + ) + +export const useNotifications = (child: Child) => + hook( + 'NOTIFICATIONS', + `notifications_${child.id}`, + [], + (s) => s.notifications, + (api) => () => api.getNotifications(child) + ) + +export const useSchedule = (child: Child, from: string, to: string) => + hook( + 'SCHEDULE', + `schedule_${child.id}_${from}_${to}`, + [], + (s) => s.schedule, + (api) => () => + api.getSchedule(child, DateTime.fromISO(from), DateTime.fromISO(to)) + ) + +export const useSchoolContacts = (child: Child) => + hook( + 'SCHOOL_CONTACTS', + `schoolContacts_${child.id}`, + [], + (s) => s.schoolContacts, + (api) => () => api.getSchoolContacts(child) + ) + +export const useTeachers = (child: Child) => + hook( + 'TEACHERS', + `teachers_${child.id}`, + [], + (s) => s.teachers, + (api) => () => api.getTeachers(child) + ) + +export const useTimetable = ( + child: Child, + week: number, + year: number, + lang: Language +) => + hook( + 'TIMETABLE', + `timetable_${child.personGuid}_${week}_${year}_${lang}`, + [], + (s) => s.timetable, + (api) => async () => { + const tt = await api.getTimetable(child, week, year, lang) + const ts = await api.getTeachers(child) + tt.forEach((element) => { + element.teacher = replaceTeacherInitials(element.teacher, ts) + }) + return tt + } + ) + +const replaceTeacherInitials = ( + initials: string, + teachers: Teacher[] +): string => { + if (!initials || teachers?.length == 0) { + return initials + } + const arr = initials.split(',') || [initials] + const arr2 = arr.map((element) => { + const t = teachers.find( + (t) => t.timeTableAbbreviation === element.trim().toUpperCase() + ) + return t ? `${t.firstname} ${t.lastname}` : element + }) + return arr2.join(', ') +} + +export const useUser = () => + hook( + 'USER', + 'user', + {}, + (s) => s.user, + (api) => () => api.getUser() + ) + +export const useChildList = (): EntityHookResult => { + const { + data: etjanstData, + status, + error, + reload: etjanstReload, + } = useEtjanstChildren() + const { data: skola24Data, reload: skola24Reload } = useSkola24Children() + + const [data, setData] = useState([]) + const reload = () => { + etjanstReload() + skola24Reload() + } + + useEffect(() => { + if (!etjanstData.length) { + return + } + setData(merge(etjanstData, skola24Data)) + }, [etjanstData, skola24Data]) + + return { + data, + status, + error, + reload, + } +} diff --git a/apps/skolplattformen-app-new/libs/hooks/src/index.ts b/apps/skolplattformen-app-new/libs/hooks/src/index.ts new file mode 100644 index 000000000..10874f616 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/index.ts @@ -0,0 +1,4 @@ +export * from './provider' +export * from './context' +export * from './hooks' +export * from './types' diff --git a/apps/skolplattformen-app-new/libs/hooks/src/middleware.ts b/apps/skolplattformen-app-new/libs/hooks/src/middleware.ts new file mode 100644 index 000000000..9f67959c6 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/middleware.ts @@ -0,0 +1,110 @@ +import { Middleware } from 'redux' +import { EntityAction, EntityStoreRootState, ExtraActionProps } from './types' + +type IMiddleware = Middleware, EntityStoreRootState> +export const apiMiddleware: IMiddleware = + (storeApi) => (next) => (action: EntityAction) => { + try { + switch (action.type) { + case 'GET_FROM_API': { + // Retrieve from cache + if (action.extra?.getFromCache) { + const cacheAction: EntityAction = { + ...action, + type: 'GET_FROM_CACHE', + } + storeApi.dispatch(cacheAction) + } + + // Call api + const apiCall = action.extra?.apiCall + if (apiCall) { + const extra = action.extra as ExtraActionProps + apiCall() + .then((res: any) => { + const resultAction: EntityAction = { + ...action, + type: 'RESULT_FROM_API', + data: res, + } + storeApi.dispatch(resultAction) + + if (extra.saveToCache && res) { + const cacheAction: EntityAction = { + ...resultAction, + type: 'STORE_IN_CACHE', + } + storeApi.dispatch(cacheAction) + } + }) + .catch((error) => { + const retries = extra.retries + 1 + + const errorAction: EntityAction = { + ...action, + extra: { + ...extra, + retries, + }, + type: 'API_ERROR', + error, + } + storeApi.dispatch(errorAction) + + // Retry 7 times + if (retries < 7) { + const retryAction: EntityAction = { + ...action, + type: 'GET_FROM_API', + extra: { + ...extra, + retries, + }, + } + setTimeout(() => { + storeApi.dispatch(retryAction) + }, 2 ** retries * 100) + } + }) + } + } + } + } catch (err) { + console.error(err) + } + return next(action) + } + +export const cacheMiddleware: IMiddleware = + (storeApi) => (next) => (action: EntityAction) => { + try { + switch (action.type) { + case 'GET_FROM_CACHE': { + const getFromCache = action.extra?.getFromCache + if (getFromCache) { + getFromCache().then((res: string | null) => { + if (res) { + const cacheResultAction: EntityAction = { + ...action, + type: 'RESULT_FROM_CACHE', + data: JSON.parse(res), + } + storeApi.dispatch(cacheResultAction) + } + }) + } + break + } + case 'STORE_IN_CACHE': { + const saveToCache = action.extra?.saveToCache + if (saveToCache && action.data) { + saveToCache(JSON.stringify(action.data)) + } + break + } + } + } catch (err) { + console.error(err) + } + return next(action) + } diff --git a/apps/skolplattformen-app-new/libs/hooks/src/provider.tsx b/apps/skolplattformen-app-new/libs/hooks/src/provider.tsx new file mode 100644 index 000000000..b3d687e3c --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/provider.tsx @@ -0,0 +1,64 @@ +import { Api } from '../../api/lib' +import React, { FC, PropsWithChildren, useEffect, useState } from 'react' +import { Provider } from 'react-redux' +import { ApiContext } from './context' +import store from './store' +import { AsyncStorage, IApiContext, Reporter } from './types' + +type TApiProvider = FC< + PropsWithChildren<{ + api: Api + storage: AsyncStorage + reporter?: Reporter + }> +> +const noopReporter: Reporter = { + log: () => { + // noop + }, + error: () => { + // noop + }, +} +export const ApiProvider: TApiProvider = ({ + children, + api, + storage, + reporter = noopReporter, +}) => { + const [isLoggedIn, setIsLoggedIn] = useState(api.isLoggedIn) + const [isFake, setIsFake] = useState(api.isFake) + + const value: IApiContext = { + api, + storage, + isLoggedIn, + isFake, + reporter, + } + + useEffect(() => { + const handler = async () => { + setIsLoggedIn(api.isLoggedIn) + setIsFake(api.isFake) + + if (!api.isLoggedIn) { + store.dispatch({ type: 'CLEAR', entity: 'ALL' }) + } + } + + api.on('login', handler) + api.on('logout', handler) + + return () => { + api.off('login', handler) + api.off('logout', handler) + } + }, [api]) + + return ( + + {children} + + ) +} diff --git a/apps/skolplattformen-app-new/libs/hooks/src/reducers.ts b/apps/skolplattformen-app-new/libs/hooks/src/reducers.ts new file mode 100644 index 000000000..ec5bf36db --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/reducers.ts @@ -0,0 +1,85 @@ +import { + CalendarItem, + Classmate, + EtjanstChild, + MenuItem, + NewsItem, + Notification, + ScheduleItem, + SchoolContact, + Skola24Child, + Teacher, + TimetableEntry, + User, +} from '../../api/lib' +import { EntityName, EntityReducer, EntityState } from './types' + +const createReducer = (entity: EntityName): EntityReducer => { + const reducer: EntityReducer = (state = {}, action) => { + if (action.entity !== entity || !action.extra) { + return state + } + const key = action.extra?.key + + const node = state[key] || { + status: 'pending', + data: action.extra.defaultValue, + } + let newNode: EntityState + switch (action.type) { + case 'GET_FROM_API': { + newNode = { + ...node, + error: undefined, + status: 'loading', + } + break + } + case 'RESULT_FROM_API': { + newNode = { + ...node, + data: action.data || node.data, + status: 'loaded', + } + break + } + case 'API_ERROR': { + newNode = { + ...node, + status: action.extra.retries < 3 ? node.status : 'error', + error: action.error, + } + break + } + case 'RESULT_FROM_CACHE': { + newNode = { + ...node, + data: action.data || node.data, + } + break + } + default: { + newNode = { ...node } + } + } + return { + ...state, + [key]: newNode, + } + } + return reducer +} + +export const user = createReducer('USER') +export const etjanstChildren = createReducer('ETJANST_CHILDREN') +export const skola24Children = createReducer('SKOLA24_CHILDREN') +export const calendar = createReducer('CALENDAR') +export const classmates = createReducer('CLASSMATES') +export const menu = createReducer('MENU') +export const news = createReducer('NEWS') +export const newsDetails = createReducer('NEWS_DETAILS') +export const notifications = createReducer('NOTIFICATIONS') +export const schedule = createReducer('SCHEDULE') +export const timetable = createReducer('TIMETABLE') +export const teachers = createReducer('TEACHERS') +export const schoolContacts = createReducer('SCHOOL_CONTACTS') diff --git a/apps/skolplattformen-app-new/libs/hooks/src/store.ts b/apps/skolplattformen-app-new/libs/hooks/src/store.ts new file mode 100644 index 000000000..15cc85a9b --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/store.ts @@ -0,0 +1,43 @@ +import { createStore, combineReducers, applyMiddleware } from 'redux' +import { apiMiddleware, cacheMiddleware } from './middleware' +import { + calendar, + classmates, + etjanstChildren, + menu, + news, + newsDetails, + notifications, + schedule, + schoolContacts, + skola24Children, + teachers, + timetable, + user, +} from './reducers' + +const appReducer = combineReducers({ + calendar, + classmates, + etjanstChildren, + menu, + news, + newsDetails, + notifications, + schedule, + schoolContacts, + skola24Children, + teachers, + timetable, + user, +}) +const rootReducer: typeof appReducer = (state, action) => { + if (action.type === 'CLEAR') { + state = undefined + } + return appReducer(state, action) +} +const enhancers = applyMiddleware(apiMiddleware, cacheMiddleware) +const store = createStore(rootReducer, enhancers) + +export default store diff --git a/apps/skolplattformen-app-new/libs/hooks/src/types.ts b/apps/skolplattformen-app-new/libs/hooks/src/types.ts new file mode 100644 index 000000000..bf2c1a512 --- /dev/null +++ b/apps/skolplattformen-app-new/libs/hooks/src/types.ts @@ -0,0 +1,107 @@ +import { + Api, + CalendarItem, + Classmate, + EtjanstChild, + MenuItem, + NewsItem, + Notification, + ScheduleItem, + SchoolContact, + Skola24Child, + Teacher, + TimetableEntry, + User, +} from '../../api/lib' +import { Action, Reducer } from 'redux' + +export interface Reporter { + log?: (message: string) => void + error?: (error: Error, label?: string) => void +} + +export interface IApiContext { + api: Api + storage: AsyncStorage + isLoggedIn: boolean + isFake: boolean + reporter: Reporter +} + +export type EntityStatus = 'pending' | 'loading' | 'loaded' | 'error' +export interface EntityState { + data: T + status: EntityStatus + error?: Error +} + +export interface ApiCall { + (): Promise +} +export interface ExtraActionProps { + apiCall: ApiCall + retries: number + key: string + defaultValue: T + getFromCache?: () => Promise + saveToCache?: (value: string) => Promise +} +export type EntityActionType = + | 'GET_FROM_API' + | 'RESULT_FROM_API' + | 'API_ERROR' + | 'GET_FROM_CACHE' + | 'RESULT_FROM_CACHE' + | 'STORE_IN_CACHE' + | 'CLEAR' +export type EntityName = + | 'USER' + | 'ETJANST_CHILDREN' + | 'SKOLA24_CHILDREN' + | 'CHILDREN' + | 'CALENDAR' + | 'CLASSMATES' + | 'MENU' + | 'NEWS' + | 'NEWS_DETAILS' + | 'NOTIFICATIONS' + | 'SCHEDULE' + | 'SCHOOL_CONTACTS' + | 'TEACHERS' + | 'TIMETABLE' + | 'ALL' +export interface EntityAction extends Action { + entity: EntityName + data?: T + error?: Error + extra?: ExtraActionProps +} +export interface EntityMap { + [key: string]: EntityState +} +export type EntityReducer = Reducer, EntityAction> + +export interface EntityStoreRootState { + etjanstChildren: EntityMap + skola24Children: EntityMap + user: EntityMap + calendar: EntityMap + classmates: EntityMap + menu: EntityMap + news: EntityMap + newsDetails: EntityMap + notifications: EntityMap + schedule: EntityMap + schoolContacts: EntityMap + teachers: EntityMap + timetable: EntityMap +} + +export interface EntityHookResult extends EntityState { + reload: () => void +} + +export interface AsyncStorage { + getItem(key: string): Promise + setItem(key: string, value: string): Promise +} diff --git a/apps/skolplattformen-app-new/metro.config.js b/apps/skolplattformen-app-new/metro.config.js new file mode 100644 index 000000000..7d886e3ab --- /dev/null +++ b/apps/skolplattformen-app-new/metro.config.js @@ -0,0 +1,11 @@ +const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config') + +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const config = {} + +module.exports = mergeConfig(getDefaultConfig(__dirname), config) diff --git a/apps/skolplattformen-app-new/package-lock.json b/apps/skolplattformen-app-new/package-lock.json new file mode 100644 index 000000000..a509e0dc0 --- /dev/null +++ b/apps/skolplattformen-app-new/package-lock.json @@ -0,0 +1,17148 @@ +{ + "name": "app", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "app", + "version": "0.0.1", + "hasInstallScript": true, + "dependencies": { + "@eva-design/eva": "^2.2.0", + "@react-native-async-storage/async-storage": "^1.19.3", + "@react-native-community/datetimepicker": "^7.6.0", + "@react-native-cookies/cookies": "^6.2.1", + "@react-navigation/bottom-tabs": "^6.5.9", + "@react-navigation/native": "^6.1.8", + "@react-navigation/native-stack": "^6.9.14", + "@react-navigation/stack": "^6.3.18", + "@ronradtke/react-native-markdown-display": "^8.0.0", + "@types/i18n-js": "^3.8.5", + "@types/luxon": "^3.3.2", + "@ui-kitten/components": "^5.3.1", + "@ui-kitten/eva-icons": "^5.3.1", + "camelcase-keys": "^7.0.1", + "change-case": "^4.1.2", + "events": "^3.3.0", + "fast-fuzzy": "^1.12.0", + "formik": "^2.4.5", + "h2m": "^0.7.0", + "he": "^1.2.0", + "i18n-js": "^3.8.0", + "js-htmlencode": "^0.3.0", + "luxon": "^3.4.3", + "mockdate": "^3.0.5", + "moment": "^2.29.4", + "node-blob": "^0.0.2", + "node-html-parser": "^6.1.10", + "personnummer": "^3.2.1", + "react": "18.2.0", + "react-native": "0.72.5", + "react-native-animatable": "^1.3.3", + "react-native-calendar-events": "^2.2.0", + "react-native-dev-menu": "^4.1.1", + "react-native-device-info": "^10.11.0", + "react-native-gesture-handler": "^2.13.1", + "react-native-localize": "^3.0.2", + "react-native-modal-datetime-picker": "^17.1.0", + "react-native-oss-license": "^0.7.0", + "react-native-restart": "^0.0.27", + "react-native-safe-area-context": "^4.7.2", + "react-native-screens": "^3.25.0", + "react-native-simple-toast": "^3.0.1", + "react-native-svg": "^13.14.0", + "react-native-typography": "^1.4.1", + "react-native-webview": "^13.6.0", + "react-redux": "^8.1.2", + "redux": "^4.2.1", + "setimmediate": "^1.0.5", + "tough-cookie": "4.1.3", + "tslib": "^2.6.2", + "valtio": "^1.11.2", + "yup": "^1.3.1" + }, + "devDependencies": { + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.23.2", + "@babel/runtime": "^7.20.0", + "@react-native/eslint-config": "^0.72.2", + "@react-native/metro-config": "^0.72.11", + "@testing-library/jest-dom": "^6.1.3", + "@testing-library/jest-native": "^5.4.3", + "@testing-library/react": "^14.0.0", + "@testing-library/react-native": "^12.3.0", + "@tsconfig/react-native": "^3.0.0", + "@types/he": "^1.2.1", + "@types/jest": "^29.5.5", + "@types/react": "^18.0.24", + "@types/react-test-renderer": "^18.0.0", + "babel-jest": "^29.7.0", + "babel-plugin-module-resolver": "^5.0.0", + "eslint": "^8.19.0", + "esm": "^3.2.25", + "jest": "^29.2.1", + "jest-environment-jsdom": "^29.7.0", + "metro-react-native-babel-preset": "0.76.8", + "prettier": "^2.4.1", + "react-test-renderer": "18.2.0", + "typescript": "4.8.4" + }, + "engines": { + "node": ">=16" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", + "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz", + "integrity": "sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.22.17", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.22.17.tgz", + "integrity": "sha512-cop/3quQBVvdz6X5SJC6AhUv3C9DrVTM06LUEXimEdWAhCSyOJIr9NiZDU9leHZ0/aiG0Sh7Zmvaku5TWYNgbA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-default-from": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.22.5.tgz", + "integrity": "sha512-ODAqWWXB/yReh/jVQDag/3/tl6lgBueQkk/TcfW/59Oykm4c8a55XloX0CTk2k2VJiFWMgHby9xNX29IbCv9dQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz", + "integrity": "sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz", + "integrity": "sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-flow": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", + "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz", + "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz", + "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz", + "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.15.tgz", + "integrity": "sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz", + "integrity": "sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz", + "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", + "dependencies": { + "@babel/compat-data": "^7.23.2", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.23.2", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.23.0", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.23.0", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-modules-systemjs": "^7.23.0", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.23.0", + "babel-plugin-polyfill-corejs2": "^0.4.6", + "babel-plugin-polyfill-corejs3": "^0.8.5", + "babel-plugin-polyfill-regenerator": "^0.5.3", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.22.15.tgz", + "integrity": "sha512-dB5aIMqpkgbTfN5vDdTRPzjqtWiZcRESNR88QYnoPR+bmdYoluOzMX9tQerTv0XzSgZYctPfO1oc0N5zdog1ew==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-transform-flow-strip-types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz", + "integrity": "sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-typescript": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.22.15.tgz", + "integrity": "sha512-V3Q3EqoQdn65RCgTLwauZaTfd1ShhwPmbBv+1dkZV/HpCGMKVyn6oFcRlI7RaKqiDQjX2Qd3AuoEguBgdjIKlg==", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/register/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", + "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.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==", + "dev": true, + "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/eslint-utils/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==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.0.tgz", + "integrity": "sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/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==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.22.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", + "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/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" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/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==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", + "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eva-design/dss": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@eva-design/dss/-/dss-2.2.0.tgz", + "integrity": "sha512-ip+iLpe8WFR1IyPGR9puJtXhkZQrWV9p+Xgg3u/3ruDNaObh/YlnfZdS0i29m6YZduW3I+lLuXSXwq5f4pAbRA==" + }, + "node_modules/@eva-design/eva": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@eva-design/eva/-/eva-2.2.0.tgz", + "integrity": "sha512-Wh98ex5cCK+YYSQNpthX1bT4CA3zDRR1WnJv0YlyvULAkmjaEvqtoGMCXzu5DH8v1fGIggu/OpAokLS7UVPe+A==" + }, + "node_modules/@eva-design/processor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@eva-design/processor/-/processor-2.2.0.tgz", + "integrity": "sha512-fEvjvilmF/R9dqXDiMoaoXxrPIb5s1APVXbacXKAxjlWl231rzOxc5sdTtJPoFTTEon5KeaKwLHtbQvz5eVvIA==" + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.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==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/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/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/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/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/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/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/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": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/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/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@jest/types/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/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.19.3.tgz", + "integrity": "sha512-CwGfoHCWdPOTPS+2fW6YRE1fFBpT9++ahLEroX5hkgwyoQ+TkmjOaUxixdEIoVua9Pz5EF2pGOIJzqOTMWfBlA==", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || 0.60 - 0.72 || 1000.0.0" + } + }, + "node_modules/@react-native-community/cli": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.7.tgz", + "integrity": "sha512-Ou8eDlF+yh2rzXeCTpMPYJ2fuqsusNOhmpYPYNQJQ2h6PvaF30kPomflgRILems+EBBuggRtcT+I+1YH4o/q6w==", + "dependencies": { + "@react-native-community/cli-clean": "11.3.7", + "@react-native-community/cli-config": "11.3.7", + "@react-native-community/cli-debugger-ui": "11.3.7", + "@react-native-community/cli-doctor": "11.3.7", + "@react-native-community/cli-hermes": "11.3.7", + "@react-native-community/cli-plugin-metro": "11.3.7", + "@react-native-community/cli-server-api": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", + "@react-native-community/cli-types": "11.3.7", + "chalk": "^4.1.2", + "commander": "^9.4.1", + "execa": "^5.0.0", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.1.3", + "prompts": "^2.4.0", + "semver": "^7.5.2" + }, + "bin": { + "react-native": "build/bin.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@react-native-community/cli-clean": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-11.3.7.tgz", + "integrity": "sha512-twtsv54ohcRyWVzPXL3F9VHGb4Qhn3slqqRs3wEuRzjR7cTmV2TIO2b1VhaqF4HlCgNd+cGuirvLtK2JJyaxMg==", + "dependencies": { + "@react-native-community/cli-tools": "11.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "prompts": "^2.4.0" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-clean/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-clean/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-clean/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/@react-native-community/cli-clean/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-config": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-11.3.7.tgz", + "integrity": "sha512-FDBLku9xskS+bx0YFJFLCmUJhEZ4/MMSC9qPYOGBollWYdgE7k/TWI0IeYFmMALAnbCdKQAYP5N29N55Tad8lg==", + "dependencies": { + "@react-native-community/cli-tools": "11.3.7", + "chalk": "^4.1.2", + "cosmiconfig": "^5.1.0", + "deepmerge": "^4.3.0", + "glob": "^7.1.3", + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-config/node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@react-native-community/cli-config/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/@react-native-community/cli-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-debugger-ui": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-11.3.7.tgz", + "integrity": "sha512-aVmKuPKHZENR8SrflkMurZqeyLwbKieHdOvaZCh1Nn/0UC5CxWcyST2DB2XQboZwsvr3/WXKJkSUO+SZ1J9qTQ==", + "dependencies": { + "serve-static": "^1.13.1" + } + }, + "node_modules/@react-native-community/cli-doctor": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-11.3.7.tgz", + "integrity": "sha512-YEHUqWISOHnsl5+NM14KHelKh68Sr5/HeEZvvNdIcvcKtZic3FU7Xd1WcbNdo3gCq5JvzGFfufx02Tabh5zmrg==", + "dependencies": { + "@react-native-community/cli-config": "11.3.7", + "@react-native-community/cli-platform-android": "11.3.7", + "@react-native-community/cli-platform-ios": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "envinfo": "^7.7.2", + "execa": "^5.0.0", + "hermes-profile-transformer": "^0.0.6", + "ip": "^1.1.5", + "node-stream-zip": "^1.9.1", + "ora": "^5.4.1", + "prompts": "^2.4.0", + "semver": "^7.5.2", + "strip-ansi": "^5.2.0", + "sudo-prompt": "^9.0.0", + "wcwidth": "^1.0.1", + "yaml": "^2.2.1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-doctor/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-doctor/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-doctor/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/@react-native-community/cli-doctor/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-doctor/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/@react-native-community/cli-doctor/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@react-native-community/cli-hermes": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-11.3.7.tgz", + "integrity": "sha512-chkKd8n/xeZkinRvtH6QcYA8rjNOKU3S3Lw/3Psxgx+hAYV0Gyk95qJHTalx7iu+PwjOOqqvCkJo5jCkYLkoqw==", + "dependencies": { + "@react-native-community/cli-platform-android": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", + "chalk": "^4.1.2", + "hermes-profile-transformer": "^0.0.6", + "ip": "^1.1.5" + } + }, + "node_modules/@react-native-community/cli-hermes/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-hermes/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-hermes/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-hermes/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-hermes/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/@react-native-community/cli-hermes/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-android": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-11.3.7.tgz", + "integrity": "sha512-WGtXI/Rm178UQb8bu1TAeFC/RJvYGnbHpULXvE20GkmeJ1HIrMjkagyk6kkY3Ej25JAP2R878gv+TJ/XiRhaEg==", + "dependencies": { + "@react-native-community/cli-tools": "11.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "glob": "^7.1.3", + "logkitty": "^0.7.1" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-platform-android/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-android/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/@react-native-community/cli-platform-android/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-ios": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-11.3.7.tgz", + "integrity": "sha512-Z/8rseBput49EldX7MogvN6zJlWzZ/4M97s2P+zjS09ZoBU7I0eOKLi0N9wx+95FNBvGQQ/0P62bB9UaFQH2jw==", + "dependencies": { + "@react-native-community/cli-tools": "11.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.0.12", + "glob": "^7.1.3", + "ora": "^5.4.1" + } + }, + "node_modules/@react-native-community/cli-platform-ios/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-platform-ios/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-platform-ios/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-platform-ios/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-platform-ios/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-platform-ios/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-ios/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/@react-native-community/cli-platform-ios/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-ios/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-ios/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-plugin-metro": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-11.3.7.tgz", + "integrity": "sha512-0WhgoBVGF1f9jXcuagQmtxpwpfP+2LbLZH4qMyo6OtYLWLG13n2uRep+8tdGzfNzl1bIuUTeE9yZSAdnf9LfYQ==", + "dependencies": { + "@react-native-community/cli-server-api": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "metro": "0.76.8", + "metro-config": "0.76.8", + "metro-core": "0.76.8", + "metro-react-native-babel-transformer": "0.76.8", + "metro-resolver": "0.76.8", + "metro-runtime": "0.76.8", + "readline": "^1.3.0" + } + }, + "node_modules/@react-native-community/cli-plugin-metro/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-plugin-metro/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-plugin-metro/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-plugin-metro/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-plugin-metro/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-plugin-metro/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-plugin-metro/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/@react-native-community/cli-plugin-metro/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-plugin-metro/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-plugin-metro/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-server-api": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-11.3.7.tgz", + "integrity": "sha512-yoFyGdvR3HxCnU6i9vFqKmmSqFzCbnFSnJ29a+5dppgPRetN+d//O8ard/YHqHzToFnXutAFf2neONn23qcJAg==", + "dependencies": { + "@react-native-community/cli-debugger-ui": "11.3.7", + "@react-native-community/cli-tools": "11.3.7", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.1", + "nocache": "^3.0.1", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^7.5.1" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@types/yargs": { + "version": "15.0.16", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.16.tgz", + "integrity": "sha512-2FeD5qezW3FvLpZ0JpfuaEWepgNLl9b2gQYiz/ce0NhoB1W/D+VZu98phITXkADYerfr/jb7JcDcVhITsc9bwg==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-server-api/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-server-api/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/@react-native-community/cli-server-api/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/@react-native-community/cli-server-api/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-11.3.7.tgz", + "integrity": "sha512-peyhP4TV6Ps1hk+MBHTFaIR1eI3u+OfGBvr5r0wPwo3FAJvldRinMgcB/TcCcOBXVORu7ba1XYjkubPeYcqAyA==", + "dependencies": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "find-up": "^5.0.0", + "mime": "^2.4.1", + "node-fetch": "^2.6.0", + "open": "^6.2.0", + "ora": "^5.4.1", + "semver": "^7.5.2", + "shell-quote": "^1.7.3" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli-tools/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli-tools/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==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/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/@react-native-community/cli-tools/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/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/@react-native-community/cli-tools/node_modules/p-locate": { + "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==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@react-native-community/cli-types": { + "version": "11.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-11.3.7.tgz", + "integrity": "sha512-OhSr/TiDQkXjL5YOs8+hvGSB+HltLn5ZI0+A3DCiMsjUgTTsYh+Z63OtyMpNjrdCEFcg0MpfdU2uxstCS6Dc5g==", + "dependencies": { + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native-community/cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/@react-native-community/cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@react-native-community/cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@react-native-community/cli/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/@react-native-community/cli/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/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/@react-native-community/cli/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/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/@react-native-community/cli/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@react-native-community/datetimepicker": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-7.6.0.tgz", + "integrity": "sha512-JRQb4bccIWXRV3UWr6ShxtZLhMVHBaV8Fq6fJk0AAysZ35F1U0MdSkRd7eyJWd3JUebsi32j1GK3mdKHoabtrw==", + "dependencies": { + "invariant": "^2.2.4" + } + }, + "node_modules/@react-native-cookies/cookies": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@react-native-cookies/cookies/-/cookies-6.2.1.tgz", + "integrity": "sha512-D17wCA0DXJkGJIxkL74Qs9sZ3sA+c+kCoGmXVknW7bVw/W+Vv1m/7mWTNi9DLBZSRddhzYw8SU0aJapIaM/g5w==", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react-native": ">= 0.60.2" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.72.0", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.72.0.tgz", + "integrity": "sha512-Im93xRJuHHxb1wniGhBMsxLwcfzdYreSZVQGDoMJgkd6+Iky61LInGEHnQCTN0fKNYF1Dvcofb4uMmE1RQHXHQ==" + }, + "node_modules/@react-native/codegen": { + "version": "0.72.7", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.72.7.tgz", + "integrity": "sha512-O7xNcGeXGbY+VoqBGNlZ3O05gxfATlwE1Q1qQf5E38dK+tXn5BY4u0jaQ9DPjfE8pBba8g/BYI1N44lynidMtg==", + "dependencies": { + "@babel/parser": "^7.20.0", + "flow-parser": "^0.206.0", + "jscodeshift": "^0.14.0", + "nullthrows": "^1.1.1" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/eslint-config": { + "version": "0.72.2", + "resolved": "https://registry.npmjs.org/@react-native/eslint-config/-/eslint-config-0.72.2.tgz", + "integrity": "sha512-rAYuQQXzi63W7+9Pu/+23od/b/lTSzHjMFibum3sKgdG2LIyvhoMEWQ5+Chu7TqebqYy1b9SDn/KEMHvpWFtNg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/eslint-parser": "^7.20.0", + "@react-native/eslint-plugin": "^0.72.0", + "@typescript-eslint/eslint-plugin": "^5.30.5", + "@typescript-eslint/parser": "^5.30.5", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-ft-flow": "^2.0.1", + "eslint-plugin-jest": "^26.5.3", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.30.1", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-native": "^4.0.0" + }, + "peerDependencies": { + "eslint": ">=8", + "prettier": ">=2" + } + }, + "node_modules/@react-native/eslint-plugin": { + "version": "0.72.0", + "resolved": "https://registry.npmjs.org/@react-native/eslint-plugin/-/eslint-plugin-0.72.0.tgz", + "integrity": "sha512-xWQthnyKd+H22TBqeJUTFebsyWAAwzUb7EQCT8F/WMZsS1sv5UG+2cM/cU9/2HEbVZgxHYuLIi915WznjKPvlg==", + "dev": true + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.72.11", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.72.11.tgz", + "integrity": "sha512-P9iRnxiR2w7EHcZ0mJ+fmbPzMby77ZzV6y9sJI3lVLJzF7TLSdbwcQyD3lwMsiL+q5lKUHoZJS4sYmih+P2HXw==" + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.72.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.72.1.tgz", + "integrity": "sha512-cRPZh2rBswFnGt5X5EUEPs0r+pAsXxYsifv/fgy9ZLQokuT52bPH+9xjDR+7TafRua5CttGW83wP4TntRcWNDA==" + }, + "node_modules/@react-native/metro-config": { + "version": "0.72.11", + "resolved": "https://registry.npmjs.org/@react-native/metro-config/-/metro-config-0.72.11.tgz", + "integrity": "sha512-661EyQnDdVelyc0qP/ew7kKkGAh6N6KlkuPLC2SQ8sxaXskVU6fSuNlpLW4bUTBUDFKG8gEOU2hp6rzk4wQnGQ==", + "dev": true, + "dependencies": { + "@react-native/js-polyfills": "^0.72.1", + "metro-config": "0.76.8", + "metro-react-native-babel-transformer": "0.76.8", + "metro-runtime": "0.76.8" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.72.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.72.0.tgz", + "integrity": "sha512-285lfdqSXaqKuBbbtP9qL2tDrfxdOFtIMvkKadtleRQkdOxx+uzGvFr82KHmc/sSiMtfXGp7JnFYWVh4sFl7Yw==" + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.72.8", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.72.8.tgz", + "integrity": "sha512-J3Q4Bkuo99k7mu+jPS9gSUSgq+lLRSI/+ahXNwV92XgJ/8UgOTxu2LPwhJnBk/sQKxq7E8WkZBnBiozukQMqrw==", + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "peerDependencies": { + "react-native": "*" + } + }, + "node_modules/@react-navigation/bottom-tabs": { + "version": "6.5.9", + "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.9.tgz", + "integrity": "sha512-366D4pwq41qKqzsrEk3OPW9atTQJrfrLHPJhX3NLOinRIuDrxal1jJwN3vzNZoEg7gIEKaPYckuqUKg0zRFdog==", + "dependencies": { + "@react-navigation/elements": "^1.3.19", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, + "node_modules/@react-navigation/core": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.9.tgz", + "integrity": "sha512-G9GH7bP9x0qqupxZnkSftnkn4JoXancElTvFc8FVGfEvxnxP+gBo3wqcknyBi7M5Vad4qecsYjCOa9wqsftv9g==", + "dependencies": { + "@react-navigation/routers": "^6.1.9", + "escape-string-regexp": "^4.0.0", + "nanoid": "^3.1.23", + "query-string": "^7.1.3", + "react-is": "^16.13.0", + "use-latest-callback": "^0.1.5" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@react-navigation/elements": { + "version": "1.3.19", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.19.tgz", + "integrity": "sha512-7hLvSYKPuDS070pza5gd43WDX7QgfuEmuTWNbCJhKdWlLudYmq3qzxGCBwCfO2dEI6+p8tla5wruaWiGKAbTYw==", + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0" + } + }, + "node_modules/@react-navigation/native": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.8.tgz", + "integrity": "sha512-0alti852nV+8oCVm9H80G6kZvrHoy51+rXBvVCRUs2rNDDozC/xPZs8tyeCJkqdw3cpxZDK8ndXF22uWq28+0Q==", + "dependencies": { + "@react-navigation/core": "^6.4.9", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "^3.1.23" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/@react-navigation/native-stack": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.14.tgz", + "integrity": "sha512-7RiZkvMFN6f0kmANc63B/0m9ttQ2JpDIPWQwPU93FP698s19KTOyu7uxgl7Oi3bvsqHFO5JfiR7B+4h8lh9dxw==", + "dependencies": { + "@react-navigation/elements": "^1.3.19", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, + "node_modules/@react-navigation/routers": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz", + "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==", + "dependencies": { + "nanoid": "^3.1.23" + } + }, + "node_modules/@react-navigation/stack": { + "version": "6.3.18", + "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.18.tgz", + "integrity": "sha512-jAXneaLAs57xvyMFkebEyGCZDyz90KnaN7fM9f5Bu+Gx3KnoppdNfT4drpmN/f5f32L0eXS4aRAvuDrFT1mFfw==", + "dependencies": { + "@react-navigation/elements": "^1.3.19", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">= 1.0.0", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, + "node_modules/@ronradtke/react-native-markdown-display": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@ronradtke/react-native-markdown-display/-/react-native-markdown-display-8.0.0.tgz", + "integrity": "sha512-i56CYXGXWDGN+dxF72dGiEn4Kld0L6c/JvcOrO4azX9YzVVl02F5EDgdb6fWUaiOl8gPqyUI7YIEU2OVGnIg6Q==", + "dependencies": { + "css-to-react-native": "^3.2.0", + "markdown-it": "^13.0.1", + "prop-types": "^15.7.2", + "react-native-fit-image": "^1.5.5" + }, + "peerDependencies": { + "react": ">=16.2.0", + "react-native": ">=0.50.4" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", + "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/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/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.3.tgz", + "integrity": "sha512-YzpjRHoCBWPzpPNtg6gnhasqtE/5O4qz8WCwDEaxtfnPO6gkaLrnuXusrGSPyhIGPezr1HM7ZH0CFaUTY9PJEQ==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.0", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-native": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-native/-/jest-native-5.4.3.tgz", + "integrity": "sha512-/sSDGaOuE+PJ1Z9Kp4u7PQScSVVXGud59I/qsBFFJvIbcn4P6yYw6cBnBmbPF+X9aRIsTJRDl6gzw5ZkJNm66w==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "jest-diff": "^29.0.1", + "jest-matcher-utils": "^29.0.1", + "pretty-format": "^29.0.3", + "redent": "^3.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-native": ">=0.59", + "react-test-renderer": ">=16.0.0" + } + }, + "node_modules/@testing-library/jest-native/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-native/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/@testing-library/jest-native/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-native/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/jest-native/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-native/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz", + "integrity": "sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react-native": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-12.3.0.tgz", + "integrity": "sha512-E2Prl8D/ey9sRgzLyfCPPmqvsevJW5tVUy4E/pBbO7nOP6OzI/jn2P3vctn/kFdkPY2aE/udlU5ZeNAben9U2A==", + "dev": true, + "dependencies": { + "jest-matcher-utils": "^29.6.2", + "pretty-format": "^29.6.2", + "redent": "^3.0.0" + }, + "peerDependencies": { + "jest": ">=28.0.0", + "react": ">=16.8.0", + "react-native": ">=0.59", + "react-test-renderer": ">=16.8.0" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tsconfig/react-native": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/react-native/-/react-native-3.0.2.tgz", + "integrity": "sha512-F7IoHEqf741lut4Z2K+IkWQRvXAhBiZMeY5L7BysG7Z2Z3MlIyFR+AagD8jQ/CqC1vowGnRwfLjeuwIpaeoJxA==", + "dev": true + }, + "node_modules/@types/aria-query": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-PHKZuMN+K5qgKIWhBodXzQslTo5P+K/6LqeKXS6O/4liIDdZqaX5RXrCK++LAw+y/nptN48YmUMFiQHRSWYwtQ==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", + "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", + "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", + "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hammerjs": { + "version": "2.0.42", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.42.tgz", + "integrity": "sha512-Xxk14BrwHnGi0xlURPRb+Y0UNn2w3cTkeFm7pKMsYOaNgH/kabbJLhcBoNIodwsbTz7Z8KcWjtDvlGH0nc0U9w==" + }, + "node_modules/@types/he": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/he/-/he-1.2.1.tgz", + "integrity": "sha512-CdNmJMcSqX1BiP3iSsWt+VgixndRIDGzWyaGpBnW3i5heATSk5bJu2j3buutsoBQNjyryqxaNpr8M7fRsGL15w==", + "dev": true + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-YIQtIg4PKr7ZyqNPZObpxfHsHEmuB8dXCxd6qVcGuQVDK2bpsF7bYNnBJ4Nn7giuACZg+WewExgrtAJ3XnA4Xw==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/i18n-js": { + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@types/i18n-js/-/i18n-js-3.8.5.tgz", + "integrity": "sha512-6LlMVfkAW8gwcgxIRjxuWxjhD+hw4Mj2VC609FpYCG5n8usb2GE2xbKsEQXWmAIe6LBN2OOw7HnSjZqMDHVtDw==" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "dev": true + }, + "node_modules/@types/luxon": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.2.tgz", + "integrity": "sha512-l5cpE57br4BIjK+9BSkFBOsWtwv6J9bJpC7gdXIzZyI0vuKvNTk0wZZrkQxMGsUAuGW9+WMNWF2IJMD7br2yeQ==" + }, + "node_modules/@types/node": { + "version": "20.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.0.tgz", + "integrity": "sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.7", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.7.tgz", + "integrity": "sha512-FbtmBWCcSa2J4zL781Zf1p5YUBXQomPEcep9QZCfRfQgTxz3pJWiDFLebohZ9fFntX5ibzOkSsrJ0TEew8cAog==" + }, + "node_modules/@types/react": { + "version": "18.2.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.23.tgz", + "integrity": "sha512-qHLW6n1q2+7KyBEYnrZpcsAmU/iiCh9WGCKgXvMxx89+TYdJWRjZohVIo9XTcoLhfX3+/hP0Pbulu3bCZQ9PSA==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.10.tgz", + "integrity": "sha512-5VEC5RgXIk1HHdyN1pHlg0cOqnxHzvPGpMMyGAP5qSaDRmyZNDaQ0kkVAkK6NYlDhP6YBID3llaXlmAS/mdgCA==", + "devOptional": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-test-renderer": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.0.2.tgz", + "integrity": "sha512-tJzMn+9GHDrdrLe0O4rwJELDfTrmdJbCn/UdYyzjlnPiXYXDl5FBNzdw4PVk2R3hJvSHKFjZcRgvZc12lV0p5Q==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.4.tgz", + "integrity": "sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==" + }, + "node_modules/@types/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.3.tgz", + "integrity": "sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==", + "dev": true + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, + "node_modules/@types/yargs": { + "version": "17.0.25", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz", + "integrity": "sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==", + "dev": true, + "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" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "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==", + "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" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/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==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ui-kitten/components": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@ui-kitten/components/-/components-5.3.1.tgz", + "integrity": "sha512-Oj1WePUQtpNfH7ftXGdkkFVmJI+JcR3cBryPJV0E+JAUdH2dbJ0oG/VA+UAgk27/u0K0OZSUkdMFuGnkDAVuYA==", + "dependencies": { + "@eva-design/dss": "^2.2.0", + "@eva-design/processor": "^2.2.0", + "fecha": "3.0.3", + "hoist-non-react-statics": "^3.2.1", + "lodash.merge": "^4.6.1" + }, + "peerDependencies": { + "react-native-svg": "*" + } + }, + "node_modules/@ui-kitten/eva-icons": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@ui-kitten/eva-icons/-/eva-icons-5.3.1.tgz", + "integrity": "sha512-7pFbEiF2vdcMGbb/6/vg0Xy/hZ3js4nFNjZTNEQPaynnndstabNW0MSRokPWYaW6EcxP77LVOsfdShtjQm7kIg==", + "dependencies": { + "react-native-eva-icons": "^1.3.1" + }, + "peerDependencies": { + "@ui-kitten/components": "5.3.1", + "react-native-svg": "*" + } + }, + "node_modules/@ui-kitten/eva-icons/node_modules/react": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.5.0.tgz", + "integrity": "sha512-nw/yB/L51kA9PsAy17T1JrzzGRk+BlFCJwFF7p+pwVxgqwPjYNeZEkkH7LXn9dmflolrYMXLWMTkQ77suKPTNQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "schedule": "^0.3.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ui-kitten/eva-icons/node_modules/react-native-eva-icons": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/react-native-eva-icons/-/react-native-eva-icons-1.3.1.tgz", + "integrity": "sha512-emd/aYXuOacuDVTx0SJoLi+xsOdCNdljQB3PTNCM9AQ3m/smG0X1TN0+ihelPO7MqoHzaH0h6lbANtwxGUy8Fw==", + "peerDependencies": { + "react": "16.5.0", + "react-native-svg": "^9.4.0" + } + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "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==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "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/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "dependencies": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "node_modules/ansi-fragments/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-fragments/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==" + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "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/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "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.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==", + "dev": true, + "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==", + "dev": true, + "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.tosorted": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", + "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "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==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/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/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-module-resolver": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz", + "integrity": "sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==", + "dev": true, + "dependencies": { + "find-babel-config": "^2.0.0", + "glob": "^8.0.3", + "pkg-up": "^3.1.0", + "reselect": "^4.1.7", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/babel-plugin-module-resolver/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/babel-plugin-module-resolver/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/babel-plugin-module-resolver/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/babel-plugin-polyfill-corejs2": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.5.tgz", + "integrity": "sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.32.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-syntax-trailing-function-commas": { + "version": "7.0.0-beta.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", + "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==" + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-fbjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz", + "integrity": "sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==", + "dependencies": { + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-class-properties": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoped-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-member-expression-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-property-literals": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "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==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz", + "integrity": "sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001539", + "electron-to-chromium": "^1.4.530", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001540", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001540.tgz", + "integrity": "sha512-9JL38jscuTJBTcuETxm8QLsFr/F6v0CYYTEU6r5+qSM98P2Q0Hmu0eG1dTG5GBUmywU3UlcVOUSIJYY47rdFSw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/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==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", + "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clipboardy": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz", + "integrity": "sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA==", + "dependencies": { + "arch": "^2.1.0", + "execa": "^0.8.0" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/core-js-compat": { + "version": "3.32.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz", + "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==", + "dependencies": { + "browserslist": "^4.21.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/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/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/css-select/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/css-select/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/css-select/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/css-select/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "engines": { + "node": "*" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", + "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dev": true, + "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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecated-react-native-prop-types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.1.0.tgz", + "integrity": "sha512-WfepZHmRbbdTvhcolb8aOKEvQdcmTMn5tKLbqbXmkBvjFjRVWAYqsXk/DBsV8TZxws8SdGHLuHaJrHSQUPRdfw==", + "dependencies": { + "@react-native/normalize-colors": "*", + "invariant": "*", + "prop-types": "*" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.531", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.531.tgz", + "integrity": "sha512-H6gi5E41Rn3/mhKlPaT1aIMg/71hTAqn0gYEllSuw9igNWtvQwu185jiCZoZD29n7Zukgh7GVZ3zGf0XvkhqjQ==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "node_modules/envinfo": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", + "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/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==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "dependencies": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-abstract": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", + "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", + "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", + "dev": true, + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.0.1" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "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==", + "dev": true, + "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", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/eslint": { + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", + "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.50.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "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" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "engines": { + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-eslint-comments/node_modules/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, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-plugin-ft-flow": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz", + "integrity": "sha512-Vbsd/b+LYA99jUbsL6viEUWShFaYQt2YQs3QN3f+aeszOhh2sgdcU0mjzDyD4yyBvMc8qy2uwvBBWfMzEX06tg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "@babel/eslint-parser": "^7.12.0", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "26.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", + "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "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==", + "dev": true, + "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-plugin-react-native": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native/-/eslint-plugin-react-native-4.1.0.tgz", + "integrity": "sha512-QLo7rzTBOl43FvVqDdq5Ql9IoElIuTdjrz9SKAXCvULvBoRZ44JGSkx9z4999ZusCsb4rK3gjS8gOGyeYqZv2Q==", + "dev": true, + "dependencies": { + "eslint-plugin-react-native-globals": "^0.1.1" + }, + "peerDependencies": { + "eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-native-globals": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz", + "integrity": "sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g==", + "dev": true + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/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==", + "dev": true + }, + "node_modules/eslint/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/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/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==", + "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" + } + }, + "node_modules/eslint/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==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/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": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.22.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", + "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/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" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/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==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/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==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.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==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "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/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/execa/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/execa/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.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==", + "dev": true + }, + "node_modules/fast-fuzzy": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fast-fuzzy/-/fast-fuzzy-1.12.0.tgz", + "integrity": "sha512-sXxGgHS+ubYpsdLnvOvJ9w5GYYZrtL9mkosG3nfuD446ahvoWEsSKBP7ieGmWIKVLnaxRDgUJkZMdxRgA2Ni+Q==", + "dependencies": { + "graphemesplit": "^2.4.1" + } + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "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" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "dev": true + }, + "node_modules/fast-xml-parser": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.1.tgz", + "integrity": "sha512-viVv3xb8D+SiS1W4cv4tva3bni08kAkx0gQnWrykMM8nXPc1FxqZPU00dCEVjkiCg4HoXd2jC4x29Nzg/l2DAA==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/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": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fecha": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-3.0.3.tgz", + "integrity": "sha512-6LQK/1jud/FZnfEEZJ7y81vw7ge81DNd/XEsX0hgMUjhS+QMljkb1C0czBaP7dMNRVrd5mw/J2J7qI2Nw+TWZw==" + }, + "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==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-babel-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.0.0.tgz", + "integrity": "sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw==", + "dev": true, + "dependencies": { + "json5": "^2.1.1", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "dev": true, + "dependencies": { + "flatted": "^3.2.7", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.5.tgz", + "integrity": "sha512-PSZF9ZuaZD03sT9YaIs0FrGJ7lSUw7rHZIex+73UYVXg46eL/wxN5PaVcPJFudE2cJu5f0fezitV5aBkLHPUOQ==" + }, + "node_modules/flow-parser": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", + "engines": { + "node": ">=0.4.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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formik": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.5.tgz", + "integrity": "sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "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/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "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==", + "dev": true, + "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/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.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==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": { + "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": ">=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==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/graphemesplit": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/graphemesplit/-/graphemesplit-2.4.4.tgz", + "integrity": "sha512-lKrpp1mk1NH26USxC/Asw4OHbhSQf5XfrWZ+CDv/dFVvd1j17kFgMotdJvOesmHkbFX9P9sBfpH8VogxOWLg8w==", + "dependencies": { + "js-base64": "^3.6.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/h2m": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/h2m/-/h2m-0.7.0.tgz", + "integrity": "sha512-HxuYZGcbG5lqt9t4YNT1+HuZ6E7CLh0urd5zT4LqoRKCf7VCx0bGzIDOuEdIz6po7XY/Fby6kbOql6ATtBofqg==", + "dependencies": { + "clipboardy": "~1.2.3", + "commander": "^2.9.0", + "htmlparser2": "^3.9.0", + "request": "^2.67.0" + }, + "bin": { + "h2m": "bin/h2m-cli.js" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/hermes-estree": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.12.0.tgz", + "integrity": "sha512-+e8xR6SCen0wyAKrMT3UD0ZCCLymKhRgjEB5sS28rKiFir/fXgLoeRilRUssFCILmGHb+OvHDUlhxs0+IEyvQw==" + }, + "node_modules/hermes-parser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.12.0.tgz", + "integrity": "sha512-d4PHnwq6SnDLhYl3LHNHvOg7nQ6rcI7QVil418REYksv0Mh3cEkHDcuhGxNQ3vgnLSLl4QSvDrFCwQNYdpWlzw==", + "dependencies": { + "hermes-estree": "0.12.0" + } + }, + "node_modules/hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", + "dependencies": { + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-profile-transformer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dependencies": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "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/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "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==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/i18n-js": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.9.2.tgz", + "integrity": "sha512-+Gm8h5HL0emzKhRx2avMKX+nKiVPXeaOZm7Euf2/pbbFcLQoJ3zZYiUykAzoRasijCoWos2Kl1tslmScTgAQKw==" + }, + "node_modules/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, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "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==", + "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==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz", + "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "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": ">=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==", + "dev": true, + "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/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/install": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", + "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "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-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "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==" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dependencies": { + "has": "^1.0.3" + }, + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "engines": { + "node": ">=0.10.0" + } + }, + "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": ">=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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "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==", + "dev": true, + "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.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "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/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/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/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/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/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/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/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-config/node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/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/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/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/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/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/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-message-util/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/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/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/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/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/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/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/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/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/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/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": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-util/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/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-validate/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/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/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/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/joi": { + "version": "17.10.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.10.2.tgz", + "integrity": "sha512-hcVhjBxRNW/is3nNLdGLIjkgXetkeGc2wyhydhz8KumG23Aerk4HPjU5zaPAMRqXQFc0xNqXTC7+zQjxr0GlKA==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + }, + "node_modules/js-htmlencode": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/js-htmlencode/-/js-htmlencode-0.3.0.tgz", + "integrity": "sha512-HedYg9SJsimM4aca37Lj0Ct0eZ1WT8CCxlgMPfUV7mCc6g3UfEUHy2b9qfzuC0uwk4gjVEJKrkWbPSdnUJBFTQ==" + }, + "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-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/jsc-android": { + "version": "250231.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", + "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==" + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==" + }, + "node_modules/jscodeshift": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "dependencies": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.21.0", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/jscodeshift/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jscodeshift/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/jscodeshift/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jscodeshift/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jscodeshift/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/jscodeshift/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/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": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "dev": true + }, + "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", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "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==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "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==", + "dev": true, + "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/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "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", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "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/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/log-symbols/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/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "dependencies": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + }, + "bin": { + "logkitty": "bin/logkitty.js" + } + }, + "node_modules/logkitty/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/logkitty/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/logkitty/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/logkitty/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/logkitty/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/logkitty/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/luxon": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz", + "integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/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": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-it": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it/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/markdown-it/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "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" + } + }, + "node_modules/metro": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.76.8.tgz", + "integrity": "sha512-oQA3gLzrrYv3qKtuWArMgHPbHu8odZOD9AoavrqSFllkPgOtmkBvNNDLCELqv5SjBfqjISNffypg+5UGG3y0pg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "accepts": "^1.3.7", + "async": "^3.2.2", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.12.0", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^27.2.0", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.76.8", + "metro-cache": "0.76.8", + "metro-cache-key": "0.76.8", + "metro-config": "0.76.8", + "metro-core": "0.76.8", + "metro-file-map": "0.76.8", + "metro-inspector-proxy": "0.76.8", + "metro-minify-terser": "0.76.8", + "metro-minify-uglify": "0.76.8", + "metro-react-native-babel-preset": "0.76.8", + "metro-resolver": "0.76.8", + "metro-runtime": "0.76.8", + "metro-source-map": "0.76.8", + "metro-symbolicate": "0.76.8", + "metro-transform-plugins": "0.76.8", + "metro-transform-worker": "0.76.8", + "mime-types": "^2.1.27", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "rimraf": "^3.0.2", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "throat": "^5.0.0", + "ws": "^7.5.1", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.76.8.tgz", + "integrity": "sha512-Hh6PW34Ug/nShlBGxkwQJSgPGAzSJ9FwQXhUImkzdsDgVu6zj5bx258J8cJVSandjNoQ8nbaHK6CaHlnbZKbyA==", + "dependencies": { + "@babel/core": "^7.20.0", + "hermes-parser": "0.12.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-cache": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.76.8.tgz", + "integrity": "sha512-QBJSJIVNH7Hc/Yo6br/U/qQDUpiUdRgZ2ZBJmvAbmAKp2XDzsapnMwK/3BGj8JNWJF7OLrqrYHsRsukSbUBpvQ==", + "dependencies": { + "metro-core": "0.76.8", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-cache-key": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.76.8.tgz", + "integrity": "sha512-buKQ5xentPig9G6T37Ww/R/bC+/V1MA5xU/D8zjnhlelsrPG6w6LtHUS61ID3zZcMZqYaELWk5UIadIdDsaaLw==", + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-config": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.76.8.tgz", + "integrity": "sha512-SL1lfKB0qGHALcAk2zBqVgQZpazDYvYFGwCK1ikz0S6Y/CM2i2/HwuZN31kpX6z3mqjv/6KvlzaKoTb1otuSAA==", + "dependencies": { + "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", + "jest-validate": "^29.2.1", + "metro": "0.76.8", + "metro-cache": "0.76.8", + "metro-core": "0.76.8", + "metro-runtime": "0.76.8" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-core": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.76.8.tgz", + "integrity": "sha512-sl2QLFI3d1b1XUUGxwzw/KbaXXU/bvFYrSKz6Sg19AdYGWFyzsgZ1VISRIDf+HWm4R/TJXluhWMEkEtZuqi3qA==", + "dependencies": { + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.76.8" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-file-map": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.76.8.tgz", + "integrity": "sha512-A/xP1YNEVwO1SUV9/YYo6/Y1MmzhL4ZnVgcJC3VmHp/BYVOXVStzgVbWv2wILe56IIMkfXU+jpXrGKKYhFyHVw==", + "dependencies": { + "anymatch": "^3.0.3", + "debug": "^2.2.0", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-regex-util": "^27.0.6", + "jest-util": "^27.2.0", + "jest-worker": "^27.2.0", + "micromatch": "^4.0.4", + "node-abort-controller": "^3.1.1", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/metro-file-map/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/metro-file-map/node_modules/@types/yargs": { + "version": "16.0.6", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.6.tgz", + "integrity": "sha512-oTP7/Q13GSPrgcwEwdlnkoZSQ1Hg9THe644qq8PG6hhJzjZ3qj1JjEFPIwWV/IXVs5XGIVqtkNOS9kh63WIJ+A==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/metro-file-map/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/metro-file-map/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/metro-file-map/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/metro-file-map/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/metro-file-map/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/metro-file-map/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/metro-file-map/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/metro-file-map/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/metro-file-map/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/metro-file-map/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/metro-file-map/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/metro-file-map/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/metro-inspector-proxy": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-inspector-proxy/-/metro-inspector-proxy-0.76.8.tgz", + "integrity": "sha512-Us5o5UEd4Smgn1+TfHX4LvVPoWVo9VsVMn4Ldbk0g5CQx3Gu0ygc/ei2AKPGTwsOZmKxJeACj7yMH2kgxQP/iw==", + "dependencies": { + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "ws": "^7.5.1", + "yargs": "^17.6.2" + }, + "bin": { + "metro-inspector-proxy": "src/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-inspector-proxy/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/metro-inspector-proxy/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/metro-minify-terser": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.76.8.tgz", + "integrity": "sha512-Orbvg18qXHCrSj1KbaeSDVYRy/gkro2PC7Fy2tDSH1c9RB4aH8tuMOIXnKJE+1SXxBtjWmQ5Yirwkth2DyyEZA==", + "dependencies": { + "terser": "^5.15.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-minify-uglify": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-minify-uglify/-/metro-minify-uglify-0.76.8.tgz", + "integrity": "sha512-6l8/bEvtVaTSuhG1FqS0+Mc8lZ3Bl4RI8SeRIifVLC21eeSDp4CEBUWSGjpFyUDfi6R5dXzYaFnSgMNyfxADiQ==", + "dependencies": { + "uglify-es": "^3.1.9" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-react-native-babel-preset": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.76.8.tgz", + "integrity": "sha512-Ptza08GgqzxEdK8apYsjTx2S8WDUlS2ilBlu9DR1CUcHmg4g3kOkFylZroogVAUKtpYQNYwAvdsjmrSdDNtiAg==", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.18.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.4.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/metro-react-native-babel-transformer": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.76.8.tgz", + "integrity": "sha512-3h+LfS1WG1PAzhq8QF0kfXjxuXetbY/lgz8vYMQhgrMMp17WM1DNJD0gjx8tOGYbpbBC1qesJ45KMS4o5TA73A==", + "dependencies": { + "@babel/core": "^7.20.0", + "babel-preset-fbjs": "^3.4.0", + "hermes-parser": "0.12.0", + "metro-react-native-babel-preset": "0.76.8", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/metro-resolver": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.76.8.tgz", + "integrity": "sha512-KccOqc10vrzS7ZhG2NSnL2dh3uVydarB7nOhjreQ7C4zyWuiW9XpLC4h47KtGQv3Rnv/NDLJYeDqaJ4/+140HQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-runtime": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.76.8.tgz", + "integrity": "sha512-XKahvB+iuYJSCr3QqCpROli4B4zASAYpkK+j3a0CJmokxCDNbgyI4Fp88uIL6rNaZfN0Mv35S0b99SdFXIfHjg==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "react-refresh": "^0.4.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-source-map": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.76.8.tgz", + "integrity": "sha512-Hh0ncPsHPVf6wXQSqJqB3K9Zbudht4aUtNpNXYXSxH+pteWqGAXnjtPsRAnCsCWl38wL0jYF0rJDdMajUI3BDw==", + "dependencies": { + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "invariant": "^2.2.4", + "metro-symbolicate": "0.76.8", + "nullthrows": "^1.1.1", + "ob1": "0.76.8", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.76.8.tgz", + "integrity": "sha512-LrRL3uy2VkzrIXVlxoPtqb40J6Bf1mlPNmUQewipc3qfKKFgtPHBackqDy1YL0njDsWopCKcfGtFYLn0PTUn3w==", + "dependencies": { + "invariant": "^2.2.4", + "metro-source-map": "0.76.8", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-symbolicate/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.76.8.tgz", + "integrity": "sha512-PlkGTQNqS51Bx4vuufSQCdSn2R2rt7korzngo+b5GCkeX5pjinPjnO2kNhQ8l+5bO0iUD/WZ9nsM2PGGKIkWFA==", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.76.8.tgz", + "integrity": "sha512-mE1fxVAnJKmwwJyDtThildxxos9+DGs9+vTrx2ktSFMEVTtXS/bIv2W6hux1pqivqAfyJpTeACXHk5u2DgGvIQ==", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "babel-preset-fbjs": "^3.4.0", + "metro": "0.76.8", + "metro-babel-transformer": "0.76.8", + "metro-cache": "0.76.8", + "metro-cache-key": "0.76.8", + "metro-source-map": "0.76.8", + "metro-transform-plugins": "0.76.8", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/metro/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/metro/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "node_modules/metro/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/metro/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/metro/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/metro/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/metro/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/metro/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/metro/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mockdate": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/mockdate/-/mockdate-3.0.5.tgz", + "integrity": "sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==" + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "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==" + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + }, + "node_modules/node-blob": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/node-blob/-/node-blob-0.0.2.tgz", + "integrity": "sha512-82wiGzMht96gPQDUYaZBdZEVvYD9aEhU6Bt9KLCr4rADZPRd7dQVY2Yj0ZG/1vp4DhVkL49nJT/M3CiMTAt3ag==" + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-html-parser": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.10.tgz", + "integrity": "sha512-6/uWdWxjQWQ7tMcFK2wWlrflsQUzh1HsEzlIf2j5+TtzfhT2yUvg3DwZYAmjEHeR3uX74ko7exjHW69J0tOzIg==", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + }, + "node_modules/node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "engines": { + "node": ">=0.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/antelle" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/ob1": { + "version": "0.76.8", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.76.8.tgz", + "integrity": "sha512-dlBkJJV5M/msj9KYA9upc+nUWVwuOFFTbu28X6kZeGwcuW+JxaHSBZ70SYQnk5M+j5JbNLR6yKHmgW4M5E7X5g==", + "engines": { + "node": ">=16" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "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==", + "dev": true, + "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==", + "dev": true, + "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.hasown": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "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/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "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", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/ora/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/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "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" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=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==" + }, + "node_modules/path-type": { + "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" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/personnummer": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/personnummer/-/personnummer-3.2.1.tgz", + "integrity": "sha512-EWDCfUBnXAUtL8/vOF/Ne7Fa12pBsYfMDQKSLK6I4bApx/rZx8rRBqPEtbhihJ2EYrc5lK2FBs7j5rTYfZirtg==", + "bin": { + "personnummer": "bin/personnummer" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sweidproject" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "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==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-expr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", + "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" + }, + "node_modules/proxy-compare": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz", + "integrity": "sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "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", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.0.tgz", + "integrity": "sha512-E3C3X1skWBdBzwpOUbmXG8SgH6BtsluSMe+s6rRcujNKG1DGi8uIfhdhszkgDpAsMoE55hwqRUzeXCmETDBpTg==", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "devOptional": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "devOptional": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, + "node_modules/react-freeze": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz", + "integrity": "sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=17.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-native": { + "version": "0.72.5", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.72.5.tgz", + "integrity": "sha512-oIewslu5DBwOmo7x5rdzZlZXCqDIna0R4dUwVpfmVteORYLr4yaZo5wQnMeR+H7x54GaMhmgeqp0ZpULtulJFg==", + "dependencies": { + "@jest/create-cache-key-function": "^29.2.1", + "@react-native-community/cli": "11.3.7", + "@react-native-community/cli-platform-android": "11.3.7", + "@react-native-community/cli-platform-ios": "11.3.7", + "@react-native/assets-registry": "^0.72.0", + "@react-native/codegen": "^0.72.7", + "@react-native/gradle-plugin": "^0.72.11", + "@react-native/js-polyfills": "^0.72.1", + "@react-native/normalize-colors": "^0.72.0", + "@react-native/virtualized-lists": "^0.72.8", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "base64-js": "^1.1.2", + "deprecated-react-native-prop-types": "4.1.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.5", + "invariant": "^2.2.4", + "jest-environment-node": "^29.2.1", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "0.76.8", + "metro-source-map": "0.76.8", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^4.27.2", + "react-refresh": "^0.4.0", + "react-shallow-renderer": "^16.15.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "stacktrace-parser": "^0.1.10", + "use-sync-external-store": "^1.0.0", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": "18.2.0" + } + }, + "node_modules/react-native-animatable": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz", + "integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==", + "dependencies": { + "prop-types": "^15.7.2" + } + }, + "node_modules/react-native-calendar-events": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-native-calendar-events/-/react-native-calendar-events-2.2.0.tgz", + "integrity": "sha512-tNUbhT6Ief0JM4OQzQAaz1ri0+MCcAoHptBcEXCz2g7q3A05pg62PR2Dio4F9t2fCAD7Y2+QggdY1ycAsF3Tsg==", + "peerDependencies": { + "react-native": ">=0.60.0" + } + }, + "node_modules/react-native-dev-menu": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-native-dev-menu/-/react-native-dev-menu-4.1.1.tgz", + "integrity": "sha512-jdYjoTpFHvGXW12enaTnrgOoEgVF5JVqv4hcO8K0KV66Cvk8YLwD3XHsEiqMat+4C1osa+IG5Yt3qAiMOLBQxQ==", + "peerDependencies": { + "react-native": ">=0.61.0" + } + }, + "node_modules/react-native-device-info": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-10.11.0.tgz", + "integrity": "sha512-qRzhuYOm5ZXQi5dhfJFjDq157oipxcEW/fo0QyMm5+TI6V6/+P/tju+Hif6z0rpLCf7MV7iDVRv2Kqha4D/yvQ==", + "peerDependencies": { + "react-native": "*" + } + }, + "node_modules/react-native-fit-image": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/react-native-fit-image/-/react-native-fit-image-1.5.5.tgz", + "integrity": "sha512-Wl3Vq2DQzxgsWKuW4USfck9zS7YzhvLNPpkwUUCF90bL32e1a0zOVQ3WsJILJOwzmPdHfzZmWasiiAUNBkhNkg==", + "dependencies": { + "prop-types": "^15.5.10" + } + }, + "node_modules/react-native-gesture-handler": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.13.1.tgz", + "integrity": "sha512-hW454X7sjuiBN+lobqw63pmT3boAmTl5OP6zQLq83iEe4T6PcHZ9lxzgCrebtgmutY8cJfq9rM2dOUVh9WBcww==", + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "lodash": "^4.17.21", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-localize": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-native-localize/-/react-native-localize-3.0.2.tgz", + "integrity": "sha512-/l/oE1LVNgIRRhLbhmfFMHiWV0xhUn0A0iz1ytLVRYywL7FTp8Rx2vkJS/q/RpExDvV7yLw2493XZBYIM1dnLQ==", + "peerDependencies": { + "react": ">=18.1.0", + "react-native": ">=0.70.0", + "react-native-macos": ">=0.70.0" + }, + "peerDependenciesMeta": { + "react-native-macos": { + "optional": true + } + } + }, + "node_modules/react-native-modal-datetime-picker": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/react-native-modal-datetime-picker/-/react-native-modal-datetime-picker-17.1.0.tgz", + "integrity": "sha512-jfTwfaCLtBffYbQ+pOGFLM+J5HmUh3vb9rT0JrrQPjxzecdc8pNYreB1c96+mVuq8bDCvaCdIeuEsslTqLJL0Q==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "@react-native-community/datetimepicker": ">=6.7.0", + "react-native": ">=0.65.0" + } + }, + "node_modules/react-native-oss-license": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/react-native-oss-license/-/react-native-oss-license-0.7.0.tgz", + "integrity": "sha512-vlzpUkp9E4RWIwtJFq2HvBkAZxs2pF8NcR7vydWtms53pLWbYNDa3NutjO6wIzawGx6vW3EjlQpTI6MUNaB41g==", + "dependencies": { + "commander": "^4.0.0", + "fs-extra": "^8.1.0", + "glob": "^7.1.5", + "he": "^1.2.0", + "install": "^0.13.0", + "path": "^0.12.7", + "read-installed": "^4.0.3", + "yaml": "^1.7.2" + }, + "bin": { + "react-native-oss-license": "bin/react-native-oss-license.js" + } + }, + "node_modules/react-native-oss-license/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/react-native-oss-license/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/react-native-restart": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/react-native-restart/-/react-native-restart-0.0.27.tgz", + "integrity": "sha512-8KScVICrXwcTSJ1rjWkqVTHyEKQIttm5AIMGSK1QG1+RS5owYlE4z/1DykOTdWfVl9l16FIk0w9Xzk9ZO6jxlA==", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-safe-area-context": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.7.2.tgz", + "integrity": "sha512-5fy/hRNJ7bI/U2SliOeKf0D80J4lXPc1NsRiNS7Xaz8YTnqlzWib1ViItkwKPfufe54YKzVBMmM32RpdzvO2gg==", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-screens": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.25.0.tgz", + "integrity": "sha512-TSC2Ad0hh763I8QT6XxMsPXAagQ+RawDSdFtKRvIz9fCYr96AjRwwaqmYivbqlDywOgcRBkIVynkFtp0ThmlYw==", + "dependencies": { + "react-freeze": "^1.0.0", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-simple-toast": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/react-native-simple-toast/-/react-native-simple-toast-3.0.1.tgz", + "integrity": "sha512-G1iUHqvhA4Obacol+fz1MKTeHDGyDFGXvnmAxYrUNBkTOA9/yaVpZBjoWfpnYXIlYtrCOcz6ll/B8nUJg4PPDA==", + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "react": "*", + "react-native": ">=0.71.0" + } + }, + "node_modules/react-native-svg": { + "version": "13.14.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.0.tgz", + "integrity": "sha512-27ZnxUkHgWICimhuj6MuqBkISN53lVvgWJB7pIypjXysAyM+nqgQBPh4vXg+7MbqLBoYvR4PiBgKfwwGAqVxHg==", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-typography": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/react-native-typography/-/react-native-typography-1.4.1.tgz", + "integrity": "sha512-dc9Zfs4jUdq4ygx4/KwO6jKTERBu6cRrfPJGntw/pA+D6BMjlWfMNuhZ/69vf4Zpsnt9s4AGe+Z/V1QFYaCXAA==", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-webview": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.6.0.tgz", + "integrity": "sha512-KapVfHEj60e+2QplhqoCMdqW4vDzzvLS3YasfjVoMV4qhsZ3padncMEqOHX6AY4FIAdRzAxG0JQs+kXczAPYeQ==", + "dependencies": { + "escape-string-regexp": "2.0.0", + "invariant": "2.2.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-webview/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-native/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/react-native/node_modules/@types/yargs": { + "version": "15.0.16", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.16.tgz", + "integrity": "sha512-2FeD5qezW3FvLpZ0JpfuaEWepgNLl9b2gQYiz/ce0NhoB1W/D+VZu98phITXkADYerfr/jb7JcDcVhITsc9bwg==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/react-native/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/react-native/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/react-native/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/react-native/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/react-native/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/react-native/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-native/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/react-native/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/react-native/node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/react-redux": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.2.tgz", + "integrity": "sha512-xJKYI189VwfsFc4CJvHqHlDrzyFTY/3vZACbE+rr/zQ34Xx1wQfB4OTOSeOSNrF6BDVe8OOdxIrAnMGXA3ggfw==", + "dependencies": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^16.8 || ^17.0 || ^18.0", + "@types/react-dom": "^16.8 || ^17.0 || ^18.0", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0", + "react-native": ">=0.59", + "redux": "^4 || ^5.0.0-beta.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/react-refresh": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", + "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-test-renderer": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.2.0.tgz", + "integrity": "sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==", + "dev": true, + "dependencies": { + "react-is": "^18.2.0", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-test-renderer/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/react-test-renderer/node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/read-installed": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz", + "integrity": "sha512-O03wg/IYuV/VtnK2h/KXEt9VIbMUFbk3ERG0Iu4FhLZw0EP0T9znqrYDGn6ncbEsXUFaUjiVAWXHzxwt3lhRPQ==", + "dependencies": { + "debuglog": "^1.0.1", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.2" + } + }, + "node_modules/read-installed/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-package-json": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", + "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", + "dependencies": { + "glob": "^7.1.1", + "json-parse-even-better-errors": "^2.3.0", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dependencies": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" + }, + "node_modules/recast": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "dependencies": { + "ast-types": "0.15.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "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" + } + }, + "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" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "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", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.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", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/schedule": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schedule/-/schedule-0.3.0.tgz", + "integrity": "sha512-20+1KVo517sR7Nt+bYBN8a+bEJDKLPEx7Ohtts1kX05E4/HY53YUNuhfkVNItmWAnBYHcpG9vsd2/CJxG+aPCQ==", + "peer": true, + "dependencies": { + "object-assign": "^4.1.1" + } + }, + "node_modules/scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "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/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "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", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==", + "engines": { + "node": "*" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz", + "integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==" + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/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==", + "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/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "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==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "node_modules/sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/terser": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", + "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/through2/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==", + "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/through2/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==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "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==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "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==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "node_modules/uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "deprecated": "support for ECMAScript is superseded by `uglify-js` as of v3.13.0", + "dependencies": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-es/node_modules/commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" + }, + "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==", + "dev": true, + "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" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "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/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use-latest-callback": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.6.tgz", + "integrity": "sha512-VO/P91A/PmKH9bcN9a7O3duSuxe6M14ZoYXgA6a8dab8doWNdhiIHzEkX/jFeTTRBsX0Ubk6nG4q2NIjNsj+bg==", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA==" + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/valtio": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.11.2.tgz", + "integrity": "sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw==", + "dependencies": { + "proxy-compare": "2.5.1", + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==" + }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.19", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz", + "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==" + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", + "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yup": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.3.1.tgz", + "integrity": "sha512-2stNyEF96SnPUxzRL99kt1bEHWytnvC2stwmTTqjoFXZRf63JtYK2pQt2AJvWcQvkrAzr/pcXvc6c5vrqsBzDg==", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/apps/skolplattformen-app-new/package.json b/apps/skolplattformen-app-new/package.json new file mode 100644 index 000000000..9201d985e --- /dev/null +++ b/apps/skolplattformen-app-new/package.json @@ -0,0 +1,98 @@ +{ + "name": "oppna_skolplattformen_new", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios --simulator \"iPhone 15\"", + "lint": "eslint .", + "start": "react-native start", + "test": "jest", + "extract-licenses": "react-native-oss-license --json > licenses-oss.json && node library-extractor.js && rm licenses-oss.json", + "postinstall": "yarn extract-licenses" + }, + "dependencies": { + "@eva-design/eva": "^2.2.0", + "@react-native-async-storage/async-storage": "^1.19.3", + "@react-native-community/datetimepicker": "^7.6.0", + "@react-native-cookies/cookies": "^6.2.1", + "@react-navigation/bottom-tabs": "^6.5.9", + "@react-navigation/native": "^6.1.8", + "@react-navigation/native-stack": "^6.9.14", + "@react-navigation/stack": "^6.3.18", + "@ronradtke/react-native-markdown-display": "^8.0.0", + "@types/i18n-js": "^3.8.5", + "@types/luxon": "^3.3.2", + "@ui-kitten/components": "^5.3.1", + "@ui-kitten/eva-icons": "^5.3.1", + "camelcase-keys": "^7.0.1", + "change-case": "^4.1.2", + "events": "^3.3.0", + "fast-fuzzy": "^1.12.0", + "formik": "^2.4.5", + "h2m": "^0.7.0", + "he": "^1.2.0", + "i18n-js": "^3.8.0", + "js-htmlencode": "^0.3.0", + "luxon": "^3.4.3", + "mockdate": "^3.0.5", + "moment": "^2.29.4", + "node-blob": "^0.0.2", + "node-html-parser": "^6.1.10", + "personnummer": "^3.2.1", + "react": "18.2.0", + "react-native": "0.72.5", + "react-native-animatable": "^1.3.3", + "react-native-calendar-events": "^2.2.0", + "react-native-dev-menu": "^4.1.1", + "react-native-device-info": "^10.11.0", + "react-native-gesture-handler": "^2.13.1", + "react-native-localize": "^3.0.2", + "react-native-modal-datetime-picker": "^17.1.0", + "react-native-oss-license": "^0.7.0", + "react-native-restart": "^0.0.27", + "react-native-safe-area-context": "^4.7.2", + "react-native-screens": "^3.25.0", + "react-native-simple-toast": "^3.0.1", + "react-native-svg": "^13.14.0", + "react-native-typography": "^1.4.1", + "react-native-webview": "^13.6.0", + "react-redux": "^8.1.2", + "redux": "^4.2.1", + "setimmediate": "^1.0.5", + "tough-cookie": "4.1.3", + "tslib": "^2.6.2", + "valtio": "^1.11.2", + "yup": "^1.3.1" + }, + "devDependencies": { + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.23.2", + "@babel/runtime": "^7.20.0", + "@react-native/eslint-config": "^0.72.2", + "@react-native/metro-config": "^0.72.11", + "@testing-library/jest-dom": "^6.1.3", + "@testing-library/jest-native": "^5.4.3", + "@testing-library/react": "^14.0.0", + "@testing-library/react-native": "^12.3.0", + "@tsconfig/react-native": "^3.0.0", + "@types/he": "^1.2.1", + "@types/jest": "^29.5.5", + "@types/react": "^18.0.24", + "@types/react-test-renderer": "^18.0.0", + "babel-jest": "^29.7.0", + "babel-plugin-module-resolver": "^5.0.0", + "eslint": "^8.19.0", + "esm": "^3.2.25", + "jest": "^29.2.1", + "jest-environment-jsdom": "^29.7.0", + "metro-react-native-babel-preset": "0.76.8", + "prettier": "^2.4.1", + "react-test-renderer": "18.2.0", + "typescript": "4.8.4" + }, + "engines": { + "node": ">=16" + } +} diff --git a/apps/skolplattformen-app-new/services/__tests__/appStorage.tests.ts b/apps/skolplattformen-app-new/services/__tests__/appStorage.tests.ts new file mode 100644 index 000000000..230e017aa --- /dev/null +++ b/apps/skolplattformen-app-new/services/__tests__/appStorage.tests.ts @@ -0,0 +1,159 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' +import { User } from '@skolplattformen/api' +import AppStorage from '../appStorage' + +beforeEach(() => { + jest.clearAllMocks() + AsyncStorage.clear() +}) + +const prefix = AppStorage.settingsStorageKeyPrefix +const temp = AppStorage.tempStorageKeyPrefix + +test('Sets setting with prefix in storage', async () => { + await AppStorage.setSetting('key', 'value') + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + prefix + 'key', + JSON.stringify('value') + ) +}) + +test('Can get setting from storage', async () => { + await AppStorage.setSetting('key', 'value') + const result = await AppStorage.getSetting('key') + + expect(result).toEqual('value') + expect(AsyncStorage.getItem).toHaveBeenCalledWith(prefix + 'key') +}) + +test('Clear only settings', async () => { + const user: User = { personalNumber: '201701012393' } + await AppStorage.setSetting('key', 'value') + await AppStorage.setSetting('key2', 'value2') + await AppStorage.setSetting('key3', 'value3') + + await AppStorage.setTemporaryItem('nonSetting', 'nonSettingValue') + await AppStorage.setPersonalData(user, 'personalData', 'personal id value') + + await AppStorage.clearAllSettings() + + const allKeys = await AsyncStorage.getAllKeys() + + expect(allKeys).toHaveLength(2) + expect(allKeys[0]).toEqual(temp + 'nonSetting') + expect(allKeys[1]).toEqual(user.personalNumber + '_' + 'personalData') +}) + +test('Clear temporary items', async () => { + const user: User = { personalNumber: '201701012393' } + await AppStorage.setSetting('settingKey1', 'settingValue1') + await AppStorage.setSetting('settingKey2', 'settingValue2') + await AppStorage.setSetting('settingKey3', 'settingValue3') + await AppStorage.setTemporaryItem('tempKey1', 'tempValue1') + await AppStorage.setTemporaryItem('tempKey2', 'tempValue2') + await AppStorage.setTemporaryItem('tempKey3', 'tempValue3') + await AppStorage.setPersonalData(user, 'personalData', 'personal id value') + + await AppStorage.clearTemporaryItems() + + const allKeys = await AsyncStorage.getAllKeys() + + expect(allKeys).toHaveLength(4) + expect(allKeys[0]).toEqual(prefix + 'settingKey1') + expect(allKeys[3]).toEqual(user.personalNumber + '_' + 'personalData') +}) + +test('Store temporary string in AsyncStorage', async () => { + await AppStorage.setTemporaryItem('tempkey', 'tempvalue') + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + temp + 'tempkey', + JSON.stringify('tempvalue') + ) +}) + +test('Get temporary string from AsyncStorage', async () => { + await AppStorage.getTemporaryItem('tempkey') + + expect(AsyncStorage.getItem).toHaveBeenCalledWith(temp + 'tempkey') +}) + +test('Store temporary object in AsyncStorage', async () => { + const obj = { a: 'foo', b: 5 } + await AppStorage.setTemporaryItem('tempkey', obj) + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + temp + 'tempkey', + JSON.stringify(obj) + ) +}) + +test('Get temporary object from AsyncStorage', async () => { + await AppStorage.getTemporaryItem('tempkey') + + expect(AsyncStorage.getItem).toHaveBeenCalledWith(temp + 'tempkey') +}) + +test('Set personal data with personal number prefix', async () => { + const obj = { a: 'gdpr', b: 'is fun' } + const user: User = { personalNumber: '201701012393' } + await AppStorage.setPersonalData(user, 'key', obj) + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + user.personalNumber + '_' + 'key', + JSON.stringify(obj) + ) +}) + +test('Set personal data does nothing if personal number missing', async () => { + const obj = { a: 'gdpr', b: 'is fun' } + const user: User = { personalNumber: '' } + await AppStorage.setPersonalData(user, 'key', obj) + + expect(AsyncStorage.setItem).not.toHaveBeenCalled() +}) + +test('Get personal data gets data if personal number matches', async () => { + const data = 'personal data' + const user: User = { personalNumber: '201701012393' } + + await AppStorage.setPersonalData(user, 'key', data) + const storedData = await AppStorage.getPersonalData(user, 'key') + + expect(storedData).toEqual(data) +}) + +test('Get no personal data gets data if personal number does not match', async () => { + const data = 'personal data' + const user: User = { personalNumber: '201701012393' } + const anotherAser: User = { personalNumber: '202112312380' } + + await AppStorage.setPersonalData(user, 'key', data) + const storedData = await AppStorage.getPersonalData(anotherAser, 'key') + + expect(user).not.toEqual(anotherAser) + expect(storedData).toEqual(null) +}) + +test('Clear only PersonalData', async () => { + await AppStorage.setSetting('settingKey1', 'settingValue1') + await AppStorage.setTemporaryItem('tempKey1', 'tempValue1') + + const data = 'personal data' + const user: User = { personalNumber: '201701012393' } + await AppStorage.setPersonalData(user, 'key', data) + + await AppStorage.clearPersonalData(user) + + const allKeys = await AsyncStorage.getAllKeys() + expect(allKeys).toHaveLength(2) + expect(allKeys).not.toContain(user.personalNumber + '_key') +}) + +test('Clear PersonalData does nothing if personalnumber is empty', async () => { + const user: User = { personalNumber: '' } + await AppStorage.clearPersonalData(user) + + expect(AsyncStorage.multiRemove).not.toHaveBeenCalled() +}) diff --git a/apps/skolplattformen-app-new/services/appStorage.ts b/apps/skolplattformen-app-new/services/appStorage.ts new file mode 100644 index 000000000..81e27dbc3 --- /dev/null +++ b/apps/skolplattformen-app-new/services/appStorage.ts @@ -0,0 +1,124 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' +import { User } from '@skolplattformen/api' + +export default class AppStorage { + static settingsStorageKeyPrefix = 'appsetting_' + static tempStorageKeyPrefix = 'tempItem_' + + /** + * Stores a setting + * @param key + * @param value + */ + static async setSetting(key: string, value: T) { + const jsonValue = JSON.stringify(value) + await AsyncStorage.setItem(this.settingsStorageKeyPrefix + key, jsonValue) + } + + /** + * Gets a stored setting + * @param key + * @returns + */ + static async getSetting(key: string): Promise { + const value = await AsyncStorage.getItem( + this.settingsStorageKeyPrefix + key + ) + return value ? (JSON.parse(value) as T) : null + } + + /** + * Stores a personal data item + * @param user + * @param key + * @param value + */ + static async setPersonalData(user: User, key: string, value: T) { + const jsonValue = JSON.stringify(value) + if (user.personalNumber) { + const storageKey = user.personalNumber + '_' + key + await AsyncStorage.setItem(storageKey, jsonValue) + } + } + + /** + * Get stored personal data + * @param user + * @param key + * @returns + */ + static async getPersonalData(user: User, key: string): Promise { + if (user.personalNumber) { + const value = await AsyncStorage.getItem(user.personalNumber + '_' + key) + return value ? (JSON.parse(value) as T) : null + } + return null + } + + /** + * Stores a temporary items. The items are cleared at logout. + * Think of this as a session storage + * @param key + * @param value + */ + static async setTemporaryItem(key: string, value: T) { + const jsonValue = JSON.stringify(value) + await AsyncStorage.setItem(this.tempStorageKeyPrefix + key, jsonValue) + } + + /** + * Gets a temporary stored item + * @param key + * @returns + */ + static async getTemporaryItem(key: string): Promise { + const value = await AsyncStorage.getItem(this.tempStorageKeyPrefix + key) + return value ? (JSON.parse(value) as T) : null + } + + /** + * Clears all settings + */ + static async clearAllSettings(): Promise { + const allKeys = await AsyncStorage.getAllKeys() + const settingsKeys = allKeys.filter((x) => + x.startsWith(this.settingsStorageKeyPrefix) + ) + await AsyncStorage.multiRemove(settingsKeys) + } + + /** + * Clear all temporary items + */ + static async clearTemporaryItems() { + const allKeys = await AsyncStorage.getAllKeys() + const notSettingsKeys = allKeys.filter((x) => + x.startsWith(this.tempStorageKeyPrefix) + ) + await AsyncStorage.multiRemove(notSettingsKeys) + } + + /** + * Clears all personal identififieble data (GDPR) + * @param user + * @returns + */ + static async clearPersonalData(user: User): Promise { + if (!user.personalNumber) { + return + } + + const allKeys = await AsyncStorage.getAllKeys() + const personalDataKeys = allKeys.filter((x) => + x.startsWith(user.personalNumber ?? '') + ) + await AsyncStorage.multiRemove(personalDataKeys) + } + + /** + * Clears all async storage for this app and all libs that it uses + */ + static async nukeAllStorage() { + await AsyncStorage.clear() + } +} diff --git a/apps/skolplattformen-app-new/services/languageService.ts b/apps/skolplattformen-app-new/services/languageService.ts new file mode 100644 index 000000000..643a223b5 --- /dev/null +++ b/apps/skolplattformen-app-new/services/languageService.ts @@ -0,0 +1,95 @@ +import merge from 'deepmerge' +import i18n from 'i18n-js' +import moment from 'moment' +import 'moment/locale/ar' +import 'moment/locale/de' +import 'moment/locale/es' +import 'moment/locale/fi' +import 'moment/locale/fr' +import 'moment/locale/it' +import 'moment/locale/ja' +import 'moment/locale/nb' +import 'moment/locale/nl' +import 'moment/locale/pl' +import 'moment/locale/pt' +import 'moment/locale/ru' +import 'moment/locale/sv' +import 'moment/locale/th' +import 'moment/locale/uk' +import 'moment/locale/zh-cn' +import { I18nManager } from 'react-native' +import { languages } from '../utils/translation' + +// const i18n = new I18n(); + +const changeListeners: Record = {} + +let allString: Record = {} + +let Strings: Record = {} +let languageCode: string +let momentLocale: string + +const rtlList: { [key: string]: boolean } = { + en: false, + de: false, + pl: false, + sv: false, + so: false, + ar: true, +} + +export const isRTL = (langCode: string) => { + if (!Object.prototype.hasOwnProperty.call(rtlList, langCode)) { + return false + } + return rtlList[langCode] +} + +const getCorrespondingMomentLocale = (languageCode?: string): string => { + const lang = languages.find(({ langCode }) => langCode === languageCode) + return lang?.locale || 'sv' +} + +export const LanguageService = { + get: () => Strings, + getLanguageCode: () => languageCode, + getLocale: () => momentLocale, + setAllData: ({ data }: { data: Record }) => { + allString = data + }, + seti18nConfig: ({ langCode }: { langCode?: string }) => { + i18n.defaultLocale = 'sv' + if (langCode) { + i18n.translations = { [langCode]: Strings } + i18n.locale = langCode + I18nManager.forceRTL(isRTL(langCode)) + } + moment.locale(momentLocale) + }, + setLanguageCode: ({ langCode }: { langCode?: string }) => { + if (langCode && allString[langCode]) { + languageCode = langCode + momentLocale = getCorrespondingMomentLocale(langCode) + Strings = merge(allString.sv, allString[langCode]) + } else { + const dataKeys = Object.keys(allString) + languageCode = dataKeys[0] + Strings = allString[languageCode] + } + Object.keys(changeListeners).forEach((k) => { + changeListeners[k](langCode) + }) + return Strings + }, + onChange: ({ key }: { key: string }, cb: (langCode: string) => void) => { + const unsubscribe = () => { + delete changeListeners[key] + } + changeListeners[key] = (langCode: string) => cb(langCode) + + return unsubscribe + }, +} + +export const i18nService = i18n diff --git a/apps/skolplattformen-app-new/styles/colors.ts b/apps/skolplattformen-app-new/styles/colors.ts new file mode 100644 index 000000000..fc549ce09 --- /dev/null +++ b/apps/skolplattformen-app-new/styles/colors.ts @@ -0,0 +1,22 @@ +type Neutral = + | 'white' + | 'black' + | 'gray200' + | 'gray500' + | 'gray600' + | 'gray700' + | 'gray800' +export const neutral: Record = { + white: '#ffffff', + gray200: '#E5E7EB', + gray500: '#6B7280', // 4.83 (AA) on white + gray600: '#4B5563', // 7.56 (AAA) on white + gray700: '#374151', // 10.31 (AAA) on white + gray800: '#1F2937', // 14.68 (AAA) on white + black: '#000000', // 21 (AAA) on white +} + +type Primary = 'primary600' +export const primary: Record = { + primary600: '#DB2575', +} diff --git a/apps/skolplattformen-app-new/styles/index.ts b/apps/skolplattformen-app-new/styles/index.ts new file mode 100644 index 000000000..e0760fd99 --- /dev/null +++ b/apps/skolplattformen-app-new/styles/index.ts @@ -0,0 +1,6 @@ +import * as Colors from './colors' +import * as Layout from './layout' +import * as Sizing from './sizing' +import * as Typography from './typography' + +export { Colors, Layout, Sizing, Typography } diff --git a/apps/skolplattformen-app-new/styles/layout.ts b/apps/skolplattformen-app-new/styles/layout.ts new file mode 100644 index 000000000..ccbb8f1d2 --- /dev/null +++ b/apps/skolplattformen-app-new/styles/layout.ts @@ -0,0 +1,43 @@ +import { ViewStyle } from 'react-native' + +type MainAxis = 'center' | 'flexStart' | 'flexEnd' +// @ts-expect-error Fix later +export const mainAxis: Record = { + center: { + alignItems: 'center', + }, + flexStart: { + alignItems: 'flex-start', + }, +} + +type CrossAxis = 'center' | 'flexEnd' | 'evenly' | 'spaceBetween' +export const crossAxis: Record = { + center: { + justifyContent: 'center', + }, + evenly: { + justifyContent: 'space-evenly', + }, + flexEnd: { + justifyContent: 'flex-end', + }, + spaceBetween: { + justifyContent: 'space-between', + }, +} + +export const center: ViewStyle = { + ...mainAxis.center, + ...crossAxis.center, +} + +type Flex = 'full' | 'row' +export const flex: Record = { + full: { + flex: 1, + }, + row: { + flexDirection: 'row', + }, +} diff --git a/apps/skolplattformen-app-new/styles/sizing.ts b/apps/skolplattformen-app-new/styles/sizing.ts new file mode 100644 index 000000000..2210da313 --- /dev/null +++ b/apps/skolplattformen-app-new/styles/sizing.ts @@ -0,0 +1,54 @@ +import { Dimensions, ImageStyle } from 'react-native' + +const { height: screenHeight, width: screenWidth } = Dimensions.get('screen') +type Screen = 'width' | 'height' +export const screen: Record = { + width: screenWidth, + height: screenHeight, +} + +export enum Ratio { + '4:3', + '16:9', +} + +export const aspectRatio = ( + modifier = 1, + ratio: Ratio = Ratio['16:9'] +): ImageStyle => { + switch (ratio) { + case Ratio['16:9']: + return { + height: ((screen.width * modifier) / 16) * 9, + width: screen.width * modifier, + } + case Ratio['4:3']: + return { + height: ((screen.width * modifier) / 4) * 3, + width: screen.width * modifier, + } + } +} + +type Layout = 't1' | 't2' | 't3' | 't4' | 't5' | 't6' +export const layout: Record = { + t1: 4, + t2: 8, + t3: 12, + t4: 16, + t5: 20, + t6: 30, +} + +/** 4px */ +export const t1 = layout.t1 +/** 8px */ +export const t2 = layout.t2 +/** 12px */ +export const t3 = layout.t3 +/** 16px */ +export const t4 = layout.t4 +/** 20px */ +export const t5 = layout.t5 +/** 30px */ +export const t6 = layout.t6 diff --git a/apps/skolplattformen-app-new/styles/typography.ts b/apps/skolplattformen-app-new/styles/typography.ts new file mode 100644 index 000000000..04ec09a6b --- /dev/null +++ b/apps/skolplattformen-app-new/styles/typography.ts @@ -0,0 +1,49 @@ +import { TextStyle } from 'react-native' +import { systemWeights } from 'react-native-typography' + +type FontSize = 'xxs' | 'xs' | 'sm' | 'base' | 'lg' | 'xl' +export const fontSize: Record = { + xxs: { + fontSize: 10, + }, + xs: { + fontSize: 12, + }, + sm: { + fontSize: 14, + }, + base: { + fontSize: 16, + }, + lg: { + fontSize: 18, + }, + xl: { + fontSize: 20, + }, +} + +type FontWeight = 'regular' | 'semibold' | 'bold' +export const fontWeight: Record = { + regular: { + ...systemWeights.regular, + }, + semibold: { + ...systemWeights.semibold, + }, + bold: { + ...systemWeights.bold, + }, +} + +export const header: TextStyle = { + ...fontSize.base, + ...fontWeight.bold, +} + +type Align = 'center' +export const align: Record = { + center: { + textAlign: 'center', + }, +} diff --git a/apps/skolplattformen-app-new/test-setup.ts b/apps/skolplattformen-app-new/test-setup.ts new file mode 100644 index 000000000..d858ee720 --- /dev/null +++ b/apps/skolplattformen-app-new/test-setup.ts @@ -0,0 +1,39 @@ +import '@testing-library/jest-native/extend-expect' +import moment from 'moment' +import 'moment/locale/sv' +import 'react-native-gesture-handler/jestSetup' + +moment.locale('sv') + +// Mock hooks +jest.mock('./libs/hooks/src') + +// Silence useNativeDriver error +jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper') + +jest.mock('@react-navigation/native') +jest.mock('@react-navigation/core') +jest.mock('react-native-localize') +jest.mock('react-native/Libraries/Linking/Linking', () => ({ + openURL: jest.fn(() => Promise.resolve('mockResolve')), +})) +jest.mock('react-native', () => { + const RN = jest.requireActual('react-native') + + RN.UIManager.measureInWindow = (_node, callback) => { + callback(0, 0, 42, 42) + } + + return RN +}) + +jest.mock('react-native-simple-toast', () => ({ + SHORT: 'short', + BOTTOM: 'bottom', + showWithGravity: jest.fn(), +})) + +jest.mock('react-native-calendar-events', () => ({ + saveEvent: jest.fn().mockResolvedValue('52'), + requestPermissions: jest.fn().mockResolvedValue('authorized'), +})) diff --git a/apps/skolplattformen-app-new/translations/ar.json b/apps/skolplattformen-app-new/translations/ar.json new file mode 100644 index 000000000..ab60e33c5 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/ar.json @@ -0,0 +1,101 @@ +{ + "abbrevations": { + "compulsorySchool": "المدرسة الاجبارية", + "leisureTimeCentre": "مركز أوقات الفراغ", + "preSchool": "مرحلة ما قبل المدرسة", + "upperSecondarySchool": "المدرسه الثانوية العليا" + }, + "abscense": { + "endTime": "وقت الإنتهاء", + "entireDay": "كل اليوم", + "invalidPersonalNumber": "الرقم الوطني غير صالح", + "personalNumberMissing": "الرقم الوطني مطلوب", + "selectAbscenseEndTime": "اختر وقت الانتهاء", + "selectAbscenseStartTime": "اختر وقت البداية", + "startTime": "وقت البداية", + "title": "الإبلاغ عن الغياب" + }, + "auth": { + "bankid": { + "OpenManually": "قم بتشغيل BankID يدوياً", + "OpenOnAnotherDevice": "افتح BankID على جهاز آخر", + "OpenOnThisDevice": "افتح BankID على هذا الجهاز", + "Waiting": "في انتظار BankID…" + }, + "chooseLoginMethod": "اختر طريقة تسجيل الدخول", + "loginAsTestUser": "سجل الدخول كمستخدم تجريبي", + "loginFailed": "تعذر تسجيل الدخول. يرجى المحاولة مرة أخرى.", + "placeholder_SocialSecurityNumber": "رقمك الوطني", + "subtitle": "البديل {{word}}", + "words": { + "agile": "رشيق", + "awaited": "في انتظار", + "better": "أفضل", + "cheap": "رخيص", + "cooler": "برودة", + "enlightened": "المستنير", + "fantastic": "جميل", + "fast": "سريع", + "first": "أول", + "free": "مجانا", + "fun": "مرح", + "homemade": "محلي الصنع", + "imperfect": "غير تام", + "open": "افتح", + "rebellious": "انفصام شخصيه", + "simple": "بسيط", + "working": "عمل" + } + }, + "calender": { + "approveAccessToCalender": "يجب عليك الموافقة على الوصول إلى التقويم الخاص بك", + "saveToCalender": "احفظ الى التقويم", + "saveToCalenderError": "هناك خطأ ما", + "saveToCalenderSuccess": "✔️ تم الحفظ في التقويم", + "showCalenderActions": "إظهار إجراءات التقويم" + }, + "children": { + "loadingErrorHeading": "عفواً!", + "loadingErrorInformationText": "تعذر تحميل هذه الصفحة. حاول من جديد أو تفقد الحالة على skolplattformen.org.", + "noKids_description": "لا يوجد أطفال مسجلين برقم الضمان الاجتماعي الخاص بك في استاد ستوكهولم", + "noKids_title": "لا اطفال", + "title": "الأطفال", + "tryAgain": "حاول من جديد", + "viewStatus": "View status on skolplattformen.org" + }, + "general": { + "changeLanguage": "تغيير اللغة", + "confirm": "تأكيد", + "loading": "جاري التحميل…", + "logout": "تسجيل خروج", + "send": "Send", + "settings": "الإعدادات", + "socialSecurityNumber": "الرقم الشخصي الوطني", + "title": "منصة المدرسة المفتوحة" + }, + "language": { + "changeLanguage": "تغيير اللغة", + "changeLanguageButton": "يحفظ" + }, + "menu": { + "emptyHeadline": "يبدو أن القائمة فارغة", + "emptyText": "لم يتم العثور على شيء لهذا الأسبوع" + }, + "navigation": { + "calender": "رزنامة", + "menu": "لائحة الطعام", + "news": "أخبار", + "notifications": "إشعارات" + }, + "news": { + "backToChild": "العودة إلى الطفل", + "noNewNewsItemsThisWeek": "لا توجد أخبار جديدة هذا الأسبوع.", + "notificationTitle": "أخبار: {{header}} ({{published}})", + "published": "منشور", + "title": "أخبار من منصة المدرسة", + "updated": "محدث" + }, + "notifications": { + "notificationTitle": "إشعار: {{message}} ({{dateCreated}})" + } +} diff --git a/apps/skolplattformen-app-new/translations/de.json b/apps/skolplattformen-app-new/translations/de.json new file mode 100644 index 000000000..9c0514abe --- /dev/null +++ b/apps/skolplattformen-app-new/translations/de.json @@ -0,0 +1,156 @@ +{ + "abbrevations": { + "compulsorySchool": "Grundschule", + "leisureTimeCentre": "Hort", + "preSchool": "Vorschule", + "upperSecondarySchool": "Gymnasium" + }, + "abscense": { + "endTime": "Endzeit", + "entireDay": "Ganzen Tag", + "invalidPersonalNumber": "Personenkennziffer ungültig", + "personalNumberMissing": "Personenkennziffer fehlt", + "selectAbscenseEndTime": "Endzeit wählen", + "selectAbscenseStartTime": "Startzeit wählen", + "startTime": "Startzeit", + "title": "Abwesenheit anmelden", + "childsPersonalNumber": "Personenkennziffer des Kindes" + }, + "auth": { + "bankid": { + "OpenManually": "BankID manuell öffnen", + "OpenOnAnotherDevice": "BankID auf einem anderen Gerät öffnen", + "OpenOnThisDevice": "BankID auf diesem Gerät öffnen", + "Waiting": "Wartet auf BankID…" + }, + "chooseLoginMethod": "Anmeldemethode auswählen", + "loginAsTestUser": "Als Testbenutzer einloggen", + "loginFailed": "Die Anmeldung ist fehlgeschlagen. Bitte versuche es nochmal.", + "placeholder_SocialSecurityNumber": "Deine Personenkennziffer", + "subtitle": "Die {{word}} Alternative", + "words": { + "agile": "agile", + "awaited": "erwartete", + "better": "bessere", + "cheap": "billige", + "cooler": "coolere", + "enlightened": "erleuchtete", + "fantastic": "fantastische", + "fast": "schnelle", + "first": "erste", + "free": "freie", + "fun": "lustige", + "homemade": "selbstgemachte", + "imperfect": "unvollkommene", + "open": "offene", + "rebellious": "rebellische", + "simple": "einfache", + "working": "funktionierende" + }, + "a11y_select_login_method": "Wähle die Anmeldemethode", + "a11y_clear_social_security_input_field": "Personenkennziffer-Feld löschen", + "a11y_image_two_boys": "Bild von zwei Personen, die ihre Mobiltelefon überprüfen", + "a11y_change_language": "Wähle deine Sprache", + "chooseSchoolPlatform": "Plattform wählen", + "freja": { + "Waiting": "Wartet auf Freja eID+…", + "OpenManually": "Freja eID+ manuell öffnen", + "OpenOnThisDevice": "Freja eID+ auf diesem Gerät öffnen" + }, + "loginSuccessful": "Eingeloggt, wird geladen…" + }, + "calender": { + "approveAccessToCalender": "Du musst Zugriff auf deinen Kalender erlauben", + "saveToCalender": "Im Kalender speichern", + "saveToCalenderError": "Ein Fehler ist aufgetreten", + "saveToCalenderSuccess": "✔️ Im Kalender gespeichert", + "showCalenderActions": "Kalender-Actions zeigen", + "emptyHeadline": "Der Kalender sieht leer aus", + "emptyText": "Nichts wurde gefunden" + }, + "children": { + "loadingErrorHeading": "Hoppla!", + "loadingErrorInformationText": "Diese Seite kann nicht geladen werden. Versuche es nochmal oder kontrolliere den aktuellen Status auf skolplattformen.org.", + "noKids_description": "Für diese Personenkennziffer gibt es keine in Stockholm registrierten Kinder", + "noKids_title": "Keine Kinder", + "title": "Deine Kinder", + "tryAgain": "Nochmal versuchen", + "viewStatus": "Status kontrollieren auf skolplattformen.org" + }, + "general": { + "changeLanguage": "Sprache ändern", + "confirm": "Bestätigen", + "loading": "Wird geladen…", + "logout": "Ausloggen", + "send": "Senden", + "settings": "Einstellungen", + "socialSecurityNumber": "Personenkennziffer", + "title": "Öppna skolplattformen", + "cancel": "Abbrechen", + "logoutAndClearPersonalData": "Ausloggen und persönliche Daten löschen", + "logoutAndClearAllDataInclSettings": "Ausloggen und alle Daten inkl. Einstellungen löschen", + "tomorrow": "Morgen" + }, + "language": { + "changeLanguage": "Sprache ändern", + "changeLanguageButton": "Speichern" + }, + "menu": { + "emptyHeadline": "Die Speisekarte sieht ein bisschen leer aus", + "emptyText": "Nichts zu zeigen für diese Woche" + }, + "navigation": { + "calender": "Kalender", + "menu": "Speisekarte", + "news": "Nachrichten", + "notifications": "Mitteilungen", + "classmates": "Mitschüler" + }, + "news": { + "backToChild": "Zurück zum Kind", + "noNewNewsItemsThisWeek": "Keine neuen Nachrichten diese Woche.", + "notificationTitle": "Nachricht: {{header}} ({{published}})", + "published": "Veröffentlicht", + "title": "Nachricht von Skolplattformen", + "updated": "Aktualisiert", + "search": { + "placeholder": "Alle Nachrichten durchsuchen …" + } + }, + "notifications": { + "notificationTitle": "Mitteilung: {{message}} ({{dateCreated}})" + }, + "schedule": { + "gymBag": "Turnbeutel", + "lunch": "Mittagessen", + "end": "Ende", + "start": "Anfang", + "week": "Woche" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Zeigt Kontaktinformation an", + "home": "Adresse", + "email": "E-Mail", + "sms": "SMS", + "call": "Anrufen", + "a11y_show_contact_info_button_label": "Kontaktinformationen anzeigen" + }, + "classmates": { + "contactsForGuardiansFor": "Kontaktinformationen der Erziehungsberechtigten für", + "child": "Kind", + "class": "Klasse" + }, + "settings": { + "appearance": "Modus", + "licenses": "Lizenzen", + "language": "Sprache", + "themeAuto": "Automatisch", + "useSystemTheme": "Systemmodus benutzen", + "settings": "Einstellungen", + "theme": "Modus" + }, + "themes": { + "light": "Hell", + "dark": "Dunkel" + } +} diff --git a/apps/skolplattformen-app-new/translations/en.json b/apps/skolplattformen-app-new/translations/en.json new file mode 100644 index 000000000..b51da78e3 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/en.json @@ -0,0 +1,156 @@ +{ + "abbrevations": { + "compulsorySchool": "Primary/lower-secondary school", + "leisureTimeCentre": "After-school care", + "preSchool": "Preschool", + "upperSecondarySchool": "Upper-secondary school" + }, + "abscense": { + "endTime": "End time", + "entireDay": "Whole day", + "childsPersonalNumber": "Child's personal identity number", + "invalidPersonalNumber": "Personal identity number invalid", + "personalNumberMissing": "Personal identity number missing", + "selectAbscenseEndTime": "Choose end time", + "selectAbscenseStartTime": "Choose start time", + "startTime": "Start time", + "title": "Report absence" + }, + "auth": { + "bankid": { + "OpenManually": "Open BankID manually", + "OpenOnAnotherDevice": "Open BankID on another device", + "OpenOnThisDevice": "Open BankID on this device", + "Waiting": "Waiting for BankID…" + }, + "freja": { + "OpenManually": "Open Freja eID+ manually", + "OpenOnThisDevice": "Open Freja eID+ on this device", + "Waiting": "Waiting for Freja eID+…" + }, + "chooseLoginMethod": "Choose login method", + "chooseSchoolPlatform": "Choose platform", + "loginAsTestUser": "Log in as a test user", + "loginFailed": "Could not log in. Please try again.", + "loginSuccessful": "Login successful, loading…", + "placeholder_SocialSecurityNumber": "Your personal identity number", + "subtitle": "The {{word}} alternative", + "words": { + "agile": "agile", + "awaited": "awaited", + "better": "better", + "cheap": "cheap", + "cooler": "cooler", + "enlightened": "enlightened", + "fantastic": "fantastic", + "fast": "fast", + "first": "first", + "free": "free", + "fun": "fun", + "homemade": "homemade", + "imperfect": "imperfect", + "open": "open", + "rebellious": "rebellious", + "simple": "simple", + "working": "working" + }, + "a11y_change_language": "Select your language", + "a11y_image_two_boys": "Picture of two people checking their mobile phones", + "a11y_clear_social_security_input_field": "Clear the personal identity number field", + "a11y_select_login_method": "Select the login method" + }, + "calender": { + "approveAccessToCalender": "You have to approve access to your calendar", + "saveToCalender": "Save in calendar", + "saveToCalenderError": "Something went wrong", + "saveToCalenderSuccess": "✔️ Saved in calendar", + "showCalenderActions": "Show calendar actions", + "emptyHeadline": "The calendar looks kinda empty", + "emptyText": "Couldn't find anything to show" + }, + "children": { + "loadingErrorHeading": "Oops!", + "loadingErrorInformationText": "This page cannot be loaded. Try again or view current status on skolplattformen.org.", + "noKids_description": "There are no children registered in the City of Stockholm for your personal identity number", + "noKids_title": "No children", + "title": "Your children", + "tryAgain": "Try again", + "viewStatus": "View status on skolplattformen.org" + }, + "general": { + "cancel": "Cancel", + "changeLanguage": "Change language", + "confirm": "Confirm", + "loading": "Loading…", + "logout": "Log out", + "logoutAndClearPersonalData": "Log out and clear personal data", + "logoutAndClearAllDataInclSettings": "Log out and clear all data including settings", + "send": "Send", + "settings": "Settings", + "socialSecurityNumber": "Personal identity number", + "title": "Öppna skolplattformen", + "tomorrow": "Tomorrow" + }, + "language": { + "changeLanguage": "Change language", + "changeLanguageButton": "Save" + }, + "menu": { + "emptyHeadline": "The lunch menu looks kinda empty", + "emptyText": "Couldn't find anything for this week" + }, + "navigation": { + "calender": "Calendar", + "menu": "Lunch", + "news": "News", + "notifications": "Notifications", + "classmates": "Classmates" + }, + "settings": { + "settings": "Settings", + "appearance": "Appearance", + "theme": "Theme", + "licenses": "Licenses", + "language": "Language", + "themeAuto": "Auto", + "useSystemTheme": "Use System Light/Dark Theme" + }, + "themes": { + "light": "Light", + "dark": "Dark" + }, + "news": { + "backToChild": "Back to child", + "noNewNewsItemsThisWeek": "No news this week.", + "notificationTitle": "News: {{header}} ({{published}})", + "published": "Published", + "title": "News from Skolplattformen", + "updated": "Updated", + "search": { + "placeholder": "Search in news…" + } + }, + "notifications": { + "notificationTitle": "Notification: {{message}} ({{dateCreated}})" + }, + "schedule": { + "start": "Start", + "end": "End", + "lunch": "Lunch", + "gymBag": "Gym bag", + "week": "Week" + }, + "classmates": { + "class": "Class", + "child": "Child", + "contactsForGuardiansFor": "Contact information for guardians for" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Shows contact information", + "a11y_show_contact_info_button_label": "Show contact information", + "call": "Call", + "sms": "SMS", + "email": "E-mail", + "home": "Address" + } +} diff --git a/apps/skolplattformen-app-new/translations/es.json b/apps/skolplattformen-app-new/translations/es.json new file mode 100644 index 000000000..4032a1d6d --- /dev/null +++ b/apps/skolplattformen-app-new/translations/es.json @@ -0,0 +1,96 @@ +{ + "news": { + "notificationTitle": "Noticia: {{header}} ({{published}})", + "noNewNewsItemsThisWeek": "No hay noticias nuevas esta semana.", + "backToChild": "Volver al niño", + "title": "Noticias de Skolplattformen", + "published": "Publicada" + }, + "navigation": { + "notifications": "Notificaciones", + "news": "Noticias", + "calender": "Calendario", + "menu": "Menú" + }, + "language": { + "changeLanguage": "Cambiar idioma", + "changeLanguageButton": "Guardar" + }, + "general": { + "send": "Enviar", + "logout": "Cerrar sesión", + "changeLanguage": "Cambiar idioma", + "socialSecurityNumber": "Personnummer", + "settings": "Configuración", + "loading": "Cargando…", + "confirm": "Confirmar", + "title": "Öppna skolplattformen", + "cancel": "Anular" + }, + "children": { + "viewStatus": "Ver estado en skolplattformen.org", + "tryAgain": "Intentar otra vez", + "title": "Tus hijos", + "noKids_title": "Sin niños" + }, + "calender": { + "showCalenderActions": "Mostrar acciones de calendario", + "saveToCalenderSuccess": "✔️ Guardado en el calendario", + "saveToCalenderError": "Algo salió mal", + "saveToCalender": "Guardar en calendario", + "approveAccessToCalender": "Tienes que aprobar el acceso a tu calendario" + }, + "auth": { + "words": { + "simple": "fácil", + "rebellious": "rebelde", + "free": "libre", + "cooler": "más guay", + "working": "funcional", + "imperfect": "imperfecto", + "first": "el primero", + "enlightened": "ilustrada", + "awaited": "esperado", + "agile": "ágil", + "fantastic": "fantástica", + "cheap": "barato", + "better": "mejor", + "homemade": "artesanal", + "open": "abierto", + "fast": "rápida", + "fun": "divertido" + }, + "subtitle": "La alternativa {{word}}", + "placeholder_SocialSecurityNumber": "Tu personnummer", + "loginFailed": "No se pudo iniciar sesión. Vuelva a intentarlo.", + "chooseLoginMethod": "Elija el método de inicio de sesión", + "bankid": { + "Waiting": "Esperando BankID…", + "OpenOnThisDevice": "Abra BankID en este dispositivo", + "OpenOnAnotherDevice": "Abra BankID en otro dispositivo", + "OpenManually": "Abrir BankID manualmente" + }, + "loginAsTestUser": "Inicie sesión como usuario de pruebas", + "a11y_change_language": "Elija su idioma", + "a11y_image_two_boys": "Fotografia de dos personas mirando su telefono movil" + }, + "abscense": { + "title": "Informar ausencia", + "startTime": "hora de inicio", + "selectAbscenseStartTime": "Elige la hora de inicio", + "personalNumberMissing": "Falta el personnummer", + "invalidPersonalNumber": "El personnumer no es válido", + "entireDay": "Día completo", + "endTime": "hora de finalización", + "selectAbscenseEndTime": "Elige la hora de finalización" + }, + "abbrevations": { + "upperSecondarySchool": "Escuela Secundaria Obligatoria", + "preSchool": "Guardería (förskola)", + "leisureTimeCentre": "Extraexcolar (fritids)", + "compulsorySchool": "Escuela obligatoria" + }, + "notifications": { + "notificationTitle": "Notificación: {{message}} ({{dateCreated}})" + } +} diff --git a/apps/skolplattformen-app-new/translations/fi.json b/apps/skolplattformen-app-new/translations/fi.json new file mode 100644 index 000000000..b372ec564 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/fi.json @@ -0,0 +1,102 @@ +{ + "auth": { + "placeholder_SocialSecurityNumber": "Henkilötunnuksesi", + "bankid": { + "Waiting": "Odotetaan BankID:iä…", + "OpenOnThisDevice": "Avaa BankID tällä laitteella", + "OpenOnAnotherDevice": "Avaa BankID toisessa laitteessa", + "OpenManually": "Avaa BankID manuaalisesti" + }, + "words": { + "working": "toimiva", + "simple": "yksinkertainen", + "rebellious": "kapinallinen", + "open": "avoin", + "imperfect": "epätäydellinen", + "homemade": "kotitekoinen", + "fun": "hauskaa", + "free": "ilmainen", + "first": "ensimmäinen", + "fast": "nopea", + "fantastic": "fantastinen", + "enlightened": "valaistunut", + "cooler": "viileämpi", + "cheap": "halpa", + "better": "parempi", + "awaited": "odotettu", + "agile": "ketterä" + }, + "subtitle": "{{word}} vaihtoehto", + "loginFailed": "Sisäänkirjautuminen epäonnistui. Yritä uudelleen.", + "loginAsTestUser": "Kirjaudu sisään testikäyttäjänä", + "chooseLoginMethod": "Valitse kirjautumistapa" + }, + "notifications": { + "notificationTitle": "Ilmoitus: {{message}} ({{dateCreated}})" + }, + "news": { + "updated": "Päivitetty", + "title": "Uutisia Skolplattformenilta", + "published": "Julkaistu", + "notificationTitle": "Uutiset: {{header}} ({{published}})", + "noNewNewsItemsThisWeek": "Tällä viikolla ei ole uusia uutisia.", + "backToChild": "Takaisin lapselle" + }, + "navigation": { + "notifications": "Ilmoitukset", + "news": "Uutiset", + "menu": "Valikko", + "calender": "Kalenteri" + }, + "menu": { + "emptyText": "Ei löytynyt mitään tälle viikolle", + "emptyHeadline": "Valikko näyttää melko tyhjältä" + }, + "language": { + "changeLanguageButton": "Tallenna", + "changeLanguage": "Vaihda kieltä" + }, + "general": { + "title": "Öppna skolplattformen", + "socialSecurityNumber": "Henkilötunnus", + "settings": "Asetukset", + "send": "Lähetä", + "logout": "Kirjaudu ulos", + "loading": "Ladataan…", + "confirm": "Hyväksy", + "changeLanguage": "Vaihda kieltä", + "cancel": "Keskeytä" + }, + "children": { + "viewStatus": "Näytä tila osoitteessa skolplattformen.org", + "tryAgain": "Yritä uudelleen", + "title": "Lapsesi", + "noKids_title": "Ei lapsia", + "noKids_description": "Tukholman kaupungilla ei ole rekisteröityjä lapsia henkilötunnuksellesi", + "loadingErrorInformationText": "Tätä sivua ei voi ladata. Yritä uudelleen tai katso nykyinen tila osoitteessa skolplattformen.org.", + "loadingErrorHeading": "Hups!" + }, + "calender": { + "showCalenderActions": "Näytä kalenteritoiminnot", + "saveToCalenderSuccess": "✔️ Tallennettu kalenteriin", + "saveToCalenderError": "Jokin meni pieleen", + "saveToCalender": "Tallenna kalenteriin", + "approveAccessToCalender": "Sinun on hyväksyttävä kalenterisi käyttöoikeus" + }, + "abscense": { + "title": "Ilmoita poissaolosta", + "startTime": "Aloitusaika", + "selectAbscenseStartTime": "Valitse aloitusaika", + "selectAbscenseEndTime": "Valitse päättymisaika", + "personalNumberMissing": "Henkilötunnus puuttuu", + "invalidPersonalNumber": "Henkilötunnus on virheellinen", + "entireDay": "Kokopäivä", + "endTime": "Lopetusaika" + }, + "abbrevations": { + "upperSecondarySchool": "Lukio", + "preSchool": "Esikoulu", + "leisureTimeCentre": "Vapaa-ajankoti", + "compulsorySchool": "Peruskoulu" + } +} diff --git a/apps/skolplattformen-app-new/translations/fr.json b/apps/skolplattformen-app-new/translations/fr.json new file mode 100644 index 000000000..f4e6a3b10 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/fr.json @@ -0,0 +1,147 @@ +{ + "general": { + "loading": "Chargement…", + "title": "Öppna skolplattformen", + "socialSecurityNumber": "Numéro d'identité personnel", + "settings": "Paramètres", + "send": "Envoyer", + "logout": "Se déconnecter", + "confirm": "Confirmer", + "changeLanguage": "Changer de langue", + "cancel": "Annuler", + "logoutAndClearPersonalData": "Se déconnecter et effacer les données personnelles", + "logoutAndClearAllDataInclSettings": "Se déconnecter et effacer toutes les données, y compris les paramètres", + "tomorrow": "Demain" + }, + "calender": { + "saveToCalenderError": "Un problème est survenu", + "saveToCalender": "Enregistrer dans le calendrier", + "approveAccessToCalender": "Vous devez approuver l'accès à votre calendrier", + "showCalenderActions": "Afficher les actions du calendrier", + "saveToCalenderSuccess": "✔️ Enregistré dans le calendrier" + }, + "auth": { + "words": { + "working": "fonctionnement", + "first": "premier", + "better": "mieux", + "simple": "simple", + "rebellious": "rebelle", + "open": "ouverte", + "imperfect": "imparfaite", + "homemade": "maison", + "fun": "amusante", + "free": "gratuite", + "fast": "rapide", + "fantastic": "fantastique", + "enlightened": "éclairée", + "cooler": "plus cool", + "cheap": "bon marché", + "awaited": "attendue", + "agile": "agile" + }, + "placeholder_SocialSecurityNumber": "Votre numéro d'identité personnel", + "subtitle": "L'alternative {{word}}", + "bankid": { + "OpenManually": "Ouvrir BankID manuellement", + "OpenOnAnotherDevice": "Ouvrez BankID sur un autre appareil", + "Waiting": "En attente de BankID…", + "OpenOnThisDevice": "Ouvrez BankID sur cet appareil" + }, + "loginFailed": "La connexion a échoué, veuillez réessayer.", + "loginAsTestUser": "Connectez-vous en tant qu'utilisateur test", + "chooseLoginMethod": "Choisissez la méthode de connexion", + "a11y_select_login_method": "Sélectionnez la méthode de connexion", + "a11y_clear_social_security_input_field": "Effacer le champ du numéro national d’identité", + "a11y_image_two_boys": "Photo de deux personnes consultant leur téléphone portable", + "a11y_change_language": "Sélectionnez votre langue", + "chooseSchoolPlatform": "Choisir la plateforme" + }, + "abscense": { + "startTime": "Heure de début", + "selectAbscenseStartTime": "Choisissez l'heure de début", + "personalNumberMissing": "Numéro personnel manquant", + "invalidPersonalNumber": "Numéro personnel invalide", + "endTime": "Heure de fin", + "selectAbscenseEndTime": "Choisissez l'heure de la fin", + "entireDay": "Toute la journée", + "title": "Signaler une absence", + "childsPersonalNumber": "Numéro national d’identité de l'enfant" + }, + "notifications": { + "notificationTitle": "Notification : {{message}} ({{dateCreated}})" + }, + "news": { + "updated": "Mise à jour", + "title": "Nouvelles de Skolplattformen", + "published": "Publié", + "notificationTitle": "Nouvelles : {{header}} ({{published}})", + "noNewNewsItemsThisWeek": "Pas de nouvelles actualités cette semaine.", + "backToChild": "Retour à l'enfant", + "search": { + "placeholder": "Rechercher toutes les nouvelles…" + } + }, + "navigation": { + "notifications": "Notifications", + "news": "Nouvelles", + "menu": "Menu", + "calender": "Calendrier", + "classmates": "Camarades de classe" + }, + "menu": { + "emptyText": "Je n'ai rien trouvé pour cette semaine", + "emptyHeadline": "Le menu a l'air un peu vide" + }, + "language": { + "changeLanguageButton": "Sauvegarder", + "changeLanguage": "Changer de langue" + }, + "children": { + "viewStatus": "Voir le statut sur skolplattformen.org", + "tryAgain": "Réessayer", + "title": "Vos enfants", + "noKids_title": "Pas d'enfants", + "noKids_description": "Il n'y a pas d'enfants enregistrés dans la ville de Stockholm pour votre numéro d'identité personnel", + "loadingErrorInformationText": "Cette page ne peut pas être chargée. Réessayez ou consultez l'état actuel sur skolplattformen.org.", + "loadingErrorHeading": "Oups !" + }, + "abbrevations": { + "upperSecondarySchool": "École secondaire supérieure", + "preSchool": "Préscolaire", + "leisureTimeCentre": "Centre de loisirs", + "compulsorySchool": "École obligatoire" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Affiche les informations de contact", + "home": "Adresse", + "email": "Courriel", + "sms": "Texto", + "call": "Appeler", + "a11y_show_contact_info_button_label": "Afficher les informations de contact" + }, + "schedule": { + "gymBag": "Sac de sport", + "lunch": "Déjeuner", + "end": "Fin", + "start": "Début" + }, + "classmates": { + "contactsForGuardiansFor": "Coordonnées des tuteurs pour", + "child": "Enfant", + "class": "Classe" + }, + "settings": { + "settings": "Paramètres", + "useSystemTheme": "Utiliser le thème clair/sombre du système", + "language": "Langue", + "appearance": "Apparence", + "theme": "Thème", + "licenses": "Licences", + "themeAuto": "Automatique" + }, + "themes": { + "light": "Clair", + "dark": "Sombre" + } +} diff --git a/apps/skolplattformen-app-new/translations/it.json b/apps/skolplattformen-app-new/translations/it.json new file mode 100644 index 000000000..e2252cfc7 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/it.json @@ -0,0 +1,144 @@ +{ + "notifications": { + "notificationTitle": "Notifica: {{message}} ({{dateCreated}})" + }, + "news": { + "notificationTitle": "Novità: {{header}} ({{published}})", + "noNewNewsItemsThisWeek": "Nessuna novità questa settimana.", + "title": "Novità da skolplattformen", + "backToChild": "Ritorna a figlio", + "search": { + "placeholder": "Cerca tutte le notizie…" + }, + "updated": "Aggiornato", + "published": "Pubblicato" + }, + "general": { + "title": "Öppna skolplattformen", + "socialSecurityNumber": "Personnummer svedese", + "settings": "Impostazioni", + "send": "Invia", + "logout": "Logout", + "loading": "Caricamento in corso…", + "confirm": "Conferma", + "changeLanguage": "Cambia lingua", + "cancel": "Interrompere", + "logoutAndClearPersonalData": "Esci ed elimina i dati personali", + "logoutAndClearAllDataInclSettings": "Esci ed elimina tutti i dati, comprese le impostazioni" + }, + "schedule": { + "end": "Finische", + "start": "Inizia", + "lunch": "Pranzo", + "gymBag": "I vestiti di ginnastica" + }, + "navigation": { + "notifications": "Notifiche", + "news": "Novità", + "menu": "Menù pranzo", + "calender": "Calendario", + "classmates": "Compagni di classe" + }, + "language": { + "changeLanguageButton": "Salva", + "changeLanguage": "Cambia lingua" + }, + "children": { + "loadingErrorHeading": "Ops!", + "title": "I tuoi figli", + "noKids_title": "Non ci sono figli", + "noKids_description": "No ci sono figli registrati a questo personnummer a Stoccolma", + "tryAgain": "Riprova", + "viewStatus": "Vedi stato su skolplattformen.org", + "loadingErrorInformationText": "Questa pagina non può essere caricata. Riprova o visualizza lo stato attuale su skolplattformen.org." + }, + "calender": { + "showCalenderActions": "Mostra calendario actions", + "saveToCalenderSuccess": "✔️ Salvato in calendario", + "saveToCalenderError": "Errore, non salvato", + "saveToCalender": "Salva in calendario", + "approveAccessToCalender": "Approva l'accesso al calendario" + }, + "auth": { + "words": { + "working": "funzionante", + "simple": "facile", + "rebellious": "ribelle", + "open": "accessibile", + "imperfect": "imperfetta", + "homemade": "fatta a mano", + "fun": "divertente", + "free": "libera", + "first": "prima", + "fast": "veloce", + "fantastic": "fantastica", + "enlightened": "illumminata", + "cooler": "più cool", + "cheap": "economica", + "better": "migliore", + "awaited": "attesa", + "agile": "agile" + }, + "subtitle": "L'alternativa {{word}}", + "placeholder_SocialSecurityNumber": "Il tuo personnummer svedese", + "loginFailed": "Accesso non riuscito, riprova.", + "loginAsTestUser": "Entra come utente test", + "chooseLoginMethod": "Scegli metodo di accesso", + "bankid": { + "Waiting": "Attendere BankID…", + "OpenOnThisDevice": "Apri BankID su questa unità", + "OpenOnAnotherDevice": "Apri BankID su un'altra unità", + "OpenManually": "Apri BankID manualmente" + }, + "a11y_select_login_method": "Seleziona il metodo di accesso", + "a11y_clear_social_security_input_field": "Cancella il campo del numero di previdenza sociale", + "a11y_image_two_boys": "Immagine di due persone che controllano i loro telefoni cellulari", + "a11y_change_language": "Seleziona la tua lingua" + }, + "abscense": { + "title": "Registra l'assenza", + "entireDay": "Giorno intero", + "endTime": "Fine", + "selectAbscenseEndTime": "Fine a", + "selectAbscenseStartTime": "Inizio da", + "startTime": "Inizio", + "personalNumberMissing": "Codice Fiscale mancante", + "invalidPersonalNumber": "Codice Fiscale non valido" + }, + "abbrevations": { + "upperSecondarySchool": "Scuola superiore", + "preSchool": "Scuola materna", + "leisureTimeCentre": "Tempo pieno", + "compulsorySchool": "Scuola inferiore e media" + }, + "menu": { + "emptyHeadline": "Il menù sembra piuttosto vuoto", + "emptyText": "Non ho trovato nulla per questa settimana" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Mostra le informazioni di contatto", + "call": "Chiama", + "sms": "SMS", + "email": "E-mail", + "home": "Indirizzo", + "a11y_show_contact_info_button_label": "Mostra le informazioni di contatto" + }, + "settings": { + "settings": "Impostazioni", + "theme": "Tema", + "themeAuto": "Automatico", + "licenses": "Licenze", + "language": "Lingua", + "appearance": "Aspetto", + "useSystemTheme": "Usa il tema chiaro/scuro del sistema" + }, + "themes": { + "light": "Chiaro", + "dark": "Scuro" + }, + "classmates": { + "class": "Classe", + "child": "Bambino", + "contactsForGuardiansFor": "Informazioni di contatto per i tutori per" + } +} diff --git a/apps/skolplattformen-app-new/translations/ja.json b/apps/skolplattformen-app-new/translations/ja.json new file mode 100644 index 000000000..295e8d399 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/ja.json @@ -0,0 +1,98 @@ +{ + "navigation": { + "notifications": "通知", + "menu": "メニュー", + "calender": "カレンダー", + "classmates": "同級生", + "news": "ニュース" + }, + "abscense": { + "endTime": "終了時間", + "personalNumberMissing": "個人識別番号が入力されていない", + "invalidPersonalNumber": "個人識別番号が無効", + "entireDay": "一日中", + "title": "不在を報告する", + "selectAbscenseEndTime": "終了時間を選択します", + "selectAbscenseStartTime": "開始時間を選択します", + "startTime": "開始時間", + "childsPersonalNumber": "子供の個人識別番号" + }, + "abbrevations": { + "upperSecondarySchool": "ギムナジウム", + "preSchool": "就学前学級", + "leisureTimeCentre": "学童保育", + "compulsorySchool": "基礎学校" + }, + "general": { + "settings": "設定", + "tomorrow": "明日" + }, + "children": { + "tryAgain": "やり直してください", + "title": "あなたの子供", + "noKids_title": "子供のない", + "loadingErrorHeading": "おっと!", + "loadingErrorInformationText": "このページを読み込むことができません。もう一度してみるか、skolplattformen.orgで現在のステータスを調べてください。", + "noKids_description": "ストックホルム市にその個人識別番号で登録された子供はいません" + }, + "auth": { + "a11y_image_two_boys": "自分の携帯電話を見ている二人", + "a11y_change_language": "あなたの言語を選択して下さい", + "words": { + "simple": "簡単", + "homemade": "自家製", + "imperfect": "不完全", + "agile": "アジャイル", + "open": "オープン", + "fun": "楽しい", + "free": "自由な", + "first": "最初", + "fast": "速い", + "fantastic": "素晴らしい", + "cheap": "安い", + "better": "より良い", + "working": "いいな機能性", + "rebellious": "反抗的な", + "enlightened": "エンライテンド", + "cooler": "かっこいい", + "awaited": "待ち受ける" + }, + "subtitle": "{{word}}の選択肢", + "chooseLoginMethod": "ログイン方法を選んでください", + "loginAsTestUser": "テスト・ユーザーでログインしてください", + "bankid": { + "OpenManually": "手動でBankIDを開ける", + "OpenOnAnotherDevice": "別のデバイスでBankIDを使用する", + "Waiting": "BankIDを待っています…", + "OpenOnThisDevice": "このデバイスでBankIDを使用する" + }, + "loginFailed": "ログインできませんでした。再試行してください。", + "placeholder_SocialSecurityNumber": "あなたの個人番号", + "freja": { + "OpenOnThisDevice": "このデバイスで Freja eID+を使用する", + "OpenManually": "手動でFreja eID+を開ける", + "Waiting": "Freja eID+を待っています…" + }, + "a11y_clear_social_security_input_field": "個人識別番号のフィールドを空にする", + "chooseSchoolPlatform": "ログイン方法を選んでください", + "loginSuccessful": "ログインは完成した、よみこんでいる。。。", + "a11y_select_login_method": "ログインする方法を選ぶ" + }, + "language": { + "changeLanguage": "他の言語を選択" + }, + "contact": { + "home": "住所" + }, + "calender": { + "approveAccessToCalender": "カレンダーのアクセスを許可する必要があります", + "saveToCalenderError": "エラーが発生しました", + "saveToCalender": "カレンダーに保存する", + "saveToCalenderSuccess": "✔️ カレンダーへに保存しました", + "emptyHeadline": "カレンダーがなんか空っぽになりそう", + "emptyText": "表示するものが見つかりませんでした" + }, + "classmates": { + "child": "子供" + } +} diff --git a/apps/skolplattformen-app-new/translations/la.json b/apps/skolplattformen-app-new/translations/la.json new file mode 100644 index 000000000..290361eaa --- /dev/null +++ b/apps/skolplattformen-app-new/translations/la.json @@ -0,0 +1,156 @@ +{ + "auth": { + "placeholder_SocialSecurityNumber": "Numerus personalis tuus", + "loginFailed": "Nomen dare non possibilis erat. Denuo conare.", + "chooseLoginMethod": "Methodum nomen dare legere", + "bankid": { + "Waiting": "BankID exspectans…", + "OpenOnThisDevice": "In hac machina BankID aperire", + "OpenOnAnotherDevice": "In machina differenti BankID aperire", + "OpenManually": "Manualiter BankID aperire" + }, + "words": { + "awaited": "exspectata", + "agile": "agilis", + "better": "melior", + "cheap": "vilis", + "cooler": "amatior", + "working": "operans", + "simple": "simplex", + "rebellious": "rebellis", + "open": "aperta", + "imperfect": "imperfecta", + "fun": "oblectans", + "free": "libera", + "fast": "celeris", + "fantastic": "mirifica", + "enlightened": "illuminata", + "first": "prima", + "homemade": "domi facta" + }, + "subtitle": "Optio {{word}}", + "loginAsTestUser": "In parte investigatoris nomen dare", + "a11y_select_login_method": "Methodum nomen dare legere", + "a11y_change_language": "Linguam legere", + "a11y_image_two_boys": "Pictura duobus hominibus telephona sua specientibus", + "a11y_clear_social_security_input_field": "Cellam numeri personalis vacuare", + "chooseSchoolPlatform": "Rostra legere", + "loginSuccessful": "Nomen tuum datum est, carricans…", + "freja": { + "OpenManually": "Manualiter Freja eID+ aperire", + "Waiting": "Freja eID+ exspectans…", + "OpenOnThisDevice": "In hac machina Freja eID+ aperire" + } + }, + "abscense": { + "title": "Absentiam referre", + "selectAbscenseStartTime": "Horam exordii legere", + "selectAbscenseEndTime": "Horam terminalem legere", + "startTime": "Hora exordii", + "personalNumberMissing": "Numerus personalis absens est", + "invalidPersonalNumber": "Numerus personalis irritus est", + "entireDay": "Totus dies", + "endTime": "Hora terminalis", + "childsPersonalNumber": "Numerus personalis filii" + }, + "abbrevations": { + "upperSecondarySchool": "Lyceum superius", + "preSchool": "Praeschola", + "leisureTimeCentre": "Centrum otii", + "compulsorySchool": "Schola fundamentalis" + }, + "children": { + "loadingErrorHeading": "Eheu!", + "loadingErrorInformationText": "Haec pagina non carricari potest. Aut denuo conare, aut statum actualem in skolplattformen.org vide.", + "viewStatus": "Statum in skolplattformen.org videre", + "tryAgain": "Denuo conare", + "title": "Filii tui", + "noKids_title": "Nulli filii", + "noKids_description": "Nulli filii pro numero personali tuo in Urbe Holmiense censi sunt" + }, + "calender": { + "showCalenderActions": "Actiones calendarii exhibere", + "saveToCalenderSuccess": "✔️ In calendarium servatus", + "saveToCalender": "In calendarium servare", + "approveAccessToCalender": "Aditum in calendarium approbare debes", + "saveToCalenderError": "Aliquis deerat", + "emptyHeadline": "Calendarium vacuum videtur", + "emptyText": "Nihil invenitur ostendere" + }, + "menu": { + "emptyText": "Hac septimana nihil invenire poterat", + "emptyHeadline": "Charta vacua videtur" + }, + "news": { + "noNewNewsItemsThisWeek": "Hac septimana nulli novi nuncii.", + "updated": "Ad diurnum missus", + "title": "Nuntii ex Skolplattformen", + "published": "Divulgatus", + "notificationTitle": "Nuntii: {{header}} ({{published}})", + "backToChild": "Ad filium revertere", + "search": { + "placeholder": "Omnibus nuntiis quaerere…" + } + }, + "notifications": { + "notificationTitle": "Nuntius: {{message}} ({{dateCreated}})" + }, + "navigation": { + "notifications": "Eventa", + "news": "Nuntii", + "menu": "Charta", + "calender": "Calendarium", + "classmates": "Discipuli" + }, + "language": { + "changeLanguageButton": "Servare", + "changeLanguage": "Linguam permutare" + }, + "general": { + "title": "Öppna skolplattformen", + "socialSecurityNumber": "Numerus personalis", + "settings": "Configurationes", + "send": "Mittere", + "logout": "Secedere", + "loading": "Carricans…", + "confirm": "Confirmare", + "changeLanguage": "Linguam permutare", + "cancel": "Rescindere", + "tomorrow": "Cras", + "logoutAndClearPersonalData": "Secedere et informationes personales purgare", + "logoutAndClearAllDataInclSettings": "Secedere et omnes informationes configurationesque purgare" + }, + "schedule": { + "start": "Exordium", + "gymBag": "Saccus gymnasticus", + "lunch": "Prandium", + "end": "Finis", + "week": "Septimana" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Notationes contactus exhibet", + "home": "Domus", + "email": "Nuntiare electrice", + "sms": "SMS", + "call": "Vocare", + "a11y_show_contact_info_button_label": "Notationes contactus exhibere" + }, + "classmates": { + "contactsForGuardiansFor": "Notationes contactus custodum", + "child": "Filius", + "class": "Classis" + }, + "settings": { + "licenses": "Licentiae", + "appearance": "Species", + "language": "Lingua", + "themeAuto": "Automato", + "useSystemTheme": "Themate lucido/obscuro systemae uti", + "settings": "Configurationes", + "theme": "Thema" + }, + "themes": { + "light": "Lucidus", + "dark": "Obscurus" + } +} diff --git a/apps/skolplattformen-app-new/translations/nb_NO.json b/apps/skolplattformen-app-new/translations/nb_NO.json new file mode 100644 index 000000000..11755b513 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/nb_NO.json @@ -0,0 +1,150 @@ +{ + "children": { + "noKids_description": "Det er ingen barn registrert i Stockholm by med det personnummeret", + "viewStatus": "Vis status på skolplattformen.org", + "tryAgain": "Prøv igjen", + "title": "Dine barn", + "noKids_title": "Ingen barn", + "loadingErrorInformationText": "Denne siden kan ikke lastes inn. Prøv igjen eller vis nåværende status på skolplattformen.org.", + "loadingErrorHeading": "Oida." + }, + "auth": { + "bankid": { + "Waiting": "Venter på BankID …", + "OpenOnThisDevice": "Åpne BankID på denne enheten", + "OpenOnAnotherDevice": "Åpne BankID på en annen enhet", + "OpenManually": "Åpne BankID manuelt" + }, + "loginAsTestUser": "Logg inn som tekstbruker", + "loginFailed": "Kunne ikke logge inn. Prøv igjen.", + "words": { + "free": "frie", + "working": "fungerende", + "simple": "enkle", + "rebellious": "rebelske", + "open": "åpne", + "imperfect": "uperfekte", + "homemade": "hjemmelagde", + "fun": "morsomme", + "first": "første", + "fast": "raske", + "fantastic": "fantastiske", + "enlightened": "opplyste", + "cooler": "kulere", + "cheap": "billige", + "better": "bedre", + "awaited": "etterlengtede", + "agile": "smidige" + }, + "subtitle": "Det {{word}} alternativet", + "placeholder_SocialSecurityNumber": "Ditt personnummer", + "chooseLoginMethod": "Velg innloggingsmetode", + "a11y_select_login_method": "Velg innloggingsmetode", + "a11y_clear_social_security_input_field": "Tøm personnummerfeltet", + "a11y_image_two_boys": "Bilde av to folk som sjekker mobiltelefonene sine", + "a11y_change_language": "Velg språk", + "chooseSchoolPlatform": "Velg plattform" + }, + "calender": { + "saveToCalender": "Lagre i kalender", + "saveToCalenderSuccess": "✔️ Lagret i kalender", + "showCalenderActions": "Vis kalenderhandlinger", + "saveToCalenderError": "Noe gikk galt", + "approveAccessToCalender": "Du må innvilge tilgang til kalenderen din", + "emptyHeadline": "Kalenderen ser tom ut", + "emptyText": "Ingenting å vise" + }, + "general": { + "loading": "Laster inn …", + "logout": "Logg ut", + "title": "Öppna skolplattformen", + "socialSecurityNumber": "Personnummer", + "confirm": "Bekreft", + "changeLanguage": "Endre språk", + "settings": "Innstillinger", + "send": "Send", + "cancel": "Avbryt", + "logoutAndClearPersonalData": "Logg ut og tøm personlig data", + "logoutAndClearAllDataInclSettings": "Logg ut og tøm all data, inkludert innstillinger", + "tomorrow": "I morgen" + }, + "news": { + "updated": "Oppdatert", + "notificationTitle": "Nyheter: {{header}} ){{published}})", + "backToChild": "Tilbake til barn", + "published": "Publisert", + "title": "Nyheter fra Skolplattformen", + "noNewNewsItemsThisWeek": "Ingen nye nyhetselementer denne uken.", + "search": { + "placeholder": "Søk i alle nyheter …" + } + }, + "abscense": { + "title": "Rapporter fravær", + "startTime": "Starttid", + "selectAbscenseStartTime": "Velg starttid", + "selectAbscenseEndTime": "Velg slutt-tid", + "personalNumberMissing": "Personnummer mangler", + "invalidPersonalNumber": "Ugyldig personnummer", + "entireDay": "Hele dagen", + "endTime": "Slutt", + "childsPersonalNumber": "Barnets personnummer" + }, + "abbrevations": { + "upperSecondarySchool": "Videregående", + "preSchool": "Førskole", + "leisureTimeCentre": "Skolefritidsordning", + "compulsorySchool": "Grunnskole" + }, + "notifications": { + "notificationTitle": "Merknad: {{message}} ({{dateCreated}})" + }, + "navigation": { + "notifications": "Merknader", + "news": "Nyheter", + "menu": "Meny", + "calender": "Kalender", + "classmates": "Klassekamerater" + }, + "menu": { + "emptyText": "Fant ikke noe denne uken", + "emptyHeadline": "Menyen ser ganske tom ut" + }, + "language": { + "changeLanguageButton": "Lagre", + "changeLanguage": "Endre språk" + }, + "schedule": { + "gymBag": "Gym-bag", + "lunch": "Lunsj", + "end": "Slutt", + "start": "Start", + "week": "Uke" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Vis kontaktinfo", + "call": "Ring", + "a11y_show_contact_info_button_label": "Vis kontaktinfo", + "sms": "SMS", + "email": "E-post", + "home": "Adresse" + }, + "classmates": { + "contactsForGuardiansFor": "Foresattes kontaktinfo for", + "class": "Klasse", + "child": "Barn" + }, + "settings": { + "settings": "Innstillinger", + "appearance": "Utseende", + "themeAuto": "Auto", + "theme": "Drakt", + "language": "Språk", + "licenses": "Lisenser", + "useSystemTheme": "Ifør systemets drakt" + }, + "themes": { + "light": "Lys", + "dark": "Mørk" + } +} diff --git a/apps/skolplattformen-app-new/translations/nl.json b/apps/skolplattformen-app-new/translations/nl.json new file mode 100644 index 000000000..a7e3a9438 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/nl.json @@ -0,0 +1,145 @@ +{ + "general": { + "loading": "Bezig met laden…", + "settings": "Instellingen", + "send": "Sturen", + "title": "Öppna skolplattformen", + "logout": "Uitloggen", + "confirm": "Bevestigen", + "changeLanguage": "Taal wijzigen", + "socialSecurityNumber": "Burgerservicenummer", + "cancel": "Annuleren", + "logoutAndClearAllDataInclSettings": "Log uit en wis alle gegevens inclusief instellingen", + "logoutAndClearPersonalData": "Uitloggen en persoonlijke gegevens wissen" + }, + "auth": { + "placeholder_SocialSecurityNumber": "Jouw burgerservicenummer", + "loginFailed": "Inloggen mislukt. Probeer het opnieuw.", + "loginAsTestUser": "Inloggen als testgebruiker", + "words": { + "working": "werkende", + "simple": "simpele", + "rebellious": "opstandige", + "open": "open", + "imperfect": "onvolmaakte", + "homemade": "zelfgemaakte", + "fun": "leuke", + "fast": "snellere", + "fantastic": "fantastische", + "enlightened": "verlichte", + "cooler": "koelere", + "agile": "flexibele", + "cheap": "goedkopere", + "better": "betere", + "awaited": "verwachte", + "free": "gratis", + "first": "eerste" + }, + "subtitle": "Het {{word}} alternatief", + "bankid": { + "OpenOnThisDevice": "Open BankID op dit apparaat", + "OpenOnAnotherDevice": "Open BankID op een andere apparaat", + "Waiting": "Watchen op BankID…", + "OpenManually": "Open BankID handmatig" + }, + "chooseLoginMethod": "Kies inlogmethode", + "a11y_select_login_method": "Selecteer de inlogmethode", + "a11y_clear_social_security_input_field": "Wis het veld voor het burgerservicenummer", + "a11y_image_two_boys": "Foto van twee mensen die naar hun mobiele telefoons kijken", + "a11y_change_language": "Selecteer je taal" + }, + "abbrevations": { + "preSchool": "Peuterschool", + "leisureTimeCentre": "Centrum voor vrijetijdsbesteding", + "compulsorySchool": "Basisschool", + "upperSecondarySchool": "Middelbare school" + }, + "abscense": { + "title": "Afwezigheid melden", + "invalidPersonalNumber": "Ongeldig burgerservicenummer", + "endTime": "Eindtijd", + "startTime": "Starttijd", + "personalNumberMissing": "Burgerservicenummer ontbreekt", + "selectAbscenseEndTime": "Kies eindtijd", + "selectAbscenseStartTime": "Kies starttijd", + "entireDay": "Hele dag", + "childsPersonalNumber": "Kinds burgerservicenummer" + }, + "children": { + "noKids_description": "Er zijn geen kinderen geregistreerd in de stad Stockholm voor jouw burgerservicenummer", + "loadingErrorInformationText": "Deze pagina kan niet worden geladen. Probeer het opnieuw of bekijk de status op skolplattformen.org.", + "viewStatus": "Bekijk de status op skolplattformen.org", + "tryAgain": "Probeer het opnieuw", + "noKids_title": "Geen kinderen", + "title": "Jouw kinderen", + "loadingErrorHeading": "Oeps!" + }, + "menu": { + "emptyText": "Vond niets te zien voor deze week", + "emptyHeadline": "Het ziet er leeg uit in het menu" + }, + "news": { + "backToChild": "Terug naar kind", + "notificationTitle": "Nieuws: {{header}} ({{published}})", + "noNewNewsItemsThisWeek": "Geen nieuwe nieuwsberichten deze week.", + "updated": "Bijgewerkt", + "title": "Nieuws van Skolplattformen", + "published": "Gepubliceerd", + "search": { + "placeholder": "Zoek al het nieuws…" + } + }, + "language": { + "changeLanguage": "Taal wijzigen", + "changeLanguageButton": "Opslaan" + }, + "calender": { + "showCalenderActions": "Agenda-acties weergeven", + "approveAccessToCalender": "Je moet de toegang tot je agenda goedkeuren", + "saveToCalenderError": "Er is iets fout gegaan", + "saveToCalenderSuccess": "✔️ Opgeslagen in kalender", + "saveToCalender": "Opslaan in kalender" + }, + "notifications": { + "notificationTitle": "Melding: {{message}} ({{dateCreated}})" + }, + "navigation": { + "notifications": "Meldingen", + "calender": "Agenda", + "menu": "Menu", + "news": "Nieuws", + "classmates": "Klasgenoten" + }, + "schedule": { + "end": "Eind", + "gymBag": "Sporttas", + "lunch": "Middageten", + "start": "Start" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Toon contactgegevens", + "email": "E-mail", + "home": "Adres", + "call": "Telefoongesprek", + "sms": "SMS", + "a11y_show_contact_info_button_label": "Toon contactgegevens" + }, + "settings": { + "useSystemTheme": "Gebruik systeem licht/donker thema", + "appearance": "Verschijning", + "theme": "Thema", + "licenses": "Licenties", + "language": "Taal", + "themeAuto": "Auto", + "settings": "Instellingen" + }, + "classmates": { + "class": "Klas", + "child": "Kind", + "contactsForGuardiansFor": "Contactgegevens voor voogden voor" + }, + "themes": { + "light": "Licht", + "dark": "Donker" + } +} diff --git a/apps/skolplattformen-app-new/translations/pl.json b/apps/skolplattformen-app-new/translations/pl.json new file mode 100644 index 000000000..fd8599bf1 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/pl.json @@ -0,0 +1,156 @@ +{ + "abbrevations": { + "compulsorySchool": "Szkoła podstawowa", + "leisureTimeCentre": "Świetlica", + "preSchool": "Przedszkole", + "upperSecondarySchool": "Liceum" + }, + "abscense": { + "endTime": "Czas zakończenia", + "entireDay": "Cały dzień", + "childsPersonalNumber": "Personnummer dziecka", + "invalidPersonalNumber": "Błąd w personnumerze", + "personalNumberMissing": "Brak personnumeru", + "selectAbscenseEndTime": "Wybierz czas zakończenia", + "selectAbscenseStartTime": "Wybierz czas rozpoczęcia", + "startTime": "Czas rozpoczęcia", + "title": "Zgłoś nieobecność" + }, + "auth": { + "bankid": { + "OpenManually": "Otwórz BankID manualnie", + "OpenOnAnotherDevice": "Otwórz BankID na innym urządzeniu", + "OpenOnThisDevice": "Otwórz BankID na tym urządzeniu", + "Waiting": "Oczekiwanie na BankID…" + }, + "freja": { + "OpenManually": "Otwórz Freja eID+ manualnie", + "OpenOnThisDevice": "Otwórz Freja eID+ na tym urządzeniu", + "Waiting": "Oczekiwanie na Freja eID+…" + }, + "chooseLoginMethod": "Wybierz sposób logowania", + "loginAsTestUser": "Zaloguj się jako użytkownik testowy", + "loginFailed": "Logowanie nie powiodło się. Spróbuj ponownie.", + "placeholder_SocialSecurityNumber": "Twój personnummer", + "subtitle": "{{word}} alternatywa", + "words": { + "agile": "Szybka", + "awaited": "Oczekiwana", + "better": "Lepsza", + "cheap": "Tania", + "cooler": "Odlotowa", + "enlightened": "Oświecona", + "fantastic": "Fantastyczna", + "fast": "Szybka", + "first": "Pierwsza", + "free": "Uwolniona", + "fun": "Śmieszna", + "homemade": "Domowa", + "imperfect": "Niedoskonała", + "open": "Otwarta", + "rebellious": "Buntownicza", + "simple": "Prosta", + "working": "Działająca" + }, + "a11y_select_login_method": "Wybierz metodę logowania", + "a11y_clear_social_security_input_field": "Wyczyść pole z personnumerem", + "a11y_image_two_boys": "Ilustracja: dwie osoby patrzą w telefony komórkowe", + "a11y_change_language": "Wybierz język", + "chooseSchoolPlatform": "Wybierz platformę", + "loginSuccessful": "Logowanie powiodło się. Trwa ładowanie…" + }, + "calender": { + "approveAccessToCalender": "Musisz zatwierdzić dostęp do kalendarza", + "saveToCalender": "Zapisz w kalendarzu", + "saveToCalenderError": "Coś poszło nie tak", + "saveToCalenderSuccess": "✔️ Zapisano w kalendarzu", + "showCalenderActions": "Pokaż opcje kalendarza", + "emptyHeadline": "Kalendarz jest pusty", + "emptyText": "Nie znaleziono nic do pokazania" + }, + "children": { + "loadingErrorHeading": "Oj!", + "loadingErrorInformationText": "Ładowanie strony nie powiodło się. Spróbuj ponownie, albo sprawdź status na skolplattformen.org.", + "noKids_description": "Nie znaleziono dzieci zarejestrowanych na Twój personnummer w mieście Sztokholm", + "noKids_title": "Nie znaleziono dzieci", + "title": "Twoje dzieci", + "tryAgain": "Spróbuj ponownie", + "viewStatus": "Sprawdź status na skolplattformen.org" + }, + "general": { + "changeLanguage": "Zmień język", + "confirm": "Potwierdź", + "loading": "Ładowanie…", + "logout": "Wyloguj", + "send": "Wyślij", + "settings": "Ustawienia", + "socialSecurityNumber": "Personnummer", + "title": "Öppna skolplattformen", + "cancel": "Anuluj", + "logoutAndClearPersonalData": "Wyloguj i skasuj dane osobowe", + "logoutAndClearAllDataInclSettings": "Wyloguj i skasuj wszystkie dane łącznie z ustawieniami", + "tomorrow": "Jutro" + }, + "language": { + "changeLanguage": "Zmień język", + "changeLanguageButton": "Zachowaj" + }, + "menu": { + "emptyHeadline": "Brak informacji", + "emptyText": "Nie znaleziono jadłospisu na ten tydzień" + }, + "navigation": { + "calender": "Kalendarz", + "menu": "Jadłospis", + "news": "Wiadomości", + "notifications": "Powiadomienia", + "classmates": "Klasa" + }, + "news": { + "backToChild": "Z powrotem do dzieci", + "noNewNewsItemsThisWeek": "Nie ma nowych wiadomości w tym tygodniu.", + "notificationTitle": "Wiadomość: {{header}} ({{published}})", + "published": "Opublikowano", + "title": "Wiadomość od szkoły", + "updated": "Uaktualniono", + "search": { + "placeholder": "Szukaj w wiadomościach…" + } + }, + "notifications": { + "notificationTitle": "Wiadomość: {{message}} ({{dateCreated}})" + }, + "schedule": { + "gymBag": "Ubrania do WF", + "lunch": "Lunch", + "end": "Kończy", + "start": "Zaczyna", + "week": "Tydzień" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Pokazuje dane kontaktowe", + "home": "Adres", + "email": "E-mail", + "sms": "SMS", + "call": "Zadzwoń", + "a11y_show_contact_info_button_label": "Pokaż dane kontaktowe" + }, + "classmates": { + "child": "Dziecko", + "class": "Klasa", + "contactsForGuardiansFor": "Dane kontaktowe do opiekuna" + }, + "themes": { + "dark": "Ciemny", + "light": "Jasny" + }, + "settings": { + "useSystemTheme": "Użyj ustawień systemu", + "themeAuto": "Auto", + "language": "Język", + "licenses": "Licencje", + "theme": "Tryb", + "appearance": "Wygląd", + "settings": "Ustawienia" + } +} diff --git a/apps/skolplattformen-app-new/translations/pt.json b/apps/skolplattformen-app-new/translations/pt.json new file mode 100644 index 000000000..97f0e62b0 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/pt.json @@ -0,0 +1,150 @@ +{ + "abscense": { + "entireDay": "O dia inteiro", + "selectAbscenseStartTime": "Indique a hora de início", + "startTime": "Hora de início", + "title": "Reportar ausência", + "selectAbscenseEndTime": "Indique a hora de fim", + "endTime": "Hora de fim", + "invalidPersonalNumber": "Número de identidade pessoal inválido", + "personalNumberMissing": "Falta o número de identidade pessoal", + "childsPersonalNumber": "Número de identidade pessoal da criança" + }, + "auth": { + "bankid": { + "OpenManually": "Abrir BankID manualmente", + "OpenOnAnotherDevice": "Abrir BankID noutro dispositivo", + "Waiting": "A aguardar pelo BankID…", + "OpenOnThisDevice": "Abrir BankID neste dispositivo" + }, + "loginAsTestUser": "Autenticar como utilizador em teste", + "loginFailed": "Não foi possível autenticar. Por favor tente novamente.", + "placeholder_SocialSecurityNumber": "O seu número de identidade pessoal", + "words": { + "agile": "ágil", + "better": "melhor", + "awaited": "esperada", + "free": "livre", + "cooler": "interessante", + "enlightened": "mais clara", + "fantastic": "fantástica", + "first": "inicial", + "homemade": "caseira", + "imperfect": "imperfeita", + "open": "aberta", + "simple": "fácil", + "working": "funcional", + "cheap": "barata", + "fun": "divertida", + "fast": "rápida", + "rebellious": "rebelde" + }, + "subtitle": "A alternativa {{word}}", + "a11y_change_language": "Selecione o seu idioma", + "a11y_image_two_boys": "Fotografia de duas pessoas a verem os seus telemóveis", + "a11y_clear_social_security_input_field": "Limpar o campo do número de identificação pessoal", + "chooseLoginMethod": "Escolha o método de autenticação", + "a11y_select_login_method": "Selecione o método de autenticação", + "chooseSchoolPlatform": "Escolha a plataforma" + }, + "abbrevations": { + "compulsorySchool": "Escola primária / secundária inferior", + "leisureTimeCentre": "Cuidados pós-escolares", + "upperSecondarySchool": "Escola secundária superior", + "preSchool": "Pré-escola" + }, + "calender": { + "showCalenderActions": "Mostrar ações do calendário", + "saveToCalenderError": "Algo correu mal", + "saveToCalenderSuccess": "✔️ Guardado no calendário", + "approveAccessToCalender": "Tem de autorizar o acesso ao seu calendário", + "saveToCalender": "Guardar no calendário", + "emptyHeadline": "O calendário parece um pouco vazio", + "emptyText": "Não encontrei nada para mostrar" + }, + "children": { + "loadingErrorHeading": "Ups!", + "loadingErrorInformationText": "Esta página não pode ser carregada. Tente novamente ou veja o estado atual em skolplattformen.org", + "noKids_description": "Não existem crianças registadas na cidade de Estocolmo para o seu número de identificação pessoal", + "noKids_title": "Sem crianças", + "tryAgain": "Tentar novamente", + "title": "Os seus filhos", + "viewStatus": "Ver estado em skolplattformen.org" + }, + "general": { + "changeLanguage": "Alterar idioma", + "confirm": "Confirmar", + "loading": "A carregar…", + "logout": "Sair", + "logoutAndClearAllDataInclSettings": "Sair e limpar todos os dados, incluindo as configurações", + "send": "Enviar", + "socialSecurityNumber": "Número de identidade pessoal", + "title": "Öppna skolplattformen", + "logoutAndClearPersonalData": "Sair e limpar dados pessoais", + "cancel": "Cancelar", + "settings": "Configurações", + "tomorrow": "Amanhã" + }, + "language": { + "changeLanguage": "Alterar idioma", + "changeLanguageButton": "Guardar" + }, + "menu": { + "emptyHeadline": "O menu do almoço parece um pouco vazio", + "emptyText": "Não consegui encontrar nada para esta semana" + }, + "navigation": { + "calender": "Calendário", + "menu": "Almoço", + "news": "Notícias", + "notifications": "Notificações", + "classmates": "Colegas de turma" + }, + "settings": { + "settings": "Configurações", + "useSystemTheme": "Usar o tema claro / escuro do sistema", + "appearance": "Aparência", + "theme": "Tema", + "licenses": "Licenças", + "language": "Idioma", + "themeAuto": "Automático" + }, + "themes": { + "light": "Claro", + "dark": "Escuro" + }, + "news": { + "backToChild": "Voltar à criança", + "noNewNewsItemsThisWeek": "Não há novidades esta semana.", + "notificationTitle": "Notícia: {{header}} ({{published}})", + "published": "Publicada", + "updated": "Atualizada", + "title": "Notícias de Skolplattformen", + "search": { + "placeholder": "Procurar nas notícias…" + } + }, + "schedule": { + "start": "Início", + "end": "Fim", + "lunch": "Almoço", + "gymBag": "Saco de ginástica", + "week": "Semana" + }, + "classmates": { + "class": "Turma", + "child": "Criança", + "contactsForGuardiansFor": "Informações de contacto dos tutores para" + }, + "contact": { + "call": "Ligar", + "email": "E-mail", + "home": "Morada", + "a11y_show_contact_info_button_hint": "Mostra informações de contacto", + "a11y_show_contact_info_button_label": "Mostrar informações de contacto", + "sms": "SMS" + }, + "notifications": { + "notificationTitle": "Notificação: {{message}} ({{dateCreated}})" + } +} diff --git a/apps/skolplattformen-app-new/translations/readme.md b/apps/skolplattformen-app-new/translations/readme.md new file mode 100644 index 000000000..f7a3e044e --- /dev/null +++ b/apps/skolplattformen-app-new/translations/readme.md @@ -0,0 +1,11 @@ +# How to help out with translating Öppna skolplattformen using Weblate + +We are using Weblate to translate our app. You can find the project [here](https://hosted.weblate.org/projects/skolplattformen-app/app-translation/). + +![Image of the weblate project](https://hosted.weblate.org/widgets/skolplattformen-app/-/app-translation/open-graph.png) + +## OSS License + +Weblate is sponsering this project through their open source license and we would be very happy if you donated to them! + +[Contribute to Weblate](https://weblate.org/sv/contribute/) diff --git a/apps/skolplattformen-app-new/translations/ru.json b/apps/skolplattformen-app-new/translations/ru.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/ru.json @@ -0,0 +1 @@ +{} diff --git a/apps/skolplattformen-app-new/translations/so.json b/apps/skolplattformen-app-new/translations/so.json new file mode 100644 index 000000000..2c848001f --- /dev/null +++ b/apps/skolplattformen-app-new/translations/so.json @@ -0,0 +1,102 @@ +{ + "abbrevations": { + "compulsorySchool": "Dugsiga khasabka ah", + "leisureTimeCentre": "Waqtiga firaaqada", + "preSchool": "Dugsiga barbaarinta", + "upperSecondarySchool": "Dugsiga sare" + }, + "abscense": { + "endTime": "End time", + "entireDay": "Maalintoo dhan", + "invalidPersonalNumber": "Personal number invalid", + "personalNumberMissing": "Personal number missing", + "selectAbscenseEndTime": "Xulo waqtiga dhamaadka", + "selectAbscenseStartTime": "Choose start time", + "startTime": "Start time", + "title": "Maqnaanshaha ka warbixi" + }, + "auth": { + "bankid": { + "OpenManually": "Sugaya BankID ...", + "OpenOnAnotherDevice": "Ku fur BankID qalab kale", + "OpenOnThisDevice": "Ku fur BankID qalabkan", + "Waiting": "Sugaya BankID ..." + }, + "chooseLoginMethod": "Xulo habka galitaanka", + "loginAsTestUser": "Soo gal isticmaalaha imtixaanka", + "loginFailed": "Soo galitaanku wuu fashilmay, fadlan iskuday markale!", + "placeholder_SocialSecurityNumber": "Lambarkaaga gaarka ah", + "subtitle": "Beddelka {{word}}", + "words": { + "agile": "kacsan", + "awaited": "sugayay", + "better": "fiican", + "cheap": "jaban", + "cooler": "ccooleroolare", + "enlightened": "iftiimiyay", + "fantastic": "cajiib ah", + "fast": "soon", + "first": "marka hore", + "free": "bilaash ah", + "fun": "madadaalo", + "homemade": "macmal ah", + "imperfect": "aan dhammaystirnayn", + "open": "furid", + "rebellious": "caasiyoobay", + "simple": "fudud", + "working": "shaqeeya" + } + }, + "calender": { + "approveAccessToCalender": "Waa inaad ansixisaa helitaanka jadwalkaaga", + "saveToCalender": "Save to calender", + "saveToCalenderError": "Waxbaa qaldamay", + "saveToCalenderSuccess": "Ved Lagu keydiyey calender", + "showCalenderActions": "Muuji ficilada calender-ka" + }, + "children": { + "loadingErrorHeading": "Oops!", + "loadingErrorInformationText": "This page cannot be loaded. Try again or view current status on skolplattformen.org.", + "noKids_description": "Ma jiraan caruur ka diiwaan gashan lambarkaaga sooshiyal sekuyuuriyada Stockholm", + "noKids_title": "Carruur ma leh", + "title": "Your kids", + "tryAgain": "Try again", + "viewStatus": "View status on skolplattformen.org" + }, + "general": { + "changeLanguage": "Change language", + "confirm": "Confirm", + "loading": "Loading...", + "logout": "Logout", + "send": "Send", + "settings": "Settings", + "socialSecurityNumber": "Personal identity number", + "title": "Öppna skolplattformen", + "cancel": "Abort" + }, + "language": { + "changeLanguage": "Beddel luqadda", + "changeLanguageButton": "Keydso" + }, + "menu": { + "emptyHeadline": "The menu looks kinda empty", + "emptyText": "Couldn't find anything for this week" + }, + "navigation": { + "calender": "Calendar", + "menu": "Liiska", + "news": "Wararka", + "notifications": "Ogeysiisyada" + }, + "news": { + "backToChild": "Ku noqo ilmaha", + "noNewNewsItemsThisWeek": "Ma jiraan warar cusub toddobaadkan.", + "notificationTitle": "Warar: {{header}} ({{published}})", + "published": "Published", + "title": "Wararka ka imanaya madasha dugsiga", + "updated": "Updated" + }, + "notifications": { + "notificationTitle": "Ogeysiis: {{message}} ({{dateCreated}})" + } +} diff --git a/apps/skolplattformen-app-new/translations/sv.json b/apps/skolplattformen-app-new/translations/sv.json new file mode 100644 index 000000000..bfd4303b2 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/sv.json @@ -0,0 +1,156 @@ +{ + "abbrevations": { + "compulsorySchool": "Grundskola", + "leisureTimeCentre": "Fritids", + "preSchool": "Förskola", + "upperSecondarySchool": "Gymnasieskola" + }, + "abscense": { + "endTime": "Sluttid", + "entireDay": "Heldag", + "childsPersonalNumber": "Barnets personnummer", + "invalidPersonalNumber": "Personnumret är ogiltigt", + "personalNumberMissing": "Personnummer saknas", + "selectAbscenseEndTime": "Välj sluttid", + "selectAbscenseStartTime": "Välj startid", + "startTime": "Starttid", + "title": "Anmäl frånvaro" + }, + "auth": { + "bankid": { + "OpenManually": "Öppna BankID manuellt", + "OpenOnAnotherDevice": "Öppna BankID på annan enhet", + "OpenOnThisDevice": "Logga in med BankID", + "Waiting": "Väntar på BankID…" + }, + "freja": { + "OpenManually": "Öppna Freja eID+ manuellt", + "OpenOnThisDevice": "Logga in med Freja eID+", + "Waiting": "Väntar på Freja eID+…" + }, + "chooseLoginMethod": "Välj inloggningsmetod", + "chooseSchoolPlatform": "Välj plattform", + "loginAsTestUser": "Logga in som testanvändare", + "loginFailed": "Inloggningen misslyckades, försök igen!", + "loginSuccessful": "Du är inloggad! - laddar…", + "placeholder_SocialSecurityNumber": "Ditt personnummer", + "subtitle": "Det {{word}} alternativet", + "words": { + "agile": "agila", + "awaited": "efterlängtade", + "better": "bättre", + "cheap": "billiga", + "cooler": "coolare", + "enlightened": "upplysta", + "fantastic": "fantastiska", + "fast": "snabba", + "first": "första", + "free": "fria", + "fun": "roliga", + "homemade": "hemmagjorda", + "imperfect": "operfekta", + "open": "öppna", + "rebellious": "rebelliska", + "simple": "enkla", + "working": "fungerande" + }, + "a11y_change_language": "Välj språk", + "a11y_image_two_boys": "Bild på två personer som kollar i mobilen", + "a11y_clear_social_security_input_field": "Rensa fältet för personnummer", + "a11y_select_login_method": "Välj hur du vill logga in" + }, + "calender": { + "approveAccessToCalender": "Du måste godkänna åtkomst till kalendern", + "saveToCalender": "Spara till kalender", + "saveToCalenderError": "Något gick fel", + "saveToCalenderSuccess": "✔️ Sparad till kalender", + "showCalenderActions": "Visa kalenderfunktioner", + "emptyText": "Hittade ingenting att visa", + "emptyHeadline": "Det ser lite tomt ut i kalendern" + }, + "children": { + "loadingErrorHeading": "Hoppsan!", + "loadingErrorInformationText": "Vi lyckades inte ladda sidan. Försök igen eller se status på skolplattformen.org.", + "noKids_description": "Det finns inga barn registrerade för ditt personnummer i Stockholms stad", + "noKids_title": "Inga barn", + "title": "Dina barn", + "tryAgain": "Försök igen", + "viewStatus": "Se status på skolplattformen.org" + }, + "general": { + "changeLanguage": "Byt språk", + "confirm": "Bekräfta", + "loading": "Laddar…", + "logout": "Logga ut", + "send": "Skicka", + "settings": "Inställningar", + "socialSecurityNumber": "Personnummer", + "title": "Öppna skolplattformen", + "cancel": "Avbryt", + "logoutAndClearAllDataInclSettings": "Logga ut och rensa all sparad data inkl inställningar", + "logoutAndClearPersonalData": "Logga ut och rensa all personlig data", + "tomorrow": "Imorgon" + }, + "language": { + "changeLanguage": "Byt språk", + "changeLanguageButton": "Spara" + }, + "menu": { + "emptyHeadline": "Det ser lite tomt ut i matsedeln", + "emptyText": "Hittade ingenting att visa för den här veckan" + }, + "navigation": { + "calender": "Kalender", + "menu": "Matsedel", + "news": "Nyheter", + "notifications": "Aviseringar", + "classmates": "Klassen" + }, + "settings": { + "settings": "Inställningar", + "appearance": "Utseende", + "theme": "Tema", + "licenses": "Licenser", + "language": "Språk", + "themeAuto": "Auto", + "useSystemTheme": "Använd telefonens inställning" + }, + "themes": { + "light": "Ljust", + "dark": "Mörkt" + }, + "news": { + "backToChild": "Tillbaka till barn", + "noNewNewsItemsThisWeek": "Inga nya inlägg denna vecka.", + "notificationTitle": "Nyhet: {{header}} ({{published}})", + "published": "Publicerad", + "title": "Nyhet från Skolplattformen", + "updated": "Uppdaterad", + "search": { + "placeholder": "Sök i alla nyheter…" + } + }, + "notifications": { + "notificationTitle": "Avisering: {{message}} ({{dateCreated}})" + }, + "schedule": { + "start": "Börjar", + "end": "Slutar", + "lunch": "Lunch", + "gymBag": "Gympapåse", + "week": "Vecka" + }, + "classmates": { + "class": "Klass", + "child": "Barn", + "contactsForGuardiansFor": "Kontaktuppgifter för vårdnadshavare till" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Visar kontaktinformation", + "a11y_show_contact_info_button_label": "Visa kontaktinformation", + "call": "Ring", + "sms": "SMS", + "email": "Maila", + "home": "Adress" + } +} diff --git a/apps/skolplattformen-app-new/translations/th.json b/apps/skolplattformen-app-new/translations/th.json new file mode 100644 index 000000000..3df06f60d --- /dev/null +++ b/apps/skolplattformen-app-new/translations/th.json @@ -0,0 +1,116 @@ +{ + "abscense": { + "entireDay": "ทั้งวัน", + "childsPersonalNumber": "เลขบัตรประจำตัวประชาชนของลูก", + "invalidPersonalNumber": "เลขบัตรประจำตัวประชาชนผิด", + "personalNumberMissing": "เลขบัตรประจำตัวประชาชนหายไป" + }, + "abbrevations": { + "preSchool": "อนุบาล", + "upperSecondarySchool": "มัธยมปลาย", + "compulsorySchool": "ประถม/มัธยมต้น" + }, + "auth": { + "bankid": { + "OpenOnAnotherDevice": "เปิด BankID ในเครื่องอื่น", + "OpenOnThisDevice": "เปิด BankID ในเครื่องนี้", + "Waiting": "กำลังรอ BankID…" + }, + "words": { + "cooler": "เจ๋งขึ้น", + "fast": "เร็ว", + "first": "แรก", + "free": "ฟรี", + "fun": "สนุก", + "imperfect": "ไม่สมบูรณ์", + "open": "เปิด", + "better": "ดีกว่า", + "cheap": "ถูก", + "simple": "ง่าย", + "fantastic": "ดีเยี่ยม", + "agile": "เปรียว", + "working": "ใช้งานได้" + }, + "loginFailed": "เข้าสู่ระบบไม่ได้ กรุณาลองใหม่อีกครั้ง", + "subtitle": "ทางเลือกที่{{word}}", + "placeholder_SocialSecurityNumber": "เลขบัตรประจำตัวประชาชนของคุณ", + "a11y_change_language": "เลือกภาษา", + "a11y_select_login_method": "เลือกวิธีการเข้าสู่ระบบ", + "freja": { + "Waiting": "กำลังรอ Freja eID+…" + } + }, + "language": { + "changeLanguageButton": "บันทึก", + "changeLanguage": "เปลี่ยนภาษา" + }, + "navigation": { + "calender": "ปฏิทิน", + "news": "ข่าวใหม่", + "notifications": "การแจ้งเตือน", + "classmates": "เพื่อนร่วมชั้น", + "menu": "อาหารเที่ยง" + }, + "general": { + "send": "ส่ง", + "cancel": "ยกเลิก", + "loading": "กำลังโหลด…", + "settings": "การตั้งค่า", + "title": "Öppna skolplattformen", + "socialSecurityNumber": "เลขบัตรประจำตัวประชาชน", + "tomorrow": "พรุ่งนี้", + "confirm": "ยืนยัน", + "changeLanguage": "เปลี่ยนภาษา", + "logout": "ออกจากระบบ" + }, + "children": { + "title": "ลูกของคุณ", + "tryAgain": "ลองอีกครั้ง", + "noKids_title": "ไม่มีลูก", + "viewStatus": "ดูสถานะบน skolplattformen.org" + }, + "settings": { + "settings": "การตั้งค่า", + "language": "ภาษา", + "themeAuto": "อัตโนมัติ", + "licenses": "ได้รับอนุญาต" + }, + "contact": { + "email": "อีเมล", + "call": "โทร", + "sms": "ข้อความ", + "home": "ที่อยู่", + "a11y_show_contact_info_button_hint": "แสดงข้อมูลการติดต่อ", + "a11y_show_contact_info_button_label": "แสดงข้อมูลการติดต่อ" + }, + "themes": { + "dark": "มืด", + "light": "แสงสว่าง" + }, + "news": { + "noNewNewsItemsThisWeek": "อาทิตย์นี้ไม่มีข่าว", + "notificationTitle": "ข่าว: {{header}} ({{published}})", + "title": "ข่าวจาก Skolplattformen", + "search": { + "placeholder": "ค้นหาข่าวต่างๆๆ…" + }, + "backToChild": "กลับไปหน้าหลักของลูก", + "published": "สิ่งที่ตีพิมพ์" + }, + "schedule": { + "week": "อาทิตย์", + "lunch": "อาหารเที่ยง", + "start": "เริ่มต้น", + "end": "สิ้นสุด" + }, + "classmates": { + "child": "ลูก", + "class": "ชั้นเรียน" + }, + "notifications": { + "notificationTitle": "การแจ้งเตือน: {{message}} ({{dateCreated}})" + }, + "calender": { + "saveToCalender": "บันทึกไว้ในปฏิทิน" + } +} diff --git a/apps/skolplattformen-app-new/translations/uk.json b/apps/skolplattformen-app-new/translations/uk.json new file mode 100644 index 000000000..c16818578 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/uk.json @@ -0,0 +1,155 @@ +{ + "abbrevations": { + "preSchool": "дитячий сад", + "upperSecondarySchool": "Старша школа", + "compulsorySchool": "Молодша/середня школа", + "leisureTimeCentre": "Група продовженого дня (\"Продленка\")" + }, + "abscense": { + "entireDay": "Цілий день", + "childsPersonalNumber": "Ідентифікаційний номер дитини", + "endTime": "час закінчення", + "invalidPersonalNumber": "Невірний ідентифікаційний номер", + "personalNumberMissing": "Ідентифікаційний код відсутній", + "startTime": "Час початку", + "title": "Додати відсутність", + "selectAbscenseEndTime": "Виберіть кінцевий час", + "selectAbscenseStartTime": "Виберіть час початку" + }, + "auth": { + "bankid": { + "OpenManually": "Відкрити BankID власноруч", + "OpenOnAnotherDevice": "Відкрити BankID на іншому пристрої", + "OpenOnThisDevice": "Відкрити BankID на цьому пристрої", + "Waiting": "Очікую на BankID…" + }, + "chooseLoginMethod": "Оберіть як увійти", + "chooseSchoolPlatform": "Оберіть платформу", + "loginFailed": "Не зміг увійти. Спробуйте ще раз.", + "placeholder_SocialSecurityNumber": "Ваш ідентифікаційний номер", + "loginAsTestUser": "Увійти як тестовий користувач", + "subtitle": "{{word}} альтернатива", + "words": { + "agile": "Гнучка", + "awaited": "Очікувана", + "better": "Краща", + "cheap": "Дешева", + "cooler": "Крутіша", + "enlightened": "Освічена", + "fantastic": "Фантастична", + "fast": "Швидка", + "first": "Перша", + "free": "Безкоштовна", + "fun": "Весела", + "homemade": "Домашня", + "imperfect": "Недосконала", + "open": "Відкрита", + "rebellious": "Бунтівна", + "simple": "Проста", + "working": "Робоча" + }, + "a11y_change_language": "Оберіть вашу мову", + "a11y_image_two_boys": "Зображення двох людей, які перевіряють свої телефони", + "a11y_clear_social_security_input_field": "Очистити поле вводу ідентифікаційного номера", + "a11y_select_login_method": "Оберіть як увійти", + "freja": { + "Waiting": "Очікую на Freja eID+…", + "OpenManually": "Відкрити Freja eID+ власноруч", + "OpenOnThisDevice": "Відкрити Freja eID+ на цьому пристрої" + } + }, + "calender": { + "approveAccessToCalender": "Вам потрібно дозволити доступ до вашого календаря", + "saveToCalender": "Зберегти у каледарі", + "saveToCalenderError": "Помилка збереження у календарі", + "saveToCalenderSuccess": "✔️ Збережено у календарі", + "showCalenderActions": "Показати дії у календарі", + "emptyHeadline": "У вашому календарі немає записів", + "emptyText": "Нічого показати" + }, + "children": { + "loadingErrorHeading": "Помилка!", + "loadingErrorInformationText": "Неможливо завантажити цю сторінку. Спробуйте ще раз або дізнайтеся статус на skolplattformen.org.", + "noKids_description": "На ваш ідентифікаційний номер не зареєстровано жодної дитини в Стокгольмі", + "noKids_title": "Немає дітей", + "title": "Ваші діти", + "tryAgain": "Спробуйте ще", + "viewStatus": "Дізнайтеся статус на skolplattformen.org" + }, + "general": { + "cancel": "Скасувати", + "changeLanguage": "Змінити мову", + "confirm": "Підтвердити", + "loading": "Завантаження…", + "logout": "Вийти", + "logoutAndClearPersonalData": "Вийти та очистити персональні дані", + "send": "Відправити", + "settings": "Налаштування", + "socialSecurityNumber": "Ідентифікаційний номер", + "title": "Відкрити skolplattformen", + "tomorrow": "Завтра", + "logoutAndClearAllDataInclSettings": "Вийти та очистити дані, включаючи налаштування" + }, + "language": { + "changeLanguage": "Змінити мову", + "changeLanguageButton": "Зберегти" + }, + "menu": { + "emptyHeadline": "Нічого немає в меню на обід", + "emptyText": "На цьому тижні нічого немає" + }, + "navigation": { + "calender": "Календар", + "menu": "Обід", + "news": "Новини", + "notifications": "Повідомлення", + "classmates": "Однокласники" + }, + "settings": { + "settings": "Налаштування", + "appearance": "Зовнішній вигляд", + "theme": "Тема", + "licenses": "Ліцензії", + "language": "Мова", + "themeAuto": "Автоматично", + "useSystemTheme": "Використати системну світлу/темну тему" + }, + "themes": { + "light": "Світла", + "dark": "Темна" + }, + "news": { + "backToChild": "Назад до дитини", + "noNewNewsItemsThisWeek": "Цього тижня новин немає.", + "notificationTitle": "Новини: {{header}} ({{published}})", + "published": "Опубліковано", + "title": "Новини від Skolplattformen", + "updated": "Оновлено", + "search": { + "placeholder": "Шукати у новинах…" + } + }, + "notifications": { + "notificationTitle": "Повідомлення: {{message}} ({{dateCreated}})" + }, + "schedule": { + "start": "Початок", + "end": "Кінець", + "lunch": "Обід", + "week": "Тиждень", + "gymBag": "Спортивна сумка" + }, + "classmates": { + "class": "Клас", + "child": "Дитина", + "contactsForGuardiansFor": "Контактна інформація для опікунів для" + }, + "contact": { + "a11y_show_contact_info_button_hint": "Показує контактну інформацію", + "a11y_show_contact_info_button_label": "Показати контактну інформацію", + "call": "Дзвінок", + "sms": "СМС", + "email": "Е-мейл", + "home": "Адреса" + } +} diff --git a/apps/skolplattformen-app-new/translations/zh_Hans.json b/apps/skolplattformen-app-new/translations/zh_Hans.json new file mode 100644 index 000000000..fcddd06fd --- /dev/null +++ b/apps/skolplattformen-app-new/translations/zh_Hans.json @@ -0,0 +1,156 @@ +{ + "abbrevations": { + "preSchool": "学前班", + "upperSecondarySchool": "高中", + "compulsorySchool": "小学/初中", + "leisureTimeCentre": "课后托管" + }, + "abscense": { + "endTime": "结束时间", + "entireDay": "全天", + "selectAbscenseEndTime": "选择结束时间", + "selectAbscenseStartTime": "选择开始时间", + "title": "报告缺席情况", + "invalidPersonalNumber": "个人身份号码无效", + "personalNumberMissing": "缺少个人身份号码", + "startTime": "开始时间", + "childsPersonalNumber": "孩子的个人身份号码" + }, + "auth": { + "bankid": { + "OpenManually": "手动打开 BankID", + "OpenOnAnotherDevice": "在另一台设备上打开 BankID", + "OpenOnThisDevice": "在本设备上打开 BankID", + "Waiting": "正在等待 BankID 响应…" + }, + "loginAsTestUser": "以测试用户身份登录", + "loginFailed": "无法登录。请重试。", + "placeholder_SocialSecurityNumber": "你的个人身份号码", + "words": { + "agile": "轻快", + "awaited": "久违", + "better": "更佳", + "cheap": "价廉", + "cooler": "酷乐", + "enlightened": "开明", + "fantastic": "匪夷", + "fast": "迅捷", + "free": "自由", + "fun": "乐趣", + "homemade": "手制", + "open": "开放", + "rebellious": "逆流", + "simple": "简单", + "imperfect": "有瑕", + "first": "一流", + "working": "可用" + }, + "subtitle": "{{word}}之选", + "a11y_clear_social_security_input_field": "清空个人身份号码栏", + "chooseLoginMethod": "选择登录方式", + "a11y_change_language": "选择您的语言", + "a11y_image_two_boys": "两个人看手机的图片", + "a11y_select_login_method": "选择登录方式", + "chooseSchoolPlatform": "选择平台", + "freja": { + "OpenManually": "手动打开 Freja eID+", + "OpenOnThisDevice": "在此设备上打开 Freja eID+", + "Waiting": "正在等待 Freja eID+ 响应…" + }, + "loginSuccessful": "登录成功,正在加载…" + }, + "calender": { + "saveToCalender": "保存到日历中", + "saveToCalenderError": "出了点问题", + "saveToCalenderSuccess": "✔️ 已保存到日历中", + "showCalenderActions": "显示日历操作", + "approveAccessToCalender": "您必须允许访问日历", + "emptyHeadline": "日历看起来有点空", + "emptyText": "找不到任何可以显示的东西" + }, + "children": { + "loadingErrorHeading": "啊噢!", + "loadingErrorInformationText": "这个页面无法加载。请重试或在 skolplattformen.org 网站上查看当前状态。", + "noKids_title": "没有找到孩子", + "title": "您的孩子", + "tryAgain": "请重试", + "viewStatus": "在 skolplattformen.org 网站上查看状态", + "noKids_description": "您的个人身份号码下没有注册在斯德哥尔摩市的孩子" + }, + "general": { + "cancel": "取消", + "changeLanguage": "更改语言", + "confirm": "确认", + "loading": "正在加载…", + "logout": "登出", + "logoutAndClearPersonalData": "登出并清除个人数据", + "logoutAndClearAllDataInclSettings": "登出并清除包括设置在内的所有数据", + "send": "发送", + "socialSecurityNumber": "个人身份号码", + "title": "开放学校平台", + "settings": "设置", + "tomorrow": "明天" + }, + "language": { + "changeLanguage": "更改语言", + "changeLanguageButton": "保存" + }, + "menu": { + "emptyHeadline": "午餐菜单看起来有点空", + "emptyText": "找不到有关这个星期的任何内容" + }, + "navigation": { + "calender": "日历", + "menu": "午餐", + "news": "新闻", + "notifications": "通知", + "classmates": "同班同学" + }, + "settings": { + "appearance": "外观", + "licenses": "许可证", + "language": "语言", + "themeAuto": "自动", + "useSystemTheme": "使用系统亮色/暗色主题", + "settings": "设置", + "theme": "主题" + }, + "themes": { + "light": "亮色", + "dark": "暗色" + }, + "news": { + "backToChild": "返回到孩子页面", + "noNewNewsItemsThisWeek": "这个星期没有新闻。", + "notificationTitle": "新闻:{{header}}({{published}})", + "published": "已发布", + "updated": "已更新", + "search": { + "placeholder": "在新闻中搜索…" + }, + "title": "来自学校平台的新闻" + }, + "notifications": { + "notificationTitle": "通知:{{message}}({{dateCreated}})" + }, + "schedule": { + "start": "开始", + "end": "结束", + "lunch": "午餐", + "gymBag": "健身袋", + "week": "星期" + }, + "classmates": { + "class": "课堂", + "child": "孩子", + "contactsForGuardiansFor": "监护人的联系信息" + }, + "contact": { + "a11y_show_contact_info_button_hint": "显示联系信息", + "a11y_show_contact_info_button_label": "显示联系信息", + "sms": "短信", + "call": "电话", + "email": "电子邮箱", + "home": "家庭地址" + } +} diff --git a/apps/skolplattformen-app-new/translations/zh_Hant.json b/apps/skolplattformen-app-new/translations/zh_Hant.json new file mode 100644 index 000000000..20cfe3eb0 --- /dev/null +++ b/apps/skolplattformen-app-new/translations/zh_Hant.json @@ -0,0 +1,144 @@ +{ + "abbrevations": { + "compulsorySchool": "小學/初中", + "leisureTimeCentre": "課後託管", + "preSchool": "學前班", + "upperSecondarySchool": "高中" + }, + "abscense": { + "endTime": "結束時間", + "entireDay": "全天", + "invalidPersonalNumber": "個人身份號碼無效", + "personalNumberMissing": "缺少個人身份號碼", + "selectAbscenseEndTime": "選擇結束時間", + "selectAbscenseStartTime": "選擇開始時間", + "startTime": "開始時間", + "title": "報告缺席情況" + }, + "auth": { + "bankid": { + "OpenManually": "手動開啟 BankID", + "OpenOnAnotherDevice": "在另一臺裝置上開啟 BankID", + "OpenOnThisDevice": "在本裝置上開啟 BankID", + "Waiting": "正在等待 BankID 響應…" + }, + "chooseLoginMethod": "選擇登入方式", + "loginAsTestUser": "以測試使用者身份登入", + "loginFailed": "無法登入。請重試。", + "placeholder_SocialSecurityNumber": "你的個人身份號碼", + "subtitle": "{{word}}之選", + "words": { + "agile": "輕快", + "awaited": "久違", + "better": "更佳", + "cheap": "價廉", + "cooler": "酷樂", + "enlightened": "開明", + "fantastic": "匪夷", + "fast": "迅捷", + "first": "一流", + "free": "自由", + "fun": "樂趣", + "homemade": "手製", + "imperfect": "有瑕", + "open": "開放", + "rebellious": "逆流", + "simple": "簡單", + "working": "可用" + }, + "a11y_change_language": "選擇您的語言", + "a11y_image_two_boys": "兩個人看手機的圖片", + "a11y_clear_social_security_input_field": "清空個人身份號碼欄", + "a11y_select_login_method": "選擇登入方式" + }, + "calender": { + "approveAccessToCalender": "您必須允許訪問日曆", + "saveToCalender": "儲存到日曆中", + "saveToCalenderError": "出了點問題", + "saveToCalenderSuccess": "✔️ 已儲存到日曆中", + "showCalenderActions": "顯示日曆操作" + }, + "children": { + "loadingErrorHeading": "啊噢!", + "loadingErrorInformationText": "這個頁面無法載入。請重試或在 skolplattformen.org 網站上檢視當前狀態。", + "noKids_description": "您的個人身份號碼下沒有註冊在斯德哥爾摩市的孩子", + "noKids_title": "沒有找到孩子", + "title": "您的孩子", + "tryAgain": "請重試", + "viewStatus": "在 skolplattformen.org 網站上檢視狀態" + }, + "general": { + "cancel": "取消", + "changeLanguage": "更改語言", + "confirm": "確認", + "loading": "正在載入…", + "logout": "登出", + "logoutAndClearPersonalData": "登出並清除個人資料", + "logoutAndClearAllDataInclSettings": "登出並清除包括設定在內的所有資料", + "send": "傳送", + "settings": "設定", + "socialSecurityNumber": "個人身份號碼", + "title": "開放學校平臺" + }, + "language": { + "changeLanguage": "更改語言", + "changeLanguageButton": "儲存" + }, + "menu": { + "emptyHeadline": "午餐選單看起來有點空", + "emptyText": "找不到有關這個星期的任何內容" + }, + "navigation": { + "calender": "日曆", + "menu": "午餐", + "news": "新聞", + "notifications": "通知", + "classmates": "同班同學" + }, + "settings": { + "settings": "設定", + "appearance": "外觀", + "theme": "主題", + "licenses": "許可證", + "language": "語言", + "themeAuto": "自動", + "useSystemTheme": "使用系統亮色/暗色主題" + }, + "themes": { + "light": "亮色", + "dark": "暗色" + }, + "news": { + "backToChild": "返回到孩子頁面", + "noNewNewsItemsThisWeek": "這個星期沒有新聞。", + "notificationTitle": "新聞:{{header}}({{published}})", + "published": "已釋出", + "title": "來自學校平臺的新聞", + "updated": "已更新", + "search": { + "placeholder": "在新聞中搜索…" + } + }, + "notifications": { + "notificationTitle": "通知:{{message}}({{dateCreated}})" + }, + "schedule": { + "start": "開始", + "end": "結束", + "lunch": "午餐", + "gymBag": "健身袋" + }, + "classmates": { + "class": "課堂", + "child": "孩子", + "contactsForGuardiansFor": "監護人的聯絡資訊" + }, + "contact": { + "a11y_show_contact_info_button_hint": "顯示聯絡資訊", + "a11y_show_contact_info_button_label": "顯示聯絡資訊", + "call": "電話", + "sms": "簡訊", + "email": "電子郵箱", + "home": "家庭地址" + } +} diff --git a/apps/skolplattformen-app-new/tsconfig.json b/apps/skolplattformen-app-new/tsconfig.json new file mode 100644 index 000000000..a5cadaeb6 --- /dev/null +++ b/apps/skolplattformen-app-new/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@tsconfig/react-native/tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@skolplattformen/api": ["libs/api/lib/index.ts"], + "@skolplattformen/api-hjarntorget": ["libs/api-hjarntorget/lib/index.ts"], + "@skolplattformen/api-skolplattformen": [ + "libs/api-skolplattformen/lib/index.ts" + ], + "@skolplattformen/curriculum": ["libs/curriculum/src/index.ts"], + "@skolplattformen/hooks": ["libs/hooks/src/index.ts"] + } + } +} diff --git a/apps/skolplattformen-app-new/types.d.ts b/apps/skolplattformen-app-new/types.d.ts new file mode 100644 index 000000000..9536d3d13 --- /dev/null +++ b/apps/skolplattformen-app-new/types.d.ts @@ -0,0 +1,36 @@ +declare module 'libraries.json' { + export interface Library { + libraryName: string + version: string + _license?: License | string + _description?: string + homepage?: string + author?: Author | string + repository?: Repository + _licenseContent?: string + } + + export interface License { + type: string + url: string + } + + export interface Author { + name: string + url?: string + email?: string + } + + export interface Repository { + type?: string + url: string + directory?: string + baseUrl?: string + web?: string + dist?: string + } + + const libraries: Library[] + + export default libraries +} diff --git a/apps/skolplattformen-app-new/ui/keyboardAvoidingView.component.tsx b/apps/skolplattformen-app-new/ui/keyboardAvoidingView.component.tsx new file mode 100644 index 000000000..1e9dfa423 --- /dev/null +++ b/apps/skolplattformen-app-new/ui/keyboardAvoidingView.component.tsx @@ -0,0 +1,32 @@ +import { StyleService, useStyleSheet } from '@ui-kitten/components' +import React from 'react' +import { + KeyboardAvoidingView as RNKeyboardAvoidingView, + Platform, +} from 'react-native' +import { Layout } from '../styles' + +type KeyboardAvoidingViewProps = { + children: React.ReactNode +} + +export const KeyboardAvoidingView: React.FC = ({ + children, +}) => { + const styles = useStyleSheet(themedStyles) + + return ( + + {children} + + ) +} + +const themedStyles = StyleService.create({ + keyboardAvoidingView: { + ...Layout.flex.full, + }, +}) diff --git a/apps/skolplattformen-app-new/ui/safeAreaView.component.tsx b/apps/skolplattformen-app-new/ui/safeAreaView.component.tsx new file mode 100644 index 000000000..659e95f57 --- /dev/null +++ b/apps/skolplattformen-app-new/ui/safeAreaView.component.tsx @@ -0,0 +1,18 @@ +import { StyleService, useStyleSheet } from '@ui-kitten/components' +import React from 'react' +import { ViewProps } from 'react-native' +import { SafeAreaView as RNSafeAreaView } from 'react-native-safe-area-context' +import { Layout } from '../styles' + +export const SafeAreaView: React.FC = ({ children }) => { + const styles = useStyleSheet(themedStyles) + + return {children} +} + +const themedStyles = StyleService.create({ + safeArea: { + ...Layout.flex.full, + backgroundColor: 'background-basic-color-2', + }, +}) diff --git a/apps/skolplattformen-app-new/ui/safeAreaViewContainer.component.tsx b/apps/skolplattformen-app-new/ui/safeAreaViewContainer.component.tsx new file mode 100644 index 000000000..496ebaa4e --- /dev/null +++ b/apps/skolplattformen-app-new/ui/safeAreaViewContainer.component.tsx @@ -0,0 +1,22 @@ +import React from 'react' +import { View, StyleSheet, Platform, StatusBar } from 'react-native' + +/** + * This view takes in account for the status bar current height on Android + */ +type SafeAreaViewContainerProps = { + children: React.ReactNode +} + +export const SafeAreaViewContainer: React.FC = ({ + children, +}) => { + return {children} +} + +const styles = StyleSheet.create({ + wrapper: { + flex: 1, + paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0, + }, +}) diff --git a/apps/skolplattformen-app-new/utils/SMS.ts b/apps/skolplattformen-app-new/utils/SMS.ts new file mode 100644 index 000000000..ad5914aed --- /dev/null +++ b/apps/skolplattformen-app-new/utils/SMS.ts @@ -0,0 +1,13 @@ +import { Linking, Platform } from 'react-native' + +const phoneNumber = '+46730121740' + +export const useSMS = () => { + const sendSMS = async (message: string) => { + const separator = Platform.OS === 'ios' ? '&' : '?' + const url = `sms:${phoneNumber}${separator}body=${message}` + await Linking.openURL(url) + } + + return { sendSMS } +} diff --git a/apps/skolplattformen-app-new/utils/__tests__/SMS.test.ts b/apps/skolplattformen-app-new/utils/__tests__/SMS.test.ts new file mode 100644 index 000000000..0e13c5972 --- /dev/null +++ b/apps/skolplattformen-app-new/utils/__tests__/SMS.test.ts @@ -0,0 +1,34 @@ +import { useSMS } from '../SMS' +import { Linking, Platform } from 'react-native' +import { renderHook } from '@testing-library/react' + +jest.mock('react-native', () => ({ + Linking: { openURL: jest.fn() }, + Platform: { OS: 'ios' }, +})) + +beforeEach(jest.clearAllMocks) + +describe('#send', () => { + test('sends a message on iOS', async () => { + const { result } = renderHook(() => useSMS()) + + await result.current.sendSMS('121212-1212') + + expect(Linking.openURL).toHaveBeenCalledWith( + 'sms:+46730121740&body=121212-1212' + ) + }) + + test('sends a message on Android', async () => { + Platform.OS = 'android' + + const { result } = renderHook(() => useSMS()) + + await result.current.sendSMS('121212-1212') + + expect(Linking.openURL).toHaveBeenCalledWith( + 'sms:+46730121740?body=121212-1212' + ) + }) +}) diff --git a/apps/skolplattformen-app-new/utils/__tests__/calendarHelpers.test.ts b/apps/skolplattformen-app-new/utils/__tests__/calendarHelpers.test.ts new file mode 100644 index 000000000..2e1b996e8 --- /dev/null +++ b/apps/skolplattformen-app-new/utils/__tests__/calendarHelpers.test.ts @@ -0,0 +1,47 @@ +import moment from 'moment' +import { getMeaningfulStartingDate } from '../calendarHelpers' + +const tuesdayMorning = moment('2021-11-30T08:20:00+0100') +const tuesdayEvening = moment('2021-11-30T19:20:26+0100') +const wednesdayEvening = moment('2021-12-01T19:20:26+0100') +const fridayEvening = moment('2021-12-03T19:20:26+0100') +const saturdayEvening = moment('2021-12-04T19:20:26+0100') +const sundayEvening = moment('2021-12-05T19:20:26+0100') +const mondayEvening = moment('2021-12-06T19:20:26+0100') + +describe('getMeaningfulStartingDate should not touch inputdate', () => { + const origDate = moment() + const origDateClone = origDate.clone() + getMeaningfulStartingDate(origDate) + + expect(origDate).toEqual(origDateClone) +}) + +describe('getMeaningfulStartingDate on weekends', () => { + it('should give next monday if on friday evening', () => { + const startDate = getMeaningfulStartingDate(fridayEvening) + expect(startDate.toISOString()).toEqual(mondayEvening.toISOString()) + }) + + it('should give next monday if on saturday', () => { + const startDate = getMeaningfulStartingDate(saturdayEvening) + expect(startDate.toISOString()).toEqual(mondayEvening.toISOString()) + }) + + it('should give next monday if on sunday', () => { + const startDate = getMeaningfulStartingDate(sundayEvening) + expect(startDate.toISOString()).toEqual(mondayEvening.toISOString()) + }) +}) + +describe('getMeaningfulStartingDate on weekdays', () => { + it('should give next day if on tuesday evening', () => { + const startDate = getMeaningfulStartingDate(tuesdayEvening) + expect(startDate.toISOString()).toEqual(wednesdayEvening.toISOString()) + }) + + it('should give same day if on tuesday morning', () => { + const startDate = getMeaningfulStartingDate(tuesdayMorning) + expect(startDate.toISOString()).toEqual(tuesdayMorning.toISOString()) + }) +}) diff --git a/apps/skolplattformen-app-new/utils/__tests__/peopleHelpers.test.ts b/apps/skolplattformen-app-new/utils/__tests__/peopleHelpers.test.ts new file mode 100644 index 000000000..1d23ce0dd --- /dev/null +++ b/apps/skolplattformen-app-new/utils/__tests__/peopleHelpers.test.ts @@ -0,0 +1,85 @@ +import { + fullName, + guardians, + initials, + sortByFirstName, + studentName, +} from '../peopleHelpers' + +describe('#studentName', () => { + test('should remove student from name', () => { + expect(studentName('Alan Nilsson (elev)')).toEqual('Alan Nilsson') + }) + + test('should remove student without spacing from name', () => { + expect(studentName('Alan Nilsson(elev)')).toEqual('Alan Nilsson') + }) + + test('handles undefined name', () => { + expect(studentName(undefined)).toBeUndefined() + }) +}) + +describe('#fullName', () => { + test('should', () => { + expect( + fullName({ + firstname: 'Margaery', + lastname: 'Eriksson', + }) + ).toEqual('Margaery Eriksson') + }) +}) + +describe('#sortByFirstName', () => { + test('sort arrays by first name', () => { + expect( + sortByFirstName([ + { + firstname: 'Margaery', + lastname: 'Eriksson', + }, + { + firstname: 'Loras', + lastname: 'Eriksson', + }, + ]) + ).toEqual([ + { + firstname: 'Loras', + lastname: 'Eriksson', + }, + { + firstname: 'Margaery', + lastname: 'Eriksson', + }, + ]) + }) +}) + +describe('#guardians', () => { + test('should join a list of guardians sorted by firstname', () => { + expect( + guardians([ + { + firstname: 'Margaery', + lastname: 'Eriksson', + }, + { + firstname: 'Loras', + lastname: 'Eriksson', + }, + ]) + ).toEqual('Loras Eriksson, Margaery Eriksson') + }) +}) +describe('#initials', () => { + test('should extract initials from name', () => { + expect(initials('Namn Namnsson')).toEqual('Na') + expect(initials('Nisse Namnsson')).toEqual('Ni') + }) + + test('handles undefined name', () => { + expect(initials(undefined)).toBeUndefined() + }) +}) diff --git a/apps/skolplattformen-app-new/utils/__tests__/translation.test.ts b/apps/skolplattformen-app-new/utils/__tests__/translation.test.ts new file mode 100644 index 000000000..c8c47336a --- /dev/null +++ b/apps/skolplattformen-app-new/utils/__tests__/translation.test.ts @@ -0,0 +1,22 @@ +import i18n from 'i18n-js' +import { translate, translations } from '../translation' + +describe('translation in swedish', () => { + beforeAll(() => { + i18n.translations = { sv: translations.sv } + i18n.locale = 'sv' + }) + it('should be able to translate the word settings', () => { + expect(translate('general.settings')).toEqual('Inställningar') + }) +}) + +describe('translation in english', () => { + beforeAll(() => { + i18n.translations = { en: translations.en } + i18n.locale = 'en' + }) + it('should be able to translate the word settings', () => { + expect(translate('general.settings')).toEqual('Settings') + }) +}) diff --git a/apps/skolplattformen-app-new/utils/calendarHelpers.ts b/apps/skolplattformen-app-new/utils/calendarHelpers.ts new file mode 100644 index 000000000..c75961ec9 --- /dev/null +++ b/apps/skolplattformen-app-new/utils/calendarHelpers.ts @@ -0,0 +1,20 @@ +import moment from 'moment' + +export const getMeaningfulStartingDate = (date = moment()) => { + const originalDate = date.clone() + let returnDate = date.clone() + // are we on the evening? + if (date.hour() > 17) { + returnDate.add('1', 'day') + } + // are we on the weekend + if (returnDate.isoWeekday() > 5) { + returnDate = returnDate.add(5, 'days').startOf('isoWeek') + returnDate + .hour(originalDate.hour()) + .minute(originalDate.minute()) + .second(originalDate.second()) + } + + return returnDate +} diff --git a/apps/skolplattformen-app-new/utils/peopleHelpers.ts b/apps/skolplattformen-app-new/utils/peopleHelpers.ts new file mode 100644 index 000000000..fe30b9d92 --- /dev/null +++ b/apps/skolplattformen-app-new/utils/peopleHelpers.ts @@ -0,0 +1,17 @@ +import { Guardian } from '@skolplattformen/api' + +export const studentName = (name?: string) => name?.replace(/\s?\(\w+\)$/, '') + +export const sortByFirstName = ( + data: T[] +): T[] => data.sort((a, b) => a.firstname.localeCompare(b.firstname)) + +export const guardians = (data: Guardian[]) => + sortByFirstName(data).map(fullName).join(', ') + +export const fullName = (person: Guardian) => + `${person.firstname} ${person.lastname}` + +export const initials = (name?: string) => { + return name?.slice(0, 2) +} diff --git a/apps/skolplattformen-app-new/utils/search.tsx b/apps/skolplattformen-app-new/utils/search.tsx new file mode 100644 index 000000000..0f3101d9b --- /dev/null +++ b/apps/skolplattformen-app-new/utils/search.tsx @@ -0,0 +1,61 @@ +import { NewsItem } from '@skolplattformen/api' +import { useNews } from '../libs/hooks/src' +import { MatchData, Searcher } from 'fast-fuzzy' +import React, { ReactNode, useMemo } from 'react' +import { Text } from 'react-native' +import { useChild } from '../components/childContext.component' +import { Typography } from '../styles' + +// https://github.com/facebook/react-native/issues/14796#issuecomment-389743259 + +global.Buffer = global.Buffer || require('buffer').Buffer + +const NUM_CHARS_AROUND_SEARCH_MATCH = 20 + +export function useNewsListSearchResults( + searchQuery: string +): MatchData[] { + const child = useChild() + const { data } = useNews(child) + + const searcher = useMemo(() => { + return new Searcher(data, { + threshold: 0.7, + keySelector: (newsItem) => newsItem.body ?? '', + returnMatchData: true, + }) + }, [data]) + + return useMemo(() => { + if (!searchQuery) { + return [] + } + return searcher.search(searchQuery) + }, [searchQuery, searcher]) +} + +function replaceNewLines(string: string): string { + return string.replace(/\n/g, ' ') +} + +export function renderSearchResultPreview( + searchResult: MatchData +): ReactNode { + const start = searchResult.match.index + const end = start + searchResult.match.length + + const beforeMatch = replaceNewLines( + searchResult.original.slice(start - NUM_CHARS_AROUND_SEARCH_MATCH, start) + ) + const match = replaceNewLines(searchResult.original.slice(start, end)) + const afterMatch = replaceNewLines( + searchResult.original.slice(end, end + NUM_CHARS_AROUND_SEARCH_MATCH) + ) + return ( + <> + {!!beforeMatch && `...${beforeMatch}`} + {match} + {!!afterMatch && `${afterMatch}...`} + + ) +} diff --git a/apps/skolplattformen-app-new/utils/testHelpers.tsx b/apps/skolplattformen-app-new/utils/testHelpers.tsx new file mode 100644 index 000000000..ebe8b5b6f --- /dev/null +++ b/apps/skolplattformen-app-new/utils/testHelpers.tsx @@ -0,0 +1,36 @@ +import * as eva from '@eva-design/eva' +import { render as rtlRender } from '@testing-library/react-native' +import { ApplicationProvider, IconRegistry } from '@ui-kitten/components' +import { EvaIconsPack } from '@ui-kitten/eva-icons' +import React, { ReactElement } from 'react' +import { LanguageProvider } from '../context/language/languageContext' +import { translations } from './translation' +import { lightTheme } from '../design/themes' + +type AllTheProvidersProps = { + children: React.ReactNode +} + +export const render = ( + ui: ReactElement, + { language = 'sv', ...options } = {} +) => { + const AllTheProviders: React.FC = ({ children }) => { + return ( + <> + + + + {children} + + + + ) + } + + return rtlRender(ui, { wrapper: AllTheProviders, ...options }) +} diff --git a/apps/skolplattformen-app-new/utils/translation.ts b/apps/skolplattformen-app-new/utils/translation.ts new file mode 100644 index 000000000..fce555d73 --- /dev/null +++ b/apps/skolplattformen-app-new/utils/translation.ts @@ -0,0 +1,183 @@ +import i18n, { TranslateOptions } from 'i18n-js' + +// const i18n = new I18n(); + +interface Language { + langCode: string + languageName: string + languageLocalName: string + locale: string + active: boolean +} + +export const languages: Language[] = [ + { + langCode: 'sv', + languageName: 'Swedish', + languageLocalName: 'Svenska', + locale: 'sv', + active: true, + }, + { + langCode: 'ar', + languageName: 'Arabic', + languageLocalName: 'اَلْعَرَبِيَّةُ', + locale: 'ar', + active: true, + }, + { + langCode: 'zh_Hant', + languageName: 'Chinese (traditional)', + languageLocalName: '繁體中文', + locale: 'zh-cn', + active: true, + }, + { + langCode: 'zh_Hans', + languageName: 'Chinese (simplified)', + languageLocalName: '简体中文', + locale: 'zh-cn', + active: true, + }, + { + langCode: 'nl', + languageName: 'Dutch', + languageLocalName: 'Nederlands', + locale: 'nl', + active: true, + }, + { + langCode: 'en', + languageName: 'English', + languageLocalName: 'English', + locale: 'en', + active: true, + }, + + { + langCode: 'de', + languageName: 'German', + languageLocalName: 'Deutsch', + locale: 'de', + active: true, + }, + + { + langCode: 'fi', + languageName: 'Finnish', + languageLocalName: 'Suomi', + locale: 'fi', + active: true, + }, + { + langCode: 'fr', + languageName: 'French', + languageLocalName: 'Français', + locale: 'fr', + active: true, + }, + { + langCode: 'it', + languageName: 'Italian', + languageLocalName: 'Italiano', + locale: 'it', + active: true, + }, + { + langCode: 'ja', + languageName: 'Japanese', + languageLocalName: '日本語', + locale: 'ja', + active: true, + }, + { + langCode: 'la', + languageName: 'Latin', + languageLocalName: 'Latina', + locale: 'sv', + active: true, + }, + { + langCode: 'nb_NO', + languageName: 'Norwegian Bokmål', + languageLocalName: 'Norsk bokmål', + locale: 'nb', + active: true, + }, + { + langCode: 'pl', + languageName: 'Polish', + languageLocalName: 'Polski', + locale: 'pl', + active: true, + }, + { + langCode: 'pt', + languageName: 'Portuguese', + languageLocalName: 'Português', + locale: 'pt', + active: true, + }, + { + langCode: 'ru', + languageName: 'Russian', + languageLocalName: 'русский', + locale: 'ru', + active: false, + }, + { + langCode: 'so', + languageName: 'Somali', + languageLocalName: 'af-Soomaali', + locale: 'sv', + active: true, + }, + { + langCode: 'es', + languageName: 'Spanish', + languageLocalName: 'Español', + locale: 'es', + active: true, + }, + { + langCode: 'th', + languageName: 'Thai', + languageLocalName: 'ไทย', + locale: 'th', + active: true, + }, + { + langCode: 'uk', + languageName: 'Ukrainian', + languageLocalName: 'український', + locale: 'uk', + active: true, + }, +] + +export const translations = { + ar: require('../translations/ar.json'), + de: require('../translations/de.json'), + en: require('../translations/en.json'), + es: require('../translations/es.json'), + fi: require('../translations/fi.json'), + fr: require('../translations/fr.json'), + it: require('../translations/it.json'), + ja: require('../translations/ja.json'), + la: require('../translations/la.json'), + nb_NO: require('../translations/nb_NO.json'), + nl: require('../translations/nl.json'), + pl: require('../translations/pl.json'), + pt: require('../translations/pt.json'), + ru: require('../translations/ru.json'), + so: require('../translations/so.json'), + sv: require('../translations/sv.json'), + th: require('../translations/th.json'), + uk: require('../translations/uk.json'), + zh_Hans: require('../translations/zh_Hans.json'), + zh_Hant: require('../translations/zh_Hant.json'), +} + +export const translate = (key: string, options?: TranslateOptions) => { + return i18n.t(key, options) +} diff --git a/apps/skolplattformen-app-new/yarn.lock b/apps/skolplattformen-app-new/yarn.lock new file mode 100644 index 000000000..2e634e9a9 --- /dev/null +++ b/apps/skolplattformen-app-new/yarn.lock @@ -0,0 +1,8721 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@adobe/css-tools@^4.3.0": + version "4.3.1" + resolved "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz" + integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg== + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9", "@babel/compat-data@^7.23.2": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz" + integrity sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ== + +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.13.16", "@babel/core@^7.20.0", "@babel/core@^7.23.2", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.8.0": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz" + integrity sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helpers" "^7.23.2" + "@babel/parser" "^7.23.0" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/eslint-parser@^7.12.0", "@babel/eslint-parser@^7.20.0": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz" + integrity sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg== + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.1" + +"@babel/generator@^7.20.0", "@babel/generator@^7.23.0", "@babel/generator@^7.7.2": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.5": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz" + integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz" + integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz" + integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.4.3": + version "0.4.3" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz" + integrity sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== + dependencies: + "@babel/types" "^7.23.0" + +"@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.22.5": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz" + integrity sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.22.20", "@babel/helper-remap-async-to-generator@^7.22.5": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz" + integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-wrap-function" "^7.22.20" + +"@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + +"@babel/helper-wrap-function@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz" + integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== + dependencies: + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.22.19" + +"@babel/helpers@^7.23.2": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz" + integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz" + integrity sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz" + integrity sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.22.15" + +"@babel/plugin-proposal-async-generator-functions@^7.0.0": + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz" + integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-export-default-from@^7.0.0": + version "7.22.17" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.22.17.tgz" + integrity sha512-cop/3quQBVvdz6X5SJC6AhUv3C9DrVTM06LUEXimEdWAhCSyOJIr9NiZDU9leHZ0/aiG0Sh7Zmvaku5TWYNgbA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-export-default-from" "^7.22.5" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.0.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.20.0": + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz" + integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.7" + +"@babel/plugin-proposal-optional-catch-binding@^7.0.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.20.0": + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz" + integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.22.5.tgz" + integrity sha512-ODAqWWXB/yReh/jVQDag/3/tl6lgBueQkk/TcfW/59Oykm4c8a55XloX0CTk2k2VJiFWMgHby9xNX29IbCv9dQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz" + integrity sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-assertions@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz" + integrity sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-attributes@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz" + integrity sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.22.5", "@babel/plugin-syntax-jsx@^7.7.2": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz" + integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.22.5", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz" + integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz" + integrity sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-async-generator-functions@^7.23.2": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz" + integrity sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-transform-async-to-generator@^7.20.0", "@babel/plugin-transform-async-to-generator@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz" + integrity sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ== + dependencies: + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.5" + +"@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz" + integrity sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz" + integrity sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz" + integrity sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-static-block@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz" + integrity sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz" + integrity sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-split-export-declaration" "^7.22.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz" + integrity sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.5" + +"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.20.0", "@babel/plugin-transform-destructuring@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz" + integrity sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-dotall-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz" + integrity sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-duplicate-keys@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz" + integrity sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-dynamic-import@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz" + integrity sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz" + integrity sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-export-namespace-from@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz" + integrity sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz" + integrity sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-flow" "^7.22.5" + +"@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz" + integrity sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz" + integrity sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg== + dependencies: + "@babel/helper-compilation-targets" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-json-strings@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz" + integrity sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz" + integrity sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-logical-assignment-operators@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz" + integrity sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz" + integrity sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-amd@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz" + integrity sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw== + dependencies: + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz" + integrity sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ== + dependencies: + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + +"@babel/plugin-transform-modules-systemjs@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz" + integrity sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg== + dependencies: + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/plugin-transform-modules-umd@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz" + integrity sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ== + dependencies: + "@babel/helper-module-transforms" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.0.0", "@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz" + integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-new-target@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz" + integrity sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz" + integrity sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz" + integrity sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz" + integrity sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.22.15" + +"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz" + integrity sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.5" + +"@babel/plugin-transform-optional-catch-binding@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz" + integrity sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.22.15", "@babel/plugin-transform-optional-chaining@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz" + integrity sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz" + integrity sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-methods@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz" + integrity sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-property-in-object@^7.22.11": + version "7.22.11" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz" + integrity sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz" + integrity sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz" + integrity sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-jsx-self@^7.0.0": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz" + integrity sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-jsx-source@^7.0.0": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz" + integrity sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz" + integrity sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/types" "^7.22.15" + +"@babel/plugin-transform-regenerator@^7.22.10": + version "7.22.10" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz" + integrity sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz" + integrity sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-runtime@^7.0.0": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.15.tgz" + integrity sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g== + dependencies: + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + babel-plugin-polyfill-corejs2 "^0.4.5" + babel-plugin-polyfill-corejs3 "^0.8.3" + babel-plugin-polyfill-regenerator "^0.5.2" + semver "^6.3.1" + +"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz" + integrity sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz" + integrity sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + +"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz" + integrity sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz" + integrity sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-typeof-symbol@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz" + integrity sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-typescript@^7.22.15", "@babel/plugin-transform-typescript@^7.5.0": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz" + integrity sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-typescript" "^7.22.5" + +"@babel/plugin-transform-unicode-escapes@^7.22.10": + version "7.22.10" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz" + integrity sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-property-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz" + integrity sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz" + integrity sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-sets-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz" + integrity sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/preset-env@^7.1.6", "@babel/preset-env@^7.23.2": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz" + integrity sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ== + dependencies: + "@babel/compat-data" "^7.23.2" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.15" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.22.15" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.22.5" + "@babel/plugin-syntax-import-attributes" "^7.22.5" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.22.5" + "@babel/plugin-transform-async-generator-functions" "^7.23.2" + "@babel/plugin-transform-async-to-generator" "^7.22.5" + "@babel/plugin-transform-block-scoped-functions" "^7.22.5" + "@babel/plugin-transform-block-scoping" "^7.23.0" + "@babel/plugin-transform-class-properties" "^7.22.5" + "@babel/plugin-transform-class-static-block" "^7.22.11" + "@babel/plugin-transform-classes" "^7.22.15" + "@babel/plugin-transform-computed-properties" "^7.22.5" + "@babel/plugin-transform-destructuring" "^7.23.0" + "@babel/plugin-transform-dotall-regex" "^7.22.5" + "@babel/plugin-transform-duplicate-keys" "^7.22.5" + "@babel/plugin-transform-dynamic-import" "^7.22.11" + "@babel/plugin-transform-exponentiation-operator" "^7.22.5" + "@babel/plugin-transform-export-namespace-from" "^7.22.11" + "@babel/plugin-transform-for-of" "^7.22.15" + "@babel/plugin-transform-function-name" "^7.22.5" + "@babel/plugin-transform-json-strings" "^7.22.11" + "@babel/plugin-transform-literals" "^7.22.5" + "@babel/plugin-transform-logical-assignment-operators" "^7.22.11" + "@babel/plugin-transform-member-expression-literals" "^7.22.5" + "@babel/plugin-transform-modules-amd" "^7.23.0" + "@babel/plugin-transform-modules-commonjs" "^7.23.0" + "@babel/plugin-transform-modules-systemjs" "^7.23.0" + "@babel/plugin-transform-modules-umd" "^7.22.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.22.5" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.11" + "@babel/plugin-transform-numeric-separator" "^7.22.11" + "@babel/plugin-transform-object-rest-spread" "^7.22.15" + "@babel/plugin-transform-object-super" "^7.22.5" + "@babel/plugin-transform-optional-catch-binding" "^7.22.11" + "@babel/plugin-transform-optional-chaining" "^7.23.0" + "@babel/plugin-transform-parameters" "^7.22.15" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.11" + "@babel/plugin-transform-property-literals" "^7.22.5" + "@babel/plugin-transform-regenerator" "^7.22.10" + "@babel/plugin-transform-reserved-words" "^7.22.5" + "@babel/plugin-transform-shorthand-properties" "^7.22.5" + "@babel/plugin-transform-spread" "^7.22.5" + "@babel/plugin-transform-sticky-regex" "^7.22.5" + "@babel/plugin-transform-template-literals" "^7.22.5" + "@babel/plugin-transform-typeof-symbol" "^7.22.5" + "@babel/plugin-transform-unicode-escapes" "^7.22.10" + "@babel/plugin-transform-unicode-property-regex" "^7.22.5" + "@babel/plugin-transform-unicode-regex" "^7.22.5" + "@babel/plugin-transform-unicode-sets-regex" "^7.22.5" + "@babel/preset-modules" "0.1.6-no-external-plugins" + "@babel/types" "^7.23.0" + babel-plugin-polyfill-corejs2 "^0.4.6" + babel-plugin-polyfill-corejs3 "^0.8.5" + babel-plugin-polyfill-regenerator "^0.5.3" + core-js-compat "^3.31.0" + semver "^6.3.1" + +"@babel/preset-flow@^7.13.13": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.22.15.tgz" + integrity sha512-dB5aIMqpkgbTfN5vDdTRPzjqtWiZcRESNR88QYnoPR+bmdYoluOzMX9tQerTv0XzSgZYctPfO1oc0N5zdog1ew== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-transform-flow-strip-types" "^7.22.5" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.23.2": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz" + integrity sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.23.0" + "@babel/plugin-transform-typescript" "^7.22.15" + +"@babel/register@^7.13.16": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/register/-/register-7.22.15.tgz" + integrity sha512-V3Q3EqoQdn65RCgTLwauZaTfd1ShhwPmbBv+1dkZV/HpCGMKVyn6oFcRlI7RaKqiDQjX2Qd3AuoEguBgdjIKlg== + dependencies: + clone-deep "^4.0.1" + find-cache-dir "^2.0.0" + make-dir "^2.1.0" + pirates "^4.0.5" + source-map-support "^0.5.16" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.20.0", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": + version "7.23.1" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz" + integrity sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.0.0", "@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.3.3": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.20.0", "@babel/traverse@^7.23.2": + version "7.23.2" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@egjs/hammerjs@^2.0.17": + version "2.0.17" + resolved "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz" + integrity sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A== + dependencies: + "@types/hammerjs" "^2.0.36" + +"@eslint-community/eslint-utils@^4.2.0": + 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" + +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.9.0" + resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.0.tgz" + integrity sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ== + +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== + 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" + +"@eslint/js@8.50.0": + version "8.50.0" + resolved "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz" + integrity sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ== + +"@eva-design/dss@^2.2.0": + version "2.2.0" + resolved "https://registry.npmjs.org/@eva-design/dss/-/dss-2.2.0.tgz" + integrity sha512-ip+iLpe8WFR1IyPGR9puJtXhkZQrWV9p+Xgg3u/3ruDNaObh/YlnfZdS0i29m6YZduW3I+lLuXSXwq5f4pAbRA== + +"@eva-design/eva@^2.2.0": + version "2.2.0" + resolved "https://registry.npmjs.org/@eva-design/eva/-/eva-2.2.0.tgz" + integrity sha512-Wh98ex5cCK+YYSQNpthX1bT4CA3zDRR1WnJv0YlyvULAkmjaEvqtoGMCXzu5DH8v1fGIggu/OpAokLS7UVPe+A== + +"@eva-design/processor@^2.2.0": + version "2.2.0" + resolved "https://registry.npmjs.org/@eva-design/processor/-/processor-2.2.0.tgz" + integrity sha512-fEvjvilmF/R9dqXDiMoaoXxrPIb5s1APVXbacXKAxjlWl231rzOxc5sdTtJPoFTTEon5KeaKwLHtbQvz5eVvIA== + +"@hapi/hoek@^9.0.0": + version "9.3.0" + resolved "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@humanwhocodes/config-array@^0.11.11": + version "0.11.11" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz" + integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/create-cache-key-function@^29.2.1": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz" + integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== + dependencies: + "@jest/types" "^29.6.3" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0", "@jest/globals@>= 28": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.3": + version "0.3.5" + resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.19" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + version "5.1.1-v1" + resolved "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz" + integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== + dependencies: + eslint-scope "5.1.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@react-native-async-storage/async-storage@^1.19.3": + version "1.19.3" + resolved "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.19.3.tgz" + integrity sha512-CwGfoHCWdPOTPS+2fW6YRE1fFBpT9++ahLEroX5hkgwyoQ+TkmjOaUxixdEIoVua9Pz5EF2pGOIJzqOTMWfBlA== + dependencies: + merge-options "^3.0.4" + +"@react-native-community/cli-clean@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-11.3.7.tgz" + integrity sha512-twtsv54ohcRyWVzPXL3F9VHGb4Qhn3slqqRs3wEuRzjR7cTmV2TIO2b1VhaqF4HlCgNd+cGuirvLtK2JJyaxMg== + dependencies: + "@react-native-community/cli-tools" "11.3.7" + chalk "^4.1.2" + execa "^5.0.0" + prompts "^2.4.0" + +"@react-native-community/cli-config@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-11.3.7.tgz" + integrity sha512-FDBLku9xskS+bx0YFJFLCmUJhEZ4/MMSC9qPYOGBollWYdgE7k/TWI0IeYFmMALAnbCdKQAYP5N29N55Tad8lg== + dependencies: + "@react-native-community/cli-tools" "11.3.7" + chalk "^4.1.2" + cosmiconfig "^5.1.0" + deepmerge "^4.3.0" + glob "^7.1.3" + joi "^17.2.1" + +"@react-native-community/cli-debugger-ui@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-11.3.7.tgz" + integrity sha512-aVmKuPKHZENR8SrflkMurZqeyLwbKieHdOvaZCh1Nn/0UC5CxWcyST2DB2XQboZwsvr3/WXKJkSUO+SZ1J9qTQ== + dependencies: + serve-static "^1.13.1" + +"@react-native-community/cli-doctor@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-11.3.7.tgz" + integrity sha512-YEHUqWISOHnsl5+NM14KHelKh68Sr5/HeEZvvNdIcvcKtZic3FU7Xd1WcbNdo3gCq5JvzGFfufx02Tabh5zmrg== + dependencies: + "@react-native-community/cli-config" "11.3.7" + "@react-native-community/cli-platform-android" "11.3.7" + "@react-native-community/cli-platform-ios" "11.3.7" + "@react-native-community/cli-tools" "11.3.7" + chalk "^4.1.2" + command-exists "^1.2.8" + envinfo "^7.7.2" + execa "^5.0.0" + hermes-profile-transformer "^0.0.6" + ip "^1.1.5" + node-stream-zip "^1.9.1" + ora "^5.4.1" + prompts "^2.4.0" + semver "^7.5.2" + strip-ansi "^5.2.0" + sudo-prompt "^9.0.0" + wcwidth "^1.0.1" + yaml "^2.2.1" + +"@react-native-community/cli-hermes@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-11.3.7.tgz" + integrity sha512-chkKd8n/xeZkinRvtH6QcYA8rjNOKU3S3Lw/3Psxgx+hAYV0Gyk95qJHTalx7iu+PwjOOqqvCkJo5jCkYLkoqw== + dependencies: + "@react-native-community/cli-platform-android" "11.3.7" + "@react-native-community/cli-tools" "11.3.7" + chalk "^4.1.2" + hermes-profile-transformer "^0.0.6" + ip "^1.1.5" + +"@react-native-community/cli-platform-android@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-11.3.7.tgz" + integrity sha512-WGtXI/Rm178UQb8bu1TAeFC/RJvYGnbHpULXvE20GkmeJ1HIrMjkagyk6kkY3Ej25JAP2R878gv+TJ/XiRhaEg== + dependencies: + "@react-native-community/cli-tools" "11.3.7" + chalk "^4.1.2" + execa "^5.0.0" + glob "^7.1.3" + logkitty "^0.7.1" + +"@react-native-community/cli-platform-ios@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-11.3.7.tgz" + integrity sha512-Z/8rseBput49EldX7MogvN6zJlWzZ/4M97s2P+zjS09ZoBU7I0eOKLi0N9wx+95FNBvGQQ/0P62bB9UaFQH2jw== + dependencies: + "@react-native-community/cli-tools" "11.3.7" + chalk "^4.1.2" + execa "^5.0.0" + fast-xml-parser "^4.0.12" + glob "^7.1.3" + ora "^5.4.1" + +"@react-native-community/cli-plugin-metro@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-11.3.7.tgz" + integrity sha512-0WhgoBVGF1f9jXcuagQmtxpwpfP+2LbLZH4qMyo6OtYLWLG13n2uRep+8tdGzfNzl1bIuUTeE9yZSAdnf9LfYQ== + dependencies: + "@react-native-community/cli-server-api" "11.3.7" + "@react-native-community/cli-tools" "11.3.7" + chalk "^4.1.2" + execa "^5.0.0" + metro "0.76.8" + metro-config "0.76.8" + metro-core "0.76.8" + metro-react-native-babel-transformer "0.76.8" + metro-resolver "0.76.8" + metro-runtime "0.76.8" + readline "^1.3.0" + +"@react-native-community/cli-server-api@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-11.3.7.tgz" + integrity sha512-yoFyGdvR3HxCnU6i9vFqKmmSqFzCbnFSnJ29a+5dppgPRetN+d//O8ard/YHqHzToFnXutAFf2neONn23qcJAg== + dependencies: + "@react-native-community/cli-debugger-ui" "11.3.7" + "@react-native-community/cli-tools" "11.3.7" + compression "^1.7.1" + connect "^3.6.5" + errorhandler "^1.5.1" + nocache "^3.0.1" + pretty-format "^26.6.2" + serve-static "^1.13.1" + ws "^7.5.1" + +"@react-native-community/cli-tools@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-11.3.7.tgz" + integrity sha512-peyhP4TV6Ps1hk+MBHTFaIR1eI3u+OfGBvr5r0wPwo3FAJvldRinMgcB/TcCcOBXVORu7ba1XYjkubPeYcqAyA== + dependencies: + appdirsjs "^1.2.4" + chalk "^4.1.2" + find-up "^5.0.0" + mime "^2.4.1" + node-fetch "^2.6.0" + open "^6.2.0" + ora "^5.4.1" + semver "^7.5.2" + shell-quote "^1.7.3" + +"@react-native-community/cli-types@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-11.3.7.tgz" + integrity sha512-OhSr/TiDQkXjL5YOs8+hvGSB+HltLn5ZI0+A3DCiMsjUgTTsYh+Z63OtyMpNjrdCEFcg0MpfdU2uxstCS6Dc5g== + dependencies: + joi "^17.2.1" + +"@react-native-community/cli@11.3.7": + version "11.3.7" + resolved "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.7.tgz" + integrity sha512-Ou8eDlF+yh2rzXeCTpMPYJ2fuqsusNOhmpYPYNQJQ2h6PvaF30kPomflgRILems+EBBuggRtcT+I+1YH4o/q6w== + dependencies: + "@react-native-community/cli-clean" "11.3.7" + "@react-native-community/cli-config" "11.3.7" + "@react-native-community/cli-debugger-ui" "11.3.7" + "@react-native-community/cli-doctor" "11.3.7" + "@react-native-community/cli-hermes" "11.3.7" + "@react-native-community/cli-plugin-metro" "11.3.7" + "@react-native-community/cli-server-api" "11.3.7" + "@react-native-community/cli-tools" "11.3.7" + "@react-native-community/cli-types" "11.3.7" + chalk "^4.1.2" + commander "^9.4.1" + execa "^5.0.0" + find-up "^4.1.0" + fs-extra "^8.1.0" + graceful-fs "^4.1.3" + prompts "^2.4.0" + semver "^7.5.2" + +"@react-native-community/datetimepicker@^7.6.0", "@react-native-community/datetimepicker@>=6.7.0": + version "7.6.0" + resolved "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-7.6.0.tgz" + integrity sha512-JRQb4bccIWXRV3UWr6ShxtZLhMVHBaV8Fq6fJk0AAysZ35F1U0MdSkRd7eyJWd3JUebsi32j1GK3mdKHoabtrw== + dependencies: + invariant "^2.2.4" + +"@react-native-cookies/cookies@^6.2.1": + version "6.2.1" + resolved "https://registry.npmjs.org/@react-native-cookies/cookies/-/cookies-6.2.1.tgz" + integrity sha512-D17wCA0DXJkGJIxkL74Qs9sZ3sA+c+kCoGmXVknW7bVw/W+Vv1m/7mWTNi9DLBZSRddhzYw8SU0aJapIaM/g5w== + dependencies: + invariant "^2.2.4" + +"@react-native/assets-registry@^0.72.0": + version "0.72.0" + resolved "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.72.0.tgz" + integrity sha512-Im93xRJuHHxb1wniGhBMsxLwcfzdYreSZVQGDoMJgkd6+Iky61LInGEHnQCTN0fKNYF1Dvcofb4uMmE1RQHXHQ== + +"@react-native/codegen@^0.72.7": + version "0.72.7" + resolved "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.72.7.tgz" + integrity sha512-O7xNcGeXGbY+VoqBGNlZ3O05gxfATlwE1Q1qQf5E38dK+tXn5BY4u0jaQ9DPjfE8pBba8g/BYI1N44lynidMtg== + dependencies: + "@babel/parser" "^7.20.0" + flow-parser "^0.206.0" + jscodeshift "^0.14.0" + nullthrows "^1.1.1" + +"@react-native/eslint-config@^0.72.2": + version "0.72.2" + resolved "https://registry.npmjs.org/@react-native/eslint-config/-/eslint-config-0.72.2.tgz" + integrity sha512-rAYuQQXzi63W7+9Pu/+23od/b/lTSzHjMFibum3sKgdG2LIyvhoMEWQ5+Chu7TqebqYy1b9SDn/KEMHvpWFtNg== + dependencies: + "@babel/core" "^7.20.0" + "@babel/eslint-parser" "^7.20.0" + "@react-native/eslint-plugin" "^0.72.0" + "@typescript-eslint/eslint-plugin" "^5.30.5" + "@typescript-eslint/parser" "^5.30.5" + eslint-config-prettier "^8.5.0" + eslint-plugin-eslint-comments "^3.2.0" + eslint-plugin-ft-flow "^2.0.1" + eslint-plugin-jest "^26.5.3" + eslint-plugin-prettier "^4.2.1" + eslint-plugin-react "^7.30.1" + eslint-plugin-react-hooks "^4.6.0" + eslint-plugin-react-native "^4.0.0" + +"@react-native/eslint-plugin@^0.72.0": + version "0.72.0" + resolved "https://registry.npmjs.org/@react-native/eslint-plugin/-/eslint-plugin-0.72.0.tgz" + integrity sha512-xWQthnyKd+H22TBqeJUTFebsyWAAwzUb7EQCT8F/WMZsS1sv5UG+2cM/cU9/2HEbVZgxHYuLIi915WznjKPvlg== + +"@react-native/gradle-plugin@^0.72.11": + version "0.72.11" + resolved "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.72.11.tgz" + integrity sha512-P9iRnxiR2w7EHcZ0mJ+fmbPzMby77ZzV6y9sJI3lVLJzF7TLSdbwcQyD3lwMsiL+q5lKUHoZJS4sYmih+P2HXw== + +"@react-native/js-polyfills@^0.72.1": + version "0.72.1" + resolved "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.72.1.tgz" + integrity sha512-cRPZh2rBswFnGt5X5EUEPs0r+pAsXxYsifv/fgy9ZLQokuT52bPH+9xjDR+7TafRua5CttGW83wP4TntRcWNDA== + +"@react-native/metro-config@^0.72.11": + version "0.72.11" + resolved "https://registry.npmjs.org/@react-native/metro-config/-/metro-config-0.72.11.tgz" + integrity sha512-661EyQnDdVelyc0qP/ew7kKkGAh6N6KlkuPLC2SQ8sxaXskVU6fSuNlpLW4bUTBUDFKG8gEOU2hp6rzk4wQnGQ== + dependencies: + "@react-native/js-polyfills" "^0.72.1" + metro-config "0.76.8" + metro-react-native-babel-transformer "0.76.8" + metro-runtime "0.76.8" + +"@react-native/normalize-colors@*", "@react-native/normalize-colors@^0.72.0": + version "0.72.0" + resolved "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.72.0.tgz" + integrity sha512-285lfdqSXaqKuBbbtP9qL2tDrfxdOFtIMvkKadtleRQkdOxx+uzGvFr82KHmc/sSiMtfXGp7JnFYWVh4sFl7Yw== + +"@react-native/virtualized-lists@^0.72.8": + version "0.72.8" + resolved "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.72.8.tgz" + integrity sha512-J3Q4Bkuo99k7mu+jPS9gSUSgq+lLRSI/+ahXNwV92XgJ/8UgOTxu2LPwhJnBk/sQKxq7E8WkZBnBiozukQMqrw== + dependencies: + invariant "^2.2.4" + nullthrows "^1.1.1" + +"@react-navigation/bottom-tabs@^6.5.9": + version "6.5.9" + resolved "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.9.tgz" + integrity sha512-366D4pwq41qKqzsrEk3OPW9atTQJrfrLHPJhX3NLOinRIuDrxal1jJwN3vzNZoEg7gIEKaPYckuqUKg0zRFdog== + dependencies: + "@react-navigation/elements" "^1.3.19" + color "^4.2.3" + warn-once "^0.1.0" + +"@react-navigation/core@^6.4.9": + version "6.4.9" + resolved "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.9.tgz" + integrity sha512-G9GH7bP9x0qqupxZnkSftnkn4JoXancElTvFc8FVGfEvxnxP+gBo3wqcknyBi7M5Vad4qecsYjCOa9wqsftv9g== + dependencies: + "@react-navigation/routers" "^6.1.9" + escape-string-regexp "^4.0.0" + nanoid "^3.1.23" + query-string "^7.1.3" + react-is "^16.13.0" + use-latest-callback "^0.1.5" + +"@react-navigation/elements@^1.3.19": + version "1.3.19" + resolved "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.19.tgz" + integrity sha512-7hLvSYKPuDS070pza5gd43WDX7QgfuEmuTWNbCJhKdWlLudYmq3qzxGCBwCfO2dEI6+p8tla5wruaWiGKAbTYw== + +"@react-navigation/native-stack@^6.9.14": + version "6.9.14" + resolved "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.14.tgz" + integrity sha512-7RiZkvMFN6f0kmANc63B/0m9ttQ2JpDIPWQwPU93FP698s19KTOyu7uxgl7Oi3bvsqHFO5JfiR7B+4h8lh9dxw== + dependencies: + "@react-navigation/elements" "^1.3.19" + warn-once "^0.1.0" + +"@react-navigation/native@^6.0.0", "@react-navigation/native@^6.1.8": + version "6.1.8" + resolved "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.8.tgz" + integrity sha512-0alti852nV+8oCVm9H80G6kZvrHoy51+rXBvVCRUs2rNDDozC/xPZs8tyeCJkqdw3cpxZDK8ndXF22uWq28+0Q== + dependencies: + "@react-navigation/core" "^6.4.9" + escape-string-regexp "^4.0.0" + fast-deep-equal "^3.1.3" + nanoid "^3.1.23" + +"@react-navigation/routers@^6.1.9": + version "6.1.9" + resolved "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz" + integrity sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA== + dependencies: + nanoid "^3.1.23" + +"@react-navigation/stack@^6.3.18": + version "6.3.18" + resolved "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.18.tgz" + integrity sha512-jAXneaLAs57xvyMFkebEyGCZDyz90KnaN7fM9f5Bu+Gx3KnoppdNfT4drpmN/f5f32L0eXS4aRAvuDrFT1mFfw== + dependencies: + "@react-navigation/elements" "^1.3.19" + color "^4.2.3" + warn-once "^0.1.0" + +"@ronradtke/react-native-markdown-display@^8.0.0": + version "8.0.0" + resolved "https://registry.npmjs.org/@ronradtke/react-native-markdown-display/-/react-native-markdown-display-8.0.0.tgz" + integrity sha512-i56CYXGXWDGN+dxF72dGiEn4Kld0L6c/JvcOrO4azX9YzVVl02F5EDgdb6fWUaiOl8gPqyUI7YIEU2OVGnIg6Q== + dependencies: + css-to-react-native "^3.2.0" + markdown-it "^13.0.1" + prop-types "^15.7.2" + react-native-fit-image "^1.5.5" + +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@testing-library/dom@^9.0.0": + version "9.3.3" + resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz" + integrity sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^5.0.1" + aria-query "5.1.3" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.5.0" + pretty-format "^27.0.2" + +"@testing-library/jest-dom@^6.1.3": + version "6.1.3" + resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.3.tgz" + integrity sha512-YzpjRHoCBWPzpPNtg6gnhasqtE/5O4qz8WCwDEaxtfnPO6gkaLrnuXusrGSPyhIGPezr1HM7ZH0CFaUTY9PJEQ== + dependencies: + "@adobe/css-tools" "^4.3.0" + "@babel/runtime" "^7.9.2" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.5.6" + lodash "^4.17.15" + redent "^3.0.0" + +"@testing-library/jest-native@^5.4.3": + version "5.4.3" + resolved "https://registry.npmjs.org/@testing-library/jest-native/-/jest-native-5.4.3.tgz" + integrity sha512-/sSDGaOuE+PJ1Z9Kp4u7PQScSVVXGud59I/qsBFFJvIbcn4P6yYw6cBnBmbPF+X9aRIsTJRDl6gzw5ZkJNm66w== + dependencies: + chalk "^4.1.2" + jest-diff "^29.0.1" + jest-matcher-utils "^29.0.1" + pretty-format "^29.0.3" + redent "^3.0.0" + +"@testing-library/react-native@^12.3.0": + version "12.3.0" + resolved "https://registry.npmjs.org/@testing-library/react-native/-/react-native-12.3.0.tgz" + integrity sha512-E2Prl8D/ey9sRgzLyfCPPmqvsevJW5tVUy4E/pBbO7nOP6OzI/jn2P3vctn/kFdkPY2aE/udlU5ZeNAben9U2A== + dependencies: + jest-matcher-utils "^29.6.2" + pretty-format "^29.6.2" + redent "^3.0.0" + +"@testing-library/react@^14.0.0": + version "14.0.0" + resolved "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz" + integrity sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg== + dependencies: + "@babel/runtime" "^7.12.5" + "@testing-library/dom" "^9.0.0" + "@types/react-dom" "^18.0.0" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@tsconfig/react-native@^3.0.0": + version "3.0.2" + resolved "https://registry.npmjs.org/@tsconfig/react-native/-/react-native-3.0.2.tgz" + integrity sha512-F7IoHEqf741lut4Z2K+IkWQRvXAhBiZMeY5L7BysG7Z2Z3MlIyFR+AagD8jQ/CqC1vowGnRwfLjeuwIpaeoJxA== + +"@types/aria-query@^5.0.1": + version "5.0.2" + resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.2.tgz" + integrity sha512-PHKZuMN+K5qgKIWhBodXzQslTo5P+K/6LqeKXS6O/4liIDdZqaX5RXrCK++LAw+y/nptN48YmUMFiQHRSWYwtQ== + +"@types/babel__core@^7.1.14": + version "7.20.2" + resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz" + integrity sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.5" + resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz" + integrity sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.2" + resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz" + integrity sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.2" + resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz" + integrity sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw== + dependencies: + "@babel/types" "^7.20.7" + +"@types/graceful-fs@^4.1.3": + version "4.1.7" + resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz" + integrity sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw== + dependencies: + "@types/node" "*" + +"@types/hammerjs@^2.0.36": + version "2.0.42" + resolved "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.42.tgz" + integrity sha512-Xxk14BrwHnGi0xlURPRb+Y0UNn2w3cTkeFm7pKMsYOaNgH/kabbJLhcBoNIodwsbTz7Z8KcWjtDvlGH0nc0U9w== + +"@types/he@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@types/he/-/he-1.2.1.tgz" + integrity sha512-CdNmJMcSqX1BiP3iSsWt+VgixndRIDGzWyaGpBnW3i5heATSk5bJu2j3buutsoBQNjyryqxaNpr8M7fRsGL15w== + +"@types/hoist-non-react-statics@^3.3.1": + version "3.3.2" + resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + integrity sha512-YIQtIg4PKr7ZyqNPZObpxfHsHEmuB8dXCxd6qVcGuQVDK2bpsF7bYNnBJ4Nn7giuACZg+WewExgrtAJ3XnA4Xw== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + +"@types/i18n-js@^3.8.5": + version "3.8.5" + resolved "https://registry.npmjs.org/@types/i18n-js/-/i18n-js-3.8.5.tgz" + integrity sha512-6LlMVfkAW8gwcgxIRjxuWxjhD+hw4Mj2VC609FpYCG5n8usb2GE2xbKsEQXWmAIe6LBN2OOw7HnSjZqMDHVtDw== + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.1" + resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" + integrity sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.2" + resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz" + integrity sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.5.5", "@types/jest@>= 28": + version "29.5.5" + resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz" + integrity sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/jsdom@^20.0.0": + version "20.0.1" + resolved "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz" + integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" + +"@types/json-schema@^7.0.9": + version "7.0.13" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz" + integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== + +"@types/luxon@^3.3.2": + version "3.3.2" + resolved "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.2.tgz" + integrity sha512-l5cpE57br4BIjK+9BSkFBOsWtwv6J9bJpC7gdXIzZyI0vuKvNTk0wZZrkQxMGsUAuGW9+WMNWF2IJMD7br2yeQ== + +"@types/node@*": + version "20.7.0" + resolved "https://registry.npmjs.org/@types/node/-/node-20.7.0.tgz" + integrity sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg== + +"@types/prop-types@*": + version "15.7.7" + resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.7.tgz" + integrity sha512-FbtmBWCcSa2J4zL781Zf1p5YUBXQomPEcep9QZCfRfQgTxz3pJWiDFLebohZ9fFntX5ibzOkSsrJ0TEew8cAog== + +"@types/react-dom@^16.8 || ^17.0 || ^18.0", "@types/react-dom@^18.0.0": + version "18.2.10" + resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.10.tgz" + integrity sha512-5VEC5RgXIk1HHdyN1pHlg0cOqnxHzvPGpMMyGAP5qSaDRmyZNDaQ0kkVAkK6NYlDhP6YBID3llaXlmAS/mdgCA== + dependencies: + "@types/react" "*" + +"@types/react-test-renderer@^18.0.0": + version "18.0.2" + resolved "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.0.2.tgz" + integrity sha512-tJzMn+9GHDrdrLe0O4rwJELDfTrmdJbCn/UdYyzjlnPiXYXDl5FBNzdw4PVk2R3hJvSHKFjZcRgvZc12lV0p5Q== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^16.8 || ^17.0 || ^18.0", "@types/react@^18.0.24", "@types/react@>=16.8": + version "18.2.23" + resolved "https://registry.npmjs.org/@types/react/-/react-18.2.23.tgz" + integrity sha512-qHLW6n1q2+7KyBEYnrZpcsAmU/iiCh9WGCKgXvMxx89+TYdJWRjZohVIo9XTcoLhfX3+/hP0Pbulu3bCZQ9PSA== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.4" + resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.4.tgz" + integrity sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ== + +"@types/semver@^7.3.12": + version "7.5.3" + resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz" + integrity sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw== + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/tough-cookie@*": + version "4.0.3" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.3.tgz" + integrity sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg== + +"@types/use-sync-external-store@^0.0.3": + version "0.0.3" + resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz" + integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== + +"@types/yargs-parser@*": + version "21.0.1" + resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz" + integrity sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ== + +"@types/yargs@^15.0.0": + version "15.0.16" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.16.tgz" + integrity sha512-2FeD5qezW3FvLpZ0JpfuaEWepgNLl9b2gQYiz/ce0NhoB1W/D+VZu98phITXkADYerfr/jb7JcDcVhITsc9bwg== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^16.0.0": + version "16.0.6" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.6.tgz" + integrity sha512-oTP7/Q13GSPrgcwEwdlnkoZSQ1Hg9THe644qq8PG6hhJzjZ3qj1JjEFPIwWV/IXVs5XGIVqtkNOS9kh63WIJ+A== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^17.0.8": + version "17.0.25" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz" + integrity sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^5.0.0", "@typescript-eslint/eslint-plugin@^5.30.5": + version "5.62.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.30.5": + version "5.62.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== + dependencies: + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== + dependencies: + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.62.0": + 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@5.62.0": + 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" + +"@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@5.62.0": + version "5.62.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + 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" + +"@typescript-eslint/visitor-keys@5.62.0": + 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" + +"@ui-kitten/components@^5.3.1", "@ui-kitten/components@5.3.1": + version "5.3.1" + resolved "https://registry.npmjs.org/@ui-kitten/components/-/components-5.3.1.tgz" + integrity sha512-Oj1WePUQtpNfH7ftXGdkkFVmJI+JcR3cBryPJV0E+JAUdH2dbJ0oG/VA+UAgk27/u0K0OZSUkdMFuGnkDAVuYA== + dependencies: + "@eva-design/dss" "^2.2.0" + "@eva-design/processor" "^2.2.0" + fecha "3.0.3" + hoist-non-react-statics "^3.2.1" + lodash.merge "^4.6.1" + +"@ui-kitten/eva-icons@^5.3.1": + version "5.3.1" + resolved "https://registry.npmjs.org/@ui-kitten/eva-icons/-/eva-icons-5.3.1.tgz" + integrity sha512-7pFbEiF2vdcMGbb/6/vg0Xy/hZ3js4nFNjZTNEQPaynnndstabNW0MSRokPWYaW6EcxP77LVOsfdShtjQm7kIg== + dependencies: + react-native-eva-icons "^1.3.1" + +abab@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz" + integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== + dependencies: + acorn "^8.1.0" + acorn-walk "^8.0.2" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.0.2: + version "8.2.0" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.1.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +agent-base@6: + version "6.0.2" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.12.3, ajv@^6.12.4: + 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" + +anser@^1.4.9: + version "1.4.10" + resolved "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz" + integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-fragments@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz" + integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== + dependencies: + colorette "^1.0.7" + slice-ansi "^2.0.0" + strip-ansi "^5.0.0" + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-regex@^5.0.0, ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +appdirsjs@^1.2.4: + version "1.2.7" + resolved "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz" + integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== + +arch@^2.1.0: + version "2.2.0" + resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + 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@^5.0.0, aria-query@5.1.3: + version "5.1.3" + resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz" + integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== + dependencies: + deep-equal "^2.0.5" + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.6: + 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" + +array-union@^2.1.0: + 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.flat@^1.3.1: + 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" + +array.prototype.flatmap@^1.3.1: + 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" + +array.prototype.tosorted@^1.1.1: + version "1.1.2" + resolved "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz" + integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + +asap@^2.0.0, asap@~2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@^1.0.0, assert-plus@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +ast-types@0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz" + integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg== + dependencies: + tslib "^2.0.1" + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^3.2.2: + version "3.2.4" + resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + +asynciterator.prototype@^1.0.0: + 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" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.12.0" + resolved "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== + +babel-core@^7.0.0-bridge.0: + version "7.0.0-bridge.0" + resolved "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz" + integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-module-resolver@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz" + integrity sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q== + dependencies: + find-babel-config "^2.0.0" + glob "^8.0.3" + pkg-up "^3.1.0" + reselect "^4.1.7" + resolve "^1.22.1" + +babel-plugin-polyfill-corejs2@^0.4.5, babel-plugin-polyfill-corejs2@^0.4.6: + version "0.4.6" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz" + integrity sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.4.3" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.8.3, babel-plugin-polyfill-corejs3@^0.8.5: + version "0.8.5" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.5.tgz" + integrity sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.3" + core-js-compat "^3.32.2" + +babel-plugin-polyfill-regenerator@^0.5.2, babel-plugin-polyfill-regenerator@^0.5.3: + version "0.5.3" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz" + integrity sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.3" + +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + +babel-plugin-transform-flow-enums@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz" + integrity sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ== + dependencies: + "@babel/plugin-syntax-flow" "^7.12.1" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-fbjs@^3.4.0: + version "3.4.0" + resolved "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz" + integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.1.2, base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.21.10, browserslist@^4.21.9, "browserslist@>= 4.21.0": + version "4.22.0" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz" + integrity sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA== + dependencies: + caniuse-lite "^1.0.30001539" + electron-to-chromium "^1.4.530" + node-releases "^2.0.13" + update-browserslist-db "^1.0.13" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase-keys@^7.0.1: + version "7.0.2" + resolved "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz" + integrity sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg== + dependencies: + camelcase "^6.3.0" + map-obj "^4.1.0" + quick-lru "^5.1.1" + type-fest "^1.2.1" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +camelcase@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +camelize@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz" + integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== + +caniuse-lite@^1.0.30001539: + version "1.0.30001540" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001540.tgz" + integrity sha512-9JL38jscuTJBTcuETxm8QLsFr/F6v0CYYTEU6r5+qSM98P2Q0Hmu0eG1dTG5GBUmywU3UlcVOUSIJYY47rdFSw== + +capital-case@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz" + integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +change-case@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz" + integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== + dependencies: + camel-case "^4.1.2" + capital-case "^1.0.4" + constant-case "^3.0.4" + dot-case "^3.0.4" + header-case "^2.0.4" + no-case "^3.0.4" + param-case "^3.0.4" + pascal-case "^3.1.2" + path-case "^3.0.4" + sentence-case "^3.0.4" + snake-case "^3.0.4" + tslib "^2.0.3" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0: + version "3.8.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== + +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.1" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz" + integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ== + +clipboardy@~1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz" + integrity sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA== + dependencies: + arch "^2.1.0" + execa "^0.8.0" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^8.0.1: + 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== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@^1.0.0, color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + +colorette@^1.0.7: + version "1.4.0" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@^2.20.0, commander@^2.9.0: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +commander@^9.4.1: + version "9.5.0" + resolved "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +commander@~2.13.0: + version "2.13.0" + resolved "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz" + integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.1: + version "1.7.4" + resolved "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +connect@^3.6.5: + version "3.7.0" + resolved "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +constant-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz" + integrity sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case "^2.0.2" + +convert-source-map@^1.6.0: + version "1.9.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-js-compat@^3.31.0, core-js-compat@^3.32.2: + version "3.32.2" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz" + integrity sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ== + dependencies: + browserslist "^4.21.10" + +core-util-is@~1.0.0, core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: + version "5.2.1" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz" + integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz" + integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-to-react-native@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz" + integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + +css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +csstype@^3.0.2: + version "3.1.2" + resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +data-urls@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== + dependencies: + abab "^2.0.6" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + +dayjs@^1.8.15: + version "1.11.10" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz" + integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== + +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@4: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debuglog@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz" + integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw== + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decimal.js@^10.4.2: + version "10.4.3" + resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + +decode-uri-component@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + +deep-equal@^2.0.5: + version "2.2.2" + resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz" + integrity sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + es-get-iterator "^1.1.3" + get-intrinsic "^1.2.1" + is-arguments "^1.1.1" + is-array-buffer "^3.0.2" + is-date-object "^1.0.5" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + isarray "^2.0.5" + object-is "^1.1.5" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.0" + side-channel "^1.0.4" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.9" + +deep-is@^0.1.3: + 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== + +deepmerge@^2.1.1: + version "2.2.1" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz" + integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +deepmerge@^4.3.0: + version "4.3.1" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +define-data-property@^1.0.1: + version "1.1.0" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz" + integrity sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: + 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" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz" + integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +deprecated-react-native-prop-types@4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.1.0.tgz" + integrity sha512-WfepZHmRbbdTvhcolb8aOKEvQdcmTMn5tKLbqbXmkBvjFjRVWAYqsXk/DBsV8TZxws8SdGHLuHaJrHSQUPRdfw== + dependencies: + "@react-native/normalize-colors" "*" + invariant "*" + prop-types "*" + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +dezalgo@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz" + integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== + dependencies: + asap "^2.0.0" + wrappy "1" + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9: + version "0.5.16" + resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz" + integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +domelementtype@^1.3.1, domelementtype@1: + version "1.3.1" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.3.0" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== + dependencies: + webidl-conversions "^7.0.0" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.530: + version "1.4.531" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.531.tgz" + integrity sha512-H6gi5E41Rn3/mhKlPaT1aIMg/71hTAqn0gYEllSuw9igNWtvQwu185jiCZoZD29n7Zukgh7GVZ3zGf0XvkhqjQ== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +entities@^1.1.1: + version "1.1.2" + resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +entities@^4.2.0: + version "4.5.0" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +entities@~3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" + integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== + +envinfo@^7.7.2: + version "7.10.0" + resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz" + integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + +errorhandler@^1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz" + integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A== + dependencies: + accepts "~1.3.7" + escape-html "~1.0.3" + +es-abstract@^1.22.1: + version "1.22.2" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz" + integrity sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.1" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.11" + +es-get-iterator@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz" + integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + is-arguments "^1.1.1" + is-map "^2.0.2" + is-set "^2.0.2" + is-string "^1.0.7" + isarray "^2.0.5" + stop-iteration-iterator "^1.0.0" + +es-iterator-helpers@^1.0.12: + version "1.0.15" + resolved "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz" + integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== + dependencies: + asynciterator.prototype "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.1" + es-abstract "^1.22.1" + es-set-tostringtag "^2.0.1" + function-bind "^1.1.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + iterator.prototype "^1.1.2" + safe-array-concat "^1.0.1" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + 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" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-prettier@^8.5.0: + version "8.10.0" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== + +eslint-plugin-eslint-comments@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz" + integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== + dependencies: + escape-string-regexp "^1.0.5" + ignore "^5.0.5" + +eslint-plugin-ft-flow@^2.0.1: + version "2.0.3" + resolved "https://registry.npmjs.org/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz" + integrity sha512-Vbsd/b+LYA99jUbsL6viEUWShFaYQt2YQs3QN3f+aeszOhh2sgdcU0mjzDyD4yyBvMc8qy2uwvBBWfMzEX06tg== + dependencies: + lodash "^4.17.21" + string-natural-compare "^3.0.1" + +eslint-plugin-jest@^26.5.3: + version "26.9.0" + resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz" + integrity sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + +eslint-plugin-prettier@^4.2.1: + version "4.2.1" + resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react-hooks@^4.6.0: + 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== + +eslint-plugin-react-native-globals@^0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz" + integrity sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g== + +eslint-plugin-react-native@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/eslint-plugin-react-native/-/eslint-plugin-react-native-4.1.0.tgz" + integrity sha512-QLo7rzTBOl43FvVqDdq5Ql9IoElIuTdjrz9SKAXCvULvBoRZ44JGSkx9z4999ZusCsb4rK3gjS8gOGyeYqZv2Q== + dependencies: + eslint-plugin-react-native-globals "^0.1.1" + +eslint-plugin-react@^7.30.1: + version "7.33.2" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz" + integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== + dependencies: + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + array.prototype.tosorted "^1.1.1" + doctrine "^2.1.0" + es-iterator-helpers "^1.0.12" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + object.hasown "^1.1.2" + object.values "^1.1.6" + prop-types "^15.8.1" + resolve "^2.0.0-next.4" + semver "^6.3.1" + string.prototype.matchall "^4.0.8" + +eslint-scope@^5.1.1, eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + 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== + +eslint-visitor-keys@^3.4.1: + 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== + +eslint-visitor-keys@^3.4.3: + 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== + +eslint@*, "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.5.0 || ^8.0.0", eslint@^8.1.0, eslint@^8.19.0, eslint@>=4.19.1, eslint@>=7.0.0, eslint@>=7.28.0, eslint@>=8: + version "8.50.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz" + integrity sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.50.0" + "@humanwhocodes/config-array" "^0.11.11" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + 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" + +esm@^3.2.25: + version "3.2.25" + resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz" + integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + 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" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-target-shim@^5.0.0, event-target-shim@^5.0.1: + 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== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz" + integrity sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA== + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + 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" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@^1.2.0, extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + 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@^1.1.2: + version "1.3.0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-fuzzy@^1.12.0: + version "1.12.0" + resolved "https://registry.npmjs.org/fast-fuzzy/-/fast-fuzzy-1.12.0.tgz" + integrity sha512-sXxGgHS+ubYpsdLnvOvJ9w5GYYZrtL9mkosG3nfuD446ahvoWEsSKBP7ieGmWIKVLnaxRDgUJkZMdxRgA2Ni+Q== + dependencies: + graphemesplit "^2.4.1" + +fast-glob@^3.2.9: + version "3.3.1" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + 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" + +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + 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@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-xml-parser@^4.0.12: + version "4.3.1" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.1.tgz" + integrity sha512-viVv3xb8D+SiS1W4cv4tva3bni08kAkx0gQnWrykMM8nXPc1FxqZPU00dCEVjkiCg4HoXd2jC4x29Nzg/l2DAA== + dependencies: + strnum "^1.0.5" + +fastq@^1.6.0: + 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" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fecha@3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/fecha/-/fecha-3.0.3.tgz" + integrity sha512-6LQK/1jud/FZnfEEZJ7y81vw7ge81DNd/XEsX0hgMUjhS+QMljkb1C0czBaP7dMNRVrd5mw/J2J7qI2Nw+TWZw== + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-babel-config@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.0.0.tgz" + integrity sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw== + dependencies: + json5 "^2.1.1" + path-exists "^4.0.0" + +find-cache-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.1.0" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz" + integrity sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew== + dependencies: + flatted "^3.2.7" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.7: + version "3.2.9" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + +flow-enums-runtime@^0.0.5: + version "0.0.5" + resolved "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.5.tgz" + integrity sha512-PSZF9ZuaZD03sT9YaIs0FrGJ7lSUw7rHZIex+73UYVXg46eL/wxN5PaVcPJFudE2cJu5f0fezitV5aBkLHPUOQ== + +flow-parser@^0.206.0, flow-parser@0.*: + version "0.206.0" + resolved "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz" + integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +formik@^2.4.5: + version "2.4.5" + resolved "https://registry.npmjs.org/formik/-/formik-2.4.5.tgz" + integrity sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ== + dependencies: + "@types/hoist-non-react-statics" "^3.3.1" + deepmerge "^2.1.1" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.21" + lodash-es "^4.17.21" + react-fast-compare "^2.0.1" + tiny-warning "^1.0.2" + tslib "^2.0.0" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: + 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" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz" + integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.5: + 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" + +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0: + version "13.22.0" + resolved "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz" + integrity sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + 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" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +graphemesplit@^2.4.1: + version "2.4.4" + resolved "https://registry.npmjs.org/graphemesplit/-/graphemesplit-2.4.4.tgz" + integrity sha512-lKrpp1mk1NH26USxC/Asw4OHbhSQf5XfrWZ+CDv/dFVvd1j17kFgMotdJvOesmHkbFX9P9sBfpH8VogxOWLg8w== + dependencies: + js-base64 "^3.6.0" + unicode-trie "^2.0.0" + +h2m@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/h2m/-/h2m-0.7.0.tgz" + integrity sha512-HxuYZGcbG5lqt9t4YNT1+HuZ6E7CLh0urd5zT4LqoRKCf7VCx0bGzIDOuEdIz6po7XY/Fby6kbOql6ATtBofqg== + dependencies: + clipboardy "~1.2.3" + commander "^2.9.0" + htmlparser2 "^3.9.0" + request "^2.67.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + 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@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + 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@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@^1.2.0, he@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +header-case@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz" + integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q== + dependencies: + capital-case "^1.0.4" + tslib "^2.0.3" + +hermes-estree@0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.12.0.tgz" + integrity sha512-+e8xR6SCen0wyAKrMT3UD0ZCCLymKhRgjEB5sS28rKiFir/fXgLoeRilRUssFCILmGHb+OvHDUlhxs0+IEyvQw== + +hermes-parser@0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.12.0.tgz" + integrity sha512-d4PHnwq6SnDLhYl3LHNHvOg7nQ6rcI7QVil418REYksv0Mh3cEkHDcuhGxNQ3vgnLSLl4QSvDrFCwQNYdpWlzw== + dependencies: + hermes-estree "0.12.0" + +hermes-profile-transformer@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz" + integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== + dependencies: + source-map "^0.7.3" + +hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +htmlparser2@^3.9.0: + version "3.10.1" + resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-proxy-agent@^5.0.0: + 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== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^5.0.1: + 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== + dependencies: + agent-base "6" + debug "4" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +i18n-js@^3.8.0: + version "3.9.2" + resolved "https://registry.npmjs.org/i18n-js/-/i18n-js-3.9.2.tgz" + integrity sha512-+Gm8h5HL0emzKhRx2avMKX+nKiVPXeaOZm7Euf2/pbbFcLQoJ3zZYiUykAzoRasijCoWos2Kl1tslmScTgAQKw== + +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.0.5, ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +image-size@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz" + integrity sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg== + dependencies: + queue "6.0.2" + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.2.1: + 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" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + 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" + +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@2, inherits@2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +install@^0.13.0: + version "0.13.0" + resolved "https://registry.npmjs.org/install/-/install-0.13.0.tgz" + integrity sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA== + +internal-slot@^1.0.4, internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@*, invariant@^2.2.4, invariant@2.2.4: + version "2.2.4" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +ip@^1.1.5: + version "1.1.8" + resolved "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== + +is-arguments@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-async-function@^2.0.0: + 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" + +is-bigint@^1.0.1: + 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" + +is-boolean-object@^1.1.0: + 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" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0, is-core-module@^2.9.0: + version "2.13.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1, is-date-object@^1.0.5: + 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" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.0.2: + 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" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + 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== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-generator-function@^1.0.10: + 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" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + 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" + +is-interactive@^1.0.0: + 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== + +is-map@^2.0.1, is-map@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz" + integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + 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" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + 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== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-regex@^1.1.4: + 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" + +is-set@^2.0.1, is-set@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz" + integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + 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" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + 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" + +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-weakmap@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz" + integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== + +is-weakref@^1.0.2: + 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" + +is-weakset@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz" + integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz" + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz" + integrity sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.6" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +iterator.prototype@^1.1.2: + 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" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.0.1, jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-jsdom@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz" + integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/jsdom" "^20.0.0" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + jsdom "^20.0.0" + +jest-environment-node@^29.2.1, jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.0.1, jest-matcher-utils@^29.6.2, jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^27.0.6: + version "27.5.1" + resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@*, jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^27.2.0: + version "27.5.1" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.2.1, jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^27.2.0: + version "27.5.1" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.2.1, "jest@>= 28", jest@>=28.0.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +joi@^17.2.1: + version "17.10.2" + resolved "https://registry.npmjs.org/joi/-/joi-17.10.2.tgz" + integrity sha512-hcVhjBxRNW/is3nNLdGLIjkgXetkeGc2wyhydhz8KumG23Aerk4HPjU5zaPAMRqXQFc0xNqXTC7+zQjxr0GlKA== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + +js-base64@^3.6.0: + version "3.7.5" + resolved "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== + +js-htmlencode@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/js-htmlencode/-/js-htmlencode-0.3.0.tgz" + integrity sha512-HedYg9SJsimM4aca37Lj0Ct0eZ1WT8CCxlgMPfUV7mCc6g3UfEUHy2b9qfzuC0uwk4gjVEJKrkWbPSdnUJBFTQ== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +jsc-android@^250231.0.0: + version "250231.0.0" + resolved "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz" + integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== + +jsc-safe-url@^0.2.2: + version "0.2.4" + resolved "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz" + integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q== + +jscodeshift@^0.14.0: + version "0.14.0" + resolved "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz" + integrity sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA== + dependencies: + "@babel/core" "^7.13.16" + "@babel/parser" "^7.13.16" + "@babel/plugin-proposal-class-properties" "^7.13.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" + "@babel/plugin-proposal-optional-chaining" "^7.13.12" + "@babel/plugin-transform-modules-commonjs" "^7.13.8" + "@babel/preset-flow" "^7.13.13" + "@babel/preset-typescript" "^7.13.0" + "@babel/register" "^7.13.16" + babel-core "^7.0.0-bridge.0" + chalk "^4.1.2" + flow-parser "0.*" + graceful-fs "^4.2.4" + micromatch "^4.0.4" + neo-async "^2.5.0" + node-dir "^0.1.17" + recast "^0.21.0" + temp "^0.8.4" + write-file-atomic "^2.3.0" + +jsdom@^20.0.0: + version "20.0.3" + resolved "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz" + integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== + dependencies: + abab "^2.0.6" + acorn "^8.8.1" + acorn-globals "^7.0.0" + cssom "^0.5.0" + cssstyle "^2.3.0" + data-urls "^3.0.2" + decimal.js "^10.4.2" + domexception "^4.0.0" + escodegen "^2.0.0" + form-data "^4.0.0" + html-encoding-sniffer "^3.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.2" + parse5 "^7.1.1" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^4.1.2" + w3c-xmlserializer "^4.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^2.0.0" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + ws "^8.11.0" + xml-name-validator "^4.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-buffer@3.0.1: + 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@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + 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-schema@0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + 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-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.1.1, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + 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" + +keyv@^4.5.3: + version "4.5.3" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz" + integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== + dependencies: + json-buffer "3.0.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + 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" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +linkify-it@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz" + integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw== + dependencies: + uc.micro "^1.0.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.merge@^4.6.1, lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +logkitty@^0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz" + integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== + dependencies: + ansi-fragments "^0.2.1" + dayjs "^1.8.15" + yargs "^15.1.0" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + 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" + +luxon@^3.4.3: + version "3.4.3" + resolved "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz" + integrity sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg== + +lz-string@^1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +map-obj@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + +markdown-it@^13.0.1: + version "13.0.2" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz" + integrity sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w== + dependencies: + argparse "^2.0.1" + entities "~3.0.1" + linkify-it "^4.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +memoize-one@^5.0.0: + version "5.2.1" + resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +metro-babel-transformer@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.76.8.tgz" + integrity sha512-Hh6PW34Ug/nShlBGxkwQJSgPGAzSJ9FwQXhUImkzdsDgVu6zj5bx258J8cJVSandjNoQ8nbaHK6CaHlnbZKbyA== + dependencies: + "@babel/core" "^7.20.0" + hermes-parser "0.12.0" + nullthrows "^1.1.1" + +metro-cache-key@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.76.8.tgz" + integrity sha512-buKQ5xentPig9G6T37Ww/R/bC+/V1MA5xU/D8zjnhlelsrPG6w6LtHUS61ID3zZcMZqYaELWk5UIadIdDsaaLw== + +metro-cache@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-cache/-/metro-cache-0.76.8.tgz" + integrity sha512-QBJSJIVNH7Hc/Yo6br/U/qQDUpiUdRgZ2ZBJmvAbmAKp2XDzsapnMwK/3BGj8JNWJF7OLrqrYHsRsukSbUBpvQ== + dependencies: + metro-core "0.76.8" + rimraf "^3.0.2" + +metro-config@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-config/-/metro-config-0.76.8.tgz" + integrity sha512-SL1lfKB0qGHALcAk2zBqVgQZpazDYvYFGwCK1ikz0S6Y/CM2i2/HwuZN31kpX6z3mqjv/6KvlzaKoTb1otuSAA== + dependencies: + connect "^3.6.5" + cosmiconfig "^5.0.5" + jest-validate "^29.2.1" + metro "0.76.8" + metro-cache "0.76.8" + metro-core "0.76.8" + metro-runtime "0.76.8" + +metro-core@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-core/-/metro-core-0.76.8.tgz" + integrity sha512-sl2QLFI3d1b1XUUGxwzw/KbaXXU/bvFYrSKz6Sg19AdYGWFyzsgZ1VISRIDf+HWm4R/TJXluhWMEkEtZuqi3qA== + dependencies: + lodash.throttle "^4.1.1" + metro-resolver "0.76.8" + +metro-file-map@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.76.8.tgz" + integrity sha512-A/xP1YNEVwO1SUV9/YYo6/Y1MmzhL4ZnVgcJC3VmHp/BYVOXVStzgVbWv2wILe56IIMkfXU+jpXrGKKYhFyHVw== + dependencies: + anymatch "^3.0.3" + debug "^2.2.0" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + invariant "^2.2.4" + jest-regex-util "^27.0.6" + jest-util "^27.2.0" + jest-worker "^27.2.0" + micromatch "^4.0.4" + node-abort-controller "^3.1.1" + nullthrows "^1.1.1" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +metro-inspector-proxy@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-inspector-proxy/-/metro-inspector-proxy-0.76.8.tgz" + integrity sha512-Us5o5UEd4Smgn1+TfHX4LvVPoWVo9VsVMn4Ldbk0g5CQx3Gu0ygc/ei2AKPGTwsOZmKxJeACj7yMH2kgxQP/iw== + dependencies: + connect "^3.6.5" + debug "^2.2.0" + node-fetch "^2.2.0" + ws "^7.5.1" + yargs "^17.6.2" + +metro-minify-terser@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.76.8.tgz" + integrity sha512-Orbvg18qXHCrSj1KbaeSDVYRy/gkro2PC7Fy2tDSH1c9RB4aH8tuMOIXnKJE+1SXxBtjWmQ5Yirwkth2DyyEZA== + dependencies: + terser "^5.15.0" + +metro-minify-uglify@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-minify-uglify/-/metro-minify-uglify-0.76.8.tgz" + integrity sha512-6l8/bEvtVaTSuhG1FqS0+Mc8lZ3Bl4RI8SeRIifVLC21eeSDp4CEBUWSGjpFyUDfi6R5dXzYaFnSgMNyfxADiQ== + dependencies: + uglify-es "^3.1.9" + +metro-react-native-babel-preset@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.76.8.tgz" + integrity sha512-Ptza08GgqzxEdK8apYsjTx2S8WDUlS2ilBlu9DR1CUcHmg4g3kOkFylZroogVAUKtpYQNYwAvdsjmrSdDNtiAg== + dependencies: + "@babel/core" "^7.20.0" + "@babel/plugin-proposal-async-generator-functions" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.18.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" + "@babel/plugin-proposal-numeric-separator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.20.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.20.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.18.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-async-to-generator" "^7.20.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.20.0" + "@babel/plugin-transform-flow-strip-types" "^7.20.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.4.0" + +metro-react-native-babel-transformer@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.76.8.tgz" + integrity sha512-3h+LfS1WG1PAzhq8QF0kfXjxuXetbY/lgz8vYMQhgrMMp17WM1DNJD0gjx8tOGYbpbBC1qesJ45KMS4o5TA73A== + dependencies: + "@babel/core" "^7.20.0" + babel-preset-fbjs "^3.4.0" + hermes-parser "0.12.0" + metro-react-native-babel-preset "0.76.8" + nullthrows "^1.1.1" + +metro-resolver@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.76.8.tgz" + integrity sha512-KccOqc10vrzS7ZhG2NSnL2dh3uVydarB7nOhjreQ7C4zyWuiW9XpLC4h47KtGQv3Rnv/NDLJYeDqaJ4/+140HQ== + +metro-runtime@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.76.8.tgz" + integrity sha512-XKahvB+iuYJSCr3QqCpROli4B4zASAYpkK+j3a0CJmokxCDNbgyI4Fp88uIL6rNaZfN0Mv35S0b99SdFXIfHjg== + dependencies: + "@babel/runtime" "^7.0.0" + react-refresh "^0.4.0" + +metro-source-map@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.76.8.tgz" + integrity sha512-Hh0ncPsHPVf6wXQSqJqB3K9Zbudht4aUtNpNXYXSxH+pteWqGAXnjtPsRAnCsCWl38wL0jYF0rJDdMajUI3BDw== + dependencies: + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" + invariant "^2.2.4" + metro-symbolicate "0.76.8" + nullthrows "^1.1.1" + ob1 "0.76.8" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-symbolicate@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.76.8.tgz" + integrity sha512-LrRL3uy2VkzrIXVlxoPtqb40J6Bf1mlPNmUQewipc3qfKKFgtPHBackqDy1YL0njDsWopCKcfGtFYLn0PTUn3w== + dependencies: + invariant "^2.2.4" + metro-source-map "0.76.8" + nullthrows "^1.1.1" + source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" + +metro-transform-plugins@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.76.8.tgz" + integrity sha512-PlkGTQNqS51Bx4vuufSQCdSn2R2rt7korzngo+b5GCkeX5pjinPjnO2kNhQ8l+5bO0iUD/WZ9nsM2PGGKIkWFA== + dependencies: + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.20.0" + nullthrows "^1.1.1" + +metro-transform-worker@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.76.8.tgz" + integrity sha512-mE1fxVAnJKmwwJyDtThildxxos9+DGs9+vTrx2ktSFMEVTtXS/bIv2W6hux1pqivqAfyJpTeACXHk5u2DgGvIQ== + dependencies: + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" + "@babel/types" "^7.20.0" + babel-preset-fbjs "^3.4.0" + metro "0.76.8" + metro-babel-transformer "0.76.8" + metro-cache "0.76.8" + metro-cache-key "0.76.8" + metro-source-map "0.76.8" + metro-transform-plugins "0.76.8" + nullthrows "^1.1.1" + +metro@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/metro/-/metro-0.76.8.tgz" + integrity sha512-oQA3gLzrrYv3qKtuWArMgHPbHu8odZOD9AoavrqSFllkPgOtmkBvNNDLCELqv5SjBfqjISNffypg+5UGG3y0pg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" + accepts "^1.3.7" + async "^3.2.2" + chalk "^4.0.0" + ci-info "^2.0.0" + connect "^3.6.5" + debug "^2.2.0" + denodeify "^1.2.1" + error-stack-parser "^2.0.6" + graceful-fs "^4.2.4" + hermes-parser "0.12.0" + image-size "^1.0.2" + invariant "^2.2.4" + jest-worker "^27.2.0" + jsc-safe-url "^0.2.2" + lodash.throttle "^4.1.1" + metro-babel-transformer "0.76.8" + metro-cache "0.76.8" + metro-cache-key "0.76.8" + metro-config "0.76.8" + metro-core "0.76.8" + metro-file-map "0.76.8" + metro-inspector-proxy "0.76.8" + metro-minify-terser "0.76.8" + metro-minify-uglify "0.76.8" + metro-react-native-babel-preset "0.76.8" + metro-resolver "0.76.8" + metro-runtime "0.76.8" + metro-source-map "0.76.8" + metro-symbolicate "0.76.8" + metro-transform-plugins "0.76.8" + metro-transform-worker "0.76.8" + mime-types "^2.1.27" + node-fetch "^2.2.0" + nullthrows "^1.1.1" + rimraf "^3.0.2" + serialize-error "^2.1.0" + source-map "^0.5.6" + strip-ansi "^6.0.0" + throat "^5.0.0" + ws "^7.5.1" + yargs "^17.6.2" + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +"mime-db@>= 1.43.0 < 2", mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^2.4.1: + version "2.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + 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" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mockdate@^3.0.5: + version "3.0.5" + resolved "https://registry.npmjs.org/mockdate/-/mockdate-3.0.5.tgz" + integrity sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ== + +moment@^2.29.4: + version "2.29.4" + resolved "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@^3.1.23: + version "3.3.6" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.5.0: + version "2.6.2" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +nocache@^3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz" + integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== + +node-abort-controller@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz" + integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== + +node-blob@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/node-blob/-/node-blob-0.0.2.tgz" + integrity sha512-82wiGzMht96gPQDUYaZBdZEVvYD9aEhU6Bt9KLCr4rADZPRd7dQVY2Yj0ZG/1vp4DhVkL49nJT/M3CiMTAt3ag== + +node-dir@^0.1.17: + version "0.1.17" + resolved "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz" + integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== + dependencies: + minimatch "^3.0.2" + +node-fetch@^2.2.0, node-fetch@^2.6.0: + version "2.7.0" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-html-parser@^6.1.10: + version "6.1.10" + resolved "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.10.tgz" + integrity sha512-6/uWdWxjQWQ7tMcFK2wWlrflsQUzh1HsEzlIf2j5+TtzfhT2yUvg3DwZYAmjEHeR3uX74ko7exjHW69J0tOzIg== + dependencies: + css-select "^5.1.0" + he "1.2.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + +node-stream-zip@^1.9.1: + version "1.15.0" + resolved "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz" + integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== + +normalize-package-data@^2.0.0: + version "2.5.0" + resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-normalize-package-bin@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +nwsapi@^2.2.2: + version "2.2.7" + resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz" + integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +ob1@0.76.8: + version "0.76.8" + resolved "https://registry.npmjs.org/ob1/-/ob1-0.76.8.tgz" + integrity sha512-dlBkJJV5M/msj9KYA9upc+nUWVwuOFFTbu28X6kZeGwcuW+JxaHSBZ70SYQnk5M+j5JbNLR6yKHmgW4M5E7X5g== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-is@^1.1.5: + version "1.1.5" + resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.entries@^1.1.6: + 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" + +object.fromentries@^2.0.6: + 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" + +object.hasown@^1.1.2: + version "1.1.3" + resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz" + integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== + dependencies: + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.values@^1.1.6: + version "1.1.7" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^6.2.0: + version "6.4.0" + resolved "https://registry.npmjs.org/open/-/open-6.4.0.tgz" + integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== + dependencies: + is-wsl "^1.1.0" + +optionator@^0.9.3: + 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" + +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-limit@^2.0.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + 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== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@^0.2.5: + version "0.2.9" + resolved "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz" + integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA== + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +parent-module@^1.0.0: + 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== + dependencies: + callsites "^3.0.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5@^7.0.0, parse5@^7.1.1: + version "7.1.2" + resolved "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz" + integrity sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +path@^0.12.7: + version "0.12.7" + resolved "https://registry.npmjs.org/path/-/path-0.12.7.tgz" + integrity sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q== + dependencies: + process "^0.11.1" + util "^0.10.3" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +personnummer@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/personnummer/-/personnummer-3.2.1.tgz" + integrity sha512-EWDCfUBnXAUtL8/vOF/Ne7Fa12pBsYfMDQKSLK6I4bApx/rZx8rRBqPEtbhihJ2EYrc5lK2FBs7j5rTYfZirtg== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pirates@^4.0.4, pirates@^4.0.5: + version "4.0.6" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + +postcss-value-parser@^4.0.2: + version "4.2.0" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + 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" + +prettier@^2.4.1, prettier@>=2, prettier@>=2.0.0: + version "2.8.8" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +pretty-format@^26.5.2: + version "26.6.2" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + +pretty-format@^27.0.2: + version "27.5.1" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +pretty-format@^29.0.0, pretty-format@^29.0.3, pretty-format@^29.6.2, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.1: + version "0.11.10" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise@^8.3.0: + version "8.3.0" + resolved "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz" + integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== + dependencies: + asap "~2.0.6" + +prompts@^2.0.1, prompts@^2.4.0: + version "2.4.2" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@*, prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +property-expr@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz" + integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA== + +proxy-compare@2.5.1: + version "2.5.1" + resolved "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz" + integrity sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA== + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + +psl@^1.1.28, psl@^1.1.33: + version "1.9.0" + resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.0" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +pure-rand@^6.0.0: + version "6.0.3" + resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz" + integrity sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w== + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +query-string@^7.1.3: + version "7.1.3" + resolved "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz" + integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +queue@6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz" + integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== + dependencies: + inherits "~2.0.3" + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +react-devtools-core@^4.27.2: + version "4.28.0" + resolved "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.0.tgz" + integrity sha512-E3C3X1skWBdBzwpOUbmXG8SgH6BtsluSMe+s6rRcujNKG1DGi8uIfhdhszkgDpAsMoE55hwqRUzeXCmETDBpTg== + dependencies: + shell-quote "^1.6.1" + ws "^7" + +"react-dom@^16.8 || ^17.0 || ^18.0", react-dom@^18.0.0: + version "18.2.0" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react-fast-compare@^2.0.1: + version "2.0.4" + resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + +react-freeze@^1.0.0: + version "1.0.3" + resolved "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz" + integrity sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g== + +"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +react-is@^18.2.0: + version "18.2.0" + resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +react-native-animatable@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz" + integrity sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w== + dependencies: + prop-types "^15.7.2" + +react-native-calendar-events@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/react-native-calendar-events/-/react-native-calendar-events-2.2.0.tgz" + integrity sha512-tNUbhT6Ief0JM4OQzQAaz1ri0+MCcAoHptBcEXCz2g7q3A05pg62PR2Dio4F9t2fCAD7Y2+QggdY1ycAsF3Tsg== + +react-native-dev-menu@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/react-native-dev-menu/-/react-native-dev-menu-4.1.1.tgz" + integrity sha512-jdYjoTpFHvGXW12enaTnrgOoEgVF5JVqv4hcO8K0KV66Cvk8YLwD3XHsEiqMat+4C1osa+IG5Yt3qAiMOLBQxQ== + +react-native-device-info@^10.11.0: + version "10.11.0" + resolved "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-10.11.0.tgz" + integrity sha512-qRzhuYOm5ZXQi5dhfJFjDq157oipxcEW/fo0QyMm5+TI6V6/+P/tju+Hif6z0rpLCf7MV7iDVRv2Kqha4D/yvQ== + +react-native-eva-icons@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/react-native-eva-icons/-/react-native-eva-icons-1.3.1.tgz" + integrity sha512-emd/aYXuOacuDVTx0SJoLi+xsOdCNdljQB3PTNCM9AQ3m/smG0X1TN0+ihelPO7MqoHzaH0h6lbANtwxGUy8Fw== + +react-native-fit-image@^1.5.5: + version "1.5.5" + resolved "https://registry.npmjs.org/react-native-fit-image/-/react-native-fit-image-1.5.5.tgz" + integrity sha512-Wl3Vq2DQzxgsWKuW4USfck9zS7YzhvLNPpkwUUCF90bL32e1a0zOVQ3WsJILJOwzmPdHfzZmWasiiAUNBkhNkg== + dependencies: + prop-types "^15.5.10" + +react-native-gesture-handler@^2.13.1, "react-native-gesture-handler@>= 1.0.0": + version "2.13.1" + resolved "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.13.1.tgz" + integrity sha512-hW454X7sjuiBN+lobqw63pmT3boAmTl5OP6zQLq83iEe4T6PcHZ9lxzgCrebtgmutY8cJfq9rM2dOUVh9WBcww== + dependencies: + "@egjs/hammerjs" "^2.0.17" + hoist-non-react-statics "^3.3.0" + invariant "^2.2.4" + lodash "^4.17.21" + prop-types "^15.7.2" + +react-native-localize@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/react-native-localize/-/react-native-localize-3.0.2.tgz" + integrity sha512-/l/oE1LVNgIRRhLbhmfFMHiWV0xhUn0A0iz1ytLVRYywL7FTp8Rx2vkJS/q/RpExDvV7yLw2493XZBYIM1dnLQ== + +react-native-modal-datetime-picker@^17.1.0: + version "17.1.0" + resolved "https://registry.npmjs.org/react-native-modal-datetime-picker/-/react-native-modal-datetime-picker-17.1.0.tgz" + integrity sha512-jfTwfaCLtBffYbQ+pOGFLM+J5HmUh3vb9rT0JrrQPjxzecdc8pNYreB1c96+mVuq8bDCvaCdIeuEsslTqLJL0Q== + dependencies: + prop-types "^15.7.2" + +react-native-oss-license@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/react-native-oss-license/-/react-native-oss-license-0.7.0.tgz" + integrity sha512-vlzpUkp9E4RWIwtJFq2HvBkAZxs2pF8NcR7vydWtms53pLWbYNDa3NutjO6wIzawGx6vW3EjlQpTI6MUNaB41g== + dependencies: + commander "^4.0.0" + fs-extra "^8.1.0" + glob "^7.1.5" + he "^1.2.0" + install "^0.13.0" + path "^0.12.7" + read-installed "^4.0.3" + yaml "^1.7.2" + +react-native-restart@^0.0.27: + version "0.0.27" + resolved "https://registry.npmjs.org/react-native-restart/-/react-native-restart-0.0.27.tgz" + integrity sha512-8KScVICrXwcTSJ1rjWkqVTHyEKQIttm5AIMGSK1QG1+RS5owYlE4z/1DykOTdWfVl9l16FIk0w9Xzk9ZO6jxlA== + +react-native-safe-area-context@^4.7.2, "react-native-safe-area-context@>= 3.0.0": + version "4.7.2" + resolved "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.7.2.tgz" + integrity sha512-5fy/hRNJ7bI/U2SliOeKf0D80J4lXPc1NsRiNS7Xaz8YTnqlzWib1ViItkwKPfufe54YKzVBMmM32RpdzvO2gg== + +react-native-screens@^3.25.0, "react-native-screens@>= 3.0.0": + version "3.25.0" + resolved "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.25.0.tgz" + integrity sha512-TSC2Ad0hh763I8QT6XxMsPXAagQ+RawDSdFtKRvIz9fCYr96AjRwwaqmYivbqlDywOgcRBkIVynkFtp0ThmlYw== + dependencies: + react-freeze "^1.0.0" + warn-once "^0.1.0" + +react-native-simple-toast@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/react-native-simple-toast/-/react-native-simple-toast-3.0.1.tgz" + integrity sha512-G1iUHqvhA4Obacol+fz1MKTeHDGyDFGXvnmAxYrUNBkTOA9/yaVpZBjoWfpnYXIlYtrCOcz6ll/B8nUJg4PPDA== + +react-native-svg@*, react-native-svg@^13.14.0, react-native-svg@^9.4.0: + version "13.14.0" + resolved "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.0.tgz" + integrity sha512-27ZnxUkHgWICimhuj6MuqBkISN53lVvgWJB7pIypjXysAyM+nqgQBPh4vXg+7MbqLBoYvR4PiBgKfwwGAqVxHg== + dependencies: + css-select "^5.1.0" + css-tree "^1.1.3" + +react-native-typography@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/react-native-typography/-/react-native-typography-1.4.1.tgz" + integrity sha512-dc9Zfs4jUdq4ygx4/KwO6jKTERBu6cRrfPJGntw/pA+D6BMjlWfMNuhZ/69vf4Zpsnt9s4AGe+Z/V1QFYaCXAA== + +react-native-webview@^13.6.0: + version "13.6.0" + resolved "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.6.0.tgz" + integrity sha512-KapVfHEj60e+2QplhqoCMdqW4vDzzvLS3YasfjVoMV4qhsZ3padncMEqOHX6AY4FIAdRzAxG0JQs+kXczAPYeQ== + dependencies: + escape-string-regexp "2.0.0" + invariant "2.2.4" + +react-native@*, "react-native@^0.0.0-0 || 0.60 - 0.72 || 1000.0.0", "react-native@>= 0.60.2", react-native@>=0.50.4, react-native@>=0.59, react-native@>=0.60.0, react-native@>=0.61.0, react-native@>=0.65.0, react-native@>=0.70.0, react-native@>=0.71.0, react-native@0.72.5: + version "0.72.5" + resolved "https://registry.npmjs.org/react-native/-/react-native-0.72.5.tgz" + integrity sha512-oIewslu5DBwOmo7x5rdzZlZXCqDIna0R4dUwVpfmVteORYLr4yaZo5wQnMeR+H7x54GaMhmgeqp0ZpULtulJFg== + dependencies: + "@jest/create-cache-key-function" "^29.2.1" + "@react-native-community/cli" "11.3.7" + "@react-native-community/cli-platform-android" "11.3.7" + "@react-native-community/cli-platform-ios" "11.3.7" + "@react-native/assets-registry" "^0.72.0" + "@react-native/codegen" "^0.72.7" + "@react-native/gradle-plugin" "^0.72.11" + "@react-native/js-polyfills" "^0.72.1" + "@react-native/normalize-colors" "^0.72.0" + "@react-native/virtualized-lists" "^0.72.8" + abort-controller "^3.0.0" + anser "^1.4.9" + base64-js "^1.1.2" + deprecated-react-native-prop-types "4.1.0" + event-target-shim "^5.0.1" + flow-enums-runtime "^0.0.5" + invariant "^2.2.4" + jest-environment-node "^29.2.1" + jsc-android "^250231.0.0" + memoize-one "^5.0.0" + metro-runtime "0.76.8" + metro-source-map "0.76.8" + mkdirp "^0.5.1" + nullthrows "^1.1.1" + pretty-format "^26.5.2" + promise "^8.3.0" + react-devtools-core "^4.27.2" + react-refresh "^0.4.0" + react-shallow-renderer "^16.15.0" + regenerator-runtime "^0.13.2" + scheduler "0.24.0-canary-efb381bbf-20230505" + stacktrace-parser "^0.1.10" + use-sync-external-store "^1.0.0" + whatwg-fetch "^3.0.0" + ws "^6.2.2" + yargs "^17.6.2" + +react-redux@^8.1.2: + version "8.1.2" + resolved "https://registry.npmjs.org/react-redux/-/react-redux-8.1.2.tgz" + integrity sha512-xJKYI189VwfsFc4CJvHqHlDrzyFTY/3vZACbE+rr/zQ34Xx1wQfB4OTOSeOSNrF6BDVe8OOdxIrAnMGXA3ggfw== + dependencies: + "@babel/runtime" "^7.12.1" + "@types/hoist-non-react-statics" "^3.3.1" + "@types/use-sync-external-store" "^0.0.3" + hoist-non-react-statics "^3.3.2" + react-is "^18.0.0" + use-sync-external-store "^1.0.0" + +react-refresh@^0.4.0: + version "0.4.3" + resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz" + integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== + +react-shallow-renderer@^16.15.0: + version "16.15.0" + resolved "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz" + integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== + dependencies: + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0 || ^18.0.0" + +react-test-renderer@>=16.0.0, react-test-renderer@>=16.8.0, react-test-renderer@18.2.0: + version "18.2.0" + resolved "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.2.0.tgz" + integrity sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA== + dependencies: + react-is "^18.2.0" + react-shallow-renderer "^16.15.0" + scheduler "^0.23.0" + +react@*, "react@^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.0.0, react@^18.2.0, react@>=16.0.0, react@>=16.2.0, react@>=16.8, react@>=16.8.0, react@>=17.0.0, react@>=18.1.0, react@18.2.0: + version "18.2.0" + resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +react@16.5.0: + version "16.5.0" + resolved "https://registry.npmjs.org/react/-/react-16.5.0.tgz" + integrity sha512-nw/yB/L51kA9PsAy17T1JrzzGRk+BlFCJwFF7p+pwVxgqwPjYNeZEkkH7LXn9dmflolrYMXLWMTkQ77suKPTNQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + schedule "^0.3.0" + +read-installed@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz" + integrity sha512-O03wg/IYuV/VtnK2h/KXEt9VIbMUFbk3ERG0Iu4FhLZw0EP0T9znqrYDGn6ncbEsXUFaUjiVAWXHzxwt3lhRPQ== + dependencies: + debuglog "^1.0.1" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + semver "2 || 3 || 4 || 5" + slide "~1.1.3" + util-extend "^1.0.1" + optionalDependencies: + graceful-fs "^4.1.2" + +read-package-json@^2.0.0: + version "2.1.2" + resolved "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz" + integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA== + dependencies: + glob "^7.1.1" + json-parse-even-better-errors "^2.3.0" + normalize-package-data "^2.0.0" + npm-normalize-package-bin "^1.0.0" + +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + 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" + +readdir-scoped-modules@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz" + integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + graceful-fs "^4.1.2" + once "^1.3.0" + +readline@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz" + integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== + +recast@^0.21.0: + version "0.21.5" + resolved "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz" + integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg== + dependencies: + ast-types "0.15.2" + esprima "~4.0.0" + source-map "~0.6.1" + tslib "^2.0.1" + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + +"redux@^4 || ^5.0.0-beta.0", redux@^4.2.1: + version "4.2.1" + resolved "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== + dependencies: + "@babel/runtime" "^7.9.2" + +reflect.getprototypeof@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz" + integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + +regenerate-unicode-properties@^10.1.0: + version "10.1.1" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.2: + version "0.13.11" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +request@^2.67.0: + version "2.88.2" + resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +reselect@^4.1.7: + version "4.1.8" + resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz" + integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1: + version "1.22.6" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz" + integrity sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.4: + version "2.0.0-next.4" + resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz" + integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + 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" + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1, safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + +schedule@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/schedule/-/schedule-0.3.0.tgz" + integrity sha512-20+1KVo517sR7Nt+bYBN8a+bEJDKLPEx7Ohtts1kX05E4/HY53YUNuhfkVNItmWAnBYHcpG9vsd2/CJxG+aPCQ== + dependencies: + object-assign "^4.1.1" + +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +scheduler@0.24.0-canary-efb381bbf-20230505: + version "0.24.0-canary-efb381bbf-20230505" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz" + integrity sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA== + dependencies: + loose-envify "^1.1.0" + +semver@^5.6.0: + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.7: + version "7.5.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +semver@^7.5.2: + version "7.5.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +semver@^7.5.3: + version "7.5.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +semver@^7.5.4: + version "7.5.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +"semver@2 || 3 || 4 || 5": + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +sentence-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz" + integrity sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz" + integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== + +serve-static@^1.13.1: + version "1.15.0" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-function-name@^2.0.0, set-function-name@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.6.1, shell-quote@^1.7.3: + version "1.8.1" + resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slide@~1.1.3: + version "1.1.6" + resolved "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz" + integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw== + +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +source-map-support@^0.5.16: + version "0.5.21" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.15" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz" + integrity sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ== + +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stop-iteration-iterator@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz" + integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== + dependencies: + internal-slot "^1.0.4" + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-natural-compare@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz" + integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.matchall@^4.0.8: + version "4.0.10" + resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz" + integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + regexp.prototype.flags "^1.5.0" + set-function-name "^2.0.0" + side-channel "^1.0.4" + +string.prototype.trim@^1.2.8: + 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" + +string.prototype.trimend@^1.0.7: + 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" + +string.prototype.trimstart@^1.0.7: + 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" + +strip-ansi@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@^3.1.1: + 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== + +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + +sudo-prompt@^9.0.0: + version "9.2.1" + resolved "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz" + integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + 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== + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +temp@^0.8.4: + version "0.8.4" + resolved "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz" + integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== + dependencies: + rimraf "~2.6.2" + +terser@^5.15.0: + version "5.20.0" + resolved "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz" + integrity sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz" + integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== + +through2@^2.0.1: + version "2.0.5" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +tiny-case@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz" + integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q== + +tiny-inflate@^1.0.0: + version "1.0.3" + resolved "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz" + integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== + +tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + 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== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz" + integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg== + +tough-cookie@^4.1.2, tough-cookie@4.1.3: + version "4.1.3" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz" + integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + +tsutils@^3.21.0: + 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" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +type-check@^0.4.0, type-check@~0.4.0: + 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" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + 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== + +type-fest@^0.21.3: + 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== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-fest@^1.2.1: + version "1.4.0" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + +type-fest@^2.19.0: + version "2.19.0" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +"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", typescript@4.8.4: + version "4.8.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz" + integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +uglify-es@^3.1.9: + version "3.3.9" + resolved "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz" + integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ== + dependencies: + commander "~2.13.0" + source-map "~0.6.1" + +unbox-primitive@^1.0.2: + 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" + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +unicode-trie@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz" + integrity sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ== + dependencies: + pako "^0.2.5" + tiny-inflate "^1.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +upper-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz" + integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg== + dependencies: + tslib "^2.0.3" + +upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz" + integrity sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg== + dependencies: + tslib "^2.0.3" + +uri-js@^4.2.2: + 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" + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-latest-callback@^0.1.5: + version "0.1.6" + resolved "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.6.tgz" + integrity sha512-VO/P91A/PmKH9bcN9a7O3duSuxe6M14ZoYXgA6a8dab8doWNdhiIHzEkX/jFeTTRBsX0Ubk6nG4q2NIjNsj+bg== + +use-sync-external-store@^1.0.0, use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz" + integrity sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA== + +util@^0.10.3: + version "0.10.4" + resolved "https://registry.npmjs.org/util/-/util-0.10.4.tgz" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-to-istanbul@^9.0.1: + version "9.1.0" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz" + integrity sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +valtio@^1.11.2: + version "1.11.2" + resolved "https://registry.npmjs.org/valtio/-/valtio-1.11.2.tgz" + integrity sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw== + dependencies: + proxy-compare "2.5.1" + use-sync-external-store "1.2.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vlq@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz" + integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== + +w3c-xmlserializer@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz" + integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== + dependencies: + xml-name-validator "^4.0.0" + +walker@^1.0.7, walker@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +warn-once@^0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz" + integrity sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q== + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + +whatwg-fetch@^3.0.0: + version "3.6.19" + resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz" + integrity sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw== + +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== + +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + 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" + +which-builtin-type@^1.1.3: + 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" + +which-collection@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz" + integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + dependencies: + is-map "^2.0.1" + is-set "^2.0.1" + is-weakmap "^2.0.1" + is-weakset "^2.0.1" + +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which-typed-array@^1.1.11, which-typed-array@^1.1.9: + version "1.1.11" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^2.3.0: + version "2.4.3" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +ws@^6.2.2: + version "6.2.2" + resolved "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz" + integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== + dependencies: + async-limiter "~1.0.0" + +ws@^7, ws@^7.5.1: + version "7.5.9" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +ws@^8.11.0: + version "8.14.2" + resolved "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz" + integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.7.2: + version "1.10.2" + resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yaml@^2.2.1: + version "2.3.2" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz" + integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^15.1.0: + version "15.4.1" + resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.3.1, yargs@^17.6.2: + version "17.7.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yup@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/yup/-/yup-1.3.1.tgz" + integrity sha512-2stNyEF96SnPUxzRL99kt1bEHWytnvC2stwmTTqjoFXZRf63JtYK2pQt2AJvWcQvkrAzr/pcXvc6c5vrqsBzDg== + dependencies: + property-expr "^2.0.5" + tiny-case "^1.0.3" + toposort "^2.0.2" + type-fest "^2.19.0"