From 134c4a49c5b7374d3bee16ea7f94741a60c92142 Mon Sep 17 00:00:00 2001 From: Miguel Alatzar Date: Tue, 6 Jul 2021 08:16:35 -0700 Subject: [PATCH] Integrate react-native-network-client (#5499) * fix: handle NSMutableData * feat: integrate react-native-network-client * fix: typos * fix: semicolon * fix: rename to urlVersion * fix: add returnDataOnly arg * fix: configure network client * fix: headers * fix: handling of serverVersion * fix: rename requests to actions * fix: action imports * fix: no need to stringify body * fix: sso flow * fix: address PR feedback * fix: invalidate client on logout * fix: address PR feedback take 2 * fix: address PR feedback take 3 * fix: tsc issues * fix: get csrf token during client creation * fix: linter * fix: invalidate client onLogout * fix: event emitter * fix: unit tests * fix: apply linter fixes * fix lint * Modify actions to add / update database values * Rename clien4.d.ts to client.d.ts * fix empty & missing translations * cleanup api client * Cleanup init & squash some TODO's * Emit certificate errors in NetworkManager * cleanup user actions * Fix NetworkManager invalidate client * Invalidate client when server screen appears * Update kotlin to 1.4.30 required by network-client * patch react-native-keychain to remove cached credential * update react-native-network-client * Use app.db instead of default.db in native code * fix use of rnnc on Android * Init PushNotifications * No need to reset serverVersion on logout * fix logout action * fix deleteServerDatabase * fix schedule expired session notification * use safeParseJSON for db json fields * unsubscribe when database component unmounts * cleanup init * session type * pass launchprops to entire login flow * Properly remove third party cookies after SSO login * recreate network client if sso with redirect fails * add missing launch props from server screen * use query prefix for database queries * Add temporary logout function to channel screen Co-authored-by: Elias Nahum --- NOTICE.txt | 2 +- android/app/build.gradle | 9 + .../mattermost/helpers/DatabaseHelper.java | 4 +- .../mattermost/rnbeta/MainApplication.java | 8 +- android/build.gradle | 4 +- app/{requests => actions}/local/timezone.ts | 6 +- app/{requests => actions}/remote/error.ts | 0 app/actions/remote/general.ts | 86 + .../remote/push_notification.ts | 40 +- app/{requests => actions}/remote/role.ts | 15 +- app/actions/remote/systems.ts | 45 + app/{requests => actions}/remote/user.ts | 345 +- app/client/rest/apps.ts | 2 +- app/client/rest/base.ts | 335 +- app/client/rest/bots.ts | 37 - app/client/rest/channels.ts | 24 +- app/client/rest/constants.ts | 7 +- app/client/rest/emojis.ts | 2 +- app/client/rest/general.ts | 21 +- app/client/rest/groups.ts | 8 +- app/client/rest/index.test.js | 32 +- app/client/rest/index.ts | 16 +- app/client/rest/integrations.ts | 8 +- app/client/rest/posts.ts | 12 +- app/client/rest/preferences.ts | 4 +- app/client/rest/teams.ts | 8 +- app/client/rest/tos.ts | 4 +- app/client/rest/users.ts | 55 +- app/constants/database.ts | 16 + app/constants/general.ts | 2 +- app/constants/index.ts | 8 +- app/constants/navigation.ts | 1 - app/constants/network.ts | 13 + app/constants/sso.ts | 3 + app/constants/view.ts | 2 - app/database/components/index.tsx | 30 +- app/database/manager/__mocks__/index.ts | 16 +- app/database/manager/index.ts | 18 +- app/database/models/app/global.ts | 3 +- app/database/models/server/draft.ts | 3 +- .../models/server/my_channel_settings.ts | 6 +- app/database/models/server/post.ts | 18 +- app/database/models/server/post_metadata.ts | 8 +- app/database/models/server/role.ts | 3 +- app/database/models/server/system.ts | 3 +- .../models/server/team_channel_history.ts | 6 +- app/database/models/server/user.ts | 22 +- app/i18n/index.ts | 4 +- app/init/credentials.ts | 22 +- app/init/fetch.js | 145 - app/init/global_event_handler.ts | 124 +- app/init/launch.ts | 7 +- app/init/network_manager.ts | 123 + app/init/push_notifications.ts | 110 +- app/queries/app/global.ts | 23 +- app/queries/app/servers.ts | 8 +- app/queries/servers/role.ts | 2 +- app/queries/servers/system.ts | 55 +- app/queries/servers/user.ts | 26 +- app/requests/local/systems.ts | 19 - app/requests/remote/general.ts | 46 - app/requests/remote/systems.ts | 22 - app/screens/channel/index.tsx | 13 +- .../forgot_password/forgot_password.test.tsx | 3 +- app/screens/forgot_password/index.tsx | 7 +- app/screens/login/index.tsx | 25 +- app/screens/login/login.test.tsx | 7 +- app/screens/login_options/index.tsx | 10 +- app/screens/mfa/index.tsx | 4 +- app/screens/mfa/mfa.test.tsx | 2 +- app/screens/navigation.ts | 6 +- app/screens/server/index.tsx | 53 +- app/screens/sso/index.tsx | 38 +- app/screens/sso/sso.test.tsx | 2 + .../sso/sso_with_redirect_url.test.tsx | 4 +- app/screens/sso/sso_with_redirect_url.tsx | 32 +- app/screens/sso/sso_with_webview.tsx | 42 +- app/utils/file.ts | 11 +- app/utils/helpers.ts | 14 + app/utils/security.ts | 2 +- app/utils/url/index.ts | 12 +- assets/base/i18n/en.json | 5 +- babel.config.js | 2 +- index.ts | 13 +- .../DatabaseHelper/DatabaseHelper.swift | 4 +- ios/Podfile | 3 + ios/Podfile.lock | 46 +- jest.config.js | 2 +- package-lock.json | 2780 ++++++++--------- package.json | 3 +- patches/react-native-keychain+7.0.0.patch | 23 +- test/setup.ts | 35 +- test/test_helper.js | 14 +- tsconfig.json | 2 +- types/api/{client4.d.ts => client.d.ts} | 7 +- types/api/session.d.ts | 10 + 96 files changed, 2539 insertions(+), 2753 deletions(-) rename app/{requests => actions}/local/timezone.ts (90%) rename app/{requests => actions}/remote/error.ts (100%) create mode 100644 app/actions/remote/general.ts rename app/{requests => actions}/remote/push_notification.ts (60%) rename app/{requests => actions}/remote/role.ts (69%) create mode 100644 app/actions/remote/systems.ts rename app/{requests => actions}/remote/user.ts (61%) delete mode 100644 app/client/rest/bots.ts create mode 100644 app/constants/network.ts delete mode 100644 app/init/fetch.js create mode 100644 app/init/network_manager.ts delete mode 100644 app/requests/local/systems.ts delete mode 100644 app/requests/remote/general.ts delete mode 100644 app/requests/remote/systems.ts rename types/api/{client4.d.ts => client.d.ts} (85%) create mode 100644 types/api/session.d.ts diff --git a/NOTICE.txt b/NOTICE.txt index 149c2ecc1..1aa5c3211 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1528,7 +1528,7 @@ This product contains a modified version of 'react-native-cookies' by Joseph P. Cookie manager for react native. * HOMEPAGE: - * https://github.com/joeferraro/react-native-cookies + * https://github.com/react-native-cookies/cookies * LICENSE: MIT diff --git a/android/app/build.gradle b/android/app/build.gradle index d91c4ae2d..1c0f1721b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -210,6 +210,15 @@ configurations.all { if (details.requested.name == 'play-services-basement') { details.useTarget group: details.requested.group, name: details.requested.name, version: '15.0.1' } + if (details.requested.name == 'okhttp') { + details.useTarget group: details.requested.group, name: details.requested.name, version: '4.9.1' + } + if (details.requested.name == 'okhttp-tls') { + details.useTarget group: details.requested.group, name: details.requested.name, version: '4.9.1' + } + if (details.requested.name == 'okhttp-urlconnection') { + details.useTarget group: details.requested.group, name: details.requested.name, version: '4.9.1' + } } } } diff --git a/android/app/src/main/java/com/mattermost/helpers/DatabaseHelper.java b/android/app/src/main/java/com/mattermost/helpers/DatabaseHelper.java index cf3b07338..6ce141a60 100644 --- a/android/app/src/main/java/com/mattermost/helpers/DatabaseHelper.java +++ b/android/app/src/main/java/com/mattermost/helpers/DatabaseHelper.java @@ -7,7 +7,7 @@ import android.net.Uri; import com.nozbe.watermelondb.Database; public class DatabaseHelper { - private static final String DEFAULT_DATABASE_NAME = "default.db"; + private static final String DEFAULT_DATABASE_NAME = "app.db"; private static Database defaultDatabase; private static void setDefaultDatabase(Context context) { @@ -21,7 +21,7 @@ public class DatabaseHelper { } String emptyArray[] = {}; - String query = "SELECT url FROM servers"; + String query = "SELECT url FROM Servers"; Cursor cursor = defaultDatabase.rawQuery(query, emptyArray); if (cursor.getCount() == 1) { diff --git a/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java b/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java index fc2884bd8..3cf4c23af 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java @@ -42,11 +42,13 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.modules.network.OkHttpClientProvider; import com.facebook.soloader.SoLoader; import org.unimodules.adapters.react.ModuleRegistryAdapter; import org.unimodules.adapters.react.ReactModuleRegistryProvider; +import com.mattermost.networkclient.RCTOkHttpClientFactory; import com.swmansion.reanimated.ReanimatedJSIModulePackage; public class MainApplication extends NavigationApplication implements INotificationsApplication, INotificationsDrawerApplication { @@ -151,8 +153,10 @@ public class MainApplication extends NavigationApplication implements INotificat SoLoader.init(this, /* native exopackage */ false); initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - // Uncomment to listen to react markers for build that has telemetry enabled - // addReactMarkerListener(); + // Tells React Native to use our RCTOkHttpClientFactory which builds an OKHttpClient + // with a cookie jar defined in APIClientModule and an interceptor to intercept all + // requests that originate from React Native's OKHttpClient + OkHttpClientProvider.setOkHttpClientFactory(new RCTOkHttpClientFactory()); } @Override diff --git a/android/build.gradle b/android/build.gradle index b3ea5149e..1cfccc653 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,8 +8,8 @@ buildscript { targetSdkVersion = 29 ndkVersion = "20.1.5948944" supportLibVersion = "28.0.0" - kotlinVersion = "1.3.61" - kotlin_version = "1.3.61" + kotlinVersion = "1.4.30" + kotlin_version = "1.4.30" firebaseVersion = "21.0.0" RNNKotlinVersion = kotlinVersion } diff --git a/app/requests/local/timezone.ts b/app/actions/local/timezone.ts similarity index 90% rename from app/requests/local/timezone.ts rename to app/actions/local/timezone.ts index 6ae33b28f..e2081aba3 100644 --- a/app/requests/local/timezone.ts +++ b/app/actions/local/timezone.ts @@ -4,8 +4,8 @@ import {getTimeZone} from 'react-native-localize'; import DatabaseManager from '@database/manager'; -import {getUserById} from '@queries/servers/user'; -import {updateMe} from '@requests/remote/user'; +import {queryUserById} from '@queries/servers/user'; +import {updateMe} from '@actions/remote/user'; import {Config} from '@typings/database/models/servers/config'; import User from '@typings/database/models/servers/user'; @@ -23,7 +23,7 @@ export const autoUpdateTimezone = async (serverUrl: string, {deviceTimezone, use return {error: `No database present for ${serverUrl}`}; } - const currentUser = await getUserById({userId, database}) ?? null; + const currentUser = await queryUserById({userId, database}) ?? null; if (!currentUser) { return null; diff --git a/app/requests/remote/error.ts b/app/actions/remote/error.ts similarity index 100% rename from app/requests/remote/error.ts rename to app/actions/remote/error.ts diff --git a/app/actions/remote/general.ts b/app/actions/remote/general.ts new file mode 100644 index 000000000..8c4061dd5 --- /dev/null +++ b/app/actions/remote/general.ts @@ -0,0 +1,86 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {SYSTEM_IDENTIFIERS} from '@constants/database'; +import DatabaseManager from '@database/manager'; +import {getServerCredentials} from '@init/credentials'; +import NetworkManager from '@init/network_manager'; + +import type {ClientResponse} from '@mattermost/react-native-network-client'; + +import type {RawSystem} from '@typings/database/database'; + +export const doPing = async (serverUrl: string) => { + const client = await NetworkManager.createClient(serverUrl); + + const certificateError = { + id: 'mobile.server_requires_client_certificate', + defaultMessage: 'Server required client certificate for authentication.', + }; + + const pingError = { + id: 'mobile.server_ping_failed', + defaultMessage: 'Cannot connect to the server. Please check your server URL and internet connection.', + }; + + let response: ClientResponse; + try { + response = await client.ping(); + + if (response.code === 401) { + // Don't invalidate the client since we want to eventually + // import a certificate with client.importClientP12() + // if for some reason cert is not imported do invalidate the client then. + return {error: {intl: certificateError}}; + } + + if (!response.ok) { + NetworkManager.invalidateClient(serverUrl); + return {error: {intl: pingError}}; + } + } catch (error) { + NetworkManager.invalidateClient(serverUrl); + return {error}; + } + + return {error: undefined}; +}; + +export const fetchConfigAndLicense = async (serverUrl: string) => { + let client; + try { + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + + try { + const [config, license] = await Promise.all([ + client.getClientConfigOld(), + client.getClientLicenseOld(), + ]); + + // If we have credentials for this server then update the values in the database + const credentials = await getServerCredentials(serverUrl); + const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; + if (credentials && operator) { + const systems: RawSystem[] = [{ + id: SYSTEM_IDENTIFIERS.CONFIG, + value: JSON.stringify(config), + }, { + id: SYSTEM_IDENTIFIERS.LICENSE, + value: JSON.stringify(license), + }]; + + operator.handleSystem({systems, prepareRecordsOnly: false}). + catch((error) => { + // eslint-disable-next-line no-console + console.log('An error ocurred while saving config & license', error); + }); + } + + return {config, license}; + } catch (error) { + return {error}; + } +}; diff --git a/app/requests/remote/push_notification.ts b/app/actions/remote/push_notification.ts similarity index 60% rename from app/requests/remote/push_notification.ts rename to app/actions/remote/push_notification.ts index fda5a2525..8139ddbc1 100644 --- a/app/requests/remote/push_notification.ts +++ b/app/actions/remote/push_notification.ts @@ -4,18 +4,13 @@ import moment from 'moment-timezone'; import {IntlShape} from 'react-intl'; -import {Client4} from '@client/rest'; import DatabaseManager from '@database/manager'; import PushNotifications from '@init/push_notifications'; -import {getCommonSystemValues} from '@app/queries/servers/system'; -import {getSessions} from '@requests/remote/user'; +import {queryCommonSystemValues} from '@app/queries/servers/system'; +import {getSessions} from '@actions/remote/user'; import {Config} from '@typings/database/models/servers/config'; -import {isMinimumServerVersion} from '@utils/helpers'; -const MAJOR_VERSION = 5; -const MINOR_VERSION = 24; - -const sortByNewest = (a: any, b: any) => { +const sortByNewest = (a: Session, b: Session) => { if (a.create_at > b.create_at) { return -1; } @@ -25,32 +20,32 @@ const sortByNewest = (a: any, b: any) => { export const scheduleExpiredNotification = async (serverUrl: string, intl: IntlShape) => { const database = DatabaseManager.serverDatabases[serverUrl].database; - const {currentUserId, config}: {currentUserId: string, config: Partial} = await getCommonSystemValues(database); + const {currentUserId, config}: {currentUserId: string, config: Partial} = await queryCommonSystemValues(database); - if (isMinimumServerVersion(Client4.serverVersion, MAJOR_VERSION, MINOR_VERSION) && config.ExtendSessionLengthWithActivity === 'true') { + if (config.ExtendSessionLengthWithActivity === 'true') { PushNotifications.cancelAllLocalNotifications(); return null; } const timeOut = setTimeout(async () => { clearTimeout(timeOut); - let sessions: any; + let sessions: Session[]|undefined; try { sessions = await getSessions(serverUrl, currentUserId); } catch (e) { - // console.warn('Failed to get current session', e); + // eslint-disable-next-line no-console + console.warn('Failed to get user sessions', e); return; } - if (!Array.isArray(sessions?.data)) { + if (!Array.isArray(sessions)) { return; } - const session = sessions.data.sort(sortByNewest)[0]; - const expiresAt = session?.expires_at || 0; //eslint-disable-line camelcase - const expiresInDays = parseInt(String(Math.ceil(Math.abs(moment.duration(moment().diff(expiresAt)).asDays()))), 10); - + const session = sessions.sort(sortByNewest)[0]; + const expiresAt = session?.expires_at ? parseInt(session.expires_at as string, 10) : 0; + const expiresInDays = Math.ceil(Math.abs(moment.duration(moment().diff(moment(expiresAt))).asDays())); const message = intl.formatMessage( { id: 'mobile.session_expired', @@ -62,17 +57,18 @@ export const scheduleExpiredNotification = async (serverUrl: string, intl: IntlS ); if (expiresAt) { + //@ts-expect-error: Does not need to set all Notification properties PushNotifications.scheduleNotification({ fireDate: expiresAt, body: message, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - userInfo: { - local: true, + payload: { + userInfo: { + local: true, + }, }, }); } - }, 20000); + }, 1000); return null; }; diff --git a/app/requests/remote/role.ts b/app/actions/remote/role.ts similarity index 69% rename from app/requests/remote/role.ts rename to app/actions/remote/role.ts index b2f48e9cc..46aa11a96 100644 --- a/app/requests/remote/role.ts +++ b/app/actions/remote/role.ts @@ -1,14 +1,21 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Client4} from '@client/rest'; import DatabaseManager from '@database/manager'; -import {getRoles} from '@app/queries/servers/role'; +import NetworkManager from '@init/network_manager'; +import {queryRoles} from '@queries/servers/role'; export const loadRolesIfNeeded = async (serverUrl: string, updatedRoles: string[]) => { + let client; + try { + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + const database = DatabaseManager.serverDatabases[serverUrl].database; const operator = DatabaseManager.serverDatabases[serverUrl].operator; - const existingRoles = ((await getRoles(database)) as unknown) as Role[]; + const existingRoles = await queryRoles(database); const roleNames = existingRoles.map((role) => { return role.name; @@ -19,7 +26,7 @@ export const loadRolesIfNeeded = async (serverUrl: string, updatedRoles: string[ }); try { - const roles = await Client4.getRolesByNames(newRoles); + const roles = await client.getRolesByNames(newRoles); await operator.handleRole({ roles, diff --git a/app/actions/remote/systems.ts b/app/actions/remote/systems.ts new file mode 100644 index 000000000..1b321432b --- /dev/null +++ b/app/actions/remote/systems.ts @@ -0,0 +1,45 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {logError} from '@actions/remote/error'; +import {forceLogoutIfNecessary} from '@actions/remote/user'; +import {SYSTEM_IDENTIFIERS} from '@constants/database'; +import DatabaseManager from '@database/manager'; +import NetworkManager from '@init/network_manager'; + +import type {RawSystem} from '@typings/database/database'; + +export const getDataRetentionPolicy = async (serverUrl: string) => { + let client; + try { + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + + let data = {}; + try { + data = await client.getDataRetentionPolicy(); + } catch (error) { + forceLogoutIfNecessary(serverUrl, error); + + logError(error); + return {error}; + } + + const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; + if (operator) { + const systems: RawSystem[] = [{ + id: SYSTEM_IDENTIFIERS.DATA_RETENTION_POLICIES, + value: JSON.stringify(data), + }]; + + operator.handleSystem({systems, prepareRecordsOnly: false}). + catch((error) => { + // eslint-disable-next-line no-console + console.log('An error ocurred while saving data retention policies', error); + }); + } + + return data; +}; diff --git a/app/requests/remote/user.ts b/app/actions/remote/user.ts similarity index 61% rename from app/requests/remote/user.ts rename to app/actions/remote/user.ts index 2aeb3d18d..94097c2d8 100644 --- a/app/requests/remote/user.ts +++ b/app/actions/remote/user.ts @@ -1,65 +1,68 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Client4} from '@client/rest'; +import {DeviceEventEmitter} from 'react-native'; + +import {autoUpdateTimezone, getDeviceTimezone, isTimezoneEnabled} from '@actions/local/timezone'; +import {logError} from '@actions/remote/error'; +import {loadRolesIfNeeded} from '@actions/remote/role'; +import {getDataRetentionPolicy} from '@actions/remote/systems'; +import {Database, General} from '@constants'; import DatabaseManager from '@database/manager'; import analytics from '@init/analytics'; -import {setServerCredentials} from '@init/credentials'; -import {getDeviceToken} from '@app/queries/app/global'; -import {getCommonSystemValues, getCurrentUserId} from '@app/queries/servers/system'; -import {createSessions} from '@requests/local/systems'; -import {autoUpdateTimezone, getDeviceTimezone, isTimezoneEnabled} from '@requests/local/timezone'; -import {logError} from '@requests/remote/error'; -import {loadRolesIfNeeded} from '@requests/remote/role'; -import {getDataRetentionPolicy} from '@requests/remote/systems'; -import {Client4Error} from '@typings/api/client4'; -import {Config} from '@typings/database/models/servers/config'; -import { - LoadMeArgs, - LoginArgs, - RawMyTeam, - RawPreference, - RawRole, - RawTeam, - RawTeamMembership, - RawUser, -} from '@typings/database/database'; -import {License} from '@typings/database/models/servers/license'; -import Role from '@typings/database/models/servers/role'; -import User from '@typings/database/models/servers/user'; +import NetworkManager from '@init/network_manager'; +import {queryDeviceToken} from '@queries/app/global'; +import {queryCommonSystemValues, queryCurrentUserId} from '@queries/servers/system'; import {getCSRFFromCookie} from '@utils/security'; +import type {Client4Error} from '@typings/api/client'; +import type {Config} from '@typings/database/models/servers/config'; +import type {LoadMeArgs, LoginArgs, RawMyTeam, RawPreference, + RawRole, RawTeam, RawTeamMembership, RawUser} from '@typings/database/database'; +import type {License} from '@typings/database/models/servers/license'; +import type Role from '@typings/database/models/servers/role'; +import type User from '@typings/database/models/servers/user'; + +type LoadedUser = { + currentUser?: RawUser, + error?: Client4Error +} + const HTTP_UNAUTHORIZED = 401; -// TODO: Requests should know the server url -// To select the right DB & Client - -export const logout = async (serverUrl: string, skipServerLogout = false) => { - return async () => { - if (!skipServerLogout) { - try { - await Client4.logout(); - } catch { - // Do nothing - } - } - - //fixme: uncomment below EventEmitter.emit - // EventEmitter.emit(NavigationTypes.NAVIGATION_RESET); - - DatabaseManager.deleteServerDatabase(serverUrl); - - return {data: true}; - }; -}; - -export const forceLogoutIfNecessary = async (serverUrl: string, err: Client4Error) => { - const database = DatabaseManager.serverDatabases[serverUrl].database; +export const completeLogin = async (serverUrl: string, user: RawUser) => { + const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return {error: `${serverUrl} database not found`}; } - const currentUserId = await getCurrentUserId(database); + const {config, license}: { config: Partial; license: Partial; } = await queryCommonSystemValues(database); + + if (!Object.keys(config)?.length || !Object.keys(license)?.length) { + return null; + } + + // Set timezone + if (isTimezoneEnabled(config)) { + const timezone = getDeviceTimezone(); + await autoUpdateTimezone(serverUrl, {deviceTimezone: timezone, userId: user.id}); + } + + // Data retention + if (config?.DataRetentionEnableMessageDeletion === 'true' && license?.IsLicensed === 'true' && license?.DataRetention === 'true') { + getDataRetentionPolicy(serverUrl); + } + + return null; +}; + +export const forceLogoutIfNecessary = async (serverUrl: string, err: Client4Error) => { + const database = DatabaseManager.serverDatabases[serverUrl]?.database; + if (!database) { + return {error: `${serverUrl} database not found`}; + } + + const currentUserId = await queryCurrentUserId(database); if ('status_code' in err && err.status_code === HTTP_UNAUTHORIZED && err?.url?.indexOf('/login') === -1 && currentUserId) { await logout(serverUrl); @@ -68,24 +71,49 @@ export const forceLogoutIfNecessary = async (serverUrl: string, err: Client4Erro return {error: null}; }; +export const getSessions = async (serverUrl: string, currentUserId: string) => { + let client; + try { + client = NetworkManager.getClient(serverUrl); + } catch { + return undefined; + } + + try { + return await client.getSessions(currentUserId); + } catch (e) { + logError(e); + await forceLogoutIfNecessary(serverUrl, e); + } + + return undefined; +}; + export const login = async (serverUrl: string, {ldapOnly = false, loginId, mfaToken, password}: LoginArgs) => { let deviceToken; - let user; + let user: RawUser; const appDatabase = DatabaseManager.appDatabase?.database; if (!appDatabase) { return {error: 'App database not found.'}; } + let client; try { - deviceToken = await getDeviceToken(appDatabase); - user = ((await Client4.login( + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + + try { + deviceToken = await queryDeviceToken(appDatabase); + user = (await client.login( loginId, password, mfaToken, deviceToken, ldapOnly, - )) as unknown) as RawUser; + ) as unknown) as RawUser; await DatabaseManager.createServerDatabase({ config: { @@ -94,7 +122,8 @@ export const login = async (serverUrl: string, {ldapOnly = false, loginId, mfaTo }, }); await DatabaseManager.setActiveServerDatabase(serverUrl); - await getCSRFFromCookie(serverUrl); + const csrfToken = await getCSRFFromCookie(serverUrl); + client.setCSRFToken(csrfToken); } catch (e) { return {error: e}; } @@ -105,24 +134,31 @@ export const login = async (serverUrl: string, {ldapOnly = false, loginId, mfaTo await completeLogin(serverUrl, user); } - return {result}; + return {error: undefined}; }; export const loadMe = async (serverUrl: string, {deviceToken, user}: LoadMeArgs) => { let currentUser = user; - const database = DatabaseManager.serverDatabases[serverUrl].database; + const database = DatabaseManager.serverDatabases[serverUrl]?.database; if (!database) { return {error: `${serverUrl} database not found`}; } + let client; + try { + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + try { if (deviceToken) { - await Client4.attachDevice(deviceToken); + await client.attachDevice(deviceToken); } if (!currentUser) { - currentUser = ((await Client4.getMe()) as unknown) as RawUser; + currentUser = (await client.getMe() as unknown) as RawUser; } } catch (e) { await forceLogoutIfNecessary(serverUrl, e); @@ -133,20 +169,20 @@ export const loadMe = async (serverUrl: string, {deviceToken, user}: LoadMeArgs) } try { - const analyticsClient = analytics.create(Client4.getUrl()); + const analyticsClient = analytics.create(serverUrl); analyticsClient.setUserId(currentUser.id); analyticsClient.setUserRoles(currentUser.roles); //todo: Ask for a unified endpoint that will serve all those values in one go.( while ensuring backward-compatibility through fallbacks to previous code-path) - const teamsRequest = Client4.getMyTeams(); + const teamsRequest = client.getMyTeams(); // Goes into myTeam table - const teamMembersRequest = Client4.getMyTeamMembers(); - const teamUnreadRequest = Client4.getMyTeamUnreads(); + const teamMembersRequest = client.getMyTeamMembers(); + const teamUnreadRequest = client.getMyTeamUnreads(); - const preferencesRequest = Client4.getMyPreferences(); - const configRequest = Client4.getClientConfigOld(); - const licenseRequest = Client4.getClientLicenseOld(); + const preferencesRequest = client.getMyPreferences(); + const configRequest = client.getClientConfigOld(); + const licenseRequest = client.getClientLicenseOld(); const [ teams, @@ -181,21 +217,17 @@ export const loadMe = async (serverUrl: string, {deviceToken, user}: LoadMeArgs) const systemRecords = operator.handleSystem({ systems: [ { - id: 'config', + id: Database.SYSTEM_IDENTIFIERS.CONFIG, value: JSON.stringify(config), }, { - id: 'license', + id: Database.SYSTEM_IDENTIFIERS.LICENSE, value: JSON.stringify(license), }, { - id: 'currentUserId', + id: Database.SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: currentUser.id, }, - { - id: 'url', - value: Client4.getUrl(), - }, ], prepareRecordsOnly: true, }); @@ -223,7 +255,7 @@ export const loadMe = async (serverUrl: string, {deviceToken, user}: LoadMeArgs) let rolesRecords: Role[] = []; if (rolesToLoad.size > 0) { - const rolesByName = ((await Client4.getRolesByNames(Array.from(rolesToLoad))) as unknown) as RawRole[]; + const rolesByName = (await client.getRolesByNames(Array.from(rolesToLoad)) as unknown) as RawRole[]; if (rolesByName?.length) { rolesRecords = await operator.handleRole({prepareRecordsOnly: true, roles: rolesByName}) as Role[]; @@ -243,109 +275,41 @@ export const loadMe = async (serverUrl: string, {deviceToken, user}: LoadMeArgs) return {currentUser, error: undefined}; }; -export const completeLogin = async (serverUrl: string, user: RawUser) => { - const database = DatabaseManager.serverDatabases[serverUrl].database; - if (!database) { - return {error: `${serverUrl} database not found`}; +export const logout = async (serverUrl: string, skipServerLogout = false) => { + if (!skipServerLogout) { + try { + const client = NetworkManager.getClient(serverUrl); + await client.logout(); + } catch (error) { + // We want to log the user even if logging out from the server failed + // eslint-disable-next-line no-console + console.warn('An error ocurred loging out from the server', serverUrl, error); + } } - const {config, license}: { config: Partial; license: Partial; } = await getCommonSystemValues(database); + DeviceEventEmitter.emit(General.SERVER_LOGOUT, serverUrl); - if (!Object.keys(config)?.length || !Object.keys(license)?.length) { - return null; - } - - const token = Client4.getToken(); - - setServerCredentials(serverUrl, user.id, token); - - // Set timezone - if (isTimezoneEnabled(config)) { - const timezone = getDeviceTimezone(); - await autoUpdateTimezone(serverUrl, {deviceTimezone: timezone, userId: user.id}); - } - - let dataRetentionPolicy: any; - const operator = DatabaseManager.serverDatabases[Client4.getUrl()].operator; - - // Data retention - if (config?.DataRetentionEnableMessageDeletion === 'true' && license?.IsLicensed === 'true' && license?.DataRetention === 'true') { - dataRetentionPolicy = await getDataRetentionPolicy(serverUrl); - await operator.handleSystem({systems: [{id: 'dataRetentionPolicy', value: dataRetentionPolicy}], prepareRecordsOnly: false}); - } - - return null; + return {data: true}; }; -export const updateMe = async (serverUrl: string, user: User) => { - const database = DatabaseManager.serverDatabases[serverUrl].database; - const operator = DatabaseManager.serverDatabases[serverUrl].operator; - if (!database) { - return {error: `${serverUrl} database not found`}; - } - - let data; - try { - data = ((await Client4.patchMe(user._raw)) as unknown) as RawUser; - } catch (e) { - logError(e); - return {error: e}; - } - - const systemRecords = operator.handleSystem({ - systems: [ - {id: 'currentUserId', value: data.id}, - {id: 'locale', value: data?.locale}, - ], - prepareRecordsOnly: true, - }); - - const userRecord = operator.handleUsers({prepareRecordsOnly: true, users: [data]}); - - //todo: ?? Do we need to write to TOS table ? See app/mm-redux/reducers/entities/users.ts/profiles/line 152 const - // tosRecords = await DataOperator.handleIsolatedEntity({ tableName: TERMS_OF_SERVICE, values: [{}], }); - const models = await Promise.all([ - systemRecords, - userRecord, - - // ...tosRecords, - ]); - - if (models?.length) { - await operator.batchRecords(models.flat()); - } - - const updatedRoles: string[] = data.roles.split(' '); - if (updatedRoles.length) { - await loadRolesIfNeeded(serverUrl, updatedRoles); - } - - return {data}; -}; -export const getSessions = async (serverUrl: string, currentUserId: string) => { - try { - const sessions = await Client4.getSessions(currentUserId); - await createSessions(serverUrl, sessions); - } catch (e) { - logError(e); - await forceLogoutIfNecessary(serverUrl, e); - } -}; - -type LoadedUser = { - currentUser?: RawUser, - error?: Client4Error -} - -export const ssoLogin = async (serverUrl: string) => { +export const ssoLogin = async (serverUrl: string, bearerToken: string, csrfToken: string) => { let deviceToken; const database = DatabaseManager.appDatabase?.database; - if (!database) { return {error: 'App database not found'}; } + let client; + try { + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + + client.setBearerToken(bearerToken); + client.setCSRFToken(csrfToken); + // Setting up active database for this SSO login flow try { await DatabaseManager.createServerDatabase({ @@ -355,7 +319,7 @@ export const ssoLogin = async (serverUrl: string) => { }, }); await DatabaseManager.setActiveServerDatabase(serverUrl); - deviceToken = await getDeviceToken(database); + deviceToken = await queryDeviceToken(database); } catch (e) { return {error: e}; } @@ -363,28 +327,67 @@ export const ssoLogin = async (serverUrl: string) => { let result; try { - result = await loadMe(serverUrl, {deviceToken}) as unknown as LoadedUser; + result = (await loadMe(serverUrl, {deviceToken}) as unknown) as LoadedUser; if (!result?.error && result?.currentUser) { await completeLogin(serverUrl, result.currentUser); } } catch (e) { - return {error: e}; + return {error: undefined}; } return result; }; -export const sendPasswordResetEmail = async (email: string) => { - let data; +export const sendPasswordResetEmail = async (serverUrl: string, email: string) => { + let client; try { - data = await Client4.sendPasswordResetEmail(email); + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + + let response; + try { + response = await client.sendPasswordResetEmail(email); } catch (e) { return { error: e, }; } return { - data, + data: response.data, error: undefined, }; }; + +export const updateMe = async (serverUrl: string, user: User) => { + const database = DatabaseManager.serverDatabases[serverUrl]?.database; + const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; + if (!database) { + return {error: `${serverUrl} database not found`}; + } + + let client; + try { + client = NetworkManager.getClient(serverUrl); + } catch (error) { + return {error}; + } + + let data; + try { + data = (await client.patchMe(user._raw) as unknown) as RawUser; + } catch (e) { + logError(e); + return {error: e}; + } + + operator.handleUsers({prepareRecordsOnly: false, users: [data]}); + + const updatedRoles: string[] = data.roles.split(' '); + if (updatedRoles.length) { + await loadRolesIfNeeded(serverUrl, updatedRoles); + } + + return {data}; +}; diff --git a/app/client/rest/apps.ts b/app/client/rest/apps.ts index 08eb32d75..9e0ab0636 100644 --- a/app/client/rest/apps.ts +++ b/app/client/rest/apps.ts @@ -21,7 +21,7 @@ const ClientApps = (superclass: any) => class extends superclass { return this.doFetch( `${this.getAppsProxyRoute()}/api/v1/call`, - {method: 'post', body: JSON.stringify(callCopy)}, + {method: 'post', body: callCopy}, ); } diff --git a/app/client/rest/base.ts b/app/client/rest/base.ts index 14c4125e9..9935a31d3 100644 --- a/app/client/rest/base.ts +++ b/app/client/rest/base.ts @@ -1,143 +1,82 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {ClientOptions} from '@typings/api/client4'; -import urlParse from 'url-parse'; +import {DeviceEventEmitter} from 'react-native'; +import {General} from '@constants'; +import {t} from '@i18n'; import {Analytics, create} from '@init/analytics'; +import {setServerCredentials} from '@init/credentials'; + +import type { + APIClientInterface, + ClientHeaders, + ClientResponse, + RequestOptions, +} from '@mattermost/react-native-network-client'; + +import type {ClientOptions} from '@typings/api/client'; import * as ClientConstants from './constants'; import ClientError from './error'; export default class ClientBase { analytics: Analytics|undefined; - clusterId = ''; - csrf = ''; - defaultHeaders: {[x: string]: string} = {}; - diagnosticId = ''; - enableLogging = false; - includeCookies = true; - logToConsole = false; - managedConfig: any = null; + apiClient: APIClientInterface; + csrfToken = ''; + requestHeaders: {[x: string]: string} = {}; serverVersion = ''; - token = ''; - translations = { - connectionError: 'There appears to be a problem with your internet connection.', - unknownError: 'We received an unexpected status code from the server.', - }; - userAgent: string|null = null; - url = ''; urlVersion = '/api/v4'; - getAbsoluteUrl(baseUrl: string) { - if (typeof baseUrl !== 'string' || !baseUrl.startsWith('/')) { - return baseUrl; + constructor(apiClient: APIClientInterface, serverUrl: string, bearerToken?: string, csrfToken?: string) { + this.apiClient = apiClient; + this.analytics = create(serverUrl); + + if (bearerToken) { + this.setBearerToken(bearerToken); + } + if (csrfToken) { + this.setCSRFToken(csrfToken); } - return this.getUrl() + baseUrl; } - getOptions(options: ClientOptions) { - const newOptions: ClientOptions = {...options}; - - const headers: {[x: string]: string} = { - [ClientConstants.HEADER_REQUESTED_WITH]: 'XMLHttpRequest', - ...this.defaultHeaders, - }; - - if (this.token) { - headers[ClientConstants.HEADER_AUTH] = `${ClientConstants.HEADER_BEARER} ${this.token}`; + invalidate() { + if (this.apiClient) { + this.apiClient.invalidate(); } - - const csrfToken = this.csrf || ''; - if (options.method && options.method.toLowerCase() !== 'get' && csrfToken) { - headers[ClientConstants.HEADER_X_CSRF_TOKEN] = csrfToken; - } - - if (this.includeCookies) { - newOptions.credentials = 'include'; - } - - if (this.userAgent) { - headers[ClientConstants.HEADER_USER_AGENT] = this.userAgent; - } - - if (newOptions.headers) { - Object.assign(headers, newOptions.headers); - } - - return { - ...newOptions, - headers, - }; } - getServerVersion() { - return this.serverVersion; - } + getRequestHeaders(requestMethod: string) { + const headers = {...this.requestHeaders}; - getToken() { - return this.token; - } + if (this.csrfToken && requestMethod.toLowerCase() !== 'get') { + headers[ClientConstants.HEADER_X_CSRF_TOKEN] = this.csrfToken; + } - getUrl() { - return this.url; - } - - getUrlVersion() { - return this.urlVersion; + return headers; } getWebSocketUrl = () => { - return `${this.getBaseRoute()}/websocket`; + return `${this.urlVersion}/websocket`; } setAcceptLanguage(locale: string) { - this.defaultHeaders['Accept-Language'] = locale; + this.requestHeaders[ClientConstants.HEADER_ACCEPT_LANGUAGE] = locale; } - setCSRF(csrfToken: string) { - this.csrf = csrfToken; + setBearerToken(bearerToken: string) { + this.requestHeaders[ClientConstants.HEADER_AUTH] = `${ClientConstants.HEADER_BEARER} ${bearerToken}`; + setServerCredentials(this.apiClient.baseUrl, bearerToken); } - setDiagnosticId(diagnosticId: string) { - this.diagnosticId = diagnosticId; - } - - setEnableLogging(enable: boolean) { - this.enableLogging = enable; - } - - setIncludeCookies(include: boolean) { - this.includeCookies = include; - } - - setManagedConfig(config: any) { - this.managedConfig = config; - } - - setUserAgent(userAgent: string) { - this.userAgent = userAgent; - } - - setToken(token: string) { - this.token = token; - } - - setUrl(url: string) { - this.url = url.replace(/\/+$/, ''); - this.analytics = create(this.url); + setCSRFToken(csrfToken: string) { + this.csrfToken = csrfToken; } // Routes - getBaseRoute() { - return `${this.url}${this.urlVersion}`; - } getUsersRoute() { - return `${this.getBaseRoute()}/users`; + return `${this.urlVersion}/users`; } getUserRoute(userId: string) { @@ -145,7 +84,7 @@ export default class ClientBase { } getTeamsRoute() { - return `${this.getBaseRoute()}/teams`; + return `${this.urlVersion}/teams`; } getTeamRoute(teamId: string) { @@ -165,7 +104,7 @@ export default class ClientBase { } getChannelsRoute() { - return `${this.getBaseRoute()}/channels`; + return `${this.urlVersion}/channels`; } getChannelRoute(channelId: string) { @@ -181,7 +120,7 @@ export default class ClientBase { } getPostsRoute() { - return `${this.getBaseRoute()}/posts`; + return `${this.urlVersion}/posts`; } getPostRoute(postId: string) { @@ -189,15 +128,15 @@ export default class ClientBase { } getReactionsRoute() { - return `${this.getBaseRoute()}/reactions`; + return `${this.urlVersion}/reactions`; } getCommandsRoute() { - return `${this.getBaseRoute()}/commands`; + return `${this.urlVersion}/commands`; } getFilesRoute() { - return `${this.getBaseRoute()}/files`; + return `${this.urlVersion}/files`; } getFileRoute(fileId: string) { @@ -208,168 +147,104 @@ export default class ClientBase { return `${this.getUserRoute(userId)}/preferences`; } - getIncomingHooksRoute() { - return `${this.getBaseRoute()}/hooks/incoming`; - } - - getIncomingHookRoute(hookId: string) { - return `${this.getBaseRoute()}/hooks/incoming/${hookId}`; - } - - getOutgoingHooksRoute() { - return `${this.getBaseRoute()}/hooks/outgoing`; - } - - getOutgoingHookRoute(hookId: string) { - return `${this.getBaseRoute()}/hooks/outgoing/${hookId}`; - } - - getOAuthRoute() { - return `${this.url}/oauth`; - } - - getOAuthAppsRoute() { - return `${this.getBaseRoute()}/oauth/apps`; - } - - getOAuthAppRoute(appId: string) { - return `${this.getOAuthAppsRoute()}/${appId}`; - } - getEmojisRoute() { - return `${this.getBaseRoute()}/emoji`; + return `${this.urlVersion}/emoji`; } getEmojiRoute(emojiId: string) { return `${this.getEmojisRoute()}/${emojiId}`; } - getBrandRoute() { - return `${this.getBaseRoute()}/brand`; - } - - getBrandImageUrl(timestamp: string) { - return `${this.getBrandRoute()}/image?t=${timestamp}`; - } - getDataRetentionRoute() { - return `${this.getBaseRoute()}/data_retention`; + return `${this.urlVersion}/data_retention`; } getRolesRoute() { - return `${this.getBaseRoute()}/roles`; + return `${this.urlVersion}/roles`; } getTimezonesRoute() { - return `${this.getBaseRoute()}/system/timezones`; + return `${this.urlVersion}/system/timezones`; } getRedirectLocationRoute() { - return `${this.getBaseRoute()}/redirect_location`; - } - - getBotsRoute() { - return `${this.getBaseRoute()}/bots`; - } - - getBotRoute(botUserId: string) { - return `${this.getBotsRoute()}/${botUserId}`; + return `${this.urlVersion}/redirect_location`; } getAppsProxyRoute() { - return `${this.url}/plugins/com.mattermost.apps`; + return '/plugins/com.mattermost.apps'; } - // Client Helpers - handleRedirectProtocol = (url: string, response: Response) => { - const serverUrl = this.getUrl(); - const parsed = urlParse(url); - - if (response.redirected) { - const redirectUrl = urlParse(response.url); - - if (serverUrl === parsed.origin && parsed.host === redirectUrl.host && parsed.protocol !== redirectUrl.protocol) { - this.setUrl(serverUrl.replace(parsed.protocol, redirectUrl.protocol)); - } + doFetch = async (url: string, options: ClientOptions, returnDataOnly = true) => { + let request; + const method = options.method?.toLowerCase(); + switch (method) { + case 'get': + request = this.apiClient!.get; + break; + case 'put': + request = this.apiClient!.put; + break; + case 'post': + request = this.apiClient!.post; + break; + case 'patch': + request = this.apiClient!.patch; + break; + case 'delete': + request = this.apiClient!.delete; + break; + default: + throw new ClientError(this.apiClient.baseUrl, { + message: 'Invalid request method', + intl: { + id: t('mobile.request.invalid_request_method'), + defaultMessage: 'Invalid request method', + }, + url, + }); } - }; - doFetch = async (url: string, options: ClientOptions) => { - const {data} = await this.doFetchWithResponse(url, options); - - return data; - }; - - doFetchWithResponse = async (url: string, options: ClientOptions) => { - const response = await fetch(url, this.getOptions(options)); - const headers = parseAndMergeNestedHeaders(response.headers); - - let data; + const requestOptions: RequestOptions = { + body: options.body, + headers: this.getRequestHeaders(method), + }; + let response: ClientResponse; try { - data = await response.json(); - } catch (err) { - throw new ClientError(this.getUrl(), { + response = await request!(url, requestOptions); + } catch (error) { + throw new ClientError(this.apiClient.baseUrl, { message: 'Received invalid response from the server.', intl: { - id: 'mobile.request.invalid_response', + id: t('mobile.request.invalid_response'), defaultMessage: 'Received invalid response from the server.', }, url, }); } - if (headers.has(ClientConstants.HEADER_X_VERSION_ID) && !headers.get('Cache-Control')) { - const serverVersion = headers.get(ClientConstants.HEADER_X_VERSION_ID); - if (serverVersion && this.serverVersion !== serverVersion) { - this.serverVersion = serverVersion; - } + const headers: ClientHeaders = response.headers || {}; + const serverVersion = headers[ClientConstants.HEADER_X_VERSION_ID] || headers[ClientConstants.HEADER_X_VERSION_ID.toLowerCase()]; + const hasCacheControl = Boolean(headers[ClientConstants.HEADER_CACHE_CONTROL] || headers[ClientConstants.HEADER_CACHE_CONTROL.toLowerCase()]); + if (serverVersion && !hasCacheControl && this.serverVersion !== serverVersion) { + this.serverVersion = serverVersion; + DeviceEventEmitter.emit(General.SERVER_VERSION_CHANGED, {serverUrl: this.apiClient.baseUrl, serverVersion}); } - if (headers.has(ClientConstants.HEADER_X_CLUSTER_ID)) { - const clusterId = headers.get(ClientConstants.HEADER_X_CLUSTER_ID); - if (clusterId && this.clusterId !== clusterId) { - this.clusterId = clusterId; - } + const bearerToken = headers[ClientConstants.HEADER_TOKEN] || headers[ClientConstants.HEADER_TOKEN.toLowerCase()]; + if (bearerToken) { + this.setBearerToken(bearerToken); } if (response.ok) { - return { - response, - headers, - data, - }; + return returnDataOnly ? response.data : response; } - const msg = data.message || ''; - - if (this.logToConsole) { - console.error(msg); // eslint-disable-line no-console - } - - throw new ClientError(this.getUrl(), { - message: msg, - server_error_id: data.id, - status_code: data.status_code, + throw new ClientError(this.apiClient.baseUrl, { + message: response.data?.message || '', + server_error_id: response.data?.id, + status_code: response.code, url, }); }; } - -function parseAndMergeNestedHeaders(originalHeaders: any) { - const headers = new Map(); - let nestedHeaders = new Map(); - originalHeaders.forEach((val: string, key: string) => { - const capitalizedKey = key.replace(/\b[a-z]/g, (l) => l.toUpperCase()); - let realVal = val; - if (val && val.match(/\n\S+:\s\S+/)) { - const nestedHeaderStrings = val.split('\n'); - realVal = nestedHeaderStrings.shift() as string; - const moreNestedHeaders = new Map( - nestedHeaderStrings.map((h: any) => h.split(/:\s/)), - ); - nestedHeaders = new Map([...nestedHeaders, ...moreNestedHeaders]); - } - headers.set(capitalizedKey, realVal); - }); - return new Map([...headers, ...nestedHeaders]); -} diff --git a/app/client/rest/bots.ts b/app/client/rest/bots.ts deleted file mode 100644 index b0636e10e..000000000 --- a/app/client/rest/bots.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {buildQueryString} from '@utils/helpers'; - -export interface ClientBotsMix { - getBot: (botUserId: string) => Promise; - getBots: (page?: number, perPage?: number) => Promise; - getBotsIncludeDeleted: (page?: number, perPage?: number) => Promise; -} - -const PER_PAGE_DEFAULT = 60; - -const ClientBots = (superclass: any) => class extends superclass { - getBot = async (botUserId: string) => { - return this.doFetch( - `${this.getBotRoute(botUserId)}`, - {method: 'get'}, - ); - } - - getBots = async (page = 0, perPage = PER_PAGE_DEFAULT) => { - return this.doFetch( - `${this.getBotsRoute()}${buildQueryString({page, per_page: perPage})}`, - {method: 'get'}, - ); - } - - getBotsIncludeDeleted = async (page = 0, perPage = PER_PAGE_DEFAULT) => { - return this.doFetch( - `${this.getBotsRoute()}${buildQueryString({include_deleted: true, page, per_page: perPage})}`, - {method: 'get'}, - ); - } -}; - -export default ClientBots; diff --git a/app/client/rest/channels.ts b/app/client/rest/channels.ts index 5c99a771d..8fd1b9594 100644 --- a/app/client/rest/channels.ts +++ b/app/client/rest/channels.ts @@ -60,7 +60,7 @@ const ClientChannels = (superclass: any) => class extends superclass { return this.doFetch( `${this.getChannelsRoute()}`, - {method: 'post', body: JSON.stringify(channel)}, + {method: 'post', body: channel}, ); }; @@ -69,7 +69,7 @@ const ClientChannels = (superclass: any) => class extends superclass { return this.doFetch( `${this.getChannelsRoute()}/direct`, - {method: 'post', body: JSON.stringify(userIds)}, + {method: 'post', body: userIds}, ); }; @@ -78,7 +78,7 @@ const ClientChannels = (superclass: any) => class extends superclass { return this.doFetch( `${this.getChannelsRoute()}/group`, - {method: 'post', body: JSON.stringify(userIds)}, + {method: 'post', body: userIds}, ); }; @@ -105,7 +105,7 @@ const ClientChannels = (superclass: any) => class extends superclass { return this.doFetch( `${this.getChannelRoute(channel.id)}`, - {method: 'put', body: JSON.stringify(channel)}, + {method: 'put', body: channel}, ); }; @@ -123,7 +123,7 @@ const ClientChannels = (superclass: any) => class extends superclass { return this.doFetch( `${this.getChannelRoute(channelId)}/privacy`, - {method: 'put', body: JSON.stringify({privacy})}, + {method: 'put', body: {privacy}}, ); }; @@ -132,7 +132,7 @@ const ClientChannels = (superclass: any) => class extends superclass { return this.doFetch( `${this.getChannelRoute(channelId)}/patch`, - {method: 'put', body: JSON.stringify(channelPatch)}, + {method: 'put', body: channelPatch}, ); }; @@ -141,7 +141,7 @@ const ClientChannels = (superclass: any) => class extends superclass { return this.doFetch( `${this.getChannelMemberRoute(props.channel_id, props.user_id)}/notify_props`, - {method: 'put', body: JSON.stringify(props)}, + {method: 'put', body: props}, ); }; @@ -232,7 +232,7 @@ const ClientChannels = (superclass: any) => class extends superclass { getChannelMembersByIds = async (channelId: string, userIds: string[]) => { return this.doFetch( `${this.getChannelMembersRoute(channelId)}/ids`, - {method: 'post', body: JSON.stringify(userIds)}, + {method: 'post', body: userIds}, ); }; @@ -242,7 +242,7 @@ const ClientChannels = (superclass: any) => class extends superclass { const member = {user_id: userId, channel_id: channelId, post_root_id: postRootId}; return this.doFetch( `${this.getChannelMembersRoute(channelId)}`, - {method: 'post', body: JSON.stringify(member)}, + {method: 'post', body: member}, ); }; @@ -273,7 +273,7 @@ const ClientChannels = (superclass: any) => class extends superclass { const data = {channel_id: channelId, prev_channel_id: prevChannelId}; return this.doFetch( `${this.getChannelsRoute()}/members/me/view`, - {method: 'post', body: JSON.stringify(data)}, + {method: 'post', body: data}, ); }; @@ -294,14 +294,14 @@ const ClientChannels = (superclass: any) => class extends superclass { searchChannels = async (teamId: string, term: string) => { return this.doFetch( `${this.getTeamRoute(teamId)}/channels/search`, - {method: 'post', body: JSON.stringify({term})}, + {method: 'post', body: {term}}, ); }; searchArchivedChannels = async (teamId: string, term: string) => { return this.doFetch( `${this.getTeamRoute(teamId)}/channels/search_archived`, - {method: 'post', body: JSON.stringify({term})}, + {method: 'post', body: {term}}, ); }; }; diff --git a/app/client/rest/constants.ts b/app/client/rest/constants.ts index c1b260485..221191379 100644 --- a/app/client/rest/constants.ts +++ b/app/client/rest/constants.ts @@ -2,12 +2,13 @@ // See LICENSE.txt for license information. export const HEADER_AUTH = 'Authorization'; +export const HEADER_ACCEPT_LANGUAGE = 'Accept-Language'; export const HEADER_BEARER = 'BEARER'; +export const HEADER_CACHE_CONTROL = 'Cache-Control'; export const HEADER_REQUESTED_WITH = 'X-Requested-With'; -export const HEADER_USER_AGENT = 'User-Agent'; -export const HEADER_X_CLUSTER_ID = 'X-Cluster-Id'; -export const HEADER_X_CSRF_TOKEN = 'X-CSRF-Token'; export const HEADER_TOKEN = 'Token'; +export const HEADER_USER_AGENT = 'User-Agent'; +export const HEADER_X_CSRF_TOKEN = 'X-CSRF-Token'; export const HEADER_X_VERSION_ID = 'X-Version-Id'; export const DEFAULT_LIMIT_BEFORE = 30; export const DEFAULT_LIMIT_AFTER = 30; diff --git a/app/client/rest/emojis.ts b/app/client/rest/emojis.ts index 170ca63e1..a946f02d6 100644 --- a/app/client/rest/emojis.ts +++ b/app/client/rest/emojis.ts @@ -84,7 +84,7 @@ const ClientEmojis = (superclass: any) => class extends superclass { searchCustomEmoji = async (term: string, options = {}) => { return this.doFetch( `${this.getEmojisRoute()}/search`, - {method: 'post', body: JSON.stringify({term, ...options})}, + {method: 'post', body: {term, ...options}}, ); }; diff --git a/app/client/rest/general.ts b/app/client/rest/general.ts index 307781711..ecff9d770 100644 --- a/app/client/rest/general.ts +++ b/app/client/rest/general.ts @@ -10,7 +10,7 @@ export interface ClientGeneralMix { ping: () => Promise; logClientError: (message: string, level?: string) => Promise; getClientConfigOld: () => Promise; - getClientLicenseOld: () => Promise; + getClientLicenseOld: () => Promise; getTimezones: () => Promise; getDataRetentionPolicy: () => Promise; getRolesByNames: (rolesNames: string[]) => Promise; @@ -20,23 +20,24 @@ export interface ClientGeneralMix { const ClientGeneral = (superclass: any) => class extends superclass { getOpenGraphMetadata = async (url: string) => { return this.doFetch( - `${this.getBaseRoute()}/opengraph`, - {method: 'post', body: JSON.stringify({url})}, + `${this.urlVersion}/opengraph`, + {method: 'post', body: {url}}, ); }; ping = async () => { return this.doFetch( - `${this.getBaseRoute()}/system/ping?time=${Date.now()}`, + `${this.urlVersion}/system/ping?time=${Date.now()}`, {method: 'get'}, + false, ); }; logClientError = async (message: string, level = 'ERROR') => { - const url = `${this.getBaseRoute()}/logs`; + const url = `${this.urlVersion}/logs`; if (!this.enableLogging) { - throw new ClientError(this.getUrl(), { + throw new ClientError(this.client.baseUrl, { message: 'Logging disabled.', url, }); @@ -44,20 +45,20 @@ const ClientGeneral = (superclass: any) => class extends superclass { return this.doFetch( url, - {method: 'post', body: JSON.stringify({message, level})}, + {method: 'post', body: {message, level}}, ); }; getClientConfigOld = async () => { return this.doFetch( - `${this.getBaseRoute()}/config/client?format=old`, + `${this.urlVersion}/config/client?format=old`, {method: 'get'}, ); }; getClientLicenseOld = async () => { return this.doFetch( - `${this.getBaseRoute()}/license/client?format=old`, + `${this.urlVersion}/license/client?format=old`, {method: 'get'}, ); }; @@ -79,7 +80,7 @@ const ClientGeneral = (superclass: any) => class extends superclass { getRolesByNames = async (rolesNames: string[]) => { return this.doFetch( `${this.getRolesRoute()}/names`, - {method: 'post', body: JSON.stringify(rolesNames)}, + {method: 'post', body: rolesNames}, ); }; diff --git a/app/client/rest/groups.ts b/app/client/rest/groups.ts index 324791602..28a6fb33e 100644 --- a/app/client/rest/groups.ts +++ b/app/client/rest/groups.ts @@ -16,7 +16,7 @@ export interface ClientGroupsMix { const ClientGroups = (superclass: any) => class extends superclass { getGroups = async (filterAllowReference = false, page = 0, perPage = PER_PAGE_DEFAULT, since = 0) => { return this.doFetch( - `${this.getBaseRoute()}/groups${buildQueryString({filter_allow_reference: filterAllowReference, page, per_page: perPage, since})}`, + `${this.urlVersion}/groups${buildQueryString({filter_allow_reference: filterAllowReference, page, per_page: perPage, since})}`, {method: 'get'}, ); }; @@ -29,21 +29,21 @@ const ClientGroups = (superclass: any) => class extends superclass { } getAllGroupsAssociatedToTeam = async (teamID: string, filterAllowReference = false) => { return this.doFetch( - `${this.getBaseRoute()}/teams/${teamID}/groups${buildQueryString({paginate: false, filter_allow_reference: filterAllowReference})}`, + `${this.urlVersion}/teams/${teamID}/groups${buildQueryString({paginate: false, filter_allow_reference: filterAllowReference})}`, {method: 'get'}, ); }; getAllGroupsAssociatedToChannelsInTeam = async (teamID: string, filterAllowReference = false) => { return this.doFetch( - `${this.getBaseRoute()}/teams/${teamID}/groups_by_channels${buildQueryString({paginate: false, filter_allow_reference: filterAllowReference})}`, + `${this.urlVersion}/teams/${teamID}/groups_by_channels${buildQueryString({paginate: false, filter_allow_reference: filterAllowReference})}`, {method: 'get'}, ); }; getAllGroupsAssociatedToChannel = async (channelID: string, filterAllowReference = false) => { return this.doFetch( - `${this.getBaseRoute()}/channels/${channelID}/groups${buildQueryString({paginate: false, filter_allow_reference: filterAllowReference})}`, + `${this.urlVersion}/channels/${channelID}/groups${buildQueryString({paginate: false, filter_allow_reference: filterAllowReference})}`, {method: 'get'}, ); }; diff --git a/app/client/rest/index.test.js b/app/client/rest/index.test.js index fc9b65565..807957664 100644 --- a/app/client/rest/index.test.js +++ b/app/client/rest/index.test.js @@ -9,7 +9,7 @@ import ClientError from '@client/rest/error'; import TestHelper from '@test/test_helper'; import {isMinimumServerVersion} from '@utils/helpers'; -describe('Client4', () => { +describe('Client', () => { beforeAll(() => { if (!nock.isActive()) { nock.activate(); @@ -20,25 +20,18 @@ describe('Client4', () => { nock.restore(); }); - it('should remove trailing slash while trying to setUrl', () => { - const client = TestHelper.createClient(); - - client.setUrl('http://localhost:8065/'); - expect(client.url).toBe('http://localhost:8065'); - - client.setUrl('http://localhost:8065/company/mattermost/'); - expect(client.url).toBe('http://localhost:8065/company/mattermost'); - }); - - describe('doFetchWithResponse', () => { + describe('doFetch', () => { it('serverVersion should be set from response header', async () => { const client = TestHelper.createClient(); assert.equal(client.serverVersion, ''); - nock(client.getBaseRoute()). - get('/users/me'). - reply(200, '{}', {[HEADER_X_VERSION_ID]: '5.0.0.5.0.0.abc123'}); + client.apiClient.get.mockReturnValueOnce({ + code: 200, + data: {}, + headers: {[HEADER_X_VERSION_ID]: '5.0.0.5.0.0.abc123'}, + ok: true, + }); await client.getMe(); @@ -46,9 +39,12 @@ describe('Client4', () => { assert.equal(isMinimumServerVersion(client.serverVersion, 5, 0, 0), true); assert.equal(isMinimumServerVersion(client.serverVersion, 5, 1, 0), false); - nock(client.getBaseRoute()). - get('/users/me'). - reply(200, '{}', {[HEADER_X_VERSION_ID]: '5.3.0.5.3.0.abc123'}); + client.apiClient.get.mockReturnValueOnce({ + code: 200, + data: {}, + headers: {[HEADER_X_VERSION_ID]: '5.3.0.5.3.0.abc123'}, + ok: true, + }); await client.getMe(); diff --git a/app/client/rest/index.ts b/app/client/rest/index.ts index 611648c4e..9107cb1d3 100644 --- a/app/client/rest/index.ts +++ b/app/client/rest/index.ts @@ -6,7 +6,6 @@ import mix from '@utils/mix'; import {DEFAULT_LIMIT_AFTER, DEFAULT_LIMIT_BEFORE, HEADER_X_VERSION_ID} from './constants'; import ClientApps, {ClientAppsMix} from './apps'; import ClientBase from './base'; -import ClientBots, {ClientBotsMix} from './bots'; import ClientChannels, {ClientChannelsMix} from './channels'; import ClientEmojis, {ClientEmojisMix} from './emojis'; import ClientFiles, {ClientFilesMix} from './files'; @@ -19,9 +18,10 @@ import ClientTeams, {ClientTeamsMix} from './teams'; import ClientTos, {ClientTosMix} from './tos'; import ClientUsers, {ClientUsersMix} from './users'; +import type {APIClientInterface} from '@mattermost/react-native-network-client'; + interface Client extends ClientBase, ClientAppsMix, - ClientBotsMix, ClientChannelsMix, ClientEmojisMix, ClientFilesMix, @@ -37,7 +37,6 @@ interface Client extends ClientBase, class Client extends mix(ClientBase).with( ClientApps, - ClientBots, ClientChannels, ClientEmojis, ClientFiles, @@ -49,8 +48,11 @@ class Client extends mix(ClientBase).with( ClientTeams, ClientTos, ClientUsers, -) {} +) { + // eslint-disable-next-line no-useless-constructor + constructor(apiClient: APIClientInterface, serverUrl: string, bearerToken?: string, csrfToken?: string) { + super(apiClient, serverUrl, bearerToken, csrfToken); + } +} -const Client4 = new Client(); - -export {Client4, Client, DEFAULT_LIMIT_AFTER, DEFAULT_LIMIT_BEFORE, HEADER_X_VERSION_ID}; +export {Client, DEFAULT_LIMIT_AFTER, DEFAULT_LIMIT_BEFORE, HEADER_X_VERSION_ID}; diff --git a/app/client/rest/integrations.ts b/app/client/rest/integrations.ts index 003c2f530..74aca38ad 100644 --- a/app/client/rest/integrations.ts +++ b/app/client/rest/integrations.ts @@ -41,7 +41,7 @@ const ClientIntegrations = (superclass: any) => class extends superclass { return this.doFetch( `${this.getCommandsRoute()}/execute`, - {method: 'post', body: JSON.stringify({command, ...commandArgs})}, + {method: 'post', body: {command, ...commandArgs}}, ); }; @@ -50,15 +50,15 @@ const ClientIntegrations = (superclass: any) => class extends superclass { return this.doFetch( `${this.getCommandsRoute()}`, - {method: 'post', body: JSON.stringify(command)}, + {method: 'post', body: command}, ); }; submitInteractiveDialog = async (data: DialogSubmission) => { this.analytics.trackAPI('api_interactive_messages_dialog_submitted'); return this.doFetch( - `${this.getBaseRoute()}/actions/dialogs/submit`, - {method: 'post', body: JSON.stringify(data)}, + `${this.urlVersion}/actions/dialogs/submit`, + {method: 'post', body: data}, ); }; }; diff --git a/app/client/rest/posts.ts b/app/client/rest/posts.ts index bc4026e44..0d0a763e5 100644 --- a/app/client/rest/posts.ts +++ b/app/client/rest/posts.ts @@ -41,7 +41,7 @@ const ClientPosts = (superclass: any) => class extends superclass { return this.doFetch( `${this.getPostsRoute()}`, - {method: 'post', body: JSON.stringify(post)}, + {method: 'post', body: post}, ); }; @@ -50,7 +50,7 @@ const ClientPosts = (superclass: any) => class extends superclass { return this.doFetch( `${this.getPostRoute(post.id)}`, - {method: 'put', body: JSON.stringify(post)}, + {method: 'put', body: post}, ); }; @@ -66,7 +66,7 @@ const ClientPosts = (superclass: any) => class extends superclass { return this.doFetch( `${this.getPostRoute(postPatch.id)}/patch`, - {method: 'put', body: JSON.stringify(postPatch)}, + {method: 'put', body: postPatch}, ); }; @@ -174,7 +174,7 @@ const ClientPosts = (superclass: any) => class extends superclass { return this.doFetch( `${this.getReactionsRoute()}`, - {method: 'post', body: JSON.stringify({user_id: userId, post_id: postId, emoji_name: emojiName})}, + {method: 'post', body: {user_id: userId, post_id: postId, emoji_name: emojiName}}, ); }; @@ -199,7 +199,7 @@ const ClientPosts = (superclass: any) => class extends superclass { return this.doFetch( `${this.getTeamRoute(teamId)}/posts/search`, - {method: 'post', body: JSON.stringify(params)}, + {method: 'post', body: params}, ); }; @@ -226,7 +226,7 @@ const ClientPosts = (superclass: any) => class extends superclass { } return this.doFetch( `${this.getPostRoute(postId)}/actions/${encodeURIComponent(actionId)}`, - {method: 'post', body: JSON.stringify(msg)}, + {method: 'post', body: msg}, ); }; }; diff --git a/app/client/rest/preferences.ts b/app/client/rest/preferences.ts index 450bd9414..6c827393a 100644 --- a/app/client/rest/preferences.ts +++ b/app/client/rest/preferences.ts @@ -11,7 +11,7 @@ const ClientPreferences = (superclass: any) => class extends superclass { savePreferences = async (userId: string, preferences: PreferenceType[]) => { return this.doFetch( `${this.getPreferencesRoute(userId)}`, - {method: 'put', body: JSON.stringify(preferences)}, + {method: 'put', body: preferences}, ); }; @@ -25,7 +25,7 @@ const ClientPreferences = (superclass: any) => class extends superclass { deletePreferences = async (userId: string, preferences: PreferenceType[]) => { return this.doFetch( `${this.getPreferencesRoute(userId)}/delete`, - {method: 'post', body: JSON.stringify(preferences)}, + {method: 'post', body: preferences}, ); }; }; diff --git a/app/client/rest/teams.ts b/app/client/rest/teams.ts index 4cc4fc79e..25b18d1b9 100644 --- a/app/client/rest/teams.ts +++ b/app/client/rest/teams.ts @@ -32,7 +32,7 @@ const ClientTeams = (superclass: any) => class extends superclass { return this.doFetch( `${this.getTeamsRoute()}`, - {method: 'post', body: JSON.stringify(team)}, + {method: 'post', body: team}, ); }; @@ -50,7 +50,7 @@ const ClientTeams = (superclass: any) => class extends superclass { return this.doFetch( `${this.getTeamRoute(team.id)}`, - {method: 'put', body: JSON.stringify(team)}, + {method: 'put', body: team}, ); }; @@ -59,7 +59,7 @@ const ClientTeams = (superclass: any) => class extends superclass { return this.doFetch( `${this.getTeamRoute(team.id)}/patch`, - {method: 'put', body: JSON.stringify(team)}, + {method: 'put', body: team}, ); }; @@ -134,7 +134,7 @@ const ClientTeams = (superclass: any) => class extends superclass { const member = {user_id: userId, team_id: teamId}; return this.doFetch( `${this.getTeamMembersRoute(teamId)}`, - {method: 'post', body: JSON.stringify(member)}, + {method: 'post', body: member}, ); }; diff --git a/app/client/rest/tos.ts b/app/client/rest/tos.ts index 997080bcf..de18d557a 100644 --- a/app/client/rest/tos.ts +++ b/app/client/rest/tos.ts @@ -10,13 +10,13 @@ const ClientTos = (superclass: any) => class extends superclass { updateMyTermsOfServiceStatus = async (termsOfServiceId: string, accepted: boolean) => { return this.doFetch( `${this.getUserRoute('me')}/terms_of_service`, - {method: 'post', body: JSON.stringify({termsOfServiceId, accepted})}, + {method: 'post', body: {termsOfServiceId, accepted}}, ); } getTermsOfService = async () => { return this.doFetch( - `${this.getBaseRoute()}/terms_of_service`, + `${this.urlVersion}/terms_of_service`, {method: 'get'}, ); } diff --git a/app/client/rest/users.ts b/app/client/rest/users.ts index bef25f181..c5aae2b60 100644 --- a/app/client/rest/users.ts +++ b/app/client/rest/users.ts @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import {General} from '@constants'; -import {buildQueryString, isMinimumServerVersion} from '@utils/helpers'; +import {buildQueryString} from '@utils/helpers'; import {PER_PAGE_DEFAULT} from './constants'; @@ -34,7 +34,7 @@ export interface ClientUsersMix { getProfilePictureUrl: (userId: string, lastPictureUpdate: number) => string; getDefaultProfilePictureUrl: (userId: string) => string; autocompleteUsers: (name: string, teamId: string, channelId: string, options?: Record) => Promise<{users: UserProfile[], out_of_channel?: UserProfile[]}>; - getSessions: (userId: string) => Promise; + getSessions: (userId: string) => Promise; checkUserMfa: (loginId: string) => Promise<{mfa_required: boolean}>; attachDevice: (deviceId: string) => Promise; searchUsers: (term: string, options: any) => Promise; @@ -59,14 +59,14 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUsersRoute()}${buildQueryString(queryParams)}`, - {method: 'post', body: JSON.stringify(user)}, + {method: 'post', body: user}, ); } patchMe = async (userPatch: Partial) => { return this.doFetch( `${this.getUserRoute('me')}/patch`, - {method: 'put', body: JSON.stringify(userPatch)}, + {method: 'put', body: userPatch}, ); } @@ -75,7 +75,7 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUserRoute(userPatch.id)}/patch`, - {method: 'put', body: JSON.stringify(userPatch)}, + {method: 'put', body: userPatch}, ); } @@ -84,7 +84,7 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUserRoute(user.id)}`, - {method: 'put', body: JSON.stringify(user)}, + {method: 'put', body: user}, ); } @@ -111,7 +111,7 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUsersRoute()}/password/reset/send`, - {method: 'post', body: JSON.stringify({email})}, + {method: 'post', body: {email}}, ); } @@ -142,13 +142,14 @@ const ClientUsers = (superclass: any) => class extends superclass { body.ldap_only = 'true'; } - const {data} = await this.doFetchWithResponse( + const {data} = await this.doFetch( `${this.getUsersRoute()}/login`, { method: 'post', - body: JSON.stringify(body), + body, headers: {'Cache-Control': 'no-store'}, }, + false, ); return data; @@ -163,9 +164,9 @@ const ClientUsers = (superclass: any) => class extends superclass { token, }; - const {data} = await this.doFetchWithResponse( + const {data} = await this.doFetch( `${this.getUsersRoute()}/login`, - {method: 'post', body: JSON.stringify(body)}, + {method: 'post', body}, ); return data; @@ -174,17 +175,11 @@ const ClientUsers = (superclass: any) => class extends superclass { logout = async () => { this.analytics.trackAPI('api_users_logout'); - const {response} = await this.doFetchWithResponse( + const response = await this.doFetch( `${this.getUsersRoute()}/logout`, {method: 'post'}, ); - if (response.ok) { - this.token = ''; - } - - this.serverVersion = ''; - return response; }; @@ -202,7 +197,7 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUsersRoute()}/ids${buildQueryString(options)}`, - {method: 'post', body: JSON.stringify(userIds)}, + {method: 'post', body: userIds}, ); }; @@ -211,7 +206,7 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUsersRoute()}/usernames`, - {method: 'post', body: JSON.stringify(usernames)}, + {method: 'post', body: usernames}, ); }; @@ -250,13 +245,7 @@ const ClientUsers = (superclass: any) => class extends superclass { getProfilesInChannel = async (channelId: string, page = 0, perPage = PER_PAGE_DEFAULT, sort = '') => { this.analytics.trackAPI('api_profiles_get_in_channel', {channel_id: channelId}); - const serverVersion = this.getServerVersion(); - let queryStringObj; - if (isMinimumServerVersion(serverVersion, 4, 7)) { - queryStringObj = {in_channel: channelId, page, per_page: perPage, sort}; - } else { - queryStringObj = {in_channel: channelId, page, per_page: perPage}; - } + const queryStringObj = {in_channel: channelId, page, per_page: perPage, sort}; return this.doFetch( `${this.getUsersRoute()}${buildQueryString(queryStringObj)}`, {method: 'get'}, @@ -268,7 +257,7 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUsersRoute()}/group_channels`, - {method: 'post', body: JSON.stringify(channelsIds)}, + {method: 'post', body: channelsIds}, ); }; @@ -351,14 +340,14 @@ const ClientUsers = (superclass: any) => class extends superclass { checkUserMfa = async (loginId: string) => { return this.doFetch( `${this.getUsersRoute()}/mfa`, - {method: 'post', body: JSON.stringify({login_id: loginId})}, + {method: 'post', body: {login_id: loginId}}, ); }; attachDevice = async (deviceId: string) => { return this.doFetch( `${this.getUsersRoute()}/sessions/device`, - {method: 'put', body: JSON.stringify({device_id: deviceId})}, + {method: 'put', body: {device_id: deviceId}}, ); }; @@ -367,14 +356,14 @@ const ClientUsers = (superclass: any) => class extends superclass { return this.doFetch( `${this.getUsersRoute()}/search`, - {method: 'post', body: JSON.stringify({term, ...options})}, + {method: 'post', body: {term, ...options}}, ); }; getStatusesByIds = async (userIds: string[]) => { return this.doFetch( `${this.getUsersRoute()}/status/ids`, - {method: 'post', body: JSON.stringify(userIds)}, + {method: 'post', body: userIds}, ); }; @@ -388,7 +377,7 @@ const ClientUsers = (superclass: any) => class extends superclass { updateStatus = async (status: UserStatus) => { return this.doFetch( `${this.getUserRoute(status.user_id)}/status`, - {method: 'put', body: JSON.stringify(status)}, + {method: 'put', body: status}, ); }; }; diff --git a/app/constants/database.ts b/app/constants/database.ts index 6f2ab223e..c97445ff8 100644 --- a/app/constants/database.ts +++ b/app/constants/database.ts @@ -47,7 +47,23 @@ export const MIGRATION_EVENTS = keyMirror({ MIGRATION_SUCCESS: null, }); +export const SYSTEM_IDENTIFIERS = { + CONFIG: 'config', + CURRENT_CHANNEL_ID: 'currentChannelId', + CURRENT_TEAM_ID: 'currentTeamId', + CURRENT_USER_ID: 'currentUserId', + DATA_RETENTION_POLICIES: 'dataRetentionPolicies', + LICENSE: 'license', +}; + +export const GLOBAL_IDENTIFIERS = { + DEVICE_TOKEN: 'deviceToken', + MENTION_COUNT: 'mentionCount', +}; + export default { + GLOBAL_IDENTIFIERS, MM_TABLES, MIGRATION_EVENTS, + SYSTEM_IDENTIFIERS, }; diff --git a/app/constants/general.ts b/app/constants/general.ts index 72082b809..a9dedcd0f 100644 --- a/app/constants/general.ts +++ b/app/constants/general.ts @@ -68,5 +68,5 @@ export default { DISABLED: 'disabled', DEFAULT_ON: 'default_on', DEFAULT_OFF: 'default_off', - REHYDRATED: 'app/REHYDRATED', + SERVER_LOGOUT: 'server_logout', }; diff --git a/app/constants/index.ts b/app/constants/index.ts index c16a28c57..170f75ac6 100644 --- a/app/constants/index.ts +++ b/app/constants/index.ts @@ -2,29 +2,33 @@ // See LICENSE.txt for license information. import Attachment from './attachment'; -import SSO from './sso'; import Database from './database'; import Device from './device'; import Files from './files'; import General from './general'; import List from './list'; import Navigation from './navigation'; +import Network from './network'; import Preferences from './preferences'; import Screens from './screens'; +import SSO, {REDIRECT_URL_SCHEME, REDIRECT_URL_SCHEME_DEV} from './sso'; import View, {Upgrade} from './view'; import WebsocketEvents from './websocket'; export { Attachment, - SSO, Database, Device, Files, General, List, Navigation, + Network, Preferences, + REDIRECT_URL_SCHEME, + REDIRECT_URL_SCHEME_DEV, Screens, + SSO, Upgrade, View, WebsocketEvents, diff --git a/app/constants/navigation.ts b/app/constants/navigation.ts index 6a40523e4..45cfe62f4 100644 --- a/app/constants/navigation.ts +++ b/app/constants/navigation.ts @@ -4,7 +4,6 @@ import keyMirror from '@utils/key_mirror'; const Navigation = keyMirror({ - NAVIGATION_RESET: null, NAVIGATION_CLOSE_MODAL: null, NAVIGATION_NO_TEAMS: null, NAVIGATION_ERROR_TEAMS: null, diff --git a/app/constants/network.ts b/app/constants/network.ts new file mode 100644 index 000000000..ac51eef7d --- /dev/null +++ b/app/constants/network.ts @@ -0,0 +1,13 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import keyMirror from '@utils/key_mirror'; + +export const CERTIFICATE_ERRORS = keyMirror({ + CLIENT_CERTIFICATE_IMPORT_ERROR: null, + CLIENT_CERTIFICATE_MISSING: null, +}); + +export default { + CERTIFICATE_ERRORS, +}; diff --git a/app/constants/sso.ts b/app/constants/sso.ts index 71e737334..cfaac0a55 100644 --- a/app/constants/sso.ts +++ b/app/constants/sso.ts @@ -3,6 +3,9 @@ import keyMirror from '@utils/key_mirror'; +export const REDIRECT_URL_SCHEME = 'mmauth://'; +export const REDIRECT_URL_SCHEME_DEV = 'mmauthbeta://'; + export default keyMirror({ GITLAB: null, GOOGLE: null, diff --git a/app/constants/view.ts b/app/constants/view.ts index f04970525..7711ba5b6 100644 --- a/app/constants/view.ts +++ b/app/constants/view.ts @@ -55,8 +55,6 @@ const ViewTypes = keyMirror({ POST_DRAFT_SELECTION_CHANGED: null, COMMENT_DRAFT_SELECTION_CHANGED: null, - NOTIFICATION_IN_APP: null, - SET_POST_DRAFT: null, SET_COMMENT_DRAFT: null, diff --git a/app/database/components/index.tsx b/app/database/components/index.tsx index b9bdfcfcc..4211e3c57 100644 --- a/app/database/components/index.tsx +++ b/app/database/components/index.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {ComponentType, useState} from 'react'; +import React, {ComponentType, useEffect, useState} from 'react'; import {Database} from '@nozbe/watermelondb'; import DatabaseProvider from '@nozbe/watermelondb/DatabaseProvider'; @@ -15,30 +15,36 @@ export function withServerDatabase( Component: ComponentType, ): ComponentType { return function ServerDatabaseComponent(props) { - const [database, setDatabase] = useState(); + const [database, setDatabase] = useState(); const db = DatabaseManager.appDatabase?.database; const observer = async (servers: Servers[]) => { const server = servers.reduce((a, b) => (b.lastActiveAt > a.lastActiveAt ? b : a)); - const serverDatabase = DatabaseManager.serverDatabases[server.url].database; - if (serverDatabase) { - setDatabase(serverDatabase); - } + const serverDatabase = DatabaseManager.serverDatabases[server.url]?.database; + setDatabase(serverDatabase); }; - db?.collections. - get(SERVERS). - query(). - observeWithColumns(['last_active_at']). - subscribe(observer); + useEffect(() => { + const subscription = db?.collections. + get(SERVERS). + query(). + observeWithColumns(['last_active_at']). + subscribe(observer); + + return () => { + subscription?.unsubscribe(); + }; + }, []); if (!database) { return null; } return ( - + ); diff --git a/app/database/manager/__mocks__/index.ts b/app/database/manager/__mocks__/index.ts index b6081a886..9ee5605e8 100644 --- a/app/database/manager/__mocks__/index.ts +++ b/app/database/manager/__mocks__/index.ts @@ -22,7 +22,7 @@ import {Channel, ChannelInfo, ChannelMembership, CustomEmoji, Draft, File, TermsOfService, User, } from '@database/models/server'; import {serverSchema} from '@database/schema/server'; -import {getActiveServer, getServer} from '@queries/app/servers'; +import {queryActiveServer, queryServer} from '@queries/app/servers'; import {deleteIOSDatabase} from '@utils/mattermost_managed'; import {hashCode} from '@utils/security'; @@ -184,7 +184,7 @@ class DatabaseManager { private isServerPresent = async (serverUrl: string): Promise => { if (this.appDatabase?.database) { - const server = await getServer(this.appDatabase.database, serverUrl); + const server = await queryServer(this.appDatabase.database, serverUrl); return Boolean(server); } @@ -194,7 +194,7 @@ class DatabaseManager { public getActiveServerUrl = async (): Promise => { const database = this.appDatabase?.database; if (database) { - const server = await getActiveServer(database); + const server = await queryActiveServer(database); return server?.url; } @@ -204,7 +204,7 @@ class DatabaseManager { public getActiveServerDatabase = async (): Promise => { const database = this.appDatabase?.database; if (database) { - const server = await getActiveServer(database); + const server = await queryActiveServer(database); if (server?.url) { return this.serverDatabases[server.url].database; } @@ -230,10 +230,10 @@ class DatabaseManager { public deleteServerDatabase = async (serverUrl: string): Promise => { if (this.appDatabase?.database) { const database = this.appDatabase?.database; - const server = await getServer(database, serverUrl); + const server = await queryServer(database, serverUrl); if (server) { - database.action(() => { - server.update((record) => { + database.action(async () => { + await server.update((record) => { record.lastActiveAt = 0; }); }); @@ -247,7 +247,7 @@ class DatabaseManager { public destroyServerDatabase = async (serverUrl: string): Promise => { if (this.appDatabase?.database) { const database = this.appDatabase?.database; - const server = await getServer(database, serverUrl); + const server = await queryServer(database, serverUrl); if (server) { database.action(async () => { await server.destroyPermanently(); diff --git a/app/database/manager/index.ts b/app/database/manager/index.ts index 06ef9d7a0..a9b466aa0 100644 --- a/app/database/manager/index.ts +++ b/app/database/manager/index.ts @@ -21,7 +21,7 @@ import {Channel, ChannelInfo, ChannelMembership, CustomEmoji, Draft, File, TermsOfService, User, } from '@database/models/server'; import {serverSchema} from '@database/schema/server'; -import {getActiveServer, getServer} from '@queries/app/servers'; +import {queryActiveServer, queryServer} from '@queries/app/servers'; import {deleteIOSDatabase, getIOSAppGroupDetails} from '@utils/mattermost_managed'; import {hashCode} from '@utils/security'; @@ -114,7 +114,7 @@ class DatabaseManager { if (serverUrl) { try { - const databaseName = hashCode(dbName); + const databaseName = hashCode(serverUrl); const databaseFilePath = this.getDatabaseFilePath(databaseName); const migrations = ServerDatabaseMigrations; const modelClasses = this.serverModels; @@ -202,7 +202,7 @@ class DatabaseManager { */ private isServerPresent = async (serverUrl: string): Promise => { if (this.appDatabase?.database) { - const server = await getServer(this.appDatabase.database, serverUrl); + const server = await queryServer(this.appDatabase.database, serverUrl); return Boolean(server); } @@ -216,7 +216,7 @@ class DatabaseManager { public getActiveServerUrl = async (): Promise => { const database = this.appDatabase?.database; if (database) { - const server = await getActiveServer(database); + const server = await queryActiveServer(database); return server?.url; } @@ -230,7 +230,7 @@ class DatabaseManager { public getActiveServerDatabase = async (): Promise => { const database = this.appDatabase?.database; if (database) { - const server = await getActiveServer(database); + const server = await queryActiveServer(database); if (server?.url) { return this.serverDatabases[server.url].database; } @@ -268,10 +268,10 @@ class DatabaseManager { public deleteServerDatabase = async (serverUrl: string): Promise => { if (this.appDatabase?.database) { const database = this.appDatabase?.database; - const server = await getServer(database, serverUrl); + const server = await queryServer(database, serverUrl); if (server) { - database.action(() => { - server.update((record) => { + database.action(async () => { + await server.update((record) => { record.lastActiveAt = 0; }); }); @@ -291,7 +291,7 @@ class DatabaseManager { public destroyServerDatabase = async (serverUrl: string): Promise => { if (this.appDatabase?.database) { const database = this.appDatabase?.database; - const server = await getServer(database, serverUrl); + const server = await queryServer(database, serverUrl); if (server) { database.action(async () => { await server.destroyPermanently(); diff --git a/app/database/models/app/global.ts b/app/database/models/app/global.ts index 295f83e12..35ad965da 100644 --- a/app/database/models/app/global.ts +++ b/app/database/models/app/global.ts @@ -5,6 +5,7 @@ import {Model} from '@nozbe/watermelondb'; import {json} from '@nozbe/watermelondb/decorators'; import {MM_TABLES} from '@constants/database'; +import {safeParseJSON} from '@utils/helpers'; const {GLOBAL} = MM_TABLES.APP; @@ -19,5 +20,5 @@ export default class Global extends Model { static table = GLOBAL; /** value : The value part of the key-value combination and whose key will be the id column */ - @json('value', (rawJson) => rawJson) value!: any; + @json('value', safeParseJSON) value!: any; } diff --git a/app/database/models/server/draft.ts b/app/database/models/server/draft.ts index 7d36d27b9..a7258e22c 100644 --- a/app/database/models/server/draft.ts +++ b/app/database/models/server/draft.ts @@ -5,6 +5,7 @@ import Model, {Associations} from '@nozbe/watermelondb/Model'; import {field, json} from '@nozbe/watermelondb/decorators'; import {MM_TABLES} from '@constants/database'; +import {safeParseJSON} from '@utils/helpers'; const {CHANNEL, DRAFT, POST} = MM_TABLES.SERVER; @@ -35,5 +36,5 @@ export default class Draft extends Model { @field('root_id') rootId!: string; /** files : The files field will hold an array of file objects that have not yet been uploaded and persisted within the FILE table */ - @json('files', (rawJson) => rawJson) files!: FileInfo[]; + @json('files', safeParseJSON) files!: FileInfo[]; } diff --git a/app/database/models/server/my_channel_settings.ts b/app/database/models/server/my_channel_settings.ts index 617e031a9..3c65d46a9 100644 --- a/app/database/models/server/my_channel_settings.ts +++ b/app/database/models/server/my_channel_settings.ts @@ -5,8 +5,10 @@ import {Relation} from '@nozbe/watermelondb'; import {field, immutableRelation, json} from '@nozbe/watermelondb/decorators'; import Model, {Associations} from '@nozbe/watermelondb/Model'; -import Channel from '@typings/database/models/servers/channel'; import {MM_TABLES} from '@constants/database'; +import {safeParseJSON} from '@utils/helpers'; + +import type Channel from '@typings/database/models/servers/channel'; const {CHANNEL, MY_CHANNEL_SETTINGS} = MM_TABLES.SERVER; @@ -29,7 +31,7 @@ export default class MyChannelSettings extends Model { @field('channel_id') channelId!: string; /** notify_props : Configurations with regards to this channel */ - @json('notify_props', (rawJson) => rawJson) notifyProps!: NotifyProps; + @json('notify_props', safeParseJSON) notifyProps!: NotifyProps; /** channel : The relation pointing to the CHANNEL table */ @immutableRelation(CHANNEL, 'channel_id') channel!: Relation; diff --git a/app/database/models/server/post.ts b/app/database/models/server/post.ts index af5a7e081..b4b126cb2 100644 --- a/app/database/models/server/post.ts +++ b/app/database/models/server/post.ts @@ -6,13 +6,15 @@ import {children, field, immutableRelation, json, lazy} from '@nozbe/watermelond import Model, {Associations} from '@nozbe/watermelondb/Model'; import {MM_TABLES} from '@constants/database'; -import Channel from '@typings/database/models/servers/channel'; -import Draft from '@typings/database/models/servers/draft'; -import File from '@typings/database/models/servers/file'; -import PostInThread from '@typings/database/models/servers/posts_in_thread'; -import PostMetadata from '@typings/database/models/servers/post_metadata'; -import Reaction from '@typings/database/models/servers/reaction'; -import User from '@typings/database/models/servers/user'; +import {safeParseJSON} from '@utils/helpers'; + +import type Channel from '@typings/database/models/servers/channel'; +import type Draft from '@typings/database/models/servers/draft'; +import type File from '@typings/database/models/servers/file'; +import type PostInThread from '@typings/database/models/servers/posts_in_thread'; +import type PostMetadata from '@typings/database/models/servers/post_metadata'; +import type Reaction from '@typings/database/models/servers/reaction'; +import type User from '@typings/database/models/servers/user'; const {CHANNEL, DRAFT, FILE, POST, POSTS_IN_THREAD, POST_METADATA, REACTION, USER} = MM_TABLES.SERVER; @@ -88,7 +90,7 @@ export default class Post extends Model { @field('user_id') userId!: string; /** props : Additional attributes for this props */ - @json('props', (rawJson) => rawJson) props!: object; + @json('props', safeParseJSON) props!: object; // A draft can be associated with this post for as long as this post is a parent post @lazy draft = this.collections.get(DRAFT).query(Q.on(POST, 'id', this.id)) as Query; diff --git a/app/database/models/server/post_metadata.ts b/app/database/models/server/post_metadata.ts index e8170ba52..9a5733f15 100644 --- a/app/database/models/server/post_metadata.ts +++ b/app/database/models/server/post_metadata.ts @@ -6,8 +6,10 @@ import {field, immutableRelation, json} from '@nozbe/watermelondb/decorators'; import Model, {Associations} from '@nozbe/watermelondb/Model'; import {MM_TABLES} from '@constants/database'; -import {PostMetadataData, PostMetadataType} from '@typings/database/database'; -import Post from '@typings/database/models/servers/post'; +import {safeParseJSON} from '@utils/helpers'; + +import type {PostMetadataData, PostMetadataType} from '@typings/database/database'; +import type Post from '@typings/database/models/servers/post'; const {POST, POST_METADATA} = MM_TABLES.SERVER; @@ -32,7 +34,7 @@ export default class PostMetadata extends Model { @field('type') type!: PostMetadataType; /** data : Different types of data ranging from embeds to images. */ - @json('data', (rawJson) => rawJson) data!: PostMetadataData; + @json('data', safeParseJSON) data!: PostMetadataData; /** post: The record representing the POST parent. */ @immutableRelation(POST, 'post_id') post!: Relation; diff --git a/app/database/models/server/role.ts b/app/database/models/server/role.ts index 84f4732ef..90b7e72cd 100644 --- a/app/database/models/server/role.ts +++ b/app/database/models/server/role.ts @@ -5,6 +5,7 @@ import {Model} from '@nozbe/watermelondb'; import {field, json} from '@nozbe/watermelondb/decorators'; import {MM_TABLES} from '@constants/database'; +import {safeParseJSON} from '@utils/helpers'; const {ROLE} = MM_TABLES.SERVER; @@ -17,6 +18,6 @@ export default class Role extends Model { @field('name') name!: string; /** permissions : The different permissions associated to that role */ - @json('permissions', (rawJson) => rawJson) permissions!: string[]; + @json('permissions', safeParseJSON) permissions!: string[]; } diff --git a/app/database/models/server/system.ts b/app/database/models/server/system.ts index a084def90..78fccddea 100644 --- a/app/database/models/server/system.ts +++ b/app/database/models/server/system.ts @@ -5,6 +5,7 @@ import {Model} from '@nozbe/watermelondb'; import {json} from '@nozbe/watermelondb/decorators'; import {MM_TABLES} from '@constants/database'; +import {safeParseJSON} from '@utils/helpers'; const {SYSTEM} = MM_TABLES.SERVER; @@ -18,5 +19,5 @@ export default class System extends Model { static table = SYSTEM; /** value : The value for that config/information and whose key will be the id column */ - @json('value', (rawJson) => rawJson) value!: any; + @json('value', safeParseJSON) value!: any; } diff --git a/app/database/models/server/team_channel_history.ts b/app/database/models/server/team_channel_history.ts index 5507e00df..956af80f9 100644 --- a/app/database/models/server/team_channel_history.ts +++ b/app/database/models/server/team_channel_history.ts @@ -6,7 +6,9 @@ import {field, immutableRelation, json} from '@nozbe/watermelondb/decorators'; import Model, {Associations} from '@nozbe/watermelondb/Model'; import {MM_TABLES} from '@constants/database'; -import Team from '@typings/database/models/servers/team'; +import {safeParseJSON} from '@utils/helpers'; + +import type Team from '@typings/database/models/servers/team'; const {TEAM, TEAM_CHANNEL_HISTORY} = MM_TABLES.SERVER; @@ -29,7 +31,7 @@ export default class TeamChannelHistory extends Model { @field('team_id') teamId!: string; /** channel_ids : An array containing the last 5 channels visited within this team order by recency */ - @json('channel_ids', (rawJson) => rawJson) channelIds!: string[]; + @json('channel_ids', safeParseJSON) channelIds!: string[]; /** team : The related record from the parent Team model */ @immutableRelation(TEAM, 'team_id') team!: Relation; diff --git a/app/database/models/server/user.ts b/app/database/models/server/user.ts index 7d5da225f..616bd2038 100644 --- a/app/database/models/server/user.ts +++ b/app/database/models/server/user.ts @@ -5,13 +5,15 @@ import {children, field, json} from '@nozbe/watermelondb/decorators'; import Model, {Associations} from '@nozbe/watermelondb/Model'; import {MM_TABLES} from '@constants/database'; -import Channel from '@typings/database/models/servers/channel'; -import ChannelMembership from '@typings/database/models/servers/channel_membership'; -import GroupMembership from '@typings/database/models/servers/group_membership'; -import Post from '@typings/database/models/servers/post'; -import Preference from '@typings/database/models/servers/preference'; -import Reaction from '@typings/database/models/servers/reaction'; -import TeamMembership from '@typings/database/models/servers/team_membership'; +import {safeParseJSON} from '@utils/helpers'; + +import type Channel from '@typings/database/models/servers/channel'; +import type ChannelMembership from '@typings/database/models/servers/channel_membership'; +import type GroupMembership from '@typings/database/models/servers/group_membership'; +import type Post from '@typings/database/models/servers/post'; +import type Preference from '@typings/database/models/servers/preference'; +import type Reaction from '@typings/database/models/servers/reaction'; +import type TeamMembership from '@typings/database/models/servers/team_membership'; const { CHANNEL, @@ -103,15 +105,15 @@ export default class User extends Model { @field('username') username!: string; /** notify_props : Notification preferences/configurations */ - @json('notify_props', (rawJson) => rawJson) notifyProps!: NotifyProps; + @json('notify_props', safeParseJSON) notifyProps!: NotifyProps; /** props : Custom objects ( e.g. custom status) can be stored in there. Its type definition is known as * 'excess property check' in Typescript land. We keep using it till we build up the final shape of this object. */ - @json('props', (rawJson) => rawJson) props!: UserProps; + @json('props', safeParseJSON) props!: UserProps; /** timezone : The timezone for this user */ - @json('timezone', (rawJson) => rawJson) timezone!: Timezone; + @json('timezone', safeParseJSON) timezone!: Timezone; /** channelsCreated : All the channels that this user created */ @children(CHANNEL) channelsCreated!: Channel[]; diff --git a/app/i18n/index.ts b/app/i18n/index.ts index 56cbea489..1896aeb3a 100644 --- a/app/i18n/index.ts +++ b/app/i18n/index.ts @@ -205,8 +205,8 @@ export function getLocaleFromLanguage(lang: string) { return locale; } -export function resetMomentLocale() { - moment.locale(DEFAULT_LOCALE); +export function resetMomentLocale(locale?: string) { + moment.locale(locale || DEFAULT_LOCALE); } export function getTranslations(locale?: string) { diff --git a/app/init/credentials.ts b/app/init/credentials.ts index db309b57b..216e497f8 100644 --- a/app/init/credentials.ts +++ b/app/init/credentials.ts @@ -8,7 +8,6 @@ import * as KeyChain from 'react-native-keychain'; import DatabaseManager from '@database/manager'; import * as analytics from '@init/analytics'; import {getIOSAppGroupDetails} from '@utils/mattermost_managed'; -import {getCSRFFromCookie} from '@utils/security'; import type {ServerCredential} from '@typings/credentials'; @@ -55,8 +54,8 @@ export const getActiveServerUrl = async () => { return serverUrl || undefined; }; -export const setServerCredentials = (serverUrl: string, userId: string, token: string) => { - if (!(serverUrl && userId && token)) { +export const setServerCredentials = (serverUrl: string, token: string) => { + if (!(serverUrl && token)) { return; } @@ -71,24 +70,21 @@ export const setServerCredentials = (serverUrl: string, userId: string, token: s accessGroup, securityLevel: KeyChain.SECURITY_LEVEL.SECURE_SOFTWARE, }; - KeyChain.setInternetCredentials(serverUrl, userId, token, options); + KeyChain.setInternetCredentials(serverUrl, token, token, options); } catch (e) { console.warn('could not set credentials', e); //eslint-disable-line no-console } }; export const removeServerCredentials = async (serverUrl: string) => { - // TODO: invalidate client and remove tokens - - KeyChain.resetInternetCredentials(serverUrl); - - AsyncStorage.removeItem(ASYNC_STORAGE_CURRENT_SERVER_KEY); + await KeyChain.resetInternetCredentials(serverUrl); + await AsyncStorage.removeItem(ASYNC_STORAGE_CURRENT_SERVER_KEY); }; export const removeActiveServerCredentials = async () => { const serverUrl = await getActiveServerUrl(); if (serverUrl) { - removeServerCredentials(serverUrl); + await removeServerCredentials(serverUrl); } }; @@ -109,12 +105,6 @@ export const getServerCredentials = async (serverUrl: string): Promise { - const serverUrl = Client4.getUrl(); - const parsed = urlParse(url); - const {redirects} = response.rnfbRespInfo; - if (redirects) { - const redirectUrl = urlParse(redirects[redirects.length - 1]); - - if (serverUrl === parsed.origin && parsed.host === redirectUrl.host && parsed.protocol !== redirectUrl.protocol) { - Client4.setUrl(serverUrl.replace(parsed.protocol, redirectUrl.protocol)); - } - } -}; - -Client4.doFetchWithResponse = async (url, options) => { - // eslint-disable-next-line no-console - console.log('Request endpoint', url); - const customHeaders = LocalConfig.CustomRequestHeaders; - - let requestOptions = { - ...Client4.getOptions(options), - }; - - if (customHeaders && Object.keys(customHeaders).length > 0) { - requestOptions = { - ...requestOptions, - headers: { - ...requestOptions.headers, - ...LocalConfig.CustomRequestHeaders, - }, - }; - } - - let response; - let headers; - - let data; - try { - response = await fetch(url, requestOptions); - headers = response.headers; - if (!url.startsWith('https') && response.rnfbRespInfo && response.rnfbRespInfo.redirects && response.rnfbRespInfo.redirects.length > 1) { - handleRedirectProtocol(url, response); - } - - data = await response.json(); - } catch (err) { - if (response && response.resp && response.resp.data && response.resp.data.includes('SSL certificate')) { - throw new ClientError(Client4.getUrl(), { - message: 'You need to use a valid client certificate in order to connect to this Mattermost server', - status_code: 401, - url, - details: err, - }); - } - - throw new ClientError(Client4.getUrl(), { - message: 'Received invalid response from the server.', - intl: { - id: t('mobile.request.invalid_response'), - defaultMessage: 'Received invalid response from the server.', - }, - url, - details: err, - }); - } - - const clusterId = headers[HEADER_X_CLUSTER_ID] || headers[HEADER_X_CLUSTER_ID.toLowerCase()]; - if (clusterId && Client4.clusterId !== clusterId) { - Client4.clusterId = clusterId; /* eslint-disable-line require-atomic-updates */ - } - - const token = headers[HEADER_TOKEN] || headers[HEADER_TOKEN.toLowerCase()]; - if (token) { - Client4.setToken(token); - } - - const serverVersion = headers[HEADER_X_VERSION_ID] || headers[HEADER_X_VERSION_ID.toLowerCase()]; - if (serverVersion && !headers['Cache-Control'] && Client4.serverVersion !== serverVersion) { - Client4.serverVersion = serverVersion; /* eslint-disable-line require-atomic-updates */ - // EventEmitter.emit(General.SERVER_VERSION_CHANGED, serverVersion); - } - - if (response.ok) { - const headersMap = new Map(); - Object.keys(headers).forEach((key) => { - headersMap.set(key, headers[key]); - }); - - return { - response, - headers: headersMap, - data, - }; - } - - const msg = data.message || ''; - - if (Client4.logToConsole) { - console.error(msg); // eslint-disable-line no-console - } - - throw new ClientError(Client4.getUrl(), { - message: msg, - server_error_id: data.id, - status_code: data.status_code, - url, - }); -}; - -const initFetchConfig = async () => { - const fetchConfig = { - auto: true, - timeout: DEFAULT_TIMEOUT, // Set the base timeout for every request to 5s - }; - - const userAgent = await DeviceInfo.getUserAgent(); - Client4.setUserAgent(userAgent); - - window.fetch = new RNFetchBlob.polyfill.Fetch(fetchConfig).build(); - - return true; -}; - -initFetchConfig(); - -export default initFetchConfig; diff --git a/app/init/global_event_handler.ts b/app/init/global_event_handler.ts index 1c971d104..7caf1f848 100644 --- a/app/init/global_event_handler.ts +++ b/app/init/global_event_handler.ts @@ -2,17 +2,20 @@ // See LICENSE.txt for license information. import {Alert, DeviceEventEmitter, Linking, Platform} from 'react-native'; -import CookieManager, {Cookie} from '@react-native-community/cookies'; -import {FileSystem} from 'react-native-unimodules'; +import CookieManager, {Cookie} from '@react-native-cookies/cookies'; import semver from 'semver'; +import {fetchConfigAndLicense} from '@actions/remote/general'; import LocalConfig from '@assets/config.json'; -import {Navigation} from '@constants'; +import {General, REDIRECT_URL_SCHEME, REDIRECT_URL_SCHEME_DEV} from '@constants'; +import DatabaseManager from '@database/manager'; import {DEFAULT_LOCALE, getTranslations, resetMomentLocale, t} from '@i18n'; import * as analytics from '@init/analytics'; import {getServerCredentials, removeServerCredentials} from '@init/credentials'; import {getLaunchPropsFromDeepLink, relaunchApp} from '@init/launch'; +import NetworkManager from '@init/network_manager'; import PushNotifications from '@init/push_notifications'; +import {queryCurrentUser} from '@queries/servers/user'; import {LaunchType} from '@typings/launch'; import {deleteFileCache} from '@utils/file'; @@ -22,10 +25,9 @@ class GlobalEventHandler { JavascriptAndNativeErrorHandler: jsAndNativeErrorHandler | undefined; constructor() { - DeviceEventEmitter.addListener(Navigation.NAVIGATION_RESET, this.onLogout); - - // DeviceEventEmitter.addListener(General.SERVER_VERSION_CHANGED, this.onServerVersionChanged); - // DeviceEventEmitter.addListener(General.CONFIG_CHANGED, this.onServerConfigChanged); + DeviceEventEmitter.addListener(General.SERVER_LOGOUT, this.onLogout); + DeviceEventEmitter.addListener(General.SERVER_VERSION_CHANGED, this.onServerVersionChanged); + DeviceEventEmitter.addListener(General.CONFIG_CHANGED, this.onServerConfigChanged); Linking.addEventListener('url', this.onDeepLink); } @@ -47,74 +49,44 @@ class GlobalEventHandler { }; onDeepLink = (event: LinkingCallbackArg) => { + if (event.url?.startsWith(REDIRECT_URL_SCHEME) || event.url?.startsWith(REDIRECT_URL_SCHEME_DEV)) { + return; + } + if (event.url) { const props = getLaunchPropsFromDeepLink(event.url); relaunchApp(props); } }; - clearCookies = async (serverUrl: string | undefined, webKit: boolean) => { + clearCookies = async (serverUrl: string, webKit: boolean) => { try { - if (serverUrl) { - const cookies = await CookieManager.get(serverUrl, webKit); - const values = Object.values(cookies); - values.forEach((cookie: Cookie) => { - CookieManager.clearByName(serverUrl, cookie.name, webKit); - }); - } else { - await CookieManager.clearAll(webKit); - } + const cookies = await CookieManager.get(serverUrl, webKit); + const values = Object.values(cookies); + values.forEach((cookie: Cookie) => { + CookieManager.clearByName(serverUrl, cookie.name, webKit); + }); } catch (error) { // Nothing to clear } } - clearCookiesAndWebData = async (serverUrl?: string) => { + clearCookiesForServer = async (serverUrl: string) => { this.clearCookies(serverUrl, false); if (Platform.OS === 'ios') { // Also delete any cookies that were set by react-native-webview this.clearCookies(serverUrl, true); - } - - // TODO: Only execute this if there are no more servers - switch (Platform.OS) { - case 'ios': { - const mainPath = FileSystem.documentDirectory?.split('/').slice(0, -1).join('/'); - const libraryDir = `${mainPath}/Library`; - const cookiesDir = `${libraryDir}/Cookies`; - const cookies = await FileSystem.getInfoAsync(cookiesDir); - const webkitDir = `${libraryDir}/WebKit`; - const webkit = await FileSystem.getInfoAsync(webkitDir); - - if (cookies.exists) { - FileSystem.deleteAsync(cookiesDir); - } - - if (webkit.exists) { - FileSystem.deleteAsync(webkitDir); - } - break; - } - - case 'android': { - const cacheDir = FileSystem.cacheDirectory; - const mainPath = cacheDir?.split('/').slice(0, -1).join('/'); - const cookies = await FileSystem.getInfoAsync(`${mainPath}/app_webview/Cookies`); - const cookiesJ = await FileSystem.getInfoAsync(`${mainPath}/app_webview/Cookies-journal`); - if (cookies.exists) { - FileSystem.deleteAsync(`${mainPath}/app_webview/Cookies`); - } - - if (cookiesJ.exists) { - FileSystem.deleteAsync(`${mainPath}/app_webview/Cookies-journal`); - } - break; - } + } else if (Platform.OS === 'android') { + CookieManager.flush(); } }; onLogout = async (serverUrl: string) => { - // TODO: Close and invalidate ApiClient & WebSocket client + await removeServerCredentials(serverUrl); + + // TODO WebSocket: invalidate WebSocket client + NetworkManager.invalidateClient(serverUrl); + await DatabaseManager.deleteServerDatabase(serverUrl); const analyticsClient = analytics.get(serverUrl); if (analyticsClient) { @@ -122,37 +94,28 @@ class GlobalEventHandler { analytics.invalidate(serverUrl); } - removeServerCredentials(serverUrl); + deleteFileCache(serverUrl); + PushNotifications.clearNotifications(serverUrl); - // TODO: remove files for the server - deleteFileCache(); - PushNotifications.clearNotifications(); - - // TODO: Only execute this if there are no more servers - // in case there are other servers switch to the appropriate locale - resetMomentLocale(); - - await this.clearCookiesAndWebData(); - - relaunchApp({launchType: LaunchType.Normal}); + this.resetLocale(); + this.clearCookiesForServer(serverUrl); + relaunchApp({launchType: LaunchType.Normal}, true); }; - onServerConfigChanged = (serverUrl: string, config: ClientConfig) => { + onServerConfigChanged = ({serverUrl, config}: {serverUrl: string, config: ClientConfig}) => { this.configureAnalytics(serverUrl, config); - // TODO: Add minimum server version checked with cloud support - // if (isMinimumServerVersion(Client4.serverVersion, 5, 24) && config.ExtendSessionLengthWithActivity === 'true') { - // PushNotifications.cancelAllLocalNotifications(); - // } + if (config.ExtendSessionLengthWithActivity === 'true') { + PushNotifications.cancelAllLocalNotifications(); + } }; - onServerVersionChanged = async (serverUrl: string, serverVersion?: string) => { + onServerVersionChanged = async ({serverUrl, serverVersion}: {serverUrl: string, serverVersion?: string}) => { const match = serverVersion?.match(/^[0-9]*.[0-9]*.[0-9]*(-[a-zA-Z0-9.-]*)?/g); const version = match && match[0]; const locale = DEFAULT_LOCALE; const translations = getTranslations(locale); - // TODO: Handle when the server is cloud if (version) { if (semver.valid(version) && semver.lt(version, LocalConfig.MinServerVersion)) { Alert.alert( @@ -166,11 +129,20 @@ class GlobalEventHandler { ); } - // TODO: Set server version in client and - // reload config and license unless done somewhere else + fetchConfigAndLicense(serverUrl); } }; + resetLocale = async () => { + if (Object.keys(DatabaseManager.serverDatabases).length) { + const serverDatabase = await DatabaseManager.getActiveServerDatabase(); + const user = await queryCurrentUser(serverDatabase!); + resetMomentLocale(user?.locale); + } else { + resetMomentLocale(); + } + } + serverUpgradeNeeded = async (serverUrl: string) => { const credentials = await getServerCredentials(serverUrl); diff --git a/app/init/launch.ts b/app/init/launch.ts index eb04a5135..69c6a5db9 100644 --- a/app/init/launch.ts +++ b/app/init/launch.ts @@ -18,7 +18,7 @@ export const initialLaunch = async () => { } const notification = await Notifications.getInitialNotification(); - if (notification) { + if (notification && notification.payload?.type === 'message') { launchAppFromNotification(notification); return; } @@ -56,7 +56,6 @@ const launchApp = async (props: LaunchProps, resetNavigation = true) => { if (serverUrl) { const credentials = await getServerCredentials(serverUrl); - if (credentials) { launchToChannel({...props, serverUrl}, resetNavigation); return; @@ -95,8 +94,8 @@ const launchToServer = (props: LaunchProps, resetNavigation: Boolean) => { goToScreen(Screens.SERVER, title, {...props}); }; -export const relaunchApp = (props: LaunchProps) => { - launchApp(props, false); +export const relaunchApp = (props: LaunchProps, resetNavigation = false) => { + launchApp(props, resetNavigation); }; export const getLaunchPropsFromDeepLink = (deepLinkUrl: string): LaunchProps => { diff --git a/app/init/network_manager.ts b/app/init/network_manager.ts new file mode 100644 index 000000000..7eeaaa5cb --- /dev/null +++ b/app/init/network_manager.ts @@ -0,0 +1,123 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {DeviceEventEmitter} from 'react-native'; +import DeviceInfo from 'react-native-device-info'; + +import Emm from '@mattermost/react-native-emm'; +import { + APIClientErrorEvent, + APIClientErrorEventHandler, + getOrCreateAPIClient, + RetryTypes, +} from '@mattermost/react-native-network-client'; + +import LocalConfig from '@assets/config.json'; +import {Client} from '@client/rest'; +import * as ClientConstants from '@client/rest/constants'; +import {CERTIFICATE_ERRORS} from '@constants/network'; +import ManagedApp from '@init/managed_app'; +import {getCSRFFromCookie} from '@utils/security'; + +import type {ServerCredential} from '@typings/credentials'; + +const CLIENT_CERTIFICATE_IMPORT_ERROR_CODES = [-103, -104, -105, -108]; +const CLIENT_CERTIFICATE_MISSING_ERROR_CODE = -200; + +class NetworkManager { + private clients: Record = {}; + + private DEFAULT_CONFIG = { + headers: { + 'X-Requested-With': 'XMLHttpRequest', + ...LocalConfig.CustomRequestHeaders, + }, + sessionConfiguration: { + allowsCellularAccess: true, + waitsForConnectivity: false, + timeoutIntervalForRequest: 30000, + timeoutIntervalForResource: 30000, + httpMaximumConnectionsPerHost: 10, + cancelRequestsOnUnauthorized: true, + }, + retryPolicyConfiguration: { + type: RetryTypes.EXPONENTIAL_RETRY, + retryLimit: 2, + exponentialBackoffBase: 2, + exponentialBackoffScale: 0.5, + }, + requestAdapterConfiguration: { + bearerAuthTokenResponseHeader: 'token', + }, + }; + + public init = async (serverCredentials: ServerCredential[]) => { + for await (const {serverUrl, token} of serverCredentials) { + try { + this.createClient(serverUrl, token); + } catch (error) { + console.log(error); //eslint-disable-line no-console + } + } + } + + public invalidateClient = (serverUrl: string) => { + this.clients[serverUrl]?.invalidate(); + delete this.clients[serverUrl]; + } + + public getClient = (serverUrl: string) => { + const client = this.clients[serverUrl]; + if (!client) { + throw new Error(`${serverUrl} client not found`); + } + + return client; + } + + public createClient = async (serverUrl: string, bearerToken?: string) => { + const config = await this.buildConfig(); + const {client} = await getOrCreateAPIClient(serverUrl, config, this.clientErrorEventHandler); + + const csrfToken = await getCSRFFromCookie(serverUrl); + this.clients[serverUrl] = new Client(client, serverUrl, bearerToken, csrfToken); + + return this.clients[serverUrl]; + } + + private buildConfig = async () => { + const userAgent = await DeviceInfo.getUserAgent(); + const headers: Record = { + ...this.DEFAULT_CONFIG.headers, + [ClientConstants.HEADER_USER_AGENT]: userAgent, + }; + + const config = { + ...this.DEFAULT_CONFIG, + headers, + }; + + if (ManagedApp.enabled) { + const managedConfig = await Emm.getManagedConfig(); + if (managedConfig?.useVPN === 'true') { + config.sessionConfiguration.waitsForConnectivity = true; + } + + if (managedConfig?.timeoutVPN) { + config.sessionConfiguration.timeoutIntervalForResource = parseInt(managedConfig.timeoutVPN, 10); + } + } + + return config; + } + + private clientErrorEventHandler: APIClientErrorEventHandler = (event: APIClientErrorEvent) => { + if (CLIENT_CERTIFICATE_IMPORT_ERROR_CODES.includes(event.errorCode)) { + DeviceEventEmitter.emit(CERTIFICATE_ERRORS.CLIENT_CERTIFICATE_IMPORT_ERROR, event.serverUrl); + } else if (CLIENT_CERTIFICATE_MISSING_ERROR_CODE === event.errorCode) { + DeviceEventEmitter.emit(CERTIFICATE_ERRORS.CLIENT_CERTIFICATE_MISSING, event.serverUrl); + } + }; +} + +export default new NetworkManager(); diff --git a/app/init/push_notifications.ts b/app/init/push_notifications.ts index 7535fd715..3dfa979d8 100644 --- a/app/init/push_notifications.ts +++ b/app/init/push_notifications.ts @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n'; -import {AppState, AppStateStatus, DeviceEventEmitter, EmitterSubscription, Platform} from 'react-native'; +import {AppState, DeviceEventEmitter, Platform} from 'react-native'; import DeviceInfo from 'react-native-device-info'; import { Notification, @@ -15,10 +15,13 @@ import { Registered, } from 'react-native-notifications'; -import {Device, Navigation, View} from '@constants'; +import {Device, General, Navigation} from '@constants'; +import {GLOBAL_IDENTIFIERS} from '@constants/database'; import DatabaseManager from '@database/manager'; import {getLaunchPropsFromNotification, relaunchApp} from '@init/launch'; import NativeNotifications from '@notifications'; +import {queryMentionCount} from '@queries/app/global'; +import {queryCurrentChannelId} from '@queries/servers/system'; import {showOverlay} from '@screens/navigation'; const CATEGORY = 'CAN_REPLY'; @@ -29,30 +32,32 @@ const NOTIFICATION_TYPE = { SESSION: 'session', }; -//todo: Do we need Ephemeral store? Should we refactor this file ? - class PushNotifications { configured = false; - pushNotificationListener: EmitterSubscription | undefined; - constructor() { + init() { Notifications.registerRemoteNotifications(); Notifications.events().registerNotificationOpened(this.onNotificationOpened); Notifications.events().registerRemoteNotificationsRegistered(this.onRemoteNotificationsRegistered); Notifications.events().registerNotificationReceivedBackground(this.onNotificationReceivedBackground); Notifications.events().registerNotificationReceivedForeground(this.onNotificationReceivedForeground); - AppState.addEventListener('change', this.onAppStateChange); } cancelAllLocalNotifications = () => { Notifications.cancelAllLocalNotifications(); }; - clearNotifications = () => { - this.setApplicationIconBadgeNumber(0); + clearNotifications = (serverUrl: string) => { + // TODO Notifications: Only cancel the local notifications that belong to this server - // TODO: Only cancel the local notifications that belong to this server + // eslint-disable-next-line no-console + console.log('Clear notifications for server', serverUrl); this.cancelAllLocalNotifications(); + + if (Platform.OS === 'ios') { + // TODO Notifications: Set the badge number to the total amount of mentions on other servers + Notifications.ios.setBadgeCount(0); + } }; clearChannelNotifications = async (channelId: string) => { @@ -69,13 +74,21 @@ class PushNotifications { } } else { const ids: string[] = []; - const badgeCount = notifications.length; - - // TODO: Set the badgeCount with default database mention count aggregate + let badgeCount = notifications.length; for (const notification of notifications) { if (notification.channel_id === channelId) { ids.push(notification.identifier); + badgeCount--; + } + } + + // Set the badgeCount with default database mention count aggregate + const appDatabase = DatabaseManager.appDatabase?.database; + if (appDatabase) { + const mentions = await queryMentionCount(appDatabase); + if (mentions) { + badgeCount = parseInt(mentions, 10); } } @@ -83,16 +96,17 @@ class PushNotifications { NativeNotifications.removeDeliveredNotifications(ids); } - this.setApplicationIconBadgeNumber(badgeCount); + if (Platform.OS === 'ios') { + badgeCount = badgeCount <= 0 ? 0 : badgeCount; + Notifications.ios.setBadgeCount(badgeCount); + } } }; createReplyCategory = () => { - const locale = DEFAULT_LOCALE; // TODO: Get the current user locale to replace the old getCurrentLocale(state); - - const replyTitle = getLocalizedMessage(locale, t('mobile.push_notification_reply.title')); - const replyButton = getLocalizedMessage(locale, t('mobile.push_notification_reply.button')); - const replyPlaceholder = getLocalizedMessage(locale, t('mobile.push_notification_reply.placeholder')); + const replyTitle = getLocalizedMessage(DEFAULT_LOCALE, t('mobile.push_notification_reply.title')); + const replyButton = getLocalizedMessage(DEFAULT_LOCALE, t('mobile.push_notification_reply.button')); + const replyPlaceholder = getLocalizedMessage(DEFAULT_LOCALE, t('mobile.push_notification_reply.placeholder')); const replyTextInput: NotificationTextInput = {buttonTitle: replyButton, placeholder: replyPlaceholder}; const replyAction = new NotificationAction(REPLY_ACTION, 'background', replyTitle, true, replyTextInput); return new NotificationCategory(CATEGORY, [replyAction]); @@ -104,13 +118,13 @@ class PushNotifications { if (payload) { switch (payload.type) { case NOTIFICATION_TYPE.CLEAR: - // Mark the channel as read + // TODO Notifications: Mark the channel as read break; case NOTIFICATION_TYPE.MESSAGE: - // fetch the posts for the channel + // TODO Notifications: fetch the posts for the channel if (foreground) { - // Show the in-app notification + this.handleInAppNotification(notification); } else if (userInteraction && !payload.userInfo?.local) { const props = getLaunchPropsFromNotification(notification); relaunchApp(props); @@ -120,8 +134,9 @@ class PushNotifications { // eslint-disable-next-line no-console console.log('Session expired notification'); - // Logout the user from the server that matches the notification - + if (payload.server_url) { + DeviceEventEmitter.emit(General.SERVER_LOGOUT, payload.server_url); + } break; } } @@ -130,17 +145,20 @@ class PushNotifications { handleInAppNotification = async (notification: NotificationWithData) => { const {payload} = notification; - // TODO: Get current channel from the database - const currentChannelId = ''; + if (payload?.server_url) { + const database = DatabaseManager.serverDatabases[payload.server_url]?.database; + const currentChannelId = await queryCurrentChannelId(database); + const channelId = currentChannelId?.value; - if (payload?.channel_id !== currentChannelId) { - const screen = 'Notification'; - const passProps = { - notification, - }; + if (channelId && payload.channel_id !== channelId) { + const screen = 'Notification'; + const passProps = { + notification, + }; - DeviceEventEmitter.emit(Navigation.NAVIGATION_SHOW_OVERLAY); - showOverlay(screen, passProps); + DeviceEventEmitter.emit(Navigation.NAVIGATION_SHOW_OVERLAY); + showOverlay(screen, passProps); + } } }; @@ -148,23 +166,6 @@ class PushNotifications { Notifications.postLocalNotification(notification); }; - onAppStateChange = (appState: AppStateStatus) => { - const isActive = appState === 'active'; - const isBackground = appState === 'background'; - - if (isActive) { - if (!this.pushNotificationListener) { - this.pushNotificationListener = DeviceEventEmitter.addListener( - View.NOTIFICATION_IN_APP, - this.handleInAppNotification, - ); - } - } else if (isBackground) { - this.pushNotificationListener?.remove(); - this.pushNotificationListener = undefined; - } - }; - onNotificationOpened = (notification: NotificationWithData, completion: () => void) => { notification.userInteraction = true; this.handleNotification(notification); @@ -204,7 +205,7 @@ class PushNotifications { } operator.handleGlobal({ - global: [{id: 'deviceToken', value: `${prefix}:${deviceToken}`}], + global: [{id: GLOBAL_IDENTIFIERS.DEVICE_TOKEN, value: `${prefix}:${deviceToken}`}], prepareRecordsOnly: false, }); @@ -221,13 +222,6 @@ class PushNotifications { } }; - setApplicationIconBadgeNumber = (value: number) => { - if (Platform.OS === 'ios') { - const count = value < 0 ? 0 : value; - Notifications.ios.setBadgeCount(count); - } - }; - scheduleNotification = (notification: Notification) => { if (notification.fireDate) { if (Platform.OS === 'ios') { diff --git a/app/queries/app/global.ts b/app/queries/app/global.ts index da6a85ccd..6e0bcd3bd 100644 --- a/app/queries/app/global.ts +++ b/app/queries/app/global.ts @@ -1,14 +1,27 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {MM_TABLES} from '@constants/database'; -import {Database, Q} from '@nozbe/watermelondb'; +import {GLOBAL_IDENTIFIERS, MM_TABLES} from '@constants/database'; +import {Database} from '@nozbe/watermelondb'; import type Global from '@typings/database/models/app/global'; const {APP: {GLOBAL}} = MM_TABLES; -export const getDeviceToken = async (appDatabase: Database) => { - const tokens = (await appDatabase.collections.get(GLOBAL).query(Q.where('id', 'deviceToken')).fetch()) as Global[]; - return tokens?.[0]?.value ?? ''; +export const queryDeviceToken = async (appDatabase: Database) => { + try { + const tokens = await appDatabase.get(GLOBAL).find(GLOBAL_IDENTIFIERS.DEVICE_TOKEN) as Global; + return tokens?.value || ''; + } catch { + return ''; + } +}; + +export const queryMentionCount = async (appDatabase: Database) => { + try { + const mentions = await appDatabase.get(GLOBAL).find(GLOBAL_IDENTIFIERS.MENTION_COUNT) as Global; + return mentions?.value || ''; + } catch { + return ''; + } }; diff --git a/app/queries/app/servers.ts b/app/queries/app/servers.ts index e2a6b3f7d..7b5483c5f 100644 --- a/app/queries/app/servers.ts +++ b/app/queries/app/servers.ts @@ -8,18 +8,18 @@ import type Servers from '@typings/database/models/app/servers'; const {APP: {SERVERS}} = MM_TABLES; -export const getServer = async (appDatabase: Database, serverUrl: string) => { +export const queryServer = async (appDatabase: Database, serverUrl: string) => { const servers = (await appDatabase.collections.get(SERVERS).query(Q.where('url', serverUrl)).fetch()) as Servers[]; return servers?.[0]; }; -export const getAllServers = async (appDatabse: Database) => { +export const queryAllServers = async (appDatabse: Database) => { return (await appDatabse.collections.get(MM_TABLES.APP.SERVERS).query().fetch()) as Servers[]; }; -export const getActiveServer = async (appDatabse: Database) => { +export const queryActiveServer = async (appDatabse: Database) => { try { - const servers = await getAllServers(appDatabse); + const servers = await queryAllServers(appDatabse); return servers.reduce((a, b) => (b.lastActiveAt > a.lastActiveAt ? b : a)); } catch { return undefined; diff --git a/app/queries/servers/role.ts b/app/queries/servers/role.ts index dc2a28673..025bde96b 100644 --- a/app/queries/servers/role.ts +++ b/app/queries/servers/role.ts @@ -8,7 +8,7 @@ import Role from '@typings/database/models/servers/role'; const {SERVER: {ROLE}} = MM_TABLES; -export const getRoles = async (database: Database) => { +export const queryRoles = async (database: Database) => { const roles = await database.collections.get(ROLE).query().fetch() as Role[]; return roles; }; diff --git a/app/queries/servers/system.ts b/app/queries/servers/system.ts index c8802102d..d66ffd5ea 100644 --- a/app/queries/servers/system.ts +++ b/app/queries/servers/system.ts @@ -1,36 +1,61 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Database, Q} from '@nozbe/watermelondb'; +import {Database} from '@nozbe/watermelondb'; -import {MM_TABLES} from '@constants/database'; +import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database'; import System from '@typings/database/models/servers/system'; const {SERVER: {SYSTEM}} = MM_TABLES; -export const getCurrentUserId = async (serverDatabase: Database) => { - const currentUserId = await serverDatabase.collections.get(SYSTEM).query(Q.where('id', 'currentUserId')).fetch() as System[]; - return currentUserId?.[0]; +export const queryCurrentChannelId = async (serverDatabase: Database) => { + try { + const currentChannelId = await serverDatabase.get(SYSTEM).find(SYSTEM_IDENTIFIERS.CURRENT_CHANNEL_ID) as System; + return currentChannelId?.value || ''; + } catch { + return ''; + } }; -export const getCommonSystemValues = async (database: Database) => { - const systemRecords = (await database.collections.get(SYSTEM).query(Q.where('id', Q.oneOf(['config', 'license', 'currentUserId']))).fetch()) as System[]; +export const queryCurrentUserId = async (serverDatabase: Database) => { + try { + const currentUserId = await serverDatabase.get(SYSTEM).find(SYSTEM_IDENTIFIERS.CURRENT_USER_ID) as System; + return currentUserId?.value || ''; + } catch { + return ''; + } +}; + +export const queryCommonSystemValues = async (database: Database) => { + const systemRecords = (await database.collections.get(SYSTEM).query().fetch()) as System[]; let config = {}; let license = {}; + let currentChannelId = ''; + let currentTeamId = ''; let currentUserId = ''; systemRecords.forEach((systemRecord) => { - if (systemRecord.id === 'config') { - config = systemRecord.value; - } - if (systemRecord.id === 'license') { - license = systemRecord.value; - } - if (systemRecord.id === 'currentUserId') { - currentUserId = systemRecord.value; + switch (systemRecord.id) { + case SYSTEM_IDENTIFIERS.CONFIG: + config = systemRecord.value; + break; + case SYSTEM_IDENTIFIERS.CURRENT_CHANNEL_ID: + currentChannelId = systemRecord.value; + break; + case SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID: + currentTeamId = systemRecord.value; + break; + case SYSTEM_IDENTIFIERS.CURRENT_USER_ID: + currentUserId = systemRecord.value; + break; + case SYSTEM_IDENTIFIERS.LICENSE: + license = systemRecord.value; + break; } }); return { + currentChannelId, + currentTeamId, currentUserId, config, license, diff --git a/app/queries/servers/user.ts b/app/queries/servers/user.ts index dbfc9cc7a..c2e2f34ef 100644 --- a/app/queries/servers/user.ts +++ b/app/queries/servers/user.ts @@ -1,12 +1,28 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Database, Q} from '@nozbe/watermelondb'; +import {Database} from '@nozbe/watermelondb'; import {MM_TABLES} from '@constants/database'; -import User from '@typings/database/models/servers/user'; -export const getUserById = async ({userId, database}: { userId: string, database: Database}) => { - const userRecords = (await database.collections.get(MM_TABLES.SERVER.USER).query(Q.where('id', userId)).fetch()) as User[]; - return userRecords?.[0]; +import type User from '@typings/database/models/servers/user'; + +import {queryCurrentUserId} from './system'; + +export const queryUserById = async ({userId, database}: { userId: string, database: Database}) => { + try { + const userRecord = (await database.collections.get(MM_TABLES.SERVER.USER).find(userId)) as User; + return userRecord; + } catch { + return undefined; + } +}; + +export const queryCurrentUser = async (database: Database) => { + const currentUserId = await queryCurrentUserId(database); + if (currentUserId) { + return queryUserById({userId: currentUserId, database}); + } + + return undefined; }; diff --git a/app/requests/local/systems.ts b/app/requests/local/systems.ts deleted file mode 100644 index 0a3cbb192..000000000 --- a/app/requests/local/systems.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import DatabaseManager from '@database/manager'; - -export const createSessions = async (serverUrl: string, sessions: any) => { - const database = DatabaseManager.serverDatabases[serverUrl].database; - const operator = DatabaseManager.serverDatabases[serverUrl].operator; - if (!database) { - return {error: `${serverUrl} database not found`}; - } - - await operator.handleSystem({ - systems: [{id: 'sessions', value: sessions}], - prepareRecordsOnly: false, - }); - - return null; -}; diff --git a/app/requests/remote/general.ts b/app/requests/remote/general.ts deleted file mode 100644 index 432deefda..000000000 --- a/app/requests/remote/general.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Client4} from '@client/rest'; - -export const doPing = async (serverUrl?: string) => { - let data; - const pingError = { - id: 'mobile.server_ping_failed', - defaultMessage: 'Cannot connect to the server. Please check your server URL and internet connection.', - }; - - try { - if (serverUrl) { - Client4.setUrl(serverUrl); - } - - data = await Client4.ping(); - if (data.status !== 'OK') { - // successful ping but not the right return {data} - return {error: {intl: pingError}}; - } - } catch (error) { - // Client4Error - if (error.status_code === 401) { - // When the server requires a client certificate to connect. - return {error}; - } - return {error: {intl: pingError}}; - } - - return {data}; -}; - -export const fetchConfigAndLicense = async () => { - try { - const [config, license] = await Promise.all([ - Client4.getClientConfigOld(), - Client4.getClientLicenseOld(), - ]); - - return {config, license}; - } catch (error) { - return {error}; - } -}; diff --git a/app/requests/remote/systems.ts b/app/requests/remote/systems.ts deleted file mode 100644 index 08d086899..000000000 --- a/app/requests/remote/systems.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Client4} from '@client/rest'; -import {logError} from '@requests/remote/error'; -import {forceLogoutIfNecessary} from '@requests/remote/user'; - -export const getDataRetentionPolicy = async (serverUrl: string) => { - let data = {}; - try { - data = await Client4.getDataRetentionPolicy(); - } catch (error) { - forceLogoutIfNecessary(serverUrl, error); - - //fixme: do we care for the below line ? It seems that the `error` object is never read ?? - // dispatch(batchActions([{type: GeneralTypes.RECEIVED_DATA_RETENTION_POLICY, error,},])); - logError(error); - return {error}; - } - - return data; -}; diff --git a/app/screens/channel/index.tsx b/app/screens/channel/index.tsx index 0eb61203e..3fb5e8180 100644 --- a/app/screens/channel/index.tsx +++ b/app/screens/channel/index.tsx @@ -13,9 +13,11 @@ import { import type {LaunchProps} from '@typings/launch'; +import {logout} from '@actions/remote/user'; + declare const global: {HermesInternal: null | {}}; -type ChannelProps = LaunchProps +type ChannelProps = LaunchProps; const Channel = (props: ChannelProps) => { // TODO: If we have LaunchProps, ensure we load the correct channel/post/modal. @@ -32,6 +34,10 @@ const Channel = (props: ChannelProps) => { // } // } + const doLogout = () => { + logout(props.serverUrl!); + }; + return ( <> @@ -48,7 +54,10 @@ const Channel = (props: ChannelProps) => { )} - {'Step One'} + {'Step One'} {'Edit '}{'screens/channel/index.tsx'}{' to change this'} {'screen and then come back to see your edits.'} diff --git a/app/screens/forgot_password/forgot_password.test.tsx b/app/screens/forgot_password/forgot_password.test.tsx index 9f75f0c6e..d2e049777 100644 --- a/app/screens/forgot_password/forgot_password.test.tsx +++ b/app/screens/forgot_password/forgot_password.test.tsx @@ -5,7 +5,7 @@ import {act, waitFor} from '@testing-library/react-native'; import React from 'react'; import {Preferences} from '@constants'; -import * as UserAPICalls from '@requests/remote/user'; +import * as UserAPICalls from '@actions/remote/user'; import {renderWithIntl, fireEvent} from '@test/intl-test-helper'; import ForgotPassword from './index'; @@ -13,6 +13,7 @@ import ForgotPassword from './index'; describe('ForgotPassword', () => { const baseProps = { componentId: 'ForgotPassword', + serverUrl: 'https://community.mattermost.com', theme: Preferences.THEMES.default, }; diff --git a/app/screens/forgot_password/index.tsx b/app/screens/forgot_password/index.tsx index 24138334c..c3936cb37 100644 --- a/app/screens/forgot_password/index.tsx +++ b/app/screens/forgot_password/index.tsx @@ -9,15 +9,16 @@ import {SafeAreaView} from 'react-native-safe-area-context'; import ErrorText from '@components/error_text'; import FormattedText from '@components/formatted_text'; -import {sendPasswordResetEmail} from '@requests/remote/user'; +import {sendPasswordResetEmail} from '@actions/remote/user'; import {isEmail} from '@utils/helpers'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; type Props = { + serverUrl: string; theme: Theme; } -const ForgotPassword = ({theme}: Props) => { +const ForgotPassword = ({serverUrl, theme}: Props) => { const [email, setEmail] = useState(''); const [error, setError] = useState(''); const [isPasswordLinkSent, setIsPasswordLinkSent] = useState(false); @@ -40,7 +41,7 @@ const ForgotPassword = ({theme}: Props) => { return; } - const {data, error: apiError = undefined} = await sendPasswordResetEmail(email); + const {data, error: apiError = undefined} = await sendPasswordResetEmail(serverUrl, email); if (data) { setIsPasswordLinkSent(true); diff --git a/app/screens/login/index.tsx b/app/screens/login/index.tsx index 586a0bdfc..27dcdd906 100644 --- a/app/screens/login/index.tsx +++ b/app/screens/login/index.tsx @@ -25,24 +25,25 @@ import ErrorText, {ClientErrorWithIntl} from '@components/error_text'; import {FORGOT_PASSWORD, MFA} from '@constants/screens'; import FormattedText from '@components/formatted_text'; import {useManagedConfig} from '@mattermost/react-native-emm'; -import {scheduleExpiredNotification} from '@requests/remote/push_notification'; -import {login} from '@requests/remote/user'; +import {scheduleExpiredNotification} from '@actions/remote/push_notification'; +import {login} from '@actions/remote/user'; import {goToScreen, resetToChannel} from '@screens/navigation'; import {t} from '@utils/i18n'; import {preventDoubleTap} from '@utils/tap'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; -type LoginProps = { +import type {LaunchProps} from '@typings/launch'; + +interface LoginProps extends LaunchProps { componentId: string; config: ClientConfig; license: ClientLicense; - serverUrl: string; theme: Theme; -}; +} export const MFA_EXPECTED_ERRORS = ['mfa.validate_token.authenticate.app_error', 'ent.mfa.validate_token.authenticate.app_error']; -const Login: NavigationFunctionComponent = ({config, license, serverUrl, theme}: LoginProps) => { +const Login: NavigationFunctionComponent = ({config, extra, launchError, launchType, license, serverUrl, theme}: LoginProps) => { const styles = getStyleSheet(theme); const loginRef = useRef(null); @@ -129,15 +130,15 @@ const Login: NavigationFunctionComponent = ({config, license, serverUrl, theme}: }); const signIn = async () => { - const result = await login(serverUrl, {loginId: loginId.toLowerCase(), password, config, license}); + const result = await login(serverUrl!, {loginId: loginId.toLowerCase(), password, config, license}); if (checkLoginResponse(result)) { await goToChannel(); } }; const goToChannel = async () => { - await scheduleExpiredNotification(serverUrl, intl); - resetToChannel({serverUrl}); + await scheduleExpiredNotification(serverUrl!, intl); + resetToChannel({extra, launchError, launchType, serverUrl}); }; const checkLoginResponse = (data: any) => { @@ -203,8 +204,12 @@ const Login: NavigationFunctionComponent = ({config, license, serverUrl, theme}: const onPressForgotPassword = () => { const screen = FORGOT_PASSWORD; const title = intl.formatMessage({id: 'password_form.title', defaultMessage: 'Password Reset'}); + const passProps = { + theme, + serverUrl, + }; - goToScreen(screen, title, {theme}); + goToScreen(screen, title, passProps); }; const createLoginPlaceholder = () => { diff --git a/app/screens/login/login.test.tsx b/app/screens/login/login.test.tsx index c04b74cd2..14af17d3f 100644 --- a/app/screens/login/login.test.tsx +++ b/app/screens/login/login.test.tsx @@ -9,7 +9,7 @@ import {waitFor, renderWithIntl, fireEvent} from '@test/intl-test-helper'; import Login from './index'; -jest.mock('@requests/remote/user', () => { +jest.mock('@actions/remote/user', () => { return { login: () => { return { @@ -137,7 +137,10 @@ describe('Login', () => { toHaveBeenCalledWith( 'ForgotPassword', 'Password Reset', - {theme: baseProps.theme}, + { + serverUrl: baseProps.serverUrl, + theme: baseProps.theme, + }, ); }); }); diff --git a/app/screens/login_options/index.tsx b/app/screens/login_options/index.tsx index 4cd6f85ce..743b51d5f 100644 --- a/app/screens/login_options/index.tsx +++ b/app/screens/login_options/index.tsx @@ -13,6 +13,8 @@ import {goToScreen} from '@screens/navigation'; import {preventDoubleTap} from '@utils/tap'; import {changeOpacity, makeStyleSheetFromTheme} from '@app/utils/theme'; +import type {LaunchProps} from '@typings/launch'; + import EmailOption from './email'; import GitLabOption from './gitlab'; import GoogleOption from './google'; @@ -21,7 +23,7 @@ import Office365Option from './office365'; import OpenIdOption from './open_id'; import SamlOption from './saml'; -type LoginOptionsProps = { +interface LoginOptionsProps extends LaunchProps { componentId: string; serverUrl: string; config: ClientConfig; @@ -57,7 +59,7 @@ const getStyles = makeStyleSheetFromTheme((theme: Theme) => ({ }, })); -const LoginOptions: NavigationFunctionComponent = ({config, license, serverUrl, theme}: LoginOptionsProps) => { +const LoginOptions: NavigationFunctionComponent = ({config, extra, launchType, launchError, license, serverUrl, theme}: LoginOptionsProps) => { const intl = useIntl(); const styles = getStyles(theme); @@ -65,13 +67,13 @@ const LoginOptions: NavigationFunctionComponent = ({config, license, serverUrl, const screen = LOGIN; const title = intl.formatMessage({id: 'mobile.routes.login', defaultMessage: 'Login'}); - goToScreen(screen, title, {config, license, serverUrl, theme}); + goToScreen(screen, title, {config, extra, launchError, launchType, license, serverUrl, theme}); }); const displaySSO = preventDoubleTap((ssoType: string) => { const screen = SSO; const title = intl.formatMessage({id: 'mobile.routes.sso', defaultMessage: 'Single Sign-On'}); - goToScreen(screen, title, {config, license, theme, ssoType, serverUrl}); + goToScreen(screen, title, {config, extra, launchError, launchType, license, theme, ssoType, serverUrl}); }); return ( diff --git a/app/screens/mfa/index.tsx b/app/screens/mfa/index.tsx index 21ae5d9af..5643b000b 100644 --- a/app/screens/mfa/index.tsx +++ b/app/screens/mfa/index.tsx @@ -18,7 +18,7 @@ import {SafeAreaView} from 'react-native-safe-area-context'; import ErrorText from '@components/error_text'; import FormattedText from '@components/formatted_text'; -import {login} from '@requests/remote/user'; +import {login} from '@actions/remote/user'; import {Config} from '@typings/database/models/servers/config'; import {License} from '@typings/database/models/servers/license'; import {t} from '@utils/i18n'; @@ -148,7 +148,7 @@ const MFA = ({config, goToChannel, license, loginId, password, serverUrl, theme} autoCapitalize='none' autoCorrect={false} keyboardType='numeric' - placeholder={formatMessage({id: t('login_mfa.token'), defaultMessage: 'MFA Token'})} + placeholder={formatMessage({id: 'login_mfa.token', defaultMessage: 'MFA Token'})} placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.5)} returnKeyType='go' underlineColorAndroid='transparent' diff --git a/app/screens/mfa/mfa.test.tsx b/app/screens/mfa/mfa.test.tsx index 88a5c2ee7..af18ce7fb 100644 --- a/app/screens/mfa/mfa.test.tsx +++ b/app/screens/mfa/mfa.test.tsx @@ -9,7 +9,7 @@ import {renderWithIntl} from '@test/intl-test-helper'; import Mfa from './index'; -jest.mock('@requests/remote/user', () => { +jest.mock('@actions/remote/user', () => { return { login: jest.fn(), }; diff --git a/app/screens/navigation.ts b/app/screens/navigation.ts index c305730b4..7e15d0913 100644 --- a/app/screens/navigation.ts +++ b/app/screens/navigation.ts @@ -1,11 +1,11 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Appearance, Keyboard, Platform} from 'react-native'; +import {Appearance, DeviceEventEmitter, Keyboard, Platform} from 'react-native'; import {Layout, Navigation, Options, OptionsModalPresentationStyle} from 'react-native-navigation'; import merge from 'deepmerge'; -import {Screens, Preferences} from '@constants'; +import {Navigation as NavigationConstants, Preferences, Screens} from '@constants'; import EphemeralStore from '@store/ephemeral_store'; @@ -234,7 +234,7 @@ export async function dismissAllModalsAndPopToRoot() { await dismissAllModals(); await popToRoot(); - // EventEmmiter.emit(NavigationTypes.NAVIGATION_DISMISS_AND_POP_TO_ROOT); + DeviceEventEmitter.emit(NavigationConstants.NAVIGATION_DISMISS_AND_POP_TO_ROOT); } export function showModal(name: string, title: string, passProps = {}, options = {}) { diff --git a/app/screens/server/index.tsx b/app/screens/server/index.tsx index 982ffe8b8..3e5427814 100644 --- a/app/screens/server/index.tsx +++ b/app/screens/server/index.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {ManagedConfig, useManagedConfig} from '@mattermost/react-native-emm'; +import {useManagedConfig, ManagedConfig} from '@mattermost/react-native-emm'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import {useIntl} from 'react-intl'; import { @@ -9,15 +9,16 @@ import { Platform, StatusBar, StyleSheet, TextInput, TouchableWithoutFeedback, View, } from 'react-native'; import Button from 'react-native-button'; -import {NavigationFunctionComponent} from 'react-native-navigation'; +import {Navigation, NavigationFunctionComponent} from 'react-native-navigation'; import {SafeAreaView} from 'react-native-safe-area-context'; +import {doPing, fetchConfigAndLicense} from '@actions/remote/general'; import LocalConfig from '@assets/config.json'; import AppVersion from '@components/app_version'; import ErrorText, {ClientErrorWithIntl} from '@components/error_text'; import FormattedText from '@components/formatted_text'; import {Screens} from '@constants'; -import {doPing, fetchConfigAndLicense} from '@requests/remote/general'; +import NetworkManager from '@init/network_manager'; import {goToScreen} from '@screens/navigation'; import {isMinimumServerVersion} from '@utils/helpers'; import {preventDoubleTap} from '@utils/tap'; @@ -33,7 +34,7 @@ interface ServerProps extends LaunchProps { let cancelPing: undefined | (() => void); -const Server: NavigationFunctionComponent = ({extra, launchType, launchError, theme}: ServerProps) => { +const Server: NavigationFunctionComponent = ({componentId, extra, launchType, launchError, theme}: ServerProps) => { // TODO: If we have LaunchProps, ensure they get passed along to subsequent screens // so that they are eventually accessible in the Channel screen. @@ -51,7 +52,7 @@ const Server: NavigationFunctionComponent = ({extra, launchType, launchError, th const styles = getStyleSheet(theme); const {formatMessage} = intl; - const displayLogin = (config: ClientConfig, license: ClientLicense) => { + const displayLogin = (serverUrl: string, config: ClientConfig, license: ClientLicense) => { const samlEnabled = config.EnableSaml === 'true' && license.IsLicensed === 'true' && license.SAML === 'true'; const gitlabEnabled = config.EnableSignUpWithGitLab === 'true'; const googleEnabled = config.EnableSignUpWithGoogle === 'true' && license.IsLicensed === 'true'; @@ -74,9 +75,12 @@ const Server: NavigationFunctionComponent = ({extra, launchType, launchError, th const passProps = { config, + extra, + launchError, + launchType, license, theme, - serverUrl: url, + serverUrl, }; const defaultOptions = { @@ -89,6 +93,7 @@ const Server: NavigationFunctionComponent = ({extra, launchType, launchError, th goToScreen(screen, title, passProps, defaultOptions); setConnecting(false); + setUrl(serverUrl); }; const handleConnect = preventDoubleTap((manualUrl?: string) => { @@ -133,38 +138,39 @@ const Server: NavigationFunctionComponent = ({extra, launchType, launchError, th }; const serverUrl = await getServerUrlAfterRedirect(pingUrl, !retryWithHttp); - const result = await doPing(serverUrl); if (canceled) { return; } - if (result.error && retryWithHttp) { - const nurl = serverUrl.replace('https:', 'http:'); - pingServer(nurl, false); - return; - } else if (result.error) { - setError(result.error); - setConnecting(false); + if (result.error) { + if (retryWithHttp) { + const nurl = serverUrl.replace('https:', 'http:'); + pingServer(nurl, false); + } else { + setError(result.error); + setConnecting(false); + } + return; } - const data = await fetchConfigAndLicense(); + const data = await fetchConfigAndLicense(serverUrl); if (data.error) { setError(data.error); setConnecting(false); return; } - displayLogin(data.config!, data.license!); + displayLogin(serverUrl, data.config!, data.license!); }; const blur = useCallback(() => { input.current?.blur(); }, []); - const handleTextChanged = useCallback((text) => { + const handleTextChanged = useCallback((text: string) => { setUrl(text); }, []); @@ -208,6 +214,19 @@ const Server: NavigationFunctionComponent = ({extra, launchType, launchError, th } }, []); + useEffect(() => { + const listener = { + componentDidAppear: () => { + if (url) { + NetworkManager.invalidateClient(url); + } + }, + }; + const unsubscribe = Navigation.events().registerComponentListener(listener, componentId); + + return () => unsubscribe.remove(); + }, [componentId, url]); + let buttonIcon; let buttonText; diff --git a/app/screens/sso/index.tsx b/app/screens/sso/index.tsx index 29610d429..548aab4b0 100644 --- a/app/screens/sso/index.tsx +++ b/app/screens/sso/index.tsx @@ -5,26 +5,26 @@ import {useManagedConfig} from '@mattermost/react-native-emm'; import React, {useState} from 'react'; import {useIntl} from 'react-intl'; -import {Client4} from '@client/rest'; import {SSO as SSOEnum} from '@constants'; -import {scheduleExpiredNotification} from '@requests/remote/push_notification'; -import {ssoLogin} from '@requests/remote/user'; +import {scheduleExpiredNotification} from '@actions/remote/push_notification'; +import {ssoLogin} from '@actions/remote/user'; import {resetToChannel} from '@screens/navigation'; -import {ErrorApi} from '@typings/api/client4'; +import {ErrorApi} from '@typings/api/client'; import {isMinimumServerVersion} from '@utils/helpers'; +import type {LaunchProps} from '@typings/launch'; + import SSOWithRedirectURL from './sso_with_redirect_url'; import SSOWithWebView from './sso_with_webview'; -interface SSOProps { +interface SSOProps extends LaunchProps { config: Partial; license: Partial; - serverUrl: string; ssoType: string; theme: Partial; } -const SSO = ({config, serverUrl, ssoType, theme}: SSOProps) => { +const SSO = ({config, extra, launchError, launchType, serverUrl, ssoType, theme}: SSOProps) => { const intl = useIntl(); const managedConfig = useManagedConfig(); @@ -70,10 +70,8 @@ const SSO = ({config, serverUrl, ssoType, theme}: SSOProps) => { setLoginError(errorMessage); }; - const onMMToken = async (token: string) => { - Client4.setToken(token); - - const {error = undefined} = await ssoLogin(serverUrl); + const doSSOLogin = async (bearerToken: string, csrfToken: string) => { + const {error = undefined} = await ssoLogin(serverUrl!, bearerToken, csrfToken); if (error) { onLoadEndError(error); setLoginError(error); @@ -83,19 +81,16 @@ const SSO = ({config, serverUrl, ssoType, theme}: SSOProps) => { }; const goToChannel = () => { - scheduleExpiredNotification(serverUrl, intl); - resetToChannel(); + scheduleExpiredNotification(serverUrl!, intl); + resetToChannel({extra, launchError, launchType, serverUrl}); }; const isSSOWithRedirectURLAvailable = isMinimumServerVersion(config.Version!, 5, 33, 0); const props = { + doSSOLogin, loginError, loginUrl, - onCSRFToken: (csrfToken: string) => { - Client4.setCSRF(csrfToken); - }, - onMMToken, setLoginError, theme, }; @@ -105,12 +100,17 @@ const SSO = ({config, serverUrl, ssoType, theme}: SSOProps) => { ); } - return ; + return ( + + ); }; export default SSO; diff --git a/app/screens/sso/sso.test.tsx b/app/screens/sso/sso.test.tsx index f75c91fbb..fc61dd5c4 100644 --- a/app/screens/sso/sso.test.tsx +++ b/app/screens/sso/sso.test.tsx @@ -5,6 +5,7 @@ import React from 'react'; import {Preferences} from '@constants'; import {renderWithIntl} from '@test/intl-test-helper'; +import {LaunchType} from '@typings/launch'; import SSOLogin from './index'; @@ -28,6 +29,7 @@ describe('SSO', () => { ssoType: 'GITLAB', theme: Preferences.THEMES.default, serverUrl: 'https://locahost:8065', + launchType: LaunchType.Normal, }; test('implement with webview when version is less than 5.32 version', async () => { diff --git a/app/screens/sso/sso_with_redirect_url.test.tsx b/app/screens/sso/sso_with_redirect_url.test.tsx index 578b4b7e3..d87dcf6b4 100644 --- a/app/screens/sso/sso_with_redirect_url.test.tsx +++ b/app/screens/sso/sso_with_redirect_url.test.tsx @@ -17,11 +17,11 @@ jest.mock('@utils/url', () => { describe('SSO with redirect url', () => { const baseProps = { customUrlScheme: 'mmauth://', + doSSOLogin: jest.fn(), intl: {}, loginError: '', loginUrl: '', - onCSRFToken: jest.fn(), - onMMToken: jest.fn(), + serverUrl: 'http://localhost:8065', setLoginError: jest.fn(), theme: Preferences.THEMES.default, }; diff --git a/app/screens/sso/sso_with_redirect_url.tsx b/app/screens/sso/sso_with_redirect_url.tsx index 832262366..910360f07 100644 --- a/app/screens/sso/sso_with_redirect_url.tsx +++ b/app/screens/sso/sso_with_redirect_url.tsx @@ -9,32 +9,36 @@ import urlParse from 'url-parse'; import FormattedText from '@components/formatted_text'; import Loading from '@components/loading'; +import {REDIRECT_URL_SCHEME, REDIRECT_URL_SCHEME_DEV} from '@constants'; +import NetworkManager from '@app/init/network_manager'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import {tryOpenURL} from '@utils/url'; interface SSOWithRedirectURLProps { + doSSOLogin: (bearerToken: string, csrfToken: string) => void; loginError: string; loginUrl: string; - onCSRFToken: (token: string) => void; - onMMToken: (token: string) => void; + serverUrl: string; setLoginError: (value: string) => void; theme: Partial } -const SSOWithRedirectURL = ({loginError, loginUrl, onCSRFToken, onMMToken, setLoginError, theme}: SSOWithRedirectURLProps) => { +const SSOWithRedirectURL = ({doSSOLogin, loginError, loginUrl, serverUrl, setLoginError, theme}: SSOWithRedirectURLProps) => { const [error, setError] = useState(''); const style = getStyleSheet(theme); const intl = useIntl(); - let customUrlScheme = 'mmauth://'; + let customUrlScheme = REDIRECT_URL_SCHEME; if (DeviceInfo.getBundleId && DeviceInfo.getBundleId().includes('rnbeta')) { - customUrlScheme = 'mmauthbeta://'; + customUrlScheme = REDIRECT_URL_SCHEME_DEV; } const redirectUrl = customUrlScheme + 'callback'; - const init = (resetErrors?: boolean) => { + const init = (resetErrors = true) => { if (resetErrors !== false) { setError(''); setLoginError(''); + NetworkManager.invalidateClient(serverUrl); + NetworkManager.createClient(serverUrl); } const parsedUrl = urlParse(loginUrl, true); parsedUrl.set('query', { @@ -60,6 +64,7 @@ const SSOWithRedirectURL = ({loginError, loginUrl, onCSRFToken, onMMToken, setLo message, ); }; + tryOpenURL(url, onError); }; @@ -67,9 +72,10 @@ const SSOWithRedirectURL = ({loginError, loginUrl, onCSRFToken, onMMToken, setLo const onURLChange = ({url}: { url: string }) => { if (url && url.startsWith(redirectUrl)) { const parsedUrl = urlParse(url, true); - if (parsedUrl.query && parsedUrl.query.MMCSRF && parsedUrl.query.MMAUTHTOKEN) { - onCSRFToken(parsedUrl.query.MMCSRF); - onMMToken(parsedUrl.query.MMAUTHTOKEN); + const bearerToken = parsedUrl.query?.MMAUTHTOKEN; + const csrfToken = parsedUrl.query?.MMCSRF; + if (bearerToken && csrfToken) { + doSSOLogin(bearerToken, csrfToken); } else { setError( intl.formatMessage({ @@ -117,14 +123,6 @@ const SSOWithRedirectURL = ({loginError, loginUrl, onCSRFToken, onMMToken, setLo defaultMessage='Please use your browser to complete the login' style={style.infoText} /> - init()}> - - )} diff --git a/app/screens/sso/sso_with_webview.tsx b/app/screens/sso/sso_with_webview.tsx index 3cd054e5f..b86b91504 100644 --- a/app/screens/sso/sso_with_webview.tsx +++ b/app/screens/sso/sso_with_webview.tsx @@ -1,10 +1,10 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import CookieManager, {Cookies} from '@react-native-community/cookies'; +import CookieManager, {Cookies} from '@react-native-cookies/cookies'; import React, {useEffect} from 'react'; import {useIntl} from 'react-intl'; -import {Alert, Text, View} from 'react-native'; +import {Alert, Platform, Text, View} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; import {WebView} from 'react-native-webview'; import { @@ -15,7 +15,6 @@ import { } from 'react-native-webview/lib/WebViewTypes'; import urlParse from 'url-parse'; -import {Client4} from '@client/rest'; import Loading from '@components/loading'; import {SSO} from '@constants'; import {popTopScreen} from '@screens/navigation'; @@ -59,20 +58,20 @@ const oneLoginFormScalingJS = ` interface SSOWithWebViewProps { completeUrlPath: string; + doSSOLogin: (bearerToken: string, csrfToken: string) => void; loginError: string; loginUrl: string; - onCSRFToken: (token: string) => void; - onMMToken: (token: string) => void; serverUrl: string; ssoType: string; theme: Partial } -const SSOWithWebView = ({completeUrlPath, loginError, loginUrl, onCSRFToken, onMMToken, serverUrl, ssoType, theme}: SSOWithWebViewProps) => { +const SSOWithWebView = ({completeUrlPath, doSSOLogin, loginError, loginUrl, serverUrl, ssoType, theme}: SSOWithWebViewProps) => { const style = getStyleSheet(theme); const intl = useIntl(); const [error, setError] = React.useState(null); const [jsCode, setJSCode] = React.useState(''); + const visitedUrls = React.useRef(new Set()).current; const [messagingEnabled, setMessagingEnabled] = React.useState(false); const [shouldRenderWebView, setShouldRenderWebView] = React.useState(true); const cookiesTimeout = React.useRef(); @@ -86,6 +85,21 @@ const SSOWithWebView = ({completeUrlPath, loginError, loginUrl, onCSRFToken, onM }; }, []); + const removeCookiesFromVisited = () => { + if (Platform.OS === 'ios') { + visitedUrls.forEach((visited) => { + CookieManager.get(visited, true).then(async (cookies: Cookies) => { + if (cookies) { + const values = Object.values(cookies); + for (const cookie of values) { + CookieManager.clearByName(visited, cookie.name, true); + } + } + }); + }); + } + }; + const extractCookie = (parsedUrl: urlParse) => { try { const original = urlParse(serverUrl); @@ -95,19 +109,16 @@ const SSOWithWebView = ({completeUrlPath, loginError, loginUrl, onCSRFToken, onM // Rebuild the server url without query string and/or hash const url = `${parsedUrl.origin}${parsedUrl.pathname}`; - Client4.setUrl(url); CookieManager.get(url, true).then((res: Cookies) => { const mmtoken = res.MMAUTHTOKEN; const csrf = res.MMCSRF; - const token = typeof mmtoken === 'object' ? mmtoken.value : mmtoken; + const bearerToken = typeof mmtoken === 'object' ? mmtoken.value : mmtoken; const csrfToken = typeof csrf === 'object' ? csrf.value : csrf; - if (csrfToken) { - onCSRFToken(csrfToken); - } - if (token) { - onMMToken(token); + if (bearerToken) { + removeCookiesFromVisited(); + doSSOLogin(bearerToken, csrfToken); if (cookiesTimeout.current) { clearTimeout(cookiesTimeout.current); } @@ -162,6 +173,10 @@ const SSOWithWebView = ({completeUrlPath, loginError, loginUrl, onCSRFToken, onM const {url} = navState; let isMessagingEnabled = false; const parsed = urlParse(url); + if (!serverUrl.includes(parsed.host)) { + visitedUrls.add(parsed.origin); + } + if (parsed.host.includes('.onelogin.com')) { setJSCode(oneLoginFormScalingJS); } else if (parsed.pathname === completeUrlPath) { @@ -193,6 +208,7 @@ const SSOWithWebView = ({completeUrlPath, loginError, loginUrl, onCSRFToken, onM { - if (!stat.includes(vectorIconsDir)) { - FileSystem.deleteAsync(stat, {idempotent: true}); - } + FileSystem.deleteAsync(stat, {idempotent: true}); }); } } diff --git a/app/utils/helpers.ts b/app/utils/helpers.ts index dcc3778a9..d3a324b89 100644 --- a/app/utils/helpers.ts +++ b/app/utils/helpers.ts @@ -6,6 +6,7 @@ // versions, and a non-equal minor version will ignore dot version. // currentVersion is a string, e.g '4.6.0' // minMajorVersion, minMinorVersion, minDotVersion are integers + export const isMinimumServerVersion = (currentVersion: string, minMajorVersion = 0, minMinorVersion = 0, minDotVersion = 0): boolean => { if (!currentVersion || typeof currentVersion !== 'string') { return false; @@ -72,3 +73,16 @@ export function isEmail(email: string): boolean { // this prevents outlook.style@domain.com addresses and multiple comma-separated addresses from being accepted return (/^[^ ,@]+@[^ ,@]+$/).test(email); } + +export function safeParseJSON(rawJson: string | Record) { + let data = rawJson; + try { + if (typeof rawJson == 'string') { + data = JSON.parse(rawJson); + } + } catch { + // Do nothing + } + + return data; +} diff --git a/app/utils/security.ts b/app/utils/security.ts index b2dc83c1b..f90874a84 100644 --- a/app/utils/security.ts +++ b/app/utils/security.ts @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import CookieManager from '@react-native-community/cookies'; +import CookieManager from '@react-native-cookies/cookies'; export async function getCSRFFromCookie(url: string) { const cookies = await CookieManager.get(url, false); diff --git a/app/utils/url/index.ts b/app/utils/url/index.ts index a131c279c..7c894c265 100644 --- a/app/utils/url/index.ts +++ b/app/utils/url/index.ts @@ -4,6 +4,8 @@ import {Linking} from 'react-native'; import urlParse from 'url-parse'; +import GenericClient from '@mattermost/react-native-network-client'; + import {Files} from '@constants'; import {DeepLinkType, DeepLinkWithData} from '@typings/launch'; import {emptyFunction} from '@utils/general'; @@ -39,12 +41,12 @@ export async function getServerUrlAfterRedirect(serverUrl: string, useHttp = fal let url = sanitizeUrl(serverUrl, useHttp); try { - const resp = await fetch(url, {method: 'HEAD'}); - if (resp.redirected) { - url = resp.url; + const resp = await GenericClient.head(url); + if (resp.redirectUrls?.length) { + url = resp.redirectUrls[resp.redirectUrls.length - 1]; } - } catch { - // do nothing + } catch (error) { + // do nothing } return sanitizeUrl(url, useHttp); diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index eb95ac5ab..3fdcbd4eb 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -1,7 +1,7 @@ { "login_mfa.enterToken": "To complete the sign in process, please enter a token from your smartphone's authenticator", - "login_mfa.token": "", - "login_mfa.tokenReq": "", + "login_mfa.token": "MFA Token", + "login_mfa.tokenReq": "Please enter an MFA token", "login.email": "Email", "login.forgot": "I forgot my password", "login.invalidPassword": "Your password is incorrect.", @@ -50,6 +50,7 @@ "mobile.push_notification_reply.button": "Send", "mobile.push_notification_reply.placeholder": "Write a reply...", "mobile.push_notification_reply.title": "Reply", + "mobile.request.invalid_request_method": "Invalid request method", "mobile.request.invalid_response": "Received invalid response from the server.", "mobile.routes.login": "Login", "mobile.routes.loginOptions": "Login Chooser", diff --git a/babel.config.js b/babel.config.js index 04b737a5b..890a68834 100644 --- a/babel.config.js +++ b/babel.config.js @@ -19,6 +19,7 @@ module.exports = { ['module-resolver', { root: ['.'], alias: { + '@actions': './app/actions', '@app': './app/', '@assets': './dist/assets', '@client': './app/client', @@ -29,7 +30,6 @@ module.exports = { '@init': './app/init', '@notifications': './app/notifications', '@queries': './app/queries', - '@requests': './app/requests', '@screens': './app/screens', '@share': './share_extension', '@store': './app/store', diff --git a/index.ts b/index.ts index 67f3c1cea..0124ff333 100644 --- a/index.ts +++ b/index.ts @@ -6,11 +6,13 @@ import 'react-native-gesture-handler'; import {ComponentDidAppearEvent, ComponentDidDisappearEvent, Navigation} from 'react-native-navigation'; import {Navigation as NavigationConstants, Screens} from './app/constants'; +import DatabaseManager from './app/database/manager'; import {getAllServerCredentials} from './app/init/credentials'; import GlobalEventHandler from './app/init/global_event_handler'; -import './app/init/fetch'; import {initialLaunch} from './app/init/launch'; +import NetworkManager from './app/init/network_manager'; import ManagedApp from './app/init/managed_app'; +import PushNotifications from './app/init/push_notifications'; import {registerScreens} from './app/screens/index'; import EphemeralStore from './app/store/ephemeral_store'; import setFontFamily from './app/utils/font_family'; @@ -23,6 +25,7 @@ if (__DEV__) { '`-[RCTRootView cancelTouches]`', 'scaleY', ]); + LogBox.ignoreLogs(['Require cycle: node_modules/zod/lib/src/index.js']); require('storybook/mattermost_storybook.ts'); } @@ -50,12 +53,12 @@ Navigation.events().registerAppLaunchedListener(async () => { registerNavigationListeners(); registerScreens(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars const serverCredentials = await getAllServerCredentials(); + const serverUrls = serverCredentials.map((credential) => credential.serverUrl); - // TODO: - // DatabaseManager.init(serverCredentials); - // NetworkClientManager.init(serverCredentials); + await DatabaseManager.init(serverUrls); + await NetworkManager.init(serverCredentials); + PushNotifications.init(); initialLaunch(); }); diff --git a/ios/DatabaseHelper/DatabaseHelper/DatabaseHelper.swift b/ios/DatabaseHelper/DatabaseHelper/DatabaseHelper.swift index fa8f158e8..041aa6c54 100644 --- a/ios/DatabaseHelper/DatabaseHelper/DatabaseHelper.swift +++ b/ios/DatabaseHelper/DatabaseHelper/DatabaseHelper.swift @@ -30,7 +30,7 @@ extension DatabaseError: LocalizedError { } public class DatabaseHelper: NSObject { - internal let DEFAULT_DB_NAME = "default.db" + internal let DEFAULT_DB_NAME = "app.db" internal var DEFAULT_DB_PATH: String internal var defaultDB: OpaquePointer? = nil @@ -64,7 +64,7 @@ public class DatabaseHelper: NSObject { } var queryStatement: OpaquePointer? - let queryString = "SELECT url FROM servers;" + let queryString = "SELECT url FROM Servers;" if sqlite3_prepare_v2(defaultDB, queryString, -1, &queryStatement, nil) == SQLITE_OK { if sqlite3_step(queryStatement) == SQLITE_ROW, let result = sqlite3_column_text(queryStatement, 0) { diff --git a/ios/Podfile b/ios/Podfile index dda011d54..48319edef 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -26,6 +26,9 @@ target 'Mattermost' do pod 'XCDYouTubeKit', '2.8.2' pod 'Swime', '3.0.6' + + # TODO: Remove this once upstream PR https://github.com/daltoniam/Starscream/pull/871 is merged + pod 'Starscream', :git => 'https://github.com/mattermost/Starscream.git', :commit => '1b4b93708fb63d2665625a11e57461772a65364a' end # Enables Flipper. diff --git a/ios/Podfile.lock b/ios/Podfile.lock index da3710a1e..897fa931d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,4 +1,5 @@ PODS: + - Alamofire (5.4.3) - boost-for-react-native (1.63.0) - BVLinearGradient (2.5.6): - React @@ -231,7 +232,7 @@ PODS: - React-jsinspector (0.64.2) - react-native-cameraroll (4.0.4): - React-Core - - react-native-cookies (5.0.1): + - react-native-cookies (6.0.8): - React-Core - react-native-document-picker (5.2.0): - React-Core @@ -241,6 +242,11 @@ PODS: - React - react-native-netinfo (6.0.0): - React-Core + - react-native-network-client (0.1.0): + - Alamofire (~> 5.4) + - React-Core + - Starscream (~> 4.0.4) + - SwiftyJSON (~> 5.0) - react-native-notifications (3.5.0): - React-Core - react-native-paste-input (0.1.3): @@ -403,7 +409,7 @@ PODS: - React - RNVectorIcons (8.1.0): - React-Core - - Rudder (1.0.18) + - Rudder (1.0.14) - SDWebImage (5.11.1): - SDWebImage/Core (= 5.11.1) - SDWebImage/Core (5.11.1) @@ -413,6 +419,8 @@ PODS: - Sentry (7.0.0): - Sentry/Core (= 7.0.0) - Sentry/Core (7.0.0) + - Starscream (4.0.4) + - SwiftyJSON (5.0.1) - Swime (3.0.6) - UMAppLoader (2.1.0) - UMBarCodeScannerInterface (6.1.0): @@ -421,7 +429,7 @@ PODS: - UMCore - UMConstantsInterface (6.1.0): - UMCore - - UMCore (7.1.0) + - UMCore (7.1.1) - UMFaceDetectorInterface (6.1.0) - UMFileSystemInterface (6.1.0) - UMFontInterface (6.1.0) @@ -469,11 +477,12 @@ DEPENDENCIES: - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)" - - "react-native-cookies (from `../node_modules/@react-native-community/cookies`)" + - "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)" - react-native-document-picker (from `../node_modules/react-native-document-picker`) - "react-native-emm (from `../node_modules/@mattermost/react-native-emm`)" - react-native-hw-keyboard-event (from `../node_modules/react-native-hw-keyboard-event`) - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" + - "react-native-network-client (from `../node_modules/@mattermost/react-native-network-client`)" - react-native-notifications (from `../node_modules/react-native-notifications`) - "react-native-paste-input (from `../node_modules/@mattermost/react-native-paste-input`)" - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) @@ -513,6 +522,7 @@ DEPENDENCIES: - RNShare (from `../node_modules/react-native-share`) - RNSVG (from `../node_modules/react-native-svg`) - RNVectorIcons (from `../node_modules/react-native-vector-icons`) + - Starscream (from `https://github.com/mattermost/Starscream.git`, commit `1b4b93708fb63d2665625a11e57461772a65364a`) - Swime (= 3.0.6) - UMAppLoader (from `../node_modules/unimodules-app-loader/ios`) - UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`) @@ -533,12 +543,14 @@ DEPENDENCIES: SPEC REPOS: trunk: + - Alamofire - boost-for-react-native - libwebp - Rudder - SDWebImage - SDWebImageWebPCoder - Sentry + - SwiftyJSON - Swime - XCDYouTubeKit - YoutubePlayer-in-WKWebView @@ -591,7 +603,7 @@ EXTERNAL SOURCES: react-native-cameraroll: :path: "../node_modules/@react-native-community/cameraroll" react-native-cookies: - :path: "../node_modules/@react-native-community/cookies" + :path: "../node_modules/@react-native-cookies/cookies" react-native-document-picker: :path: "../node_modules/react-native-document-picker" react-native-emm: @@ -600,6 +612,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-hw-keyboard-event" react-native-netinfo: :path: "../node_modules/@react-native-community/netinfo" + react-native-network-client: + :path: "../node_modules/@mattermost/react-native-network-client" react-native-notifications: :path: "../node_modules/react-native-notifications" react-native-paste-input: @@ -678,6 +692,9 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-svg" RNVectorIcons: :path: "../node_modules/react-native-vector-icons" + Starscream: + :commit: 1b4b93708fb63d2665625a11e57461772a65364a + :git: https://github.com/mattermost/Starscream.git UMAppLoader: :path: "../node_modules/unimodules-app-loader/ios" UMBarCodeScannerInterface: @@ -709,14 +726,20 @@ EXTERNAL SOURCES: Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" +CHECKOUT OPTIONS: + Starscream: + :commit: 1b4b93708fb63d2665625a11e57461772a65364a + :git: https://github.com/mattermost/Starscream.git + SPEC CHECKSUMS: + Alamofire: e447a2774a40c996748296fa2c55112fdbbc42f9 boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872 DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de EXConstants: c4dd28acc12039c999612507a5f935556f2c86ce EXFileSystem: dcf2273f49431e5037347c733a2dc5d08e0d0a9e FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b - FBReactNativeSpec: d35931295aacfe996e833c01a3701d4aa7a80cb4 + FBReactNativeSpec: cef0cc6d50abc92e8cf52f140aa22b5371cfec0b glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62 jail-monkey: 01cd0a75aa1034d08fd851869e6e6c3b063242d7 libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0 @@ -735,11 +758,12 @@ SPEC CHECKSUMS: React-jsiexecutor: 80c46bd381fd06e418e0d4f53672dc1d1945c4c3 React-jsinspector: cc614ec18a9ca96fd275100c16d74d62ee11f0ae react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2 - react-native-cookies: ce50e42ace7cf0dd47769260ca5bbe8eee607e4e + react-native-cookies: 2cb6ef472da68610dfcf0eaee68464c244943abd react-native-document-picker: f1b5398801b332c77bc62ae0eae2116f49bdff26 react-native-emm: 1652c0f3ebc39ca0cb57a43f60b96f932b7b7f19 react-native-hw-keyboard-event: b517cefb8d5c659a38049c582de85ff43337dc53 react-native-netinfo: e849fc21ca2f4128a5726c801a82fc6f4a6db50d + react-native-network-client: 30ab97e7e6c8d6f2d2b10cc1ebad0cbf9c894c6e react-native-notifications: 89a73cd2cd2648e1734fa10e3507681c9e4f14de react-native-paste-input: dbf0099efd191ddf53e55a4a454bea0783ce4e1d react-native-safe-area-context: f0906bf8bc9835ac9a9d3f97e8bde2a997d8da79 @@ -779,16 +803,18 @@ SPEC CHECKSUMS: RNShare: 5ac8f6532ca4cd80fc71caef1cfbba1854a6a045 RNSVG: 551acb6562324b1d52a4e0758f7ca0ec234e278f RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4 - Rudder: 2a70cad66a3f5f3f6be056bf1ce0ce8d10b5ca67 + Rudder: 40f3a255fab3f8bbe120e496f90019de68c1aca1 SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21 Sentry: 89d26e036063b9cb9caa59b6951dd2f8277aa13b + Starscream: 5178aed56b316f13fa3bc55694e583d35dd414d9 + SwiftyJSON: 2f33a42c6fbc52764d96f13368585094bfd8aa5e Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b UMAppLoader: fe2708bb0ac5cd70052bc207d06aa3b7e72b9e97 UMBarCodeScannerInterface: 79f92bea5f7af39b381a4c82298105ceb537408a UMCameraInterface: 81ff46700da88435f17afedfc88915eaede7e6a6 UMConstantsInterface: bb94dd46039dcde276ed50225b29e22785e604bf - UMCore: 60b35f4d217461f7b54934b0c5be67442871f01f + UMCore: 2f671796d7439604a1cf8ac7bbe5809cd5c50437 UMFaceDetectorInterface: 791eec55ffca1171992976b7eceb73e69e391c58 UMFileSystemInterface: f72245e90ce78fa6427180ff0b0904ead13d8161 UMFontInterface: 5843cff7db85a42ba629aaac53d33091c35524d3 @@ -802,6 +828,6 @@ SPEC CHECKSUMS: Yoga: 575c581c63e0d35c9a83f4b46d01d63abc1100ac YoutubePlayer-in-WKWebView: cfbf46da51d7370662a695a8f351e5fa1d3e1008 -PODFILE CHECKSUM: 34335a8d329b001fdfa695c4fb3c8928db80f375 +PODFILE CHECKSUM: 7741358261bad1ae9b7877b2299303396085e050 COCOAPODS: 1.10.1 diff --git a/jest.config.js b/jest.config.js index 675469b3d..81b0fd2ab 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,6 +20,6 @@ module.exports = { '/dist/assets/images/video_player/$1@2x.png', }, transformIgnorePatterns: [ - 'node_modules/(?!(@react-native|react-native)|jail-monkey|@sentry/react-native|react-navigation|@react-native-community/cameraroll|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|sentry-expo|native-base|unimodules-permissions-interface)', + 'node_modules/(?!(@react-native|react-native)|jail-monkey|@sentry/react-native|react-navigation|@react-native-community/cameraroll|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|sentry-expo|native-base|unimodules-permissions-interface|validator)', ], }; diff --git a/package-lock.json b/package-lock.json index 945dea15e..954b81eea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,15 +17,16 @@ "@formatjs/intl-pluralrules": "4.0.27", "@formatjs/intl-relativetimeformat": "9.1.6", "@mattermost/react-native-emm": "1.1.3", + "@mattermost/react-native-network-client": "github:mattermost/react-native-network-client", "@mattermost/react-native-paste-input": "0.1.3", "@nozbe/watermelondb": "0.22.0", "@nozbe/with-observables": "1.3.0", "@react-native-community/async-storage": "1.12.1", "@react-native-community/cameraroll": "4.0.4", "@react-native-community/clipboard": "1.5.1", - "@react-native-community/cookies": "5.0.1", "@react-native-community/masked-view": "0.1.11", "@react-native-community/netinfo": "6.0.0", + "@react-native-cookies/cookies": "6.0.8", "@rudderstack/rudder-sdk-react-native": "1.0.10", "@sentry/react-native": "2.5.2", "commonmark": "github:mattermost/commonmark.js#f6ab98dede6ce4b4e7adea140ac77249bfb2d6ce", @@ -184,9 +185,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz", - "integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", "engines": { "node": ">=6.9.0" } @@ -396,9 +397,9 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.5.tgz", - "integrity": "sha512-UxUeEYPrqH1Q/k0yRku1JE7dyfyehNwT6SVkMHvYvPDv4+uu627VXBckVj891BO8ruKBkiDoGnZf4qPDD8abDQ==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", "dependencies": { "@babel/types": "^7.14.5" }, @@ -571,9 +572,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.6.tgz", - "integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -598,9 +599,9 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz", - "integrity": "sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-remap-async-to-generator": "^7.14.5", @@ -767,11 +768,11 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz", - "integrity": "sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", + "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", "dependencies": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.14.7", "@babel/helper-compilation-targets": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", @@ -1213,9 +1214,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz", - "integrity": "sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", + "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1409,9 +1410,9 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz", - "integrity": "sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", + "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.14.5" }, @@ -1923,16 +1924,16 @@ } }, "node_modules/@babel/traverse": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.5.tgz", - "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", "dependencies": { "@babel/code-frame": "^7.14.5", "@babel/generator": "^7.14.5", "@babel/helper-function-name": "^7.14.5", "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.5", + "@babel/parser": "^7.14.7", "@babel/types": "^7.14.5", "debug": "^4.1.0", "globals": "^11.1.0" @@ -3084,9 +3085,9 @@ "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==" }, "node_modules/@hapi/topo": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", - "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "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" } @@ -3347,25 +3348,25 @@ } }, "node_modules/@jest/environment": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.0.3.tgz", - "integrity": "sha512-pN9m7fbKsop5vc3FOfH8NF7CKKdRbEZzcxfIo1n2TT6ucKWLFq0P6gCJH0GpnQp036++yY9utHOxpeT1WnkWTA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.0.6.tgz", + "integrity": "sha512-4XywtdhwZwCpPJ/qfAkqExRsERW+UaoSRStSHCCiQTUpoYdLukj+YJbQSFrZjhlUDRZeNiU9SFH0u7iNimdiIg==", "dev": true, "peer": true, "dependencies": { - "@jest/fake-timers": "^27.0.3", - "@jest/types": "^27.0.2", + "@jest/fake-timers": "^27.0.6", + "@jest/types": "^27.0.6", "@types/node": "*", - "jest-mock": "^27.0.3" + "jest-mock": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/@jest/environment/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -3380,9 +3381,9 @@ } }, "node_modules/@jest/environment/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -3446,27 +3447,27 @@ } }, "node_modules/@jest/fake-timers": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.0.3.tgz", - "integrity": "sha512-fQ+UCKRIYKvTCEOyKPnaPnomLATIhMnHC/xPZ7yT1Uldp7yMgMxoYIFidDbpSTgB79+/U+FgfoD30c6wg3IUjA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.0.6.tgz", + "integrity": "sha512-sqd+xTWtZ94l3yWDKnRTdvTeZ+A/V7SSKrxsrOKSqdyddb9CeNRF8fbhAU0D7ZJBpTTW2nbp6MftmKJDZfW2LQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@sinonjs/fake-timers": "^7.0.2", "@types/node": "*", - "jest-message-util": "^27.0.2", - "jest-mock": "^27.0.3", - "jest-util": "^27.0.2" + "jest-message-util": "^27.0.6", + "jest-mock": "^27.0.6", + "jest-util": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/@jest/fake-timers/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -3481,9 +3482,9 @@ } }, "node_modules/@jest/fake-timers/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -3554,19 +3555,19 @@ } }, "node_modules/@jest/fake-timers/node_modules/jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", "dev": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3575,13 +3576,13 @@ } }, "node_modules/@jest/fake-timers/node_modules/jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -3593,13 +3594,13 @@ } }, "node_modules/@jest/fake-timers/node_modules/pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -4570,6 +4571,19 @@ "react-native": "*" } }, + "node_modules/@mattermost/react-native-network-client": { + "version": "0.1.0", + "resolved": "git+ssh://git@github.com/mattermost/react-native-network-client.git#dce7eed0a74959837da50c8c239b67944b0bd888", + "license": "MIT", + "dependencies": { + "validator": "13.1.17", + "zod": "1.11.13" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/@mattermost/react-native-paste-input": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@mattermost/react-native-paste-input/-/react-native-paste-input-0.1.3.tgz", @@ -4612,19 +4626,6 @@ "upath": "^1.1.1" } }, - "node_modules/@nicolo-ribaudo/chokidar-2/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, - "optional": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5410,17 +5411,6 @@ "react-native": ">=0.57.0" } }, - "node_modules/@react-native-community/cookies": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cookies/-/cookies-5.0.1.tgz", - "integrity": "sha512-Is/kWBmYBFtX4DOImfglK5Bz2w3PdpgMGTqdVQSbZlFdSDw32lwFMk1mLSAzL5EcUEDwJJbcEATbU3JGSZSVXw==", - "dependencies": { - "invariant": "^2.2.4" - }, - "peerDependencies": { - "react-native": ">= 0.60.2" - } - }, "node_modules/@react-native-community/eslint-config": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/eslint-config/-/eslint-config-3.0.0.tgz", @@ -5480,6 +5470,17 @@ "react-native": ">=0.59" } }, + "node_modules/@react-native-cookies/cookies": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@react-native-cookies/cookies/-/cookies-6.0.8.tgz", + "integrity": "sha512-srQ9XM/IgvakwiZ7Ck9AOAyPYkcFsAVBEfz5Ct3iHWapoA9fYU25hCWrJWl4dd5993cEMm10XDx7sn7b6pzVxw==", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react-native": ">= 0.60.2" + } + }, "node_modules/@react-native-windows/cli": { "version": "0.64.4", "resolved": "https://registry.npmjs.org/@react-native-windows/cli/-/cli-0.64.4.tgz", @@ -5964,9 +5965,9 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/wizard": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@sentry/wizard/-/wizard-1.2.8.tgz", - "integrity": "sha512-2gHVOT7YcoG56hUgzVG53ID7eThQJxN7Fu+jNZH1WBCG3qSuj+ied2CZ3U+/VsxB6l13GBVwqlHH9GaVptrh3g==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@sentry/wizard/-/wizard-1.2.9.tgz", + "integrity": "sha512-j6OdWF2W3Q24EmIXnNiomspJWKXicAPYnAUF1kcE4c+RuKxv/WFmPkSgg57BZRQ4613GUeHrs3eHGW6FDovolg==", "dependencies": { "@sentry/cli": "^1.52.4", "chalk": "^2.4.1", @@ -8422,9 +8423,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz", - "integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.0.tgz", + "integrity": "sha512-IilJZ1hJBUZwMOVDNTdflOOLzJB/ZtljYVa7k3gEZN/jqIJIPkWHC6dvbX+DD2CwZDHB9wAKzZPzzqMIkW37/w==", "dev": true, "dependencies": { "@babel/types": "^7.3.0" @@ -8526,9 +8527,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "15.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", - "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==" + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz", + "integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.0", @@ -8555,9 +8556,9 @@ "dev": true }, "node_modules/@types/prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-hkc1DATxFLQo4VxPDpMH1gCkPpBbpOoJ/4nhuXw4n63/0R6bCpQECj4+K226UJ4JO/eJQz+1mC2I7JsWanAdQw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.1.tgz", + "integrity": "sha512-NVkb4p4YjI8E3O6+1m8I+8JlMpFZwfSbPGdaw0wXuyPRTEz0SLKwBUWNSO7Maoi8tQMPC8JLZNWkrcKPI7/sLA==", "dev": true }, "node_modules/@types/prop-types": { @@ -8703,15 +8704,15 @@ "dev": true }, "node_modules/@types/stack-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", - "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "node_modules/@types/tapable": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.7.tgz", - "integrity": "sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", "dev": true }, "node_modules/@types/tinycolor2": { @@ -8721,9 +8722,9 @@ "dev": true }, "node_modules/@types/uglify-js": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.0.tgz", - "integrity": "sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", + "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", "dev": true, "dependencies": { "source-map": "^0.6.1" @@ -8739,9 +8740,9 @@ } }, "node_modules/@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.4.tgz", + "integrity": "sha512-zfyYsDTK1HTGYXU3fTiM76+om93HcFtsZd2M0bO/CL4DiETV7mSa/pIVN/6+G3esOqEMdg2An5cHHbK5t+9w+A==", "dev": true }, "node_modules/@types/url-parse": { @@ -8751,9 +8752,9 @@ "dev": true }, "node_modules/@types/webpack": { - "version": "4.41.29", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.29.tgz", - "integrity": "sha512-6pLaORaVNZxiB3FSHbyBiWM7QdazAWda1zvAq4SbZObZqHSDbWLi62iFdblVea6SK9eyBIVp5yHhKt/yNQdR7Q==", + "version": "4.41.30", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.30.tgz", + "integrity": "sha512-GUHyY+pfuQ6haAfzu4S14F+R5iGRwN6b2FRNJY7U0NilmFAqbsOfK6j1HwuLBAqwRIT+pVdNDJGJ6e8rpp0KHA==", "dev": true, "dependencies": { "@types/node": "*", @@ -8765,15 +8766,15 @@ } }, "node_modules/@types/webpack-env": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz", - "integrity": "sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.2.tgz", + "integrity": "sha512-vKx7WNQNZDyJveYcHAm9ZxhqSGLYwoyLhrHjLBOkw3a7cT76sTdjgtwyijhk1MaHyRIuSztcVwrUOO/NEu68Dw==", "dev": true }, "node_modules/@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.1.tgz", + "integrity": "sha512-MjM1R6iuw8XaVbtkCBz0N349cyqBjJHCbQiOeppe3VBeFvxqs74RKHAVt9LkxTnUWc7YLZOEsUfPUnmK6SBPKQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -8813,17 +8814,17 @@ } }, "node_modules/@types/yargs": { - "version": "15.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", - "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "20.2.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", - "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "4.28.0", @@ -8880,24 +8881,6 @@ "eslint": "*" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, "node_modules/@typescript-eslint/parser": { "version": "4.28.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.0.tgz", @@ -9007,9 +8990,9 @@ "peer": true }, "node_modules/@unimodules/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.1.0.tgz", - "integrity": "sha512-oLRT4Bkah3GEopkxmTgpHsRTRp+NJ1907ZjE9y/HLh32q7O/3mcbpY77Uvm+EXW0Vh14gOlU+bmkpC0hz3we0w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.1.1.tgz", + "integrity": "sha512-Sa7X+WkrhZzcckavjuQu4mq6BTPWsio7OITfoNNzjL0CEmfHfo3DNWQWoVyj+wCgMnjGUT1l3+q3AQlI+CaCLA==", "dependencies": { "compare-versions": "^3.4.0" } @@ -9630,14 +9613,6 @@ "node": ">=0.10.0" } }, - "node_modules/anymatch/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/anymatch/node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -9679,9 +9654,9 @@ "dev": true }, "node_modules/appdirsjs": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.4.tgz", - "integrity": "sha512-WO5StDORR6JF/xYnXk/Fm0yu+iULaV5ULKuUw0Tu+jbgiTlSquaWBCgbpnsHLMXldf+fM3Gxn5p7vjond7He6w==" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.5.tgz", + "integrity": "sha512-UyaAyzj+7XLoKhbXJi4zoAw8IDXCiLNCKfQEiuCsCCTkDmiG1vpCliQn/MoUvO3DZqCN1i6gOahokcFtNSIrVA==" }, "node_modules/applicationinsights": { "version": "1.8.10", @@ -10858,14 +10833,6 @@ "node": ">=0.10.0" } }, - "node_modules/base/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/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -11559,9 +11526,9 @@ "dev": true }, "node_modules/caniuse-lite": { - "version": "1.0.30001239", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz", - "integrity": "sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ==", + "version": "1.0.30001241", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001241.tgz", + "integrity": "sha512-1uoSZ1Pq1VpH0WerIMqwptXHNNGfdl7d1cJUFs80CwQ/lVzdhTvsFZCeNFslze7AjsQnb4C85tzclPa1VShbeQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/browserslist" @@ -11665,7 +11632,6 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, - "optional": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -11687,7 +11653,6 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, - "optional": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -11701,7 +11666,6 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "optional": true, "engines": { "node": ">=8" } @@ -11711,7 +11675,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "optional": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -11724,7 +11687,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "optional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -11732,25 +11694,11 @@ "node": ">=8" } }, - "node_modules/chokidar/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, - "optional": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/chokidar/node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "optional": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -11763,7 +11711,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "optional": true, "engines": { "node": ">=0.12.0" } @@ -11773,7 +11720,6 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "optional": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -11786,7 +11732,6 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "optional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -12017,14 +11962,6 @@ "node": ">=6" } }, - "node_modules/clone-deep/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/cls-hooked": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", @@ -12447,9 +12384,9 @@ } }, "node_modules/core-js": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.0.tgz", - "integrity": "sha512-GUbtPllXMYRzIgHNZ4dTYTcUemls2cni83Q4Q/TrFONHfhcg9oEGOtaGHfb0cpzec60P96UKPvMkjX1jET8rUw==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz", + "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==", "dev": true, "hasInstallScript": true, "funding": { @@ -12458,9 +12395,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.0.tgz", - "integrity": "sha512-8X6lWsG+s7IfOKzV93a7fRYfWRZobOfjw5V5rrq43Vh/W+V6qYxl7Akalsvgab4PFT/4L/pjQbdBUEM36NXKrw==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.2.tgz", + "integrity": "sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ==", "dependencies": { "browserslist": "^4.16.6", "semver": "7.0.0" @@ -12479,9 +12416,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.0.tgz", - "integrity": "sha512-RO+LFAso8DB6OeBX9BAcEGvyth36QtxYon1OyVsITNVtSKr/Hos0BXZwnsOJ7o+O6KHtK+O+cJIEj9NGg6VwFA==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.2.tgz", + "integrity": "sha512-D42L7RYh1J2grW8ttxoY1+17Y4wXZeKe7uyplAI3FkNQyI5OgBIAjUfFiTPfL1rs0qLpxaabITNbjKl1Sp82tA==", "dev": true, "hasInstallScript": true, "funding": { @@ -12815,9 +12752,9 @@ } }, "node_modules/decimal.js": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", - "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, "node_modules/decode-uri-component": { @@ -13433,14 +13370,14 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.3.752", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz", - "integrity": "sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==" + "version": "1.3.766", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.766.tgz", + "integrity": "sha512-u2quJ862q9reRKh/je3GXis3w38+RoXH1J9N3XjtsS6NzmUAosNsyZgUVFZPN/ZlJ3v6T0rTyZR3q/J5c6Sy5w==" }, "node_modules/element-resize-detector": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.2.tgz", - "integrity": "sha512-+LOXRkCJc4I5WhEJxIDjhmE3raF8jtOMBDqSCgZTMz2TX3oXAX5pE2+MDeopJlGdXzP7KzPbBJaUGfNaP9HG4A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.3.tgz", + "integrity": "sha512-+dhNzUgLpq9ol5tyhoG7YLoXL3ssjfFW+0gpszXPwRU6NjGr1fVHMEAF8fVzIiRJq57Nre0RFeIjJwI8Nh2NmQ==", "dev": true, "dependencies": { "batch-processor": "1.0.0" @@ -14103,27 +14040,21 @@ } }, "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^1.1.0" + "eslint-visitor-keys": "^2.0.0" }, "engines": { - "node": ">=6" + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" + }, + "peerDependencies": { + "eslint": ">=5" } }, "node_modules/eslint-visitor-keys": { @@ -14201,16 +14132,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/eslint/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "eslint-visitor-keys": "^1.1.0" }, "engines": { - "node": ">= 6" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" } }, "node_modules/eslint/node_modules/globals": { @@ -14600,27 +14543,27 @@ } }, "node_modules/expect": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", - "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.6.tgz", + "integrity": "sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-styles": "^5.0.0", - "jest-get-type": "^27.0.1", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-regex-util": "^27.0.1" + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-regex-util": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/expect/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -14635,9 +14578,9 @@ } }, "node_modules/expect/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -14701,19 +14644,19 @@ } }, "node_modules/expect/node_modules/jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", "dev": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -14722,9 +14665,9 @@ } }, "node_modules/expect/node_modules/jest-regex-util": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", - "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", "dev": true, "peer": true, "engines": { @@ -14732,13 +14675,13 @@ } }, "node_modules/expect/node_modules/pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -14976,14 +14919,6 @@ "node": ">=0.10.0" } }, - "node_modules/extglob/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/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -14997,34 +14932,21 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", + "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" }, "engines": { "node": ">=8" } }, - "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", @@ -15471,15 +15393,6 @@ "node": ">=0.10.0" } }, - "node_modules/findup-sync/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/findup-sync/node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -15527,9 +15440,9 @@ } }, "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz", + "integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A==", "dev": true }, "node_modules/flow-parser": { @@ -15663,6 +15576,28 @@ "node": ">= 4.0" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -15713,15 +15648,6 @@ "node": ">=0.10.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -16230,25 +16156,15 @@ } }, "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "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": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, "node_modules/glob-to-regexp": { @@ -16292,15 +16208,6 @@ "node": ">=6" } }, - "node_modules/global-prefix/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -17255,6 +17162,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-alphabetical": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", @@ -17381,6 +17299,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-date-object": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", @@ -17560,6 +17489,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -17944,28 +17884,28 @@ } }, "node_modules/jest-circus": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.0.4.tgz", - "integrity": "sha512-QD+eblDiRphta630WRKewuASLs/oY1Zki2G4bccntRvrTHQ63ljwFR5TLduuK4Zg0ZPzW0+8o6AP7KRd1yKOjw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.0.6.tgz", + "integrity": "sha512-OJlsz6BBeX9qR+7O9lXefWoc2m9ZqcZ5Ohlzz0pTEAG4xMiZUJoacY8f4YDHxgk0oKYxj277AfOk9w6hZYvi1Q==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^27.0.3", - "@jest/test-result": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/environment": "^27.0.6", + "@jest/test-result": "^27.0.6", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^27.0.2", + "expect": "^27.0.6", "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.2", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-runtime": "^27.0.4", - "jest-snapshot": "^27.0.4", - "jest-util": "^27.0.2", - "pretty-format": "^27.0.2", + "jest-each": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-runtime": "^27.0.6", + "jest-snapshot": "^27.0.6", + "jest-util": "^27.0.6", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3", "throat": "^6.0.1" @@ -17975,17 +17915,17 @@ } }, "node_modules/jest-circus/node_modules/@jest/console": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.0.2.tgz", - "integrity": "sha512-/zYigssuHLImGeMAACkjI4VLAiiJznHgAl3xnFT19iWyct2LhrH3KXOjHRmxBGTkiPLZKKAJAgaPpiU9EZ9K+w==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.0.6.tgz", + "integrity": "sha512-fMlIBocSHPZ3JxgWiDNW/KPj6s+YRd0hicb33IrmelCcjXo/pXPwvuiKFmZz+XuqI/1u7nbUK10zSsWL/1aegg==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.0.2", - "jest-util": "^27.0.2", + "jest-message-util": "^27.0.6", + "jest-util": "^27.0.6", "slash": "^3.0.0" }, "engines": { @@ -17993,24 +17933,24 @@ } }, "node_modules/jest-circus/node_modules/@jest/globals": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.0.3.tgz", - "integrity": "sha512-OzsIuf7uf+QalqAGbjClyezzEcLQkdZ+7PejUrZgDs+okdAK8GwRCGcYCirHvhMBBQh60Jr3NlIGbn/KBPQLEQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.0.6.tgz", + "integrity": "sha512-DdTGCP606rh9bjkdQ7VvChV18iS7q0IMJVP1piwTWyWskol4iqcVwthZmoJEf7obE1nc34OpIyoVGPeqLC+ryw==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^27.0.3", - "@jest/types": "^27.0.2", - "expect": "^27.0.2" + "@jest/environment": "^27.0.6", + "@jest/types": "^27.0.6", + "expect": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-circus/node_modules/@jest/source-map": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.1.tgz", - "integrity": "sha512-yMgkF0f+6WJtDMdDYNavmqvbHtiSpwRN2U/W+6uztgfqgkq/PXdKPqjBTUF1RD/feth4rH5N3NW0T5+wIuln1A==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", + "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", "dev": true, "peer": true, "dependencies": { @@ -18023,14 +17963,14 @@ } }, "node_modules/jest-circus/node_modules/@jest/test-result": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.0.2.tgz", - "integrity": "sha512-gcdWwL3yP5VaIadzwQtbZyZMgpmes8ryBAJp70tuxghiA8qL4imJyZex+i+USQH2H4jeLVVszhwntgdQ97fccA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.0.6.tgz", + "integrity": "sha512-ja/pBOMTufjX4JLEauLxE3LQBPaI2YjGFtXexRAjt1I/MbfNlMx0sytSX3tn5hSLzQsR3Qy2rd0hc1BWojtj9w==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/console": "^27.0.6", + "@jest/types": "^27.0.6", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -18039,22 +17979,22 @@ } }, "node_modules/jest-circus/node_modules/@jest/transform": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.0.2.tgz", - "integrity": "sha512-H8sqKlgtDfVog/s9I4GG2XMbi4Ar7RBxjsKQDUhn2XHAi3NG+GoQwWMER+YfantzExbjNqQvqBHzo/G2pfTiPw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.0.6.tgz", + "integrity": "sha512-rj5Dw+mtIcntAUnMlW/Vju5mr73u8yg+irnHwzgtgoeI6cCPOvUwQ0D1uQtc/APmWgvRweEb1g05pkUpxH3iCA==", "dev": true, "peer": true, "dependencies": { "@babel/core": "^7.1.0", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "babel-plugin-istanbul": "^6.0.0", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.2", - "jest-regex-util": "^27.0.1", - "jest-util": "^27.0.2", + "jest-haste-map": "^27.0.6", + "jest-regex-util": "^27.0.6", + "jest-util": "^27.0.6", "micromatch": "^4.0.4", "pirates": "^4.0.1", "slash": "^3.0.0", @@ -18066,9 +18006,9 @@ } }, "node_modules/jest-circus/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -18083,9 +18023,9 @@ } }, "node_modules/jest-circus/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -18167,9 +18107,9 @@ "peer": true }, "node_modules/jest-circus/node_modules/diff-sequences": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", - "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", "dev": true, "peer": true, "engines": { @@ -18200,38 +18140,38 @@ } }, "node_modules/jest-circus/node_modules/jest-diff": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", - "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", + "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.1", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-circus/node_modules/jest-haste-map": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.0.2.tgz", - "integrity": "sha512-37gYfrYjjhEfk37C4bCMWAC0oPBxDpG0qpl8lYg8BT//wf353YT/fzgA7+Dq0EtM7rPFS3JEcMsxdtDwNMi2cA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.0.6.tgz", + "integrity": "sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.0.1", - "jest-serializer": "^27.0.1", - "jest-util": "^27.0.2", - "jest-worker": "^27.0.2", + "jest-regex-util": "^27.0.6", + "jest-serializer": "^27.0.6", + "jest-util": "^27.0.6", + "jest-worker": "^27.0.6", "micromatch": "^4.0.4", "walker": "^1.0.7" }, @@ -18243,19 +18183,19 @@ } }, "node_modules/jest-circus/node_modules/jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", "dev": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -18264,9 +18204,9 @@ } }, "node_modules/jest-circus/node_modules/jest-regex-util": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", - "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", "dev": true, "peer": true, "engines": { @@ -18274,19 +18214,19 @@ } }, "node_modules/jest-circus/node_modules/jest-resolve": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.0.4.tgz", - "integrity": "sha512-BcfyK2i3cG79PDb/6gB6zFeFQlcqLsQjGBqznFCpA0L/3l1L/oOsltdUjs5eISAWA9HS9qtj8v2PSZr/yWxONQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.0.6.tgz", + "integrity": "sha512-yKmIgw2LgTh7uAJtzv8UFHGF7Dm7XfvOe/LQ3Txv101fLM8cx2h1QVwtSJ51Q/SCxpIiKfVn6G2jYYMDNHZteA==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "chalk": "^4.0.0", "escalade": "^3.1.1", "graceful-fs": "^4.2.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", + "jest-util": "^27.0.6", + "jest-validate": "^27.0.6", "resolve": "^1.20.0", "slash": "^3.0.0" }, @@ -18295,20 +18235,20 @@ } }, "node_modules/jest-circus/node_modules/jest-runtime": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.0.4.tgz", - "integrity": "sha512-voJB4xbAjS/qYPboV+e+gmg3jfvHJJY4CagFWBOM9dQKtlaiTjcpD2tWwla84Z7PtXSQPeIpXY0qksA9Dum29A==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.0.6.tgz", + "integrity": "sha512-BhvHLRVfKibYyqqEFkybsznKwhrsu7AWx2F3y9G9L95VSIN3/ZZ9vBpm/XCS2bS+BWz3sSeNGLzI3TVQ0uL85Q==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^27.0.2", - "@jest/environment": "^27.0.3", - "@jest/fake-timers": "^27.0.3", - "@jest/globals": "^27.0.3", - "@jest/source-map": "^27.0.1", - "@jest/test-result": "^27.0.2", - "@jest/transform": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/console": "^27.0.6", + "@jest/environment": "^27.0.6", + "@jest/fake-timers": "^27.0.6", + "@jest/globals": "^27.0.6", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.0.6", + "@jest/transform": "^27.0.6", + "@jest/types": "^27.0.6", "@types/yargs": "^16.0.0", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", @@ -18316,14 +18256,14 @@ "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-mock": "^27.0.3", - "jest-regex-util": "^27.0.1", - "jest-resolve": "^27.0.4", - "jest-snapshot": "^27.0.4", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", + "jest-haste-map": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-mock": "^27.0.6", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.0.6", + "jest-snapshot": "^27.0.6", + "jest-util": "^27.0.6", + "jest-validate": "^27.0.6", "slash": "^3.0.0", "strip-bom": "^4.0.0", "yargs": "^16.0.3" @@ -18333,9 +18273,9 @@ } }, "node_modules/jest-circus/node_modules/jest-serializer": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.1.tgz", - "integrity": "sha512-svy//5IH6bfQvAbkAEg1s7xhhgHTtXu0li0I2fdKHDsLP2P2MOiscPQIENQep8oU2g2B3jqLyxKKzotZOz4CwQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", + "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", "dev": true, "peer": true, "dependencies": { @@ -18347,9 +18287,9 @@ } }, "node_modules/jest-circus/node_modules/jest-snapshot": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.0.4.tgz", - "integrity": "sha512-hnjrvpKGdSMvKfbHyaG5Kul7pDJGZvjVy0CKpzhu28MmAssDXS6GpynhXzgst1wBQoKD8c9b2VS2a5yhDLQRCA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.0.6.tgz", + "integrity": "sha512-NTHaz8He+ATUagUgE7C/UtFcRoHqR2Gc+KDfhQIyx+VFgwbeEMjeP+ILpUTLosZn/ZtbNdCF5LkVnN/l+V751A==", "dev": true, "peer": true, "dependencies": { @@ -18359,23 +18299,23 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.0.0", - "@jest/transform": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/transform": "^27.0.6", + "@jest/types": "^27.0.6", "@types/babel__traverse": "^7.0.4", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.0.2", + "expect": "^27.0.6", "graceful-fs": "^4.2.4", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "jest-haste-map": "^27.0.2", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-resolve": "^27.0.4", - "jest-util": "^27.0.2", + "jest-diff": "^27.0.6", + "jest-get-type": "^27.0.6", + "jest-haste-map": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-resolve": "^27.0.6", + "jest-util": "^27.0.6", "natural-compare": "^1.4.0", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "semver": "^7.3.2" }, "engines": { @@ -18383,13 +18323,13 @@ } }, "node_modules/jest-circus/node_modules/jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -18401,27 +18341,27 @@ } }, "node_modules/jest-circus/node_modules/jest-validate": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.0.2.tgz", - "integrity": "sha512-UgBF6/oVu1ofd1XbaSotXKihi8nZhg0Prm8twQ9uCuAfo59vlxCXMPI/RKmrZEVgi3Nd9dS0I8A0wzWU48pOvg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.0.6.tgz", + "integrity": "sha512-yhZZOaMH3Zg6DC83n60pLmdU1DQE46DW+KLozPiPbSbPhlXXaiUTDlhHQhHFpaqIFRrInko1FHXjTRpjWRuWfA==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.0.1", + "jest-get-type": "^27.0.6", "leven": "^3.1.0", - "pretty-format": "^27.0.2" + "pretty-format": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-circus/node_modules/jest-worker": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.2.tgz", - "integrity": "sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.6.tgz", + "integrity": "sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA==", "dev": true, "peer": true, "dependencies": { @@ -18450,13 +18390,13 @@ } }, "node_modules/jest-circus/node_modules/pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -18937,26 +18877,26 @@ } }, "node_modules/jest-each": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.0.2.tgz", - "integrity": "sha512-OLMBZBZ6JkoXgUenDtseFRWA43wVl2BwmZYIWQws7eS7pqsIvePqj/jJmEnfq91ALk3LNphgwNK/PRFBYi7ITQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.0.6.tgz", + "integrity": "sha512-m6yKcV3bkSWrUIjxkE9OC0mhBZZdhovIW5ergBYirqnkLXkyEn3oUUF/QZgyecA1cF1QFyTE8bRRl8Tfg1pfLA==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "chalk": "^4.0.0", - "jest-get-type": "^27.0.1", - "jest-util": "^27.0.2", - "pretty-format": "^27.0.2" + "jest-get-type": "^27.0.6", + "jest-util": "^27.0.6", + "pretty-format": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-each/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -18971,9 +18911,9 @@ } }, "node_modules/jest-each/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -19044,13 +18984,13 @@ } }, "node_modules/jest-each/node_modules/jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -19062,13 +19002,13 @@ } }, "node_modules/jest-each/node_modules/pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -19183,27 +19123,27 @@ } }, "node_modules/jest-environment-node": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.0.3.tgz", - "integrity": "sha512-co2/IVnIFL3cItpFULCvXFg9us4gvWXgs7mutAMPCbFhcqh56QAOdKhNzC2+RycsC/k4mbMj1VF+9F/NzA0ROg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.0.6.tgz", + "integrity": "sha512-+Vi6yLrPg/qC81jfXx3IBlVnDTI6kmRr08iVa2hFCWmJt4zha0XW7ucQltCAPhSR0FEKEoJ3i+W4E6T0s9is0w==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^27.0.3", - "@jest/fake-timers": "^27.0.3", - "@jest/types": "^27.0.2", + "@jest/environment": "^27.0.6", + "@jest/fake-timers": "^27.0.6", + "@jest/types": "^27.0.6", "@types/node": "*", - "jest-mock": "^27.0.3", - "jest-util": "^27.0.2" + "jest-mock": "^27.0.6", + "jest-util": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-environment-node/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -19218,9 +19158,9 @@ } }, "node_modules/jest-environment-node/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -19291,13 +19231,13 @@ } }, "node_modules/jest-environment-node/node_modules/jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -19322,9 +19262,9 @@ } }, "node_modules/jest-get-type": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", - "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", "dev": true, "peer": true, "engines": { @@ -19584,25 +19524,25 @@ } }, "node_modules/jest-matcher-utils": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", - "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz", + "integrity": "sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "jest-diff": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-matcher-utils/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -19617,9 +19557,9 @@ } }, "node_modules/jest-matcher-utils/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -19660,9 +19600,9 @@ } }, "node_modules/jest-matcher-utils/node_modules/diff-sequences": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", - "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", "dev": true, "peer": true, "engines": { @@ -19680,29 +19620,29 @@ } }, "node_modules/jest-matcher-utils/node_modules/jest-diff": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", - "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", + "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.1", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -19826,13 +19766,13 @@ } }, "node_modules/jest-mock": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.0.3.tgz", - "integrity": "sha512-O5FZn5XDzEp+Xg28mUz4ovVcdwBBPfAhW9+zJLO0Efn2qNbYcDaJvSlRiQ6BCZUCVOJjALicuJQI9mRFjv1o9Q==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.0.6.tgz", + "integrity": "sha512-lzBETUoK8cSxts2NYXSBWT+EJNzmUVtVVwS1sU9GwE1DLCfGsngg+ZVSIe0yd0ZSm+y791esiuo+WSwpXJQ5Bw==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*" }, "engines": { @@ -19840,9 +19780,9 @@ } }, "node_modules/jest-mock/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "dependencies": { @@ -19857,9 +19797,9 @@ } }, "node_modules/jest-mock/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "dependencies": { @@ -20981,14 +20921,6 @@ "node": ">=0.10.0" } }, - "node_modules/jscodeshift/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/jscodeshift/node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -21069,9 +21001,9 @@ } }, "node_modules/jsdom/node_modules/acorn": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.0.tgz", - "integrity": "sha512-ULr0LDaEqQrMFGyQ3bhJkLsbtrQ8QibAseGZeaSUiT/6zb9IvIkomWHJIvgvwad+hinRAgsI51JcWk2yvwyL+w==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", + "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -21174,12 +21106,9 @@ "integrity": "sha1-kYiJ6hP40KQufFVyUO7nE63JXDU=" }, "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dependencies": { - "is-buffer": "^1.1.5" - }, + "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" } @@ -23132,16 +23061,16 @@ } }, "node_modules/mocha": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.1.tgz", - "integrity": "sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", + "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", "dev": true, "peer": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", @@ -23154,12 +23083,12 @@ "minimatch": "3.0.4", "ms": "2.1.3", "nanoid": "3.1.23", - "serialize-javascript": "5.0.1", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.4", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -23176,20 +23105,6 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "peer": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/mocha/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -23197,51 +23112,6 @@ "dev": true, "peer": true }, - "node_modules/mocha/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "peer": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "peer": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -23255,19 +23125,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "peer": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/mocha/node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -23285,19 +23142,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/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, - "peer": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/mocha/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -23308,29 +23152,6 @@ "node": ">=8" } }, - "node_modules/mocha/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "peer": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/mocha/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -23409,19 +23230,6 @@ "node": ">=8" } }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "peer": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -23438,19 +23246,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/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==", - "dev": true, - "peer": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/mocha/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -23713,14 +23508,6 @@ "node": ">=0.10.0" } }, - "node_modules/nanomatch/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/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -23941,9 +23728,9 @@ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==" }, "node_modules/node-stream-zip": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.13.5.tgz", - "integrity": "sha512-Lfi9xhSNvnJU35+4ZFlECXKJ70etAgJYWAVCdcEpksPnMrgwNqwkCJqdunoViVoFFV38C7AIodYE+2apuoK9Gw==", + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.13.6.tgz", + "integrity": "sha512-c7tRSVkLNOHvasWgmZ2d86cDgTWEygnkuuHNOY9c0mR3yLZtQTTrGvMaJ/fPs6+LOJn3240y30l5sjLaXFtcvw==", "engines": { "node": ">=0.10.0" }, @@ -24089,6 +23876,17 @@ "node": ">=0.10.0" } }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", @@ -25386,9 +25184,9 @@ } }, "node_modules/prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", + "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -25462,13 +25260,10 @@ } }, "node_modules/prismjs": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", - "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", - "dev": true, - "optionalDependencies": { - "clipboard": "^2.0.0" - } + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz", + "integrity": "sha512-mNPsedLuk90RVJioIky8ANZEwYm5w9LcvCXrxHlwf4fNVSn8jEipMybMkWUyyF0JhnC+C4VcOVSBuHRKs1L5Ow==", + "dev": true }, "node_modules/process": { "version": "0.11.10", @@ -25716,6 +25511,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The", "dev": true, "engines": { "node": ">=0.4.x" @@ -25854,9 +25650,9 @@ } }, "node_modules/react-colorful": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.2.2.tgz", - "integrity": "sha512-Xdb1Rl6lZ5SMdNBH59eE0lGqR1g2LVD8IgPlw0WeMDrOC65lYI8fgMEwj/0dDpVRVMh5qp73ciISDst/t2O2iQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.2.3.tgz", + "integrity": "sha512-lAge4syxosZg9SX8fJiwOLd9ZJSW3poPBtypnz1aMiFoHsRnK5G3+INGGx9DGtsrso4h5uFYbiFpjAfWyK3Kag==", "dev": true, "peerDependencies": { "react": ">=16.8.0", @@ -26045,6 +25841,28 @@ "node": ">=6" } }, + "node_modules/react-dev-utils/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/react-dev-utils/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-dev-utils/node_modules/globby": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", @@ -26164,15 +25982,6 @@ "json5": "lib/cli.js" } }, - "node_modules/react-dev-utils/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-dev-utils/node_modules/loader-utils": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", @@ -27257,9 +27066,9 @@ } }, "node_modules/react-native-windows": { - "version": "0.64.11", - "resolved": "https://registry.npmjs.org/react-native-windows/-/react-native-windows-0.64.11.tgz", - "integrity": "sha512-zlR5YOULsHOFIjUTFncToRkNSpNdM2M8xz3SSIb3vKMnz+V4WxyEzc92SY+AgeWuOcbKqpiSHjkSkmUb/Hzh1w==", + "version": "0.64.12", + "resolved": "https://registry.npmjs.org/react-native-windows/-/react-native-windows-0.64.12.tgz", + "integrity": "sha512-9wjDLvB7u8z1OvF25vQ4xwacWC6WFn/EUJrJ7yWX2IwqEUJOzNY6mxwCEspNf00lXs34d9e+xTlluUHrbPrNIg==", "peer": true, "dependencies": { "@babel/runtime": "^7.0.0", @@ -27656,15 +27465,6 @@ "node": ">=0.10.0" } }, - "node_modules/readdirp/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readdirp/node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -27735,14 +27535,14 @@ } }, "node_modules/refractor": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.3.1.tgz", - "integrity": "sha512-vaN6R56kLMuBszHSWlwTpcZ8KTMG6aUCok4GrxYDT20UIOXxOc5o6oDc8tNTzSlH3m2sI+Eu9Jo2kVdDcUTWYw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.4.0.tgz", + "integrity": "sha512-dBeD02lC5eytm9Gld2Mx0cMcnR+zhSnsTfPpWqFaMgUMJfC9A6bcN3Br/NaXrnBJcuxnLFR90k1jrkaSyV8umg==", "dev": true, "dependencies": { "hastscript": "^6.0.0", "parse-entities": "^2.0.0", - "prismjs": "~1.23.0" + "prismjs": "~1.24.0" }, "funding": { "type": "github", @@ -28368,6 +28168,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", "dependencies": { "@cnakazawa/watch": "^1.0.3", "anymatch": "^2.0.0", @@ -28507,14 +28308,6 @@ "node": ">=0.10.0" } }, - "node_modules/sane/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/sane/node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -28734,9 +28527,9 @@ } }, "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "peer": true, "dependencies": { @@ -28846,14 +28639,6 @@ "node": ">=8" } }, - "node_modules/shallow-clone/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/shallow-equal": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", @@ -29099,14 +28884,6 @@ "node": ">=0.10.0" } }, - "node_modules/snapdragon-node/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/snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", @@ -29118,6 +28895,17 @@ "node": ">=0.10.0" } }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/snapdragon/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -30297,6 +30085,17 @@ "node": ">=0.10.0" } }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -30393,14 +30192,6 @@ "node": ">=0.10.0" } }, - "node_modules/to-regex/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/toggle-selection": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", @@ -30494,9 +30285,9 @@ } }, "node_modules/ts-jest/node_modules/@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", @@ -30510,9 +30301,9 @@ } }, "node_modules/ts-jest/node_modules/@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -30577,12 +30368,12 @@ } }, "node_modules/ts-jest/node_modules/jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "dependencies": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -31409,6 +31200,14 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/validator": { + "version": "13.1.17", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.1.17.tgz", + "integrity": "sha512-zL5QBoemJ3jYFb2/j38y7ljhwYGXVLUp8H6W1nVxadnAOvUOytec+L7BHh1oBQ82/TzWXHd+GSaxUWp4lROkLg==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -31533,6 +31332,30 @@ "node": ">= 4.0" } }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -32109,15 +31932,6 @@ "node": ">=4" } }, - "node_modules/webpack/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/webpack/node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -32283,9 +32097,9 @@ "dev": true }, "node_modules/whatwg-url": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.6.0.tgz", - "integrity": "sha512-os0KkeeqUOl7ccdDT1qqUcS4KH4tcBTSKK5Nl5WKb2lyxInIZ/CpjkqKa1Ss12mjfdcRX9mHmPPs7/SxG1Hbdw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, "dependencies": { "lodash": "^4.7.0", @@ -32440,9 +32254,9 @@ } }, "node_modules/workerpool": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.4.tgz", - "integrity": "sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true, "peer": true }, @@ -32494,9 +32308,9 @@ } }, "node_modules/ws": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz", - "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz", + "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==", "engines": { "node": ">=8.3.0" }, @@ -32757,6 +32571,11 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-1.11.13.tgz", + "integrity": "sha512-10+KA7eWa8g1hbKIXkOnhjJ4RKEwX85ECz3VJzP+pWkJOFKn76bHy1kG0d1JHBwmdElLcCsaB0O9HqIfT1vZnw==" } }, "dependencies": { @@ -32786,9 +32605,9 @@ } }, "@babel/compat-data": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz", - "integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==" + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==" }, "@babel/core": { "version": "7.14.6", @@ -32943,9 +32762,9 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.5.tgz", - "integrity": "sha512-UxUeEYPrqH1Q/k0yRku1JE7dyfyehNwT6SVkMHvYvPDv4+uu627VXBckVj891BO8ruKBkiDoGnZf4qPDD8abDQ==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", "requires": { "@babel/types": "^7.14.5" } @@ -33073,9 +32892,9 @@ } }, "@babel/parser": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.6.tgz", - "integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==" + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==" }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.14.5", @@ -33088,9 +32907,9 @@ } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz", - "integrity": "sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-remap-async-to-generator": "^7.14.5", @@ -33191,11 +33010,11 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz", - "integrity": "sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", + "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", "requires": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.14.7", "@babel/helper-compilation-targets": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", @@ -33478,9 +33297,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz", - "integrity": "sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", + "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", "requires": { "@babel/helper-plugin-utils": "^7.14.5" } @@ -33596,9 +33415,9 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz", - "integrity": "sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", + "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5" } @@ -33943,16 +33762,16 @@ } }, "@babel/traverse": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.5.tgz", - "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", "requires": { "@babel/code-frame": "^7.14.5", "@babel/generator": "^7.14.5", "@babel/helper-function-name": "^7.14.5", "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.5", + "@babel/parser": "^7.14.7", "@babel/types": "^7.14.5", "debug": "^4.1.0", "globals": "^11.1.0" @@ -34912,9 +34731,9 @@ "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==" }, "@hapi/topo": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", - "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "requires": { "@hapi/hoek": "^9.0.0" } @@ -35106,22 +34925,22 @@ } }, "@jest/environment": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.0.3.tgz", - "integrity": "sha512-pN9m7fbKsop5vc3FOfH8NF7CKKdRbEZzcxfIo1n2TT6ucKWLFq0P6gCJH0GpnQp036++yY9utHOxpeT1WnkWTA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.0.6.tgz", + "integrity": "sha512-4XywtdhwZwCpPJ/qfAkqExRsERW+UaoSRStSHCCiQTUpoYdLukj+YJbQSFrZjhlUDRZeNiU9SFH0u7iNimdiIg==", "dev": true, "peer": true, "requires": { - "@jest/fake-timers": "^27.0.3", - "@jest/types": "^27.0.2", + "@jest/fake-timers": "^27.0.6", + "@jest/types": "^27.0.6", "@types/node": "*", - "jest-mock": "^27.0.3" + "jest-mock": "^27.0.6" }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -35133,9 +34952,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -35183,24 +35002,24 @@ } }, "@jest/fake-timers": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.0.3.tgz", - "integrity": "sha512-fQ+UCKRIYKvTCEOyKPnaPnomLATIhMnHC/xPZ7yT1Uldp7yMgMxoYIFidDbpSTgB79+/U+FgfoD30c6wg3IUjA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.0.6.tgz", + "integrity": "sha512-sqd+xTWtZ94l3yWDKnRTdvTeZ+A/V7SSKrxsrOKSqdyddb9CeNRF8fbhAU0D7ZJBpTTW2nbp6MftmKJDZfW2LQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@sinonjs/fake-timers": "^7.0.2", "@types/node": "*", - "jest-message-util": "^27.0.2", - "jest-mock": "^27.0.3", - "jest-util": "^27.0.2" + "jest-message-util": "^27.0.6", + "jest-mock": "^27.0.6", + "jest-util": "^27.0.6" }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -35212,9 +35031,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -35267,31 +35086,31 @@ } }, "jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", "dev": true, "peer": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -35300,13 +35119,13 @@ } }, "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -36044,6 +35863,14 @@ "integrity": "sha512-mqNJ6SQlzBp+F0qg411nOlQXJLj9pVUyDoVAbHGRP4p7PcAU2cQEbEyOJ82luLcqj+9+bcoW2tl19bO35FomWQ==", "requires": {} }, + "@mattermost/react-native-network-client": { + "version": "git+ssh://git@github.com/mattermost/react-native-network-client.git#dce7eed0a74959837da50c8c239b67944b0bd888", + "from": "@mattermost/react-native-network-client@github:mattermost/react-native-network-client", + "requires": { + "validator": "13.1.17", + "zod": "1.11.13" + } + }, "@mattermost/react-native-paste-input": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@mattermost/react-native-paste-input/-/react-native-paste-input-0.1.3.tgz", @@ -36078,18 +35905,6 @@ "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", "upath": "^1.1.1" - }, - "dependencies": { - "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, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - } } }, "@nodelib/fs.scandir": { @@ -36695,14 +36510,6 @@ "integrity": "sha512-AHAmrkLEH5UtPaDiRqoULERHh3oNv7Dgs0bTC0hO5Z2GdNokAMPT5w8ci8aMcRemcwbtdHjxChgtjbeA38GBdA==", "requires": {} }, - "@react-native-community/cookies": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@react-native-community/cookies/-/cookies-5.0.1.tgz", - "integrity": "sha512-Is/kWBmYBFtX4DOImfglK5Bz2w3PdpgMGTqdVQSbZlFdSDw32lwFMk1mLSAzL5EcUEDwJJbcEATbU3JGSZSVXw==", - "requires": { - "invariant": "^2.2.4" - } - }, "@react-native-community/eslint-config": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/eslint-config/-/eslint-config-3.0.0.tgz", @@ -36751,6 +36558,14 @@ "integrity": "sha512-Z9M8VGcF2IZVOo2x+oUStvpCW/8HjIRi4+iQCu5n+PhC7OqCQX58KYAzdBr///alIfRXiu6oMb+lK+rXQH1FvQ==", "requires": {} }, + "@react-native-cookies/cookies": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@react-native-cookies/cookies/-/cookies-6.0.8.tgz", + "integrity": "sha512-srQ9XM/IgvakwiZ7Ck9AOAyPYkcFsAVBEfz5Ct3iHWapoA9fYU25hCWrJWl4dd5993cEMm10XDx7sn7b6pzVxw==", + "requires": { + "invariant": "^2.2.4" + } + }, "@react-native-windows/cli": { "version": "0.64.4", "resolved": "https://registry.npmjs.org/@react-native-windows/cli/-/cli-0.64.4.tgz", @@ -37171,9 +36986,9 @@ } }, "@sentry/wizard": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@sentry/wizard/-/wizard-1.2.8.tgz", - "integrity": "sha512-2gHVOT7YcoG56hUgzVG53ID7eThQJxN7Fu+jNZH1WBCG3qSuj+ied2CZ3U+/VsxB6l13GBVwqlHH9GaVptrh3g==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@sentry/wizard/-/wizard-1.2.9.tgz", + "integrity": "sha512-j6OdWF2W3Q24EmIXnNiomspJWKXicAPYnAUF1kcE4c+RuKxv/WFmPkSgg57BZRQ4613GUeHrs3eHGW6FDovolg==", "requires": { "@sentry/cli": "^1.52.4", "chalk": "^2.4.1", @@ -39243,9 +39058,9 @@ } }, "@types/babel__traverse": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz", - "integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.0.tgz", + "integrity": "sha512-IilJZ1hJBUZwMOVDNTdflOOLzJB/ZtljYVa7k3gEZN/jqIJIPkWHC6dvbX+DD2CwZDHB9wAKzZPzzqMIkW37/w==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -39347,9 +39162,9 @@ "dev": true }, "@types/node": { - "version": "15.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", - "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==" + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz", + "integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -39376,9 +39191,9 @@ "dev": true }, "@types/prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-hkc1DATxFLQo4VxPDpMH1gCkPpBbpOoJ/4nhuXw4n63/0R6bCpQECj4+K226UJ4JO/eJQz+1mC2I7JsWanAdQw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.1.tgz", + "integrity": "sha512-NVkb4p4YjI8E3O6+1m8I+8JlMpFZwfSbPGdaw0wXuyPRTEz0SLKwBUWNSO7Maoi8tQMPC8JLZNWkrcKPI7/sLA==", "dev": true }, "@types/prop-types": { @@ -39525,15 +39340,15 @@ "dev": true }, "@types/stack-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", - "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "@types/tapable": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.7.tgz", - "integrity": "sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", "dev": true }, "@types/tinycolor2": { @@ -39543,9 +39358,9 @@ "dev": true }, "@types/uglify-js": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.0.tgz", - "integrity": "sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", + "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", "dev": true, "requires": { "source-map": "^0.6.1" @@ -39560,9 +39375,9 @@ } }, "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.4.tgz", + "integrity": "sha512-zfyYsDTK1HTGYXU3fTiM76+om93HcFtsZd2M0bO/CL4DiETV7mSa/pIVN/6+G3esOqEMdg2An5cHHbK5t+9w+A==", "dev": true }, "@types/url-parse": { @@ -39572,9 +39387,9 @@ "dev": true }, "@types/webpack": { - "version": "4.41.29", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.29.tgz", - "integrity": "sha512-6pLaORaVNZxiB3FSHbyBiWM7QdazAWda1zvAq4SbZObZqHSDbWLi62iFdblVea6SK9eyBIVp5yHhKt/yNQdR7Q==", + "version": "4.41.30", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.30.tgz", + "integrity": "sha512-GUHyY+pfuQ6haAfzu4S14F+R5iGRwN6b2FRNJY7U0NilmFAqbsOfK6j1HwuLBAqwRIT+pVdNDJGJ6e8rpp0KHA==", "dev": true, "requires": { "@types/node": "*", @@ -39604,15 +39419,15 @@ } }, "@types/webpack-env": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz", - "integrity": "sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.2.tgz", + "integrity": "sha512-vKx7WNQNZDyJveYcHAm9ZxhqSGLYwoyLhrHjLBOkw3a7cT76sTdjgtwyijhk1MaHyRIuSztcVwrUOO/NEu68Dw==", "dev": true }, "@types/webpack-sources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", - "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.1.tgz", + "integrity": "sha512-MjM1R6iuw8XaVbtkCBz0N349cyqBjJHCbQiOeppe3VBeFvxqs74RKHAVt9LkxTnUWc7YLZOEsUfPUnmK6SBPKQ==", "dev": true, "requires": { "@types/node": "*", @@ -39629,17 +39444,17 @@ } }, "@types/yargs": { - "version": "15.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", - "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "20.2.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", - "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" }, "@typescript-eslint/eslint-plugin": { "version": "4.28.0", @@ -39668,17 +39483,6 @@ "@typescript-eslint/typescript-estree": "4.28.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - } } }, "@typescript-eslint/parser": { @@ -39742,9 +39546,9 @@ "peer": true }, "@unimodules/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.1.0.tgz", - "integrity": "sha512-oLRT4Bkah3GEopkxmTgpHsRTRp+NJ1907ZjE9y/HLh32q7O/3mcbpY77Uvm+EXW0Vh14gOlU+bmkpC0hz3we0w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.1.1.tgz", + "integrity": "sha512-Sa7X+WkrhZzcckavjuQu4mq6BTPWsio7OITfoNNzjL0CEmfHfo3DNWQWoVyj+wCgMnjGUT1l3+q3AQlI+CaCLA==", "requires": { "compare-versions": "^3.4.0" } @@ -40280,11 +40084,6 @@ "is-plain-object": "^2.0.4" } }, - "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==" - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -40322,9 +40121,9 @@ "dev": true }, "appdirsjs": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.4.tgz", - "integrity": "sha512-WO5StDORR6JF/xYnXk/Fm0yu+iULaV5ULKuUw0Tu+jbgiTlSquaWBCgbpnsHLMXldf+fM3Gxn5p7vjond7He6w==" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.5.tgz", + "integrity": "sha512-UyaAyzj+7XLoKhbXJi4zoAw8IDXCiLNCKfQEiuCsCCTkDmiG1vpCliQn/MoUvO3DZqCN1i6gOahokcFtNSIrVA==" }, "applicationinsights": { "version": "1.8.10", @@ -41299,11 +41098,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "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==" } } }, @@ -41870,9 +41664,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001239", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz", - "integrity": "sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ==" + "version": "1.0.30001241", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001241.tgz", + "integrity": "sha512-1uoSZ1Pq1VpH0WerIMqwptXHNNGfdl7d1cJUFs80CwQ/lVzdhTvsFZCeNFslze7AjsQnb4C85tzclPa1VShbeQ==" }, "capture-exit": { "version": "2.0.0", @@ -41948,7 +41742,6 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, - "optional": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -41965,7 +41758,6 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, - "optional": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -41975,15 +41767,13 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "optional": true + "dev": true }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "optional": true, "requires": { "fill-range": "^7.0.1" } @@ -41993,27 +41783,15 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "optional": true, "requires": { "to-regex-range": "^5.0.1" } }, - "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, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "optional": true, "requires": { "binary-extensions": "^2.0.0" } @@ -42022,15 +41800,13 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "optional": true + "dev": true }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "optional": true, "requires": { "picomatch": "^2.2.1" } @@ -42040,7 +41816,6 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "optional": true, "requires": { "is-number": "^7.0.0" } @@ -42222,13 +41997,6 @@ "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", "shallow-clone": "^3.0.0" - }, - "dependencies": { - "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==" - } } }, "cls-hooked": { @@ -42591,15 +42359,15 @@ } }, "core-js": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.0.tgz", - "integrity": "sha512-GUbtPllXMYRzIgHNZ4dTYTcUemls2cni83Q4Q/TrFONHfhcg9oEGOtaGHfb0cpzec60P96UKPvMkjX1jET8rUw==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz", + "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==", "dev": true }, "core-js-compat": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.0.tgz", - "integrity": "sha512-8X6lWsG+s7IfOKzV93a7fRYfWRZobOfjw5V5rrq43Vh/W+V6qYxl7Akalsvgab4PFT/4L/pjQbdBUEM36NXKrw==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.2.tgz", + "integrity": "sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ==", "requires": { "browserslist": "^4.16.6", "semver": "7.0.0" @@ -42613,9 +42381,9 @@ } }, "core-js-pure": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.0.tgz", - "integrity": "sha512-RO+LFAso8DB6OeBX9BAcEGvyth36QtxYon1OyVsITNVtSKr/Hos0BXZwnsOJ7o+O6KHtK+O+cJIEj9NGg6VwFA==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.2.tgz", + "integrity": "sha512-D42L7RYh1J2grW8ttxoY1+17Y4wXZeKe7uyplAI3FkNQyI5OgBIAjUfFiTPfL1rs0qLpxaabITNbjKl1Sp82tA==", "dev": true }, "core-util-is": { @@ -42891,9 +42659,9 @@ "dev": true }, "decimal.js": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", - "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, "decode-uri-component": { @@ -43408,14 +43176,14 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.752", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz", - "integrity": "sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==" + "version": "1.3.766", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.766.tgz", + "integrity": "sha512-u2quJ862q9reRKh/je3GXis3w38+RoXH1J9N3XjtsS6NzmUAosNsyZgUVFZPN/ZlJ3v6T0rTyZR3q/J5c6Sy5w==" }, "element-resize-detector": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.2.tgz", - "integrity": "sha512-+LOXRkCJc4I5WhEJxIDjhmE3raF8jtOMBDqSCgZTMz2TX3oXAX5pE2+MDeopJlGdXzP7KzPbBJaUGfNaP9HG4A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.3.tgz", + "integrity": "sha512-+dhNzUgLpq9ol5tyhoG7YLoXL3ssjfFW+0gpszXPwRU6NjGr1fVHMEAF8fVzIiRJq57Nre0RFeIjJwI8Nh2NmQ==", "dev": true, "requires": { "batch-processor": "1.0.0" @@ -43821,13 +43589,21 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } } }, "globals": { @@ -44028,20 +43804,12 @@ } }, "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } + "eslint-visitor-keys": "^2.0.0" } }, "eslint-visitor-keys": { @@ -44284,24 +44052,24 @@ } }, "expect": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", - "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.6.tgz", + "integrity": "sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-styles": "^5.0.0", - "jest-get-type": "^27.0.1", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-regex-util": "^27.0.1" + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-regex-util": "^27.0.6" }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -44313,9 +44081,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -44360,38 +44128,38 @@ "peer": true }, "jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", "dev": true, "peer": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-regex-util": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", - "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", "dev": true, "peer": true }, "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -44596,11 +44364,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "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==" } } }, @@ -44617,28 +44380,16 @@ "dev": true }, "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", + "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "dependencies": { - "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, - "requires": { - "is-glob": "^4.0.1" - } - } + "micromatch": "^4.0.4" } }, "fast-json-stable-stringify": { @@ -45026,12 +44777,6 @@ "is-plain-object": "^2.0.4" } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -45072,9 +44817,9 @@ } }, "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz", + "integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A==", "dev": true }, "flow-parser": { @@ -45178,6 +44923,27 @@ "nan": "^2.12.1" } }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -45216,12 +44982,6 @@ "is-plain-object": "^2.0.4" } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -45614,24 +45374,12 @@ } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "is-glob": "^4.0.1" } }, "glob-to-regexp": { @@ -45667,14 +45415,6 @@ "ini": "^1.3.5", "kind-of": "^6.0.2", "which": "^1.3.1" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } } }, "globals": { @@ -46400,6 +46140,16 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-alphabetical": { @@ -46485,6 +46235,16 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-date-object": { @@ -46590,6 +46350,16 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-number-object": { @@ -46876,64 +46646,64 @@ } }, "jest-circus": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.0.4.tgz", - "integrity": "sha512-QD+eblDiRphta630WRKewuASLs/oY1Zki2G4bccntRvrTHQ63ljwFR5TLduuK4Zg0ZPzW0+8o6AP7KRd1yKOjw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.0.6.tgz", + "integrity": "sha512-OJlsz6BBeX9qR+7O9lXefWoc2m9ZqcZ5Ohlzz0pTEAG4xMiZUJoacY8f4YDHxgk0oKYxj277AfOk9w6hZYvi1Q==", "dev": true, "peer": true, "requires": { - "@jest/environment": "^27.0.3", - "@jest/test-result": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/environment": "^27.0.6", + "@jest/test-result": "^27.0.6", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^27.0.2", + "expect": "^27.0.6", "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.2", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-runtime": "^27.0.4", - "jest-snapshot": "^27.0.4", - "jest-util": "^27.0.2", - "pretty-format": "^27.0.2", + "jest-each": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-runtime": "^27.0.6", + "jest-snapshot": "^27.0.6", + "jest-util": "^27.0.6", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3", "throat": "^6.0.1" }, "dependencies": { "@jest/console": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.0.2.tgz", - "integrity": "sha512-/zYigssuHLImGeMAACkjI4VLAiiJznHgAl3xnFT19iWyct2LhrH3KXOjHRmxBGTkiPLZKKAJAgaPpiU9EZ9K+w==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.0.6.tgz", + "integrity": "sha512-fMlIBocSHPZ3JxgWiDNW/KPj6s+YRd0hicb33IrmelCcjXo/pXPwvuiKFmZz+XuqI/1u7nbUK10zSsWL/1aegg==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.0.2", - "jest-util": "^27.0.2", + "jest-message-util": "^27.0.6", + "jest-util": "^27.0.6", "slash": "^3.0.0" } }, "@jest/globals": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.0.3.tgz", - "integrity": "sha512-OzsIuf7uf+QalqAGbjClyezzEcLQkdZ+7PejUrZgDs+okdAK8GwRCGcYCirHvhMBBQh60Jr3NlIGbn/KBPQLEQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.0.6.tgz", + "integrity": "sha512-DdTGCP606rh9bjkdQ7VvChV18iS7q0IMJVP1piwTWyWskol4iqcVwthZmoJEf7obE1nc34OpIyoVGPeqLC+ryw==", "dev": true, "peer": true, "requires": { - "@jest/environment": "^27.0.3", - "@jest/types": "^27.0.2", - "expect": "^27.0.2" + "@jest/environment": "^27.0.6", + "@jest/types": "^27.0.6", + "expect": "^27.0.6" } }, "@jest/source-map": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.1.tgz", - "integrity": "sha512-yMgkF0f+6WJtDMdDYNavmqvbHtiSpwRN2U/W+6uztgfqgkq/PXdKPqjBTUF1RD/feth4rH5N3NW0T5+wIuln1A==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", + "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", "dev": true, "peer": true, "requires": { @@ -46943,35 +46713,35 @@ } }, "@jest/test-result": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.0.2.tgz", - "integrity": "sha512-gcdWwL3yP5VaIadzwQtbZyZMgpmes8ryBAJp70tuxghiA8qL4imJyZex+i+USQH2H4jeLVVszhwntgdQ97fccA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.0.6.tgz", + "integrity": "sha512-ja/pBOMTufjX4JLEauLxE3LQBPaI2YjGFtXexRAjt1I/MbfNlMx0sytSX3tn5hSLzQsR3Qy2rd0hc1BWojtj9w==", "dev": true, "peer": true, "requires": { - "@jest/console": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/console": "^27.0.6", + "@jest/types": "^27.0.6", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/transform": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.0.2.tgz", - "integrity": "sha512-H8sqKlgtDfVog/s9I4GG2XMbi4Ar7RBxjsKQDUhn2XHAi3NG+GoQwWMER+YfantzExbjNqQvqBHzo/G2pfTiPw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.0.6.tgz", + "integrity": "sha512-rj5Dw+mtIcntAUnMlW/Vju5mr73u8yg+irnHwzgtgoeI6cCPOvUwQ0D1uQtc/APmWgvRweEb1g05pkUpxH3iCA==", "dev": true, "peer": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "babel-plugin-istanbul": "^6.0.0", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.2", - "jest-regex-util": "^27.0.1", - "jest-util": "^27.0.2", + "jest-haste-map": "^27.0.6", + "jest-regex-util": "^27.0.6", + "jest-util": "^27.0.6", "micromatch": "^4.0.4", "pirates": "^4.0.1", "slash": "^3.0.0", @@ -46980,9 +46750,9 @@ } }, "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -46994,9 +46764,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -47057,9 +46827,9 @@ "peer": true }, "diff-sequences": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", - "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", "dev": true, "peer": true }, @@ -47081,98 +46851,98 @@ } }, "jest-diff": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", - "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", + "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", "dev": true, "peer": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.1", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" } }, "jest-haste-map": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.0.2.tgz", - "integrity": "sha512-37gYfrYjjhEfk37C4bCMWAC0oPBxDpG0qpl8lYg8BT//wf353YT/fzgA7+Dq0EtM7rPFS3JEcMsxdtDwNMi2cA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.0.6.tgz", + "integrity": "sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.0.1", - "jest-serializer": "^27.0.1", - "jest-util": "^27.0.2", - "jest-worker": "^27.0.2", + "jest-regex-util": "^27.0.6", + "jest-serializer": "^27.0.6", + "jest-util": "^27.0.6", + "jest-worker": "^27.0.6", "micromatch": "^4.0.4", "walker": "^1.0.7" } }, "jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", "dev": true, "peer": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-regex-util": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", - "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", "dev": true, "peer": true }, "jest-resolve": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.0.4.tgz", - "integrity": "sha512-BcfyK2i3cG79PDb/6gB6zFeFQlcqLsQjGBqznFCpA0L/3l1L/oOsltdUjs5eISAWA9HS9qtj8v2PSZr/yWxONQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.0.6.tgz", + "integrity": "sha512-yKmIgw2LgTh7uAJtzv8UFHGF7Dm7XfvOe/LQ3Txv101fLM8cx2h1QVwtSJ51Q/SCxpIiKfVn6G2jYYMDNHZteA==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "chalk": "^4.0.0", "escalade": "^3.1.1", "graceful-fs": "^4.2.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", + "jest-util": "^27.0.6", + "jest-validate": "^27.0.6", "resolve": "^1.20.0", "slash": "^3.0.0" } }, "jest-runtime": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.0.4.tgz", - "integrity": "sha512-voJB4xbAjS/qYPboV+e+gmg3jfvHJJY4CagFWBOM9dQKtlaiTjcpD2tWwla84Z7PtXSQPeIpXY0qksA9Dum29A==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.0.6.tgz", + "integrity": "sha512-BhvHLRVfKibYyqqEFkybsznKwhrsu7AWx2F3y9G9L95VSIN3/ZZ9vBpm/XCS2bS+BWz3sSeNGLzI3TVQ0uL85Q==", "dev": true, "peer": true, "requires": { - "@jest/console": "^27.0.2", - "@jest/environment": "^27.0.3", - "@jest/fake-timers": "^27.0.3", - "@jest/globals": "^27.0.3", - "@jest/source-map": "^27.0.1", - "@jest/test-result": "^27.0.2", - "@jest/transform": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/console": "^27.0.6", + "@jest/environment": "^27.0.6", + "@jest/fake-timers": "^27.0.6", + "@jest/globals": "^27.0.6", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.0.6", + "@jest/transform": "^27.0.6", + "@jest/types": "^27.0.6", "@types/yargs": "^16.0.0", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", @@ -47180,23 +46950,23 @@ "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-mock": "^27.0.3", - "jest-regex-util": "^27.0.1", - "jest-resolve": "^27.0.4", - "jest-snapshot": "^27.0.4", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", + "jest-haste-map": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-mock": "^27.0.6", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.0.6", + "jest-snapshot": "^27.0.6", + "jest-util": "^27.0.6", + "jest-validate": "^27.0.6", "slash": "^3.0.0", "strip-bom": "^4.0.0", "yargs": "^16.0.3" } }, "jest-serializer": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.1.tgz", - "integrity": "sha512-svy//5IH6bfQvAbkAEg1s7xhhgHTtXu0li0I2fdKHDsLP2P2MOiscPQIENQep8oU2g2B3jqLyxKKzotZOz4CwQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", + "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", "dev": true, "peer": true, "requires": { @@ -47205,9 +46975,9 @@ } }, "jest-snapshot": { - "version": "27.0.4", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.0.4.tgz", - "integrity": "sha512-hnjrvpKGdSMvKfbHyaG5Kul7pDJGZvjVy0CKpzhu28MmAssDXS6GpynhXzgst1wBQoKD8c9b2VS2a5yhDLQRCA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.0.6.tgz", + "integrity": "sha512-NTHaz8He+ATUagUgE7C/UtFcRoHqR2Gc+KDfhQIyx+VFgwbeEMjeP+ILpUTLosZn/ZtbNdCF5LkVnN/l+V751A==", "dev": true, "peer": true, "requires": { @@ -47217,34 +46987,34 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.0.0", - "@jest/transform": "^27.0.2", - "@jest/types": "^27.0.2", + "@jest/transform": "^27.0.6", + "@jest/types": "^27.0.6", "@types/babel__traverse": "^7.0.4", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.0.2", + "expect": "^27.0.6", "graceful-fs": "^4.2.4", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "jest-haste-map": "^27.0.2", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-resolve": "^27.0.4", - "jest-util": "^27.0.2", + "jest-diff": "^27.0.6", + "jest-get-type": "^27.0.6", + "jest-haste-map": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-resolve": "^27.0.6", + "jest-util": "^27.0.6", "natural-compare": "^1.4.0", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "semver": "^7.3.2" } }, "jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -47253,24 +47023,24 @@ } }, "jest-validate": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.0.2.tgz", - "integrity": "sha512-UgBF6/oVu1ofd1XbaSotXKihi8nZhg0Prm8twQ9uCuAfo59vlxCXMPI/RKmrZEVgi3Nd9dS0I8A0wzWU48pOvg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.0.6.tgz", + "integrity": "sha512-yhZZOaMH3Zg6DC83n60pLmdU1DQE46DW+KLozPiPbSbPhlXXaiUTDlhHQhHFpaqIFRrInko1FHXjTRpjWRuWfA==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.0.1", + "jest-get-type": "^27.0.6", "leven": "^3.1.0", - "pretty-format": "^27.0.2" + "pretty-format": "^27.0.6" } }, "jest-worker": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.2.tgz", - "integrity": "sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.6.tgz", + "integrity": "sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA==", "dev": true, "peer": true, "requires": { @@ -47292,13 +47062,13 @@ } }, "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -47664,23 +47434,23 @@ } }, "jest-each": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.0.2.tgz", - "integrity": "sha512-OLMBZBZ6JkoXgUenDtseFRWA43wVl2BwmZYIWQws7eS7pqsIvePqj/jJmEnfq91ALk3LNphgwNK/PRFBYi7ITQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.0.6.tgz", + "integrity": "sha512-m6yKcV3bkSWrUIjxkE9OC0mhBZZdhovIW5ergBYirqnkLXkyEn3oUUF/QZgyecA1cF1QFyTE8bRRl8Tfg1pfLA==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "chalk": "^4.0.0", - "jest-get-type": "^27.0.1", - "jest-util": "^27.0.2", - "pretty-format": "^27.0.2" + "jest-get-type": "^27.0.6", + "jest-util": "^27.0.6", + "pretty-format": "^27.0.6" }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -47692,9 +47462,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -47747,13 +47517,13 @@ } }, "jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -47762,13 +47532,13 @@ } }, "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -47865,24 +47635,24 @@ } }, "jest-environment-node": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.0.3.tgz", - "integrity": "sha512-co2/IVnIFL3cItpFULCvXFg9us4gvWXgs7mutAMPCbFhcqh56QAOdKhNzC2+RycsC/k4mbMj1VF+9F/NzA0ROg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.0.6.tgz", + "integrity": "sha512-+Vi6yLrPg/qC81jfXx3IBlVnDTI6kmRr08iVa2hFCWmJt4zha0XW7ucQltCAPhSR0FEKEoJ3i+W4E6T0s9is0w==", "dev": true, "peer": true, "requires": { - "@jest/environment": "^27.0.3", - "@jest/fake-timers": "^27.0.3", - "@jest/types": "^27.0.2", + "@jest/environment": "^27.0.6", + "@jest/fake-timers": "^27.0.6", + "@jest/types": "^27.0.6", "@types/node": "*", - "jest-mock": "^27.0.3", - "jest-util": "^27.0.2" + "jest-mock": "^27.0.6", + "jest-util": "^27.0.6" }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -47894,9 +47664,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -47949,13 +47719,13 @@ } }, "jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -47976,9 +47746,9 @@ } }, "jest-get-type": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", - "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", "dev": true, "peer": true }, @@ -48185,22 +47955,22 @@ } }, "jest-matcher-utils": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", - "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz", + "integrity": "sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==", "dev": true, "peer": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "jest-diff": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -48212,9 +47982,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -48243,9 +48013,9 @@ } }, "diff-sequences": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", - "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", "dev": true, "peer": true }, @@ -48257,26 +48027,26 @@ "peer": true }, "jest-diff": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", - "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", + "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", "dev": true, "peer": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.1", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" } }, "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" @@ -48370,20 +48140,20 @@ } }, "jest-mock": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.0.3.tgz", - "integrity": "sha512-O5FZn5XDzEp+Xg28mUz4ovVcdwBBPfAhW9+zJLO0Efn2qNbYcDaJvSlRiQ6BCZUCVOJjALicuJQI9mRFjv1o9Q==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.0.6.tgz", + "integrity": "sha512-lzBETUoK8cSxts2NYXSBWT+EJNzmUVtVVwS1sU9GwE1DLCfGsngg+ZVSIe0yd0ZSm+y791esiuo+WSwpXJQ5Bw==", "dev": true, "peer": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*" }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "peer": true, "requires": { @@ -48395,9 +48165,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "peer": true, "requires": { @@ -49243,11 +49013,6 @@ "is-plain-object": "^2.0.4" } }, - "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==" - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -49316,9 +49081,9 @@ }, "dependencies": { "acorn": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.0.tgz", - "integrity": "sha512-ULr0LDaEqQrMFGyQ3bhJkLsbtrQ8QibAseGZeaSUiT/6zb9IvIkomWHJIvgvwad+hinRAgsI51JcWk2yvwyL+w==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", + "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", "dev": true } } @@ -49399,12 +49164,9 @@ "integrity": "sha1-kYiJ6hP40KQufFVyUO7nE63JXDU=" }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "klaw": { "version": "1.3.1", @@ -51057,16 +50819,16 @@ } }, "mocha": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.1.tgz", - "integrity": "sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", + "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", "dev": true, "peer": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", @@ -51079,28 +50841,17 @@ "minimatch": "3.0.4", "ms": "2.1.3", "nanoid": "3.1.23", - "serialize-javascript": "5.0.1", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.4", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "dependencies": { - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "peer": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -51108,40 +50859,6 @@ "dev": true, "peer": true }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "peer": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "peer": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "peer": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -51149,16 +50866,6 @@ "dev": true, "peer": true }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "peer": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -51170,16 +50877,6 @@ "path-exists": "^4.0.0" } }, - "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, - "peer": true, - "requires": { - "is-glob": "^4.0.1" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -51187,23 +50884,6 @@ "dev": true, "peer": true }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "peer": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "peer": true - }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -51258,16 +50938,6 @@ "dev": true, "peer": true }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "peer": true, - "requires": { - "picomatch": "^2.2.1" - } - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -51278,16 +50948,6 @@ "has-flag": "^4.0.0" } }, - "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==", - "dev": true, - "peer": true, - "requires": { - "is-number": "^7.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -51497,11 +51157,6 @@ "requires": { "is-plain-object": "^2.0.4" } - }, - "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==" } } }, @@ -51699,9 +51354,9 @@ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==" }, "node-stream-zip": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.13.5.tgz", - "integrity": "sha512-Lfi9xhSNvnJU35+4ZFlECXKJ70etAgJYWAVCdcEpksPnMrgwNqwkCJqdunoViVoFFV38C7AIodYE+2apuoK9Gw==" + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.13.6.tgz", + "integrity": "sha512-c7tRSVkLNOHvasWgmZ2d86cDgTWEygnkuuHNOY9c0mR3yLZtQTTrGvMaJ/fPs6+LOJn3240y30l5sjLaXFtcvw==" }, "node-version": { "version": "1.2.0", @@ -51816,6 +51471,16 @@ "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "object-inspect": { @@ -52805,9 +52470,9 @@ "dev": true }, "prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", + "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", "dev": true }, "prettier-linter-helpers": { @@ -52862,13 +52527,10 @@ "dev": true }, "prismjs": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", - "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", - "dev": true, - "requires": { - "clipboard": "^2.0.0" - } + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz", + "integrity": "sha512-mNPsedLuk90RVJioIky8ANZEwYm5w9LcvCXrxHlwf4fNVSn8jEipMybMkWUyyF0JhnC+C4VcOVSBuHRKs1L5Ow==", + "dev": true }, "process": { "version": "0.11.10", @@ -53180,9 +52842,9 @@ } }, "react-colorful": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.2.2.tgz", - "integrity": "sha512-Xdb1Rl6lZ5SMdNBH59eE0lGqR1g2LVD8IgPlw0WeMDrOC65lYI8fgMEwj/0dDpVRVMh5qp73ciISDst/t2O2iQ==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.2.3.tgz", + "integrity": "sha512-lAge4syxosZg9SX8fJiwOLd9ZJSW3poPBtypnz1aMiFoHsRnK5G3+INGGx9DGtsrso4h5uFYbiFpjAfWyK3Kag==", "dev": true, "requires": {} }, @@ -53332,6 +52994,27 @@ "locate-path": "^3.0.0" } }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, "globby": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", @@ -53427,12 +53110,6 @@ "minimist": "^1.2.0" } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "loader-utils": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", @@ -54315,9 +53992,9 @@ } }, "react-native-windows": { - "version": "0.64.11", - "resolved": "https://registry.npmjs.org/react-native-windows/-/react-native-windows-0.64.11.tgz", - "integrity": "sha512-zlR5YOULsHOFIjUTFncToRkNSpNdM2M8xz3SSIb3vKMnz+V4WxyEzc92SY+AgeWuOcbKqpiSHjkSkmUb/Hzh1w==", + "version": "0.64.12", + "resolved": "https://registry.npmjs.org/react-native-windows/-/react-native-windows-0.64.12.tgz", + "integrity": "sha512-9wjDLvB7u8z1OvF25vQ4xwacWC6WFn/EUJrJ7yWX2IwqEUJOzNY6mxwCEspNf00lXs34d9e+xTlluUHrbPrNIg==", "peer": true, "requires": { "@babel/runtime": "^7.0.0", @@ -54630,12 +54307,6 @@ "is-plain-object": "^2.0.4" } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -54695,14 +54366,14 @@ } }, "refractor": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.3.1.tgz", - "integrity": "sha512-vaN6R56kLMuBszHSWlwTpcZ8KTMG6aUCok4GrxYDT20UIOXxOc5o6oDc8tNTzSlH3m2sI+Eu9Jo2kVdDcUTWYw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.4.0.tgz", + "integrity": "sha512-dBeD02lC5eytm9Gld2Mx0cMcnR+zhSnsTfPpWqFaMgUMJfC9A6bcN3Br/NaXrnBJcuxnLFR90k1jrkaSyV8umg==", "dev": true, "requires": { "hastscript": "^6.0.0", "parse-entities": "^2.0.0", - "prismjs": "~1.23.0" + "prismjs": "~1.24.0" } }, "regenerate": { @@ -55290,11 +54961,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, - "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==" - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -55472,9 +55138,9 @@ } }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "peer": true, "requires": { @@ -55569,13 +55235,6 @@ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "requires": { "kind-of": "^6.0.2" - }, - "dependencies": { - "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==" - } } }, "shallow-equal": { @@ -55796,11 +55455,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "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==" } } }, @@ -55810,6 +55464,16 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "requires": { "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "sockjs-client": { @@ -56730,6 +56394,16 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "to-regex": { @@ -56794,11 +56468,6 @@ "requires": { "is-plain-object": "^2.0.4" } - }, - "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==" } } }, @@ -56882,9 +56551,9 @@ }, "dependencies": { "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", @@ -56895,9 +56564,9 @@ } }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -56944,12 +56613,12 @@ } }, "jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", + "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", "dev": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -57592,6 +57261,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "validator": { + "version": "13.1.17", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.1.17.tgz", + "integrity": "sha512-zL5QBoemJ3jYFb2/j38y7ljhwYGXVLUp8H6W1nVxadnAOvUOytec+L7BHh1oBQ82/TzWXHd+GSaxUWp4lROkLg==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -57696,6 +57370,29 @@ "bindings": "^1.5.0", "nan": "^2.12.1" } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } } } }, @@ -57847,12 +57544,6 @@ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -58302,9 +57993,9 @@ "dev": true }, "whatwg-url": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.6.0.tgz", - "integrity": "sha512-os0KkeeqUOl7ccdDT1qqUcS4KH4tcBTSKK5Nl5WKb2lyxInIZ/CpjkqKa1Ss12mjfdcRX9mHmPPs7/SxG1Hbdw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, "requires": { "lodash": "^4.7.0", @@ -58428,9 +58119,9 @@ } }, "workerpool": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.4.tgz", - "integrity": "sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true, "peer": true }, @@ -58472,9 +58163,9 @@ } }, "ws": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz", - "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz", + "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==", "requires": {} }, "xcode": { @@ -58675,6 +58366,11 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + "zod": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-1.11.13.tgz", + "integrity": "sha512-10+KA7eWa8g1hbKIXkOnhjJ4RKEwX85ECz3VJzP+pWkJOFKn76bHy1kG0d1JHBwmdElLcCsaB0O9HqIfT1vZnw==" } } } diff --git a/package.json b/package.json index 9a42c5102..79f109169 100644 --- a/package.json +++ b/package.json @@ -15,13 +15,14 @@ "@formatjs/intl-pluralrules": "4.0.27", "@formatjs/intl-relativetimeformat": "9.1.6", "@mattermost/react-native-emm": "1.1.3", + "@mattermost/react-native-network-client": "github:mattermost/react-native-network-client", "@mattermost/react-native-paste-input": "0.1.3", "@nozbe/watermelondb": "0.22.0", "@nozbe/with-observables": "1.3.0", "@react-native-community/async-storage": "1.12.1", "@react-native-community/cameraroll": "4.0.4", "@react-native-community/clipboard": "1.5.1", - "@react-native-community/cookies": "5.0.1", + "@react-native-cookies/cookies": "6.0.8", "@react-native-community/masked-view": "0.1.11", "@react-native-community/netinfo": "6.0.0", "@rudderstack/rudder-sdk-react-native": "1.0.10", diff --git a/patches/react-native-keychain+7.0.0.patch b/patches/react-native-keychain+7.0.0.patch index 01e13b5e8..7b24ab157 100644 --- a/patches/react-native-keychain+7.0.0.patch +++ b/patches/react-native-keychain+7.0.0.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m -index 38ccdf3..bdc4713 100644 +index 38ccdf3..3c80299 100644 --- a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m +++ b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m -@@ -272,6 +272,34 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server +@@ -272,6 +272,37 @@ SecAccessControlCreateFlags accessControlValue(NSDictionary *options) return SecItemDelete((__bridge CFDictionaryRef) query); } @@ -25,8 +25,11 @@ index 38ccdf3..bdc4713 100644 + result = (__bridge NSArray*)(resultRef); + if (result != NULL) { + for (id entry in result) { -+ NSString *server = [entry objectForKey:(__bridge NSString *)kSecAttrServer]; -+ [servers addObject:server]; ++ NSMutableData *serverData = [entry objectForKey:(__bridge NSString *)kSecAttrServer]; ++ if (serverData != NULL) { ++ NSString *server = [[NSString alloc] initWithData:serverData encoding:NSUTF8StringEncoding]; ++ [servers addObject:server]; ++ } + } + } + } @@ -37,7 +40,7 @@ index 38ccdf3..bdc4713 100644 -(NSArray*)getAllServicesForSecurityClasses:(NSArray *)secItemClasses { NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys: -@@ -592,4 +620,14 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server +@@ -592,4 +623,14 @@ RCT_EXPORT_METHOD(getAllGenericPasswordServices:(RCTPromiseResolveBlock)resolve } } @@ -53,7 +56,7 @@ index 38ccdf3..bdc4713 100644 + @end diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java -index 3da433f..112cc74 100644 +index 3da433f..731b991 100644 --- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java +++ b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java @@ -1,6 +1,7 @@ @@ -111,6 +114,14 @@ index 3da433f..112cc74 100644 promise.resolve(credentials); } catch (KeyStoreAccessException e) { +@@ -372,6 +381,7 @@ public class KeychainModule extends ReactContextBaseJavaModule { + } + // And then we remove the entry in the shared preferences + prefsStorage.removeEntry(alias); ++ cachedCredentialsMap.remove(alias); + + promise.resolve(true); + } catch (KeyStoreAccessException e) { diff --git a/node_modules/react-native-keychain/index.js b/node_modules/react-native-keychain/index.js index b73cfb2..a754505 100644 --- a/node_modules/react-native-keychain/index.js diff --git a/test/setup.ts b/test/setup.ts index efe303d0d..8a7050826 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -96,6 +96,36 @@ jest.doMock('react-native', () => { }, }), }, + APIClient: { + getConstants: () => ({ + EVENTS: { + UPLOAD_PROGRESS: 'APIClient-UploadProgress', + CLIENT_ERROR: 'APIClient-Error', + }, + RETRY_TYPES: { + EXPONENTIAL_RETRY: 'exponential', + LINEAR_RETRY: 'linear', + }, + }), + }, + WebSocketClient: { + getConstants: () => ({ + EVENTS: { + OPEN_EVENT: 'WebSocketClient-Open', + CLOSE_EVENT: 'WebSocketClient-Close', + ERROR_EVENT: 'WebSocketClient-Error', + MESSAGE_EVENT: 'WebSocketClient-Message', + READY_STATE_EVENT: 'WebSocketClient-ReadyState', + CLIENT_ERROR: 'WebSocketClient-Error', + }, + READY_STATE: { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3, + }, + }), + }, }; const Linking = { @@ -169,6 +199,7 @@ jest.mock('react-native-device-info', () => { hasNotch: () => true, isTablet: () => false, getApplicationName: () => 'Mattermost', + getUserAgent: () => 'user-agent', }; }); @@ -181,7 +212,7 @@ jest.mock('react-native-localize', () => ({ ]), })); -jest.mock('@react-native-community/cookies', () => ({ +jest.mock('@react-native-cookies/cookies', () => ({ addEventListener: jest.fn(), removeEventListener: jest.fn(), openURL: jest.fn(), @@ -278,6 +309,8 @@ jest.mock('@screens/navigation', () => ({ dismissOverlay: jest.fn(() => Promise.resolve()), })); +jest.mock('@mattermost/react-native-emm'); + declare const global: {requestAnimationFrame: (callback: any) => void}; global.requestAnimationFrame = (callback) => { setTimeout(callback, 0); diff --git a/test/test_helper.js b/test/test_helper.js index b51c8d78b..1f2d21b20 100644 --- a/test/test_helper.js +++ b/test/test_helper.js @@ -43,11 +43,17 @@ class TestHelper { }; createClient = () => { - const client = new Client(); + const mockApiClient = { + baseUrl: 'https://community.mattermost.com', + delete: jest.fn(), + head: jest.fn(), + get: jest.fn(), + patch: jest.fn(), + post: jest.fn(), + put: jest.fn(), + }; - client.setUrl(Config.DefaultServerUrl || Config.TestServerUrl); - - return client; + return new Client(mockApiClient, mockApiClient.baseUrl); }; fakeChannel = (teamId) => { diff --git a/tsconfig.json b/tsconfig.json index f98adc014..ce14b2088 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,6 +33,7 @@ "resolveJsonModule": true, "baseUrl": ".", "paths": { + "@actions/*": ["app/actions/*"], "@app/*": ["app/*"], "@assets/*": ["dist/assets/*"], "@client/*": ["app/client/*"], @@ -44,7 +45,6 @@ "@init/*": ["app/init/*"], "@notifications": ["app/notifications/index"], "@queries/*": ["app/queries/*"], - "@requests/*": ["app/requests/*"], "@screens/*": ["app/screens/*"], "@selectors/*": ["app/selectors/*"], "@share/*": ["share_extension/*"], diff --git a/types/api/client4.d.ts b/types/api/client.d.ts similarity index 85% rename from types/api/client4.d.ts rename to types/api/client.d.ts index 16b4ca89d..5b6ca5205 100644 --- a/types/api/client4.d.ts +++ b/types/api/client.d.ts @@ -25,11 +25,6 @@ export type ErrorApi = { }; export type Client4Error = ErrorOffline | ErrorInvalidResponse | ErrorApi; export type ClientOptions = { - headers?: { - [x: string]: string; - }; - method?: string; - url?: string; - credentials?: 'omit' | 'same-origin' | 'include'; body?: any; + method?: string; }; diff --git a/types/api/session.d.ts b/types/api/session.d.ts new file mode 100644 index 000000000..2b3a5174f --- /dev/null +++ b/types/api/session.d.ts @@ -0,0 +1,10 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +interface Session { + id: string, + create_at: string|number; + device_id?: string; + expires_at: string|number; + user_id: string; +}