WIP Handle migration
This commit is contained in:
parent
9c58731403
commit
c81ecd1ec1
|
@ -13,7 +13,6 @@ import { useLocalState } from '@ente/shared/hooks/useLocalState';
|
|||
import { setupI18n } from '@/ui/i18n';
|
||||
import HTTPService from '@ente/shared/network/HTTPService';
|
||||
import { LS_KEYS, getData } from '@ente/shared/storage/localStorage';
|
||||
import { getUserLocaleString } from '@ente/shared/storage/localStorage/helpers';
|
||||
import { getTheme } from '@ente/shared/themes';
|
||||
import { THEME_COLOR } from '@ente/shared/themes/constants';
|
||||
import createEmotionCache from '@ente/shared/themes/createEmotionCache';
|
||||
|
@ -64,7 +63,7 @@ export default function App(props: EnteAppProps) {
|
|||
const [themeColor] = useLocalState(LS_KEYS.THEME, THEME_COLOR.DARK);
|
||||
|
||||
useEffect(() => {
|
||||
setupI18n(getUserLocaleString()).finally(() => setIsI18nReady(true));
|
||||
setupI18n().finally(() => setIsI18nReady(true));
|
||||
}, []);
|
||||
|
||||
const setupPackageName = () => {
|
||||
|
|
|
@ -37,7 +37,6 @@ import { useLocalState } from '@ente/shared/hooks/useLocalState';
|
|||
import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
|
||||
import { getTheme } from '@ente/shared/themes';
|
||||
import '../../public/css/global.css';
|
||||
import { getUserLocaleString } from '@ente/shared/storage/localStorage/helpers';
|
||||
|
||||
type AppContextType = {
|
||||
showNavBar: (show: boolean) => void;
|
||||
|
@ -81,7 +80,7 @@ export default function App(props: EnteAppProps) {
|
|||
|
||||
useEffect(() => {
|
||||
//setup i18n
|
||||
setupI18n(getUserLocaleString()).finally(() => setIsI18nReady(true));
|
||||
setupI18n().finally(() => setIsI18nReady(true));
|
||||
// set client package name in headers
|
||||
HTTPService.setHeaders({
|
||||
'X-Client-Package': CLIENT_PACKAGE_NAMES.get(APPS.AUTH),
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
"uuid": "^9.0.0",
|
||||
"vscode-uri": "^3.0.7",
|
||||
"xml-js": "^1.6.11",
|
||||
"yup": "^0.29.3",
|
||||
"zxcvbn": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -76,7 +75,6 @@
|
|||
"@types/react-window-infinite-loader": "^1.0.3",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@types/wicg-file-system-access": "^2020.9.5",
|
||||
"@types/yup": "^0.29.7",
|
||||
"@types/zxcvbn": "^4.4.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ import { REDIRECTS } from 'constants/redirects';
|
|||
import {
|
||||
getLocalMapEnabled,
|
||||
getToken,
|
||||
getUserLocaleString,
|
||||
setLocalMapEnabled,
|
||||
} from '@ente/shared/storage/localStorage/helpers';
|
||||
import { isExportInProgress } from 'utils/export';
|
||||
|
@ -163,7 +162,7 @@ export default function App(props: EnteAppProps) {
|
|||
|
||||
useEffect(() => {
|
||||
//setup i18n
|
||||
setupI18n(getUserLocaleString()).finally(() => setIsI18nReady(true));
|
||||
setupI18n().finally(() => setIsI18nReady(true));
|
||||
// set client package name in headers
|
||||
HTTPService.setHeaders({
|
||||
'X-Client-Package': CLIENT_PACKAGE_NAMES.get(APPS.PHOTOS),
|
||||
|
|
|
@ -4,6 +4,14 @@ import Backend from "i18next-http-backend";
|
|||
import { isDevBuild } from "@/utils/env";
|
||||
import { getUserLocales } from "get-user-locale";
|
||||
import { includes } from "@/utils/type-guards";
|
||||
import {
|
||||
type LSKey,
|
||||
getLSString,
|
||||
setLSString,
|
||||
removeLSString,
|
||||
} from "@/utils/local-storage";
|
||||
import { object, string } from "yup";
|
||||
import { logError } from "@/utils/logging";
|
||||
|
||||
/**
|
||||
* List of all {@link SupportedLocale}s.
|
||||
|
@ -41,8 +49,9 @@ export type SupportedLocale = (typeof supportedLocales)[number];
|
|||
*
|
||||
* - react-i18next, which adds React specific APIs
|
||||
*/
|
||||
export const setupI18n = async (savedLocaleString?: string) => {
|
||||
const locale = closestSupportedLocale(savedLocaleString);
|
||||
export const setupI18n = async () => {
|
||||
const localeString = savedLocaleStringMigratingIfNeeded();
|
||||
const locale = closestSupportedLocale(localeString);
|
||||
|
||||
// https://www.i18next.com/overview/api
|
||||
await i18n
|
||||
|
@ -100,6 +109,70 @@ export const setupI18n = async (savedLocaleString?: string) => {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Read and return the locale (if any) that we'd previously saved in local
|
||||
* storage.
|
||||
*
|
||||
* If it finds a locale stored in the old format, it also updates the saved
|
||||
* value and returns it in the new format.
|
||||
*/
|
||||
const savedLocaleStringMigratingIfNeeded = () => {
|
||||
const ls = getLSString("locale");
|
||||
|
||||
// An older version of our code had stored only the language code, not the
|
||||
// full locale. Migrate these to the new locale format. Luckily, all such
|
||||
// languages can be unambiguously mapped to locales in our current set.
|
||||
//
|
||||
// This migration is dated Feb 2024. And it can be removed after a few
|
||||
// months, because by then either customers would've opened the app and
|
||||
// their setting migrated to the new format, or the browser would've cleared
|
||||
// the older local storage entry anyway.
|
||||
|
||||
if (!ls) {
|
||||
// Nothing found
|
||||
return ls;
|
||||
}
|
||||
|
||||
if (includes(supportedLocales, ls)) {
|
||||
// Already in the new format
|
||||
return ls;
|
||||
}
|
||||
|
||||
let value: string | undefined;
|
||||
try {
|
||||
const oldFormatData = object({ value: string() }).json().cast(ls);
|
||||
value = oldFormatData.value;
|
||||
} catch (e) {
|
||||
// Not a valid JSON, or not in the format we expected it. This shouldn't
|
||||
// have happened, we're the only one setting it.
|
||||
logError("Failed to parse locale obtained from local storage", e);
|
||||
// Also remove the old key, it is not parseable by us anymore.
|
||||
removeLSString("locale");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const newValue = mapOldValue(value);
|
||||
if (newValue) setLSString("locale", newValue);
|
||||
return newValue;
|
||||
};
|
||||
|
||||
const mapOldValue = (value: string | undefined) => {
|
||||
switch (value) {
|
||||
case "en":
|
||||
return "en-US";
|
||||
case "fr":
|
||||
return "fr-FR";
|
||||
case "zh":
|
||||
return "zh-CN";
|
||||
case "nl":
|
||||
return "nl-NL";
|
||||
case "es":
|
||||
return "es-ES";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the closest / best matching {@link SupportedLocale}.
|
||||
*
|
||||
|
@ -117,21 +190,6 @@ export function closestSupportedLocale(
|
|||
const ss = savedLocaleString;
|
||||
if (ss && includes(supportedLocales, ss)) return ss;
|
||||
|
||||
// An older version of our code had stored only the language code, not the
|
||||
// full locale. Map these to the default region we'd started off with.
|
||||
switch (savedLocaleString) {
|
||||
case "en":
|
||||
return "en-US";
|
||||
case "fr":
|
||||
return "fr-FR";
|
||||
case "zh":
|
||||
return "zh-CN";
|
||||
case "nl":
|
||||
return "nl-NL";
|
||||
case "es":
|
||||
return "es-ES";
|
||||
}
|
||||
|
||||
for (const us of getUserLocales()) {
|
||||
// Exact match
|
||||
if (us && includes(supportedLocales, us)) return us;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Keys corresponding to the values that we save in local storage.
|
||||
* Keys corresponding to the items that we save in local storage.
|
||||
*
|
||||
* The type of each of the these keys is {@link LSKey}.
|
||||
*
|
||||
|
@ -17,17 +17,24 @@ export const lsKeys = ["locale"] as const;
|
|||
export type LSKey = (typeof lsKeys)[number];
|
||||
|
||||
/**
|
||||
* Read a previously saved string value from local storage
|
||||
* Read a previously saved string from local storage
|
||||
*/
|
||||
export const getLSString = (key: LSKey) => {
|
||||
const value = localStorage.getItem(key);
|
||||
if (value === null) return undefined;
|
||||
return value;
|
||||
const item = localStorage.getItem(key);
|
||||
if (item === null) return undefined;
|
||||
return item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Save a string value in local storage
|
||||
* Save a string in local storage
|
||||
*/
|
||||
export const setLSString = (key: LSKey, value: string) => {
|
||||
localStorage.setItem(key, value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an string from local storage.
|
||||
*/
|
||||
export const removeLSString = (key: LSKey) => {
|
||||
localStorage.removeItem(key);
|
||||
};
|
||||
|
|
33
packages/utils/logging.ts
Normal file
33
packages/utils/logging.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Log an error
|
||||
*
|
||||
* The {@link message} property describes what went wrong. Generally in such
|
||||
* situations we also have an "error" object that has specific details about the
|
||||
* issue - that gets passed as the second parameter.
|
||||
*
|
||||
* Note that the "error" {@link e} is not typed. This is because in JavaScript,
|
||||
* any arbitrary value can be thrown. So this function allows us to pass it an
|
||||
* arbitrary value as the error, and will internally figure out how best to deal
|
||||
* with it.
|
||||
*
|
||||
* Where and how this error gets logged is dependent on where this code is
|
||||
* running. The default implementation logs a string to the console, but in
|
||||
* practice the layers above us will use the hooks provided in this file to
|
||||
* route and show this error elsewhere.
|
||||
*
|
||||
* TODO (MR): Currently this is a placeholder function to funnel error logs
|
||||
* through. This needs to do what the existing logError does, but it cannot have
|
||||
* a direct Sentry dependency here. For now, we just log on the console.
|
||||
*/
|
||||
export const logError = (message: string, e: unknown) => {
|
||||
let es: string;
|
||||
if (e instanceof Error) {
|
||||
// In practice, we expect ourselves to be called with Error objects, so
|
||||
// this is the happy path so to say.
|
||||
es = `${e.name}: ${e.message}\n${e.stack}`;
|
||||
} else {
|
||||
// For the rest rare cases, use the default string serialization of e.
|
||||
es = String(e);
|
||||
}
|
||||
console.error(`${message}: ${es}`);
|
||||
};
|
|
@ -4,7 +4,8 @@
|
|||
"private": true,
|
||||
"dependencies": {
|
||||
"is-electron": "^2.2",
|
||||
"libsodium-wrappers": "0.7.9"
|
||||
"libsodium-wrappers": "0.7.9",
|
||||
"yup": "^1.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@/build-config": "*",
|
||||
|
|
54
yarn.lock
54
yarn.lock
|
@ -41,7 +41,7 @@
|
|||
chalk "^2.4.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.5", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.8", "@babel/runtime@^7.14.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.8", "@babel/runtime@^7.14.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7":
|
||||
version "7.23.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
|
||||
integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==
|
||||
|
@ -579,7 +579,7 @@
|
|||
"@sentry/types" "7.77.0"
|
||||
"@sentry/utils" "7.77.0"
|
||||
|
||||
"@sentry/cli@^1.74.6":
|
||||
"@sentry/cli@1.75.0", "@sentry/cli@^1.74.6":
|
||||
version "1.75.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.75.0.tgz#4a5e71b5619cd4e9e6238cc77857c66f6b38d86a"
|
||||
integrity sha512-vT8NurHy00GcN8dNqur4CMIYvFH3PaKdkX3qllVvi4syybKqjwoz+aWRCvprbYv0knweneFkLt1SmBWqazUMfA==
|
||||
|
@ -960,11 +960,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.8.tgz#a8b739854ccb74b8048ef607d3701e9d506830e7"
|
||||
integrity sha512-ggMz8nOygG7d/stpH40WVaNvBwuyYLnrg5Mbyf6bmsj/8+gb6Ei4ZZ9/4PNpcPNTT8th9Q8sM8wYmWGjMWLX/A==
|
||||
|
||||
"@types/yup@^0.29.7":
|
||||
version "0.29.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.14.tgz#754f1dccedcc66fc2bbe290c27f5323b407ceb00"
|
||||
integrity sha512-Ynb/CjHhE/Xp/4bhHmQC4U1Ox+I2OpfRYF3dnNgQqn1cHa6LK3H1wJMNPT02tSVZA6FYuXE2ITORfbnb6zBCSA==
|
||||
|
||||
"@types/zxcvbn@^4.4.1":
|
||||
version "4.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/zxcvbn/-/zxcvbn-4.4.4.tgz#987f5fcd87e957097433c476c3a1c91a54f53131"
|
||||
|
@ -2217,11 +2212,6 @@ flatted@^3.2.9:
|
|||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
|
||||
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
|
||||
|
||||
fn-name@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c"
|
||||
integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA==
|
||||
|
||||
follow-redirects@^1.15.4:
|
||||
version "1.15.5"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020"
|
||||
|
@ -2986,7 +2976,7 @@ libsodium-wrappers@0.7.9:
|
|||
dependencies:
|
||||
libsodium "^0.7.0"
|
||||
|
||||
libsodium@^0.7.0:
|
||||
libsodium@0.7.9, libsodium@^0.7.0:
|
||||
version "0.7.9"
|
||||
resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.9.tgz#4bb7bcbf662ddd920d8795c227ae25bbbfa3821b"
|
||||
integrity sha512-gfeADtR4D/CM0oRUviKBViMGXZDgnFdMKMzHsvBdqLBHd9ySi6EtYnmuhHVDDYgYpAO8eU8hEY+F8vIUAPh08A==
|
||||
|
@ -3024,7 +3014,7 @@ locate-path@^6.0.0:
|
|||
dependencies:
|
||||
p-locate "^5.0.0"
|
||||
|
||||
lodash-es@^4.17.11, lodash-es@^4.17.21:
|
||||
lodash-es@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
|
@ -3039,7 +3029,7 @@ lodash.merge@^4.6.2:
|
|||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash@^4.17.15, lodash@^4.17.21:
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
@ -3527,7 +3517,7 @@ prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2,
|
|||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
property-expr@^2.0.2:
|
||||
property-expr@^2.0.5:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.6.tgz#f77bc00d5928a6c748414ad12882e83f24aec1e8"
|
||||
integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==
|
||||
|
@ -4169,11 +4159,6 @@ supports-preserve-symlinks-flag@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
synchronous-promise@^2.0.13:
|
||||
version "2.0.17"
|
||||
resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.17.tgz#38901319632f946c982152586f2caf8ddc25c032"
|
||||
integrity sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==
|
||||
|
||||
tapable@^2.2.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
||||
|
@ -4197,6 +4182,11 @@ through@^2.3.8:
|
|||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
|
||||
|
||||
tiny-case@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03"
|
||||
integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==
|
||||
|
||||
tiny-warning@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||
|
@ -4286,6 +4276,11 @@ type-fest@^0.7.1:
|
|||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48"
|
||||
integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==
|
||||
|
||||
type-fest@^2.19.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
|
||||
integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
|
||||
|
||||
typed-array-buffer@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3"
|
||||
|
@ -4550,18 +4545,15 @@ yocto-queue@^0.1.0:
|
|||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
yup@^0.29.3:
|
||||
version "0.29.3"
|
||||
resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.3.tgz#69a30fd3f1c19f5d9e31b1cf1c2b851ce8045fea"
|
||||
integrity sha512-RNUGiZ/sQ37CkhzKFoedkeMfJM0vNQyaz+wRZJzxdKE7VfDeVKH8bb4rr7XhRLbHJz5hSjoDNwMEIaKhuMZ8gQ==
|
||||
yup@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/yup/-/yup-1.3.3.tgz#d2f6020ad1679754c5f8178a29243d5447dead04"
|
||||
integrity sha512-v8QwZSsHH2K3/G9WSkp6mZKO+hugKT1EmnMqLNUcfu51HU9MDyhlETT/JgtzprnrnQHPWsjc6MUDMBp/l9fNnw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.10.5"
|
||||
fn-name "~3.0.0"
|
||||
lodash "^4.17.15"
|
||||
lodash-es "^4.17.11"
|
||||
property-expr "^2.0.2"
|
||||
synchronous-promise "^2.0.13"
|
||||
property-expr "^2.0.5"
|
||||
tiny-case "^1.0.3"
|
||||
toposort "^2.0.2"
|
||||
type-fest "^2.19.0"
|
||||
|
||||
zxcvbn@^4.4.2:
|
||||
version "4.4.2"
|
||||
|
|
Loading…
Reference in a new issue