From 693684a103c21d3a9ae6566d03689069208db1d4 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 7 Aug 2021 18:09:44 +0300 Subject: [PATCH 01/47] Extract ProviderInterface Captured existing storage interface from Onyx to separate file Storage provider mocking When we have provider.js and provider.native.js we need to have the mock implemented at the provider level instead of the AsyncStorage level --- .../async-storage.js | 1 - lib/Onyx.js | 21 +++++----- lib/storage/__mocks__/index.native.js | 3 ++ lib/storage/index.d.ts | 14 +++++++ lib/storage/index.js | 3 ++ lib/storage/index.native.js | 3 ++ package.json | 3 +- tests/setupAfterEnv.js | 1 + tests/unit/cacheEvictionTest.js | 8 ++-- tests/unit/onyxCacheTest.js | 40 +++++++++---------- 10 files changed, 61 insertions(+), 36 deletions(-) delete mode 100644 __mocks__/@react-native-async-storage/async-storage.js create mode 100644 lib/storage/__mocks__/index.native.js create mode 100644 lib/storage/index.d.ts create mode 100644 lib/storage/index.js create mode 100644 lib/storage/index.native.js create mode 100644 tests/setupAfterEnv.js diff --git a/__mocks__/@react-native-async-storage/async-storage.js b/__mocks__/@react-native-async-storage/async-storage.js deleted file mode 100644 index 1051fa919..000000000 --- a/__mocks__/@react-native-async-storage/async-storage.js +++ /dev/null @@ -1 +0,0 @@ -export {default} from '@react-native-async-storage/async-storage/jest/async-storage-mock'; diff --git a/lib/Onyx.js b/lib/Onyx.js index c0e820bc4..a89393dd2 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -1,7 +1,8 @@ import _ from 'underscore'; -import AsyncStorage from '@react-native-async-storage/async-storage'; import Str from 'expensify-common/lib/str'; import lodashMerge from 'lodash/merge'; +import Storage from './storage'; + import {registerLogger, logInfo, logAlert} from './Logger'; import cache from './OnyxCache'; import createDeferredTask from './createDeferredTask'; @@ -52,7 +53,7 @@ function get(key) { } // Otherwise retrieve the value from storage and capture a promise to aid concurrent usages - const promise = AsyncStorage.getItem(key) + const promise = Storage.getItem(key) .then((val) => { const parsed = val && JSON.parse(val); cache.set(key, parsed); @@ -82,7 +83,7 @@ function getAllKeys() { } // Otherwise retrieve the keys from storage and capture a promise to aid concurrent usages - const promise = AsyncStorage.getAllKeys() + const promise = Storage.getAllKeys() .then((keys) => { _.each(keys, key => cache.addKey(key)); return keys; @@ -437,7 +438,7 @@ function remove(key) { // Optimistically inform subscribers on the next tick Promise.resolve().then(() => keyChanged(key, null)); - return AsyncStorage.removeItem(key); + return Storage.removeItem(key); } /** @@ -480,7 +481,7 @@ function set(key, val) { Promise.resolve().then(() => keyChanged(key, val)); // Write the thing to persistent storage, which will trigger a storage event for any other tabs open on this domain - return AsyncStorage.setItem(key, JSON.stringify(val)) + return Storage.setItem(key, JSON.stringify(val)) .catch(error => evictStorageAndRetry(error, set, key, val)); } @@ -511,7 +512,7 @@ function multiSet(data) { Promise.resolve().then(() => keyChanged(key, val)); }); - return AsyncStorage.multiSet(keyValuePairs) + return Storage.multiSet(keyValuePairs) .catch(error => evictStorageAndRetry(error, multiSet, data)); } @@ -588,7 +589,7 @@ function merge(key, val) { * @returns {Promise} */ function initializeWithDefaultKeyStates() { - return AsyncStorage.multiGet(_.keys(defaultKeyStates)) + return Storage.multiGet(_.keys(defaultKeyStates)) .then((pairs) => { const asObject = _.chain(pairs) .map(([key, val]) => [key, val && JSON.parse(val)]) @@ -614,7 +615,7 @@ function clear() { cache.set(key, null); }); }) - .then(AsyncStorage.clear) + .then(Storage.clear) .then(initializeWithDefaultKeyStates); } @@ -652,11 +653,11 @@ function mergeCollection(collectionKey, collection) { // New keys will be added via multiSet while existing keys will be updated using multiMerge // This is because setting a key that doesn't exist yet with multiMerge will throw errors if (keyValuePairsForExistingCollection.length > 0) { - promises.push(AsyncStorage.multiMerge(keyValuePairsForExistingCollection)); + promises.push(Storage.multiMerge(keyValuePairsForExistingCollection)); } if (keyValuePairsForNewCollection.length > 0) { - promises.push(AsyncStorage.multiSet(keyValuePairsForNewCollection)); + promises.push(Storage.multiSet(keyValuePairsForNewCollection)); } // Merge original data to cache diff --git a/lib/storage/__mocks__/index.native.js b/lib/storage/__mocks__/index.native.js new file mode 100644 index 000000000..53221653a --- /dev/null +++ b/lib/storage/__mocks__/index.native.js @@ -0,0 +1,3 @@ +import * as Storage from '@react-native-async-storage/async-storage/jest/async-storage-mock'; + +export default Storage; diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts new file mode 100644 index 000000000..47d6e0462 --- /dev/null +++ b/lib/storage/index.d.ts @@ -0,0 +1,14 @@ +interface ProviderInterface { + getAllKeys(): Promise, + getItem(key: string): Promise, + multiGet(keys: string[]): Promise>, + removeItem(key: string): Promise, + setItem(key: string, value: string): Promise, + multiSet(pairs: Array<[string, string|null]>): Promise, + multiMerge(pairs: Array<[string, string|null]>): Promise, + clear(): Promise, +} + +declare const Storage: ProviderInterface; + +export = Storage; diff --git a/lib/storage/index.js b/lib/storage/index.js new file mode 100644 index 000000000..9c856a811 --- /dev/null +++ b/lib/storage/index.js @@ -0,0 +1,3 @@ +import Storage from '@react-native-async-storage/async-storage'; + +export default Storage; diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js new file mode 100644 index 000000000..9c856a811 --- /dev/null +++ b/lib/storage/index.native.js @@ -0,0 +1,3 @@ +import Storage from '@react-native-async-storage/async-storage'; + +export default Storage; diff --git a/package.json b/package.json index 9374ddb17..5c3e9e36f 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,8 @@ "timers": "fake", "testEnvironment": "jsdom", "setupFilesAfterEnv": [ - "@testing-library/jest-native/extend-expect" + "@testing-library/jest-native/extend-expect", + "/tests/setupAfterEnv.js" ] } } diff --git a/tests/setupAfterEnv.js b/tests/setupAfterEnv.js new file mode 100644 index 000000000..4cdababc4 --- /dev/null +++ b/tests/setupAfterEnv.js @@ -0,0 +1 @@ +jest.mock('../lib/storage'); diff --git a/tests/unit/cacheEvictionTest.js b/tests/unit/cacheEvictionTest.js index e9555a901..59ada4077 100644 --- a/tests/unit/cacheEvictionTest.js +++ b/tests/unit/cacheEvictionTest.js @@ -1,4 +1,4 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; +import Storage from '../../lib/storage'; import Onyx from '../../index'; import waitForPromisesToResolve from '../utils/waitForPromisesToResolve'; @@ -14,7 +14,7 @@ test('Cache eviction', () => { const collection = {}; // Given an evictable key previously set in storage - return AsyncStorage.setItem(`${ONYX_KEYS.COLLECTION.TEST_KEY}${RECORD_TO_EVICT}`, JSON.stringify({test: 'evict'})) + return Storage.setItem(`${ONYX_KEYS.COLLECTION.TEST_KEY}${RECORD_TO_EVICT}`, JSON.stringify({test: 'evict'})) .then(() => { // When we initialize Onyx and mark the set collection key as a safeEvictionKey Onyx.init({ @@ -42,10 +42,10 @@ test('Cache eviction', () => { expect(collection[`${ONYX_KEYS.COLLECTION.TEST_KEY}${RECORD_TO_EVICT}`]).toStrictEqual({test: 'evict'}); // When we set a new key we want to add and force the first attempt to fail - const originalSetItem = AsyncStorage.setItem; + const originalSetItem = Storage.setItem; const setItemMock = jest.fn(originalSetItem) .mockImplementationOnce(() => new Promise((_resolve, reject) => reject())); - AsyncStorage.setItem = setItemMock; + Storage.setItem = setItemMock; return Onyx.set(`${ONYX_KEYS.COLLECTION.TEST_KEY}${RECORD_TO_ADD}`, {test: 'add'}) .then(() => { diff --git a/tests/unit/onyxCacheTest.js b/tests/unit/onyxCacheTest.js index 7891f1bf6..c82e24382 100644 --- a/tests/unit/onyxCacheTest.js +++ b/tests/unit/onyxCacheTest.js @@ -394,7 +394,7 @@ describe('Onyx', () => { describe('Onyx with Cache', () => { let Onyx; let withOnyx; - let AsyncStorageMock; + let StorageMock; /** @type OnyxCache */ let cache; @@ -411,7 +411,7 @@ describe('Onyx', () => { const OnyxModule = require('../../index'); Onyx = OnyxModule.default; withOnyx = OnyxModule.withOnyx; - AsyncStorageMock = require('@react-native-async-storage/async-storage').default; + StorageMock = require('../../lib/storage').default; cache = require('../../lib/OnyxCache').default; Onyx.init({ @@ -443,8 +443,8 @@ describe('Onyx', () => { })(ViewWithText); // GIVEN some string value for that key exists in storage - AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); - AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); + StorageMock.getItem.mockResolvedValue('"mockValue"'); + StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); return initOnyx() .then(() => { // WHEN multiple components are rendered @@ -459,7 +459,7 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called only once - expect(AsyncStorageMock.getItem).toHaveBeenCalledTimes(1); + expect(StorageMock.getItem).toHaveBeenCalledTimes(1); }); }); @@ -474,8 +474,8 @@ describe('Onyx', () => { // GIVEN some string value for that key exists in storage return initOnyx() .then(() => { - AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); - AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); + StorageMock.getItem.mockResolvedValue('"mockValue"'); + StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); // WHEN multiple components are rendered render( @@ -489,14 +489,14 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called only once - expect(AsyncStorageMock.getAllKeys).toHaveBeenCalledTimes(1); + expect(StorageMock.getAllKeys).toHaveBeenCalledTimes(1); }); }); it('Should keep recently accessed items in cache', () => { // GIVEN Storage with 10 different keys - AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); - AsyncStorageMock.getAllKeys.mockResolvedValue( + StorageMock.getItem.mockResolvedValue('"mockValue"'); + StorageMock.getAllKeys.mockResolvedValue( _.range(10).map(number => `${ONYX_KEYS.COLLECTION.MOCK_COLLECTION}${number}`) ); let connections; @@ -542,8 +542,8 @@ describe('Onyx', () => { })(ViewWithText); // GIVEN some string value for that key exists in storage - AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); - AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); + StorageMock.getItem.mockResolvedValue('"mockValue"'); + StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); return initOnyx() .then(() => { @@ -561,7 +561,7 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called twice - expect(AsyncStorageMock.getItem).toHaveBeenCalledTimes(2); + expect(StorageMock.getItem).toHaveBeenCalledTimes(2); }); }); @@ -580,9 +580,9 @@ describe('Onyx', () => { })(ViewWithText); // GIVEN some values exist in storage - AsyncStorageMock.setItem(ONYX_KEYS.TEST_KEY, JSON.stringify({ID: 15, data: 'mock object with ID'})); - AsyncStorageMock.setItem(ONYX_KEYS.ANOTHER_TEST, JSON.stringify('mock text')); - AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY, ONYX_KEYS.ANOTHER_TEST]); + StorageMock.setItem(ONYX_KEYS.TEST_KEY, JSON.stringify({ID: 15, data: 'mock object with ID'})); + StorageMock.setItem(ONYX_KEYS.ANOTHER_TEST, JSON.stringify('mock text')); + StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY, ONYX_KEYS.ANOTHER_TEST]); return initOnyx() .then(() => { // WHEN the components are rendered multiple times @@ -596,8 +596,8 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called exactly two times (once for each key) - expect(AsyncStorageMock.getItem).toHaveBeenCalledTimes(2); - expect(AsyncStorageMock.getItem.mock.calls).toEqual([ + expect(StorageMock.getItem).toHaveBeenCalledTimes(2); + expect(StorageMock.getItem.mock.calls).toEqual([ [ONYX_KEYS.TEST_KEY], [ONYX_KEYS.ANOTHER_TEST] ]); @@ -606,8 +606,8 @@ describe('Onyx', () => { it('Should clean cache when connections to eviction keys happen', () => { // GIVEN storage with some data - AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); - AsyncStorageMock.getAllKeys.mockResolvedValue(_.range(1, 10).map(n => `key${n}`)); + StorageMock.getItem.mockResolvedValue('"mockValue"'); + StorageMock.getAllKeys.mockResolvedValue(_.range(1, 10).map(n => `key${n}`)); jest.useFakeTimers(); From 535cf4898b10cd486fccd2a25725818f03db4799 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Thu, 26 Aug 2021 01:30:21 +0300 Subject: [PATCH 02/47] Add expo-file-system as peerDependency --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 5c3e9e36f..84c760b24 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ }, "peerDependencies": { "@react-native-async-storage/async-storage": "^1.15.5", + "expo-file-system": "^11.1.3", "react": "^17.0.2", "react-native-performance": "^2.0.0" }, From c8c8a61d877db0e68c9dd48a84d992ade56ecd31 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 14:21:06 +0300 Subject: [PATCH 03/47] chore: add expo-file-system as dev dependency for intellisense --- package-lock.json | 332 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 333 insertions(+) diff --git a/package-lock.json b/package-lock.json index 5d08b0a78..043baffeb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1620,6 +1620,256 @@ "strip-json-comments": "^3.1.1" } }, + "@expo/config-plugins": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-3.1.0.tgz", + "integrity": "sha512-V5qxaxCAExBM0TXmbU1QKiZcAGP3ecu7KXede8vByT15cro5PkcWu2sSdJCYbHQ/gw6Vf/i8sr8gKlN8V8TSLg==", + "dev": true, + "requires": { + "@expo/config-types": "^42.0.0", + "@expo/json-file": "8.2.33", + "@expo/plist": "0.0.14", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.3.5", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "^0.4.23" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "dev": true + }, + "xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "dev": true, + "requires": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + } + } + } + }, + "@expo/config-types": { + "version": "42.0.0", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-42.0.0.tgz", + "integrity": "sha512-Rj02OMZke2MrGa/1Y/EScmR7VuWbDEHPJyvfFyyLbadUt+Yv6isCdeFzDt71I7gJlPR9T4fzixeYLrtXXOTq0w==", + "dev": true + }, + "@expo/json-file": { + "version": "8.2.33", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.33.tgz", + "integrity": "sha512-CDnhjdirUs6OdN5hOSTJ2y3i9EiJMk7Z5iDljC5xyCHCrUex7oyI8vbRsZEojAahxZccgL/PrO+CjakiFFWurg==", + "dev": true, + "requires": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "@expo/plist": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.14.tgz", + "integrity": "sha512-bb4Ua1M/OdNgS8KiGdSDUjZ/bbPfv3xdPY/lz8Ctp/adlj/QgB8xA7tVPeqSSfJPZqFRwU0qLCnRhpUOnP51VQ==", + "dev": true, + "requires": { + "@xmldom/xmldom": "~0.7.0", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", + "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", + "dev": true + } + } + }, "@hapi/hoek": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", @@ -3053,6 +3303,12 @@ } } }, + "@xmldom/xmldom": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.2.tgz", + "integrity": "sha512-t/Zqo0ewes3iq6zGqEqJNUWI27Acr3jkmSUNp6E3nl0Z2XbtqAG5XYqPNLdYonILmhcxANsIidh69tHzjXtuRg==", + "dev": true + }, "abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -3410,6 +3666,12 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -5887,6 +6149,31 @@ } } }, + "expo-file-system": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-11.1.3.tgz", + "integrity": "sha512-FBRcD6ojrkrZiTZ8O7Fbo833HhZtkhKtLDj4RNZIMpF1i+ZBD2bmeMcfLMeRHNYcBeJno9C4AVXoNQFqDCGQDg==", + "dev": true, + "requires": { + "@expo/config-plugins": "^3.0.0", + "expo-modules-core": "~0.2.0", + "uuid": "^3.4.0" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "expo-modules-core": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.2.0.tgz", + "integrity": "sha512-inpfZ5X/BaTtbj2wG9PA9AC0MN8VyId6KSRlVuEg7+ziurHBy/kKDFxpOddUokhwiln2uhoYPSStJjR/tKypdw==", + "dev": true + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6349,6 +6636,12 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, + "getenv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/getenv/-/getenv-1.0.0.tgz", + "integrity": "sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -9209,6 +9502,15 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -12989,6 +13291,24 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + } + } + }, "xmlbuilder": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", @@ -13028,6 +13348,12 @@ "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", @@ -13130,6 +13456,12 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 84c760b24..e7fc9cf30 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-react-native-web": "^0.13.5", "babel-plugin-transform-class-properties": "^6.24.1", + "expo-file-system": "^11.1.3", "eslint": "^7.6.0", "eslint-config-expensify": "^2.0.11", "jest": "^26.5.2", From 95df46d1bc68539517ca3e9fe8767c91df764fe4 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 14:21:50 +0300 Subject: [PATCH 04/47] Create storage/fs.native.js --- lib/storage/fs.native.js | 59 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 lib/storage/fs.native.js diff --git a/lib/storage/fs.native.js b/lib/storage/fs.native.js new file mode 100644 index 000000000..efed57ec1 --- /dev/null +++ b/lib/storage/fs.native.js @@ -0,0 +1,59 @@ +/** + * The native FS handler + * We storage images in our app's directory space, which does not require special + * permission + */ + +import FileSystem from 'expo-file-system'; + +const LOCAL_PATH = `${FileSystem.documentDirectory}user_files/`; + +class NativeFileHandler { + /** + * Create a local copy of a file + * @param {{ uri: string, name: string, size: number }} file + * @returns {Promise<{uri: string, name: string, size: number}>} A reference to the file stored locally + */ + storeLocally(file) { + // Todo: perhaps check size here and abort if the size is larger than 20MB + + const destination = `${LOCAL_PATH}${file.name}`; + + const copyTask = FileSystem + .copyAsync({from: file.uri, to: destination}) + .then(() => ({...file, uri: destination})); + + // Todo: do something about the error, e.g. run eviction logic if it's due to lack of space + copyTask.catch(console.error); + + // Todo: it might be best to move the checks mentioned here to the caller of the method + // Because the requirements/logic will be the same for web + + return copyTask; + } + + /** + * A list of all the files we have locally + * @returns {Promise} + */ + getLocalFileList() { + // Todo: remove this + FileSystem.getInfoAsync(LOCAL_PATH, {size: true}) + .then(result => console.debug('getInfoAsync: ', result)); + + return FileSystem.readDirectoryAsync(LOCAL_PATH); + } + + /** + * Remove the file from the local FS + * @param {string|{uri: string}} file - works with either a path or a file object + * @return {Promise} + */ + deleteLocally(file) { + return FileSystem.deleteAsync(file.uri || file, {idempotent: true}); + } +} + +const instance = new NativeFileHandler(); + +export default instance; From d77e1c5a06f015b78e91e0a7133f9b9a713fe8cb Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 16:02:11 +0300 Subject: [PATCH 05/47] Create storage/fs.js for web and desktop --- lib/storage/fs.js | 101 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 lib/storage/fs.js diff --git a/lib/storage/fs.js b/lib/storage/fs.js new file mode 100644 index 000000000..fe82561f9 --- /dev/null +++ b/lib/storage/fs.js @@ -0,0 +1,101 @@ +/** + * The web and desktop FS handler + * On web we don't have access to the underlying file system so we use the + * Cache API to save Files + */ + +const CACHE_KEY = 'expensify_user_files'; +const LOCAL_PATH = `${global.location.origin}/${CACHE_KEY}/`; + +class WebFileHandler { + /** + * Create a local copy of a file + * @param {File} file + * @returns {Promise} + */ + storeLocally(file) { + // We can also make this work with Blobs eg `|| file instanceof Blob` + const isSupported = file instanceof File; + + if (!isSupported) { + // eslint-disable-next-line no-undef + if (__DEV__) { + throw new Error('Unsupported file param'); + } + + return Promise.resolve(file); + } + + return global.caches.open(CACHE_KEY) + .then((cache) => { + /** + * Only Response objects can be put into cache + * But we can take advantage of dealing with Request/Responses + * and respond from cache for the given destination + * */ + const localRef = this.getLocalRef(file); + const response = new Response(file); + cache.put(localRef, response); + + return file; + }); + } + + /** + * On Web (and Desktop) we cannot reference local file paths directly from cache + * we need to identify such entries and make them available again by reading + * the file from cache + * E.g. if the browser is closed and re-opened and `uri` created with `URL.createObjectURL` + * become invalid, but we can recreated them using the file from cache + * @param {{ name: string, type: string }} file + * @returns {Promise} Undefined will be returned if we don't have such file stored locally + */ + getFileFromCache(file) { + // When we've already got a File instance we don't need to retrieved again from cache + if (file instanceof File) { + Promise.resolve(file); + } + + return global.caches.open(CACHE_KEY) + .then((cache) => { + const localRef = this.getLocalRef(file); + return cache.match(localRef); + }) + .then(response => response && response.blob()) + .then(blob => blob && new File([blob], file.name, file.type)); + } + + /** + * A list of all the files we have locally + * @return {Promise} + */ + getLocalFileList() { + return global.caches.open(CACHE_KEY) + .then(cache => cache.keys()); + } + + /** + * Remove the file from cache + * @param {{ name: string }} file + * @return {Promise | PromiseLike} + */ + deleteLocally(file) { + return global.caches.open(CACHE_KEY) + .then((cache) => { + const localRef = this.getLocalRef(file); + return cache.delete(localRef); + }); + } + + /** + * @private + * @param {{ name: string }} file + * @return {string} + */ + getLocalRef(file) { + return `${LOCAL_PATH}${file.name}`; + } +} +const instance = new WebFileHandler(); + +export default instance; From b53c79a6e99f545cb6429f8571346b3d79ef897d Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 17:20:45 +0300 Subject: [PATCH 06/47] Add `localforage` as peer dependency --- package-lock.json | 24 ++++++++++++++++++++++++ package.json | 8 +++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 043baffeb..271e4d30e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6910,6 +6910,12 @@ "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, "import-fresh": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", @@ -9416,6 +9422,15 @@ "type-check": "~0.4.0" } }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -9434,6 +9449,15 @@ "strip-bom": "^3.0.0" } }, + "localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "dev": true, + "requires": { + "lie": "3.1.1" + } + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", diff --git a/package.json b/package.json index e7fc9cf30..ac1fd5cbd 100644 --- a/package.json +++ b/package.json @@ -32,21 +32,23 @@ "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-react-native-web": "^0.13.5", "babel-plugin-transform-class-properties": "^6.24.1", - "expo-file-system": "^11.1.3", "eslint": "^7.6.0", "eslint-config-expensify": "^2.0.11", + "expo-file-system": "^11.1.3", "jest": "^26.5.2", "jest-cli": "^26.5.2", + "localforage": "^1.10.0", + "metro-react-native-babel-preset": "^0.61.0", "prop-types": "^15.7.2", "react": "^17.0.2", "react-native": "0.64.1", "react-native-performance": "^2.0.0", - "react-test-renderer": "16.13.1", - "metro-react-native-babel-preset": "^0.61.0" + "react-test-renderer": "16.13.1" }, "peerDependencies": { "@react-native-async-storage/async-storage": "^1.15.5", "expo-file-system": "^11.1.3", + "localforage": "^1.10.0", "react": "^17.0.2", "react-native-performance": "^2.0.0" }, From e45b66a821cc630b3818f6b4375ddeec2726fb5e Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 17:51:30 +0300 Subject: [PATCH 07/47] Create LocalForage provider this should allow us to store and retrieve Files as well as anything else from storage for web and desktop --- lib/storage/providers/LocalForage.js | 87 ++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 lib/storage/providers/LocalForage.js diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js new file mode 100644 index 000000000..362213216 --- /dev/null +++ b/lib/storage/providers/LocalForage.js @@ -0,0 +1,87 @@ +/** + * @file + * The storage provider based on localforage allows us to store most anything in it's + * natural form in the underlying DB without having to stringify or de-stringify it + */ + +import localforage from 'localforage'; +import _ from 'underscore'; +import lodashMerge from 'lodash/merge'; + +/** + * @implements {StorageProvider} + */ +class Storage { + constructor() { + /** @type {import('localforage').LocalForageDbMethods} */ + this.store = localforage.createInstance({ + name: 'OnyxDb' + }); + } + + clear() { + return this.store.clear(); + } + + getAllKeys() { + return this.store.keys(); + } + + getItem(key) { + return this.store.getItem(key); + } + + multiGet(keys) { + const pairs = []; + const remainingKeys = new Set(keys); + + return this.store.iterate((value, key) => { + if (remainingKeys.has(key)) { + remainingKeys.delete(key); + pairs.push([key, value]); + } + + // Exist early (don't iterate all keys) if we've mapped everything + if (remainingKeys.size === 0) { + return true; + } + + return undefined; + }) + .then(() => pairs); + } + + multiMerge(pairs) { + const tasks = pairs.map(([key, delta]) => this.getItem(key) + .then((existing) => { + let merged = delta; + + if (existing) { + if (_.isObject(existing)) { + merged = lodashMerge(existing, delta); + } + } + + return this.setItem(key, merged); + })); + + return Promise.all(tasks).then(() => Promise.resolve()); + } + + multiSet(pairs) { + const tasks = pairs.map(([key, value]) => this.setItem(key, value)); + return Promise.all(tasks).then(() => Promise.resolve()); + } + + removeItem(key) { + return this.store.removeItem(key); + } + + setItem(key, value) { + return this.store.setItem(key, value).then(() => Promise.resolve()); + } +} + +const instance = new Storage(); + +export default instance; From 55afdb2a6d1d2d351c4c86a203a66370b1c31187 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 18:05:56 +0300 Subject: [PATCH 08/47] Create AsyncStorage provider This is the same Provider we had up until now but the JSON parsing and stringifying is capsulated here instead of Onyx --- lib/storage/providers/AsyncStorage.js | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 lib/storage/providers/AsyncStorage.js diff --git a/lib/storage/providers/AsyncStorage.js b/lib/storage/providers/AsyncStorage.js new file mode 100644 index 000000000..57dd1a414 --- /dev/null +++ b/lib/storage/providers/AsyncStorage.js @@ -0,0 +1,52 @@ +/** + * The AsyncStorage provider stores everything in a key/value store by + * converting the value to a JSON string + */ + +import AsyncStorage from '@react-native-async-storage/async-storage'; + +/** + * @implements {StorageProvider} + */ +class AsyncStorageProvider { + async getAllKeys() { + return AsyncStorage.getAllKeys(); + } + + async getItem(key) { + return AsyncStorage.getItem(key) + .then((value) => { + const parsed = value && JSON.parse(value); + return parsed; + }); + } + + async multiGet(keys) { + return AsyncStorage.multiGet(keys) + .then(pairs => pairs.map(([key, value]) => [key, value && JSON.parse(value)])); + } + + async removeItem(key) { + return AsyncStorage.removeItem(key); + } + + async setItem(key, value) { + return AsyncStorage.setItem(key, value && JSON.stringify(value)); + } + + async multiSet(pairs) { + const stringPairs = pairs.map(([key, value]) => [key, value && JSON.stringify(value)]); + return AsyncStorage.multiSet(stringPairs); + } + + async multiMerge(pairs) { + const stringPairs = pairs.map(([key, value]) => [key, value && JSON.stringify(value)]); + return AsyncStorage.multiMerge(stringPairs); + } + + async clear() { + return AsyncStorage.clear(); + } +} + +export default AsyncStorageProvider; From 05136251f64427e7a57f11f06cb50043e66224c6 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 18:11:05 +0300 Subject: [PATCH 09/47] Move NativeFileHandler to providers --- lib/storage/{fs.native.js => providers/NativeFileHandler.js} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename lib/storage/{fs.native.js => providers/NativeFileHandler.js} (96%) diff --git a/lib/storage/fs.native.js b/lib/storage/providers/NativeFileHandler.js similarity index 96% rename from lib/storage/fs.native.js rename to lib/storage/providers/NativeFileHandler.js index efed57ec1..64e04f0ae 100644 --- a/lib/storage/fs.native.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -6,7 +6,7 @@ import FileSystem from 'expo-file-system'; -const LOCAL_PATH = `${FileSystem.documentDirectory}user_files/`; +const LOCAL_PATH = `${FileSystem.documentDirectory}onyx_files/`; class NativeFileHandler { /** From 628c56def695f91d6f908717a8107b41d9c25522 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 20:20:55 +0300 Subject: [PATCH 10/47] Remove JSON parse/stringify handling from Onyx This is handled by Storage providers --- lib/Onyx.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index a89393dd2..8622ce3b0 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -55,9 +55,8 @@ function get(key) { // Otherwise retrieve the value from storage and capture a promise to aid concurrent usages const promise = Storage.getItem(key) .then((val) => { - const parsed = val && JSON.parse(val); - cache.set(key, parsed); - return parsed; + cache.set(key, val); + return val; }) .catch(err => logInfo(`Unable to get item from persistent storage. Key: ${key} Error: ${err}`)); @@ -470,7 +469,7 @@ function evictStorageAndRetry(error, ionMethod, ...args) { * Write a value to our store with the given key * * @param {string} key - * @param {mixed} val + * @param {*} val * @returns {Promise} */ function set(key, val) { @@ -481,7 +480,7 @@ function set(key, val) { Promise.resolve().then(() => keyChanged(key, val)); // Write the thing to persistent storage, which will trigger a storage event for any other tabs open on this domain - return Storage.setItem(key, JSON.stringify(val)) + return Storage.setItem(key, val) .catch(error => evictStorageAndRetry(error, set, key, val)); } @@ -493,7 +492,7 @@ function set(key, val) { * @return {Array<[string, string]>} an array of stringified key - value pairs */ function prepareKeyValuePairsForStorage(data) { - return _.keys(data).map(key => [key, JSON.stringify(data[key])]); + return _.map(data, (value, key) => [key, value]); } /** @@ -591,10 +590,7 @@ function merge(key, val) { function initializeWithDefaultKeyStates() { return Storage.multiGet(_.keys(defaultKeyStates)) .then((pairs) => { - const asObject = _.chain(pairs) - .map(([key, val]) => [key, val && JSON.parse(val)]) - .object() - .value(); + const asObject = _.object(pairs); const merged = lodashMerge(asObject, defaultKeyStates); cache.merge(merged); From 42eab2ae16de9a4ae50516aaa2337016d8b8bb75 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 20:22:42 +0300 Subject: [PATCH 11/47] Update NativeFileHandler Use FileSystem from unimodules as that's how to use expo's file system on a bare RN project Ad helper methods to check file items --- lib/storage/providers/NativeFileHandler.js | 47 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 64e04f0ae..4a5affbec 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -4,20 +4,20 @@ * permission */ -import FileSystem from 'expo-file-system'; +import {FileSystem} from 'react-native-unimodules'; const LOCAL_PATH = `${FileSystem.documentDirectory}onyx_files/`; class NativeFileHandler { /** * Create a local copy of a file - * @param {{ uri: string, name: string, size: number }} file - * @returns {Promise<{uri: string, name: string, size: number}>} A reference to the file stored locally + * @param {{ uri: string, name: string }} file + * @returns {Promise<{uri: string, name: string}>} A reference to the file stored locally */ storeLocally(file) { // Todo: perhaps check size here and abort if the size is larger than 20MB - const destination = `${LOCAL_PATH}${file.name}`; + const destination = this.getLocalDestination(file); const copyTask = FileSystem .copyAsync({from: file.uri, to: destination}) @@ -52,8 +52,41 @@ class NativeFileHandler { deleteLocally(file) { return FileSystem.deleteAsync(file.uri || file, {idempotent: true}); } -} -const instance = new NativeFileHandler(); + /** + * Check if the object is a File + * @param {object} file + * @returns {boolean} + */ + isFile(file) { + if (!file) { + return false; + } + return Boolean( + file.uri + && file.name + && file.type + ); + } + + /** + * Check if a file is already saved locally + * @param {{ name: string, uri: string }} file + * @returns {boolean} + */ + isAvailableLocally(file) { + const dest = this.getLocalDestination(file); + return dest === file.uri; + } + + /** + * @private + * @param {{ name: string }} file + * @returns {string} + */ + getLocalDestination(file) { + return `${LOCAL_PATH}${file.name}`; + } +} -export default instance; +export default NativeFileHandler; From 355fa1975b8aea6c804d32493ab66f6d116e8627 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 20:23:06 +0300 Subject: [PATCH 12/47] Update Storage type definitions --- lib/storage/index.d.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts index 47d6e0462..0c7bfa75c 100644 --- a/lib/storage/index.d.ts +++ b/lib/storage/index.d.ts @@ -1,14 +1,12 @@ -interface ProviderInterface { +interface StorageProvider { getAllKeys(): Promise, - getItem(key: string): Promise, - multiGet(keys: string[]): Promise>, + getItem(key: string): Promise, + multiGet(keys: string[]): Promise>, removeItem(key: string): Promise, - setItem(key: string, value: string): Promise, - multiSet(pairs: Array<[string, string|null]>): Promise, - multiMerge(pairs: Array<[string, string|null]>): Promise, + setItem(key: string, value: T): Promise, + multiSet(pairs: Array<[string, T|null]>): Promise, + multiMerge(pairs: Array<[string, T|null]>): Promise, clear(): Promise, } -declare const Storage: ProviderInterface; - -export = Storage; +export = StorageProvider; From 661990ad4b066cc881a99802155a1a079ce9abf2 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 20:23:28 +0300 Subject: [PATCH 13/47] Remove fs.js - this is completely covered by localForage --- lib/storage/fs.js | 101 ---------------------------------------------- 1 file changed, 101 deletions(-) delete mode 100644 lib/storage/fs.js diff --git a/lib/storage/fs.js b/lib/storage/fs.js deleted file mode 100644 index fe82561f9..000000000 --- a/lib/storage/fs.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * The web and desktop FS handler - * On web we don't have access to the underlying file system so we use the - * Cache API to save Files - */ - -const CACHE_KEY = 'expensify_user_files'; -const LOCAL_PATH = `${global.location.origin}/${CACHE_KEY}/`; - -class WebFileHandler { - /** - * Create a local copy of a file - * @param {File} file - * @returns {Promise} - */ - storeLocally(file) { - // We can also make this work with Blobs eg `|| file instanceof Blob` - const isSupported = file instanceof File; - - if (!isSupported) { - // eslint-disable-next-line no-undef - if (__DEV__) { - throw new Error('Unsupported file param'); - } - - return Promise.resolve(file); - } - - return global.caches.open(CACHE_KEY) - .then((cache) => { - /** - * Only Response objects can be put into cache - * But we can take advantage of dealing with Request/Responses - * and respond from cache for the given destination - * */ - const localRef = this.getLocalRef(file); - const response = new Response(file); - cache.put(localRef, response); - - return file; - }); - } - - /** - * On Web (and Desktop) we cannot reference local file paths directly from cache - * we need to identify such entries and make them available again by reading - * the file from cache - * E.g. if the browser is closed and re-opened and `uri` created with `URL.createObjectURL` - * become invalid, but we can recreated them using the file from cache - * @param {{ name: string, type: string }} file - * @returns {Promise} Undefined will be returned if we don't have such file stored locally - */ - getFileFromCache(file) { - // When we've already got a File instance we don't need to retrieved again from cache - if (file instanceof File) { - Promise.resolve(file); - } - - return global.caches.open(CACHE_KEY) - .then((cache) => { - const localRef = this.getLocalRef(file); - return cache.match(localRef); - }) - .then(response => response && response.blob()) - .then(blob => blob && new File([blob], file.name, file.type)); - } - - /** - * A list of all the files we have locally - * @return {Promise} - */ - getLocalFileList() { - return global.caches.open(CACHE_KEY) - .then(cache => cache.keys()); - } - - /** - * Remove the file from cache - * @param {{ name: string }} file - * @return {Promise | PromiseLike} - */ - deleteLocally(file) { - return global.caches.open(CACHE_KEY) - .then((cache) => { - const localRef = this.getLocalRef(file); - return cache.delete(localRef); - }); - } - - /** - * @private - * @param {{ name: string }} file - * @return {string} - */ - getLocalRef(file) { - return `${LOCAL_PATH}${file.name}`; - } -} -const instance = new WebFileHandler(); - -export default instance; From 019ea8ca9c6e5a28ee42b6980c7321692b807c6c Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Fri, 27 Aug 2021 20:28:03 +0300 Subject: [PATCH 14/47] Update package with unimodules --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ac1fd5cbd..1885bd50d 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "babel-plugin-transform-class-properties": "^6.24.1", "eslint": "^7.6.0", "eslint-config-expensify": "^2.0.11", - "expo-file-system": "^11.1.3", "jest": "^26.5.2", "jest-cli": "^26.5.2", "localforage": "^1.10.0", @@ -47,10 +46,10 @@ }, "peerDependencies": { "@react-native-async-storage/async-storage": "^1.15.5", - "expo-file-system": "^11.1.3", "localforage": "^1.10.0", "react": "^17.0.2", - "react-native-performance": "^2.0.0" + "react-native-performance": "^2.0.0", + "react-native-unimodules": "^0.13.3" }, "peerDependenciesMeta": { "react-native-performance": { From ef48097c7b45a70f285d6f84c873de1632e36bbf Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 12:38:51 +0300 Subject: [PATCH 15/47] Update stringification --- lib/storage/providers/AsyncStorage.js | 36 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/storage/providers/AsyncStorage.js b/lib/storage/providers/AsyncStorage.js index 57dd1a414..294b8f992 100644 --- a/lib/storage/providers/AsyncStorage.js +++ b/lib/storage/providers/AsyncStorage.js @@ -3,17 +3,18 @@ * converting the value to a JSON string */ +import _ from 'underscore'; import AsyncStorage from '@react-native-async-storage/async-storage'; /** * @implements {StorageProvider} */ class AsyncStorageProvider { - async getAllKeys() { + getAllKeys() { return AsyncStorage.getAllKeys(); } - async getItem(key) { + getItem(key) { return AsyncStorage.getItem(key) .then((value) => { const parsed = value && JSON.parse(value); @@ -21,32 +22,45 @@ class AsyncStorageProvider { }); } - async multiGet(keys) { + multiGet(keys) { return AsyncStorage.multiGet(keys) .then(pairs => pairs.map(([key, value]) => [key, value && JSON.parse(value)])); } - async removeItem(key) { + removeItem(key) { return AsyncStorage.removeItem(key); } - async setItem(key, value) { - return AsyncStorage.setItem(key, value && JSON.stringify(value)); + setItem(key, value) { + return AsyncStorage.setItem(key, this.prepareValueForStorage((value))); } - async multiSet(pairs) { - const stringPairs = pairs.map(([key, value]) => [key, value && JSON.stringify(value)]); + multiSet(pairs) { + const stringPairs = pairs.map(([key, value]) => [key, this.prepareValueForStorage(value)]); return AsyncStorage.multiSet(stringPairs); } - async multiMerge(pairs) { - const stringPairs = pairs.map(([key, value]) => [key, value && JSON.stringify(value)]); + multiMerge(pairs) { + const stringPairs = pairs.map(([key, value]) => [key, this.prepareValueForStorage(value)]); return AsyncStorage.multiMerge(stringPairs); } - async clear() { + clear() { return AsyncStorage.clear(); } + + /** + * @private + * @param {*} value + * @returns {string|null} + */ + prepareValueForStorage(value) { + if (_.isUndefined(value) || _.isNull(value)) { + return value; + } + + return JSON.stringify(value); + } } export default AsyncStorageProvider; From 86d8ad9f607254d33ef53df2bdf9d22786ff2e99 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 14:27:25 +0300 Subject: [PATCH 16/47] NativeStorage implementation handling File items --- .../__mocks__/{index.native.js => index.js} | 0 lib/storage/index.js | 10 ++- lib/storage/index.native.js | 82 ++++++++++++++++++- lib/storage/providers/LocalForage.js | 6 +- 4 files changed, 90 insertions(+), 8 deletions(-) rename lib/storage/__mocks__/{index.native.js => index.js} (100%) diff --git a/lib/storage/__mocks__/index.native.js b/lib/storage/__mocks__/index.js similarity index 100% rename from lib/storage/__mocks__/index.native.js rename to lib/storage/__mocks__/index.js diff --git a/lib/storage/index.js b/lib/storage/index.js index 9c856a811..b5930b36a 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -1,3 +1,9 @@ -import Storage from '@react-native-async-storage/async-storage'; +/** + * On Web and Desktop it's enough to leave everything to localforage + */ -export default Storage; +import Storage from './providers/LocalForage'; + +const instance = new Storage(); + +export default instance; diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index 9c856a811..f6940dfdc 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -1,3 +1,81 @@ -import Storage from '@react-native-async-storage/async-storage'; +/** + * On native we can leave almost everything to AsyncStorage but should + * handle files. When we see that a file is saved we should move it to our "local space" (App Documents) + * so that it's not lost - image pickers and document pickers would move files to cache which + * can be cleared before we've uploaded them + */ -export default Storage; +import _ from 'underscore'; + +import lodashSet from 'lodash/set'; + +import BaseStorage from './providers/AsyncStorage'; +import FileHandler from './providers/NativeFileHandler'; + +/** + * We override the saving methods of storage handler and check for files, when the + * saved data contains a file we keep a copy in our "local space" + */ +class NativeStorage extends BaseStorage { + constructor() { + super(); + this.fs = new FileHandler(); + } + + setItem(key, value) { + return this.storeAnyFilesLocally(key, value) + .then(valueToWrite => super.setItem(key, valueToWrite)); + } + + /** + * @private + * Traverse an object and store any files locally + * We check object values and follow recursively for any files + * If we find files we first store them locally and then update values with the local path + * @param {string} key + * @param {object} obj + * @returns {Promise} the input object with file references updated and copied locally + */ + storeAnyFilesLocally(key, obj) { + const writeFileTasks = []; + const updates = {[key]: obj}; + + const recurse = (objPath, nextValue) => { + if (this.fs.isFile(nextValue)) { + // Only copy files that are not yet copied locally + if (!this.fs.isAvailableLocally(nextValue)) { + const task = this.fs.storeLocally(nextValue) + .then((savedFile) => { + lodashSet(updates, objPath, savedFile); + }); + + writeFileTasks.push(task); + } + } else if (_.isObject(nextValue)) { + // Otherwise check nested keys + Object.keys(nextValue) + .forEach(nestedKey => recurse([...objPath, nestedKey], nextValue[nestedKey])); + } + }; + + recurse([key], obj); + + if (writeFileTasks.length > 0) { + return Promise.all(writeFileTasks) + .then(() => { + // The object is changed when the top level key was a file + if (obj !== updates[key]) { + return updates[key]; + } + + return obj; + }); + } + + return Promise.resolve(obj); + } +} + +const instance = new NativeStorage(); + +export default instance; diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 362213216..7ae6d3fec 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -1,6 +1,6 @@ /** * @file - * The storage provider based on localforage allows us to store most anything in it's + * The storage provider based on localforage allows us to store most anything in its * natural form in the underlying DB without having to stringify or de-stringify it */ @@ -82,6 +82,4 @@ class Storage { } } -const instance = new Storage(); - -export default instance; +export default Storage; From 20dd1122691f53411889c1eaba1bf3daae817ec8 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 14:56:35 +0300 Subject: [PATCH 17/47] Simplify Native file save handling Instead of trying to guess and handle files leave this to happen explicitly by the library user --- lib/storage/index.d.ts | 1 + lib/storage/index.js | 17 +++++- lib/storage/index.native.js | 68 ++++------------------ lib/storage/providers/AsyncStorage.js | 3 - lib/storage/providers/LocalForage.js | 3 - lib/storage/providers/NativeFileHandler.js | 2 +- 6 files changed, 29 insertions(+), 65 deletions(-) diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts index 0c7bfa75c..9cf89d4eb 100644 --- a/lib/storage/index.d.ts +++ b/lib/storage/index.d.ts @@ -7,6 +7,7 @@ interface StorageProvider { multiSet(pairs: Array<[string, T|null]>): Promise, multiMerge(pairs: Array<[string, T|null]>): Promise, clear(): Promise, + storeFileLocally(file: any): Promise<{uri: string, type: string, name: string}|File> } export = StorageProvider; diff --git a/lib/storage/index.js b/lib/storage/index.js index b5930b36a..ff7678968 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -4,6 +4,21 @@ import Storage from './providers/LocalForage'; -const instance = new Storage(); +/** + * @implements {StorageProvider} + */ +class WebStorage extends Storage { + /** + * On web we just return the passed file + * We don't need to do anything as we can just save the File to LocalForage + * @param {File} file + * @returns {Promise} + */ + storeFileLocally(file) { + return Promise.resolve(file); + } +} + +const instance = new WebStorage(); export default instance; diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index f6940dfdc..36383e7e4 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -5,74 +5,28 @@ * can be cleared before we've uploaded them */ -import _ from 'underscore'; - -import lodashSet from 'lodash/set'; - -import BaseStorage from './providers/AsyncStorage'; +import Storage from './providers/AsyncStorage'; import FileHandler from './providers/NativeFileHandler'; /** - * We override the saving methods of storage handler and check for files, when the - * saved data contains a file we keep a copy in our "local space" + * @implements {StorageProvider} */ -class NativeStorage extends BaseStorage { +class NativeStorage extends Storage { constructor() { super(); this.fs = new FileHandler(); - } - - setItem(key, value) { - return this.storeAnyFilesLocally(key, value) - .then(valueToWrite => super.setItem(key, valueToWrite)); + this.storeFileLocally = this.storeFileLocally.bind(this); } /** - * @private - * Traverse an object and store any files locally - * We check object values and follow recursively for any files - * If we find files we first store them locally and then update values with the local path - * @param {string} key - * @param {object} obj - * @returns {Promise} the input object with file references updated and copied locally + * On native we copy the file locally and return a reference to the new file + * This allows us to stringify and save the reference in our regular storage + * e.g. as part of a persisted request or an optimistic report action + * @param {{ uri: string, name: string }} file + * @returns {Promise<{uri: string, name: string, type: string}>} */ - storeAnyFilesLocally(key, obj) { - const writeFileTasks = []; - const updates = {[key]: obj}; - - const recurse = (objPath, nextValue) => { - if (this.fs.isFile(nextValue)) { - // Only copy files that are not yet copied locally - if (!this.fs.isAvailableLocally(nextValue)) { - const task = this.fs.storeLocally(nextValue) - .then((savedFile) => { - lodashSet(updates, objPath, savedFile); - }); - - writeFileTasks.push(task); - } - } else if (_.isObject(nextValue)) { - // Otherwise check nested keys - Object.keys(nextValue) - .forEach(nestedKey => recurse([...objPath, nestedKey], nextValue[nestedKey])); - } - }; - - recurse([key], obj); - - if (writeFileTasks.length > 0) { - return Promise.all(writeFileTasks) - .then(() => { - // The object is changed when the top level key was a file - if (obj !== updates[key]) { - return updates[key]; - } - - return obj; - }); - } - - return Promise.resolve(obj); + storeFileLocally(file) { + return this.fs.storeLocally(file); } } diff --git a/lib/storage/providers/AsyncStorage.js b/lib/storage/providers/AsyncStorage.js index 294b8f992..302f9093b 100644 --- a/lib/storage/providers/AsyncStorage.js +++ b/lib/storage/providers/AsyncStorage.js @@ -6,9 +6,6 @@ import _ from 'underscore'; import AsyncStorage from '@react-native-async-storage/async-storage'; -/** - * @implements {StorageProvider} - */ class AsyncStorageProvider { getAllKeys() { return AsyncStorage.getAllKeys(); diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 7ae6d3fec..99116c4b4 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -8,9 +8,6 @@ import localforage from 'localforage'; import _ from 'underscore'; import lodashMerge from 'lodash/merge'; -/** - * @implements {StorageProvider} - */ class Storage { constructor() { /** @type {import('localforage').LocalForageDbMethods} */ diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 4a5affbec..685d8b0b3 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -12,7 +12,7 @@ class NativeFileHandler { /** * Create a local copy of a file * @param {{ uri: string, name: string }} file - * @returns {Promise<{uri: string, name: string}>} A reference to the file stored locally + * @returns {Promise<{uri: string, name: string, type: string}>} A reference to the file stored locally */ storeLocally(file) { // Todo: perhaps check size here and abort if the size is larger than 20MB From 44486848afdd85d3c17c562230d419e9b61d537b Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 15:20:55 +0300 Subject: [PATCH 18/47] Simplify providers, move away from class based implementations --- lib/storage/index.js | 13 ++--- lib/storage/index.native.js | 29 ++++------ lib/storage/providers/AsyncStorage.js | 63 +++++++++------------- lib/storage/providers/LocalForage.js | 55 +++++++------------ lib/storage/providers/NativeFileHandler.js | 38 ++++++------- 5 files changed, 79 insertions(+), 119 deletions(-) diff --git a/lib/storage/index.js b/lib/storage/index.js index ff7678968..f76bdfdb2 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -4,10 +4,9 @@ import Storage from './providers/LocalForage'; -/** - * @implements {StorageProvider} - */ -class WebStorage extends Storage { +const webStorage = { + ...Storage, + /** * On web we just return the passed file * We don't need to do anything as we can just save the File to LocalForage @@ -17,8 +16,6 @@ class WebStorage extends Storage { storeFileLocally(file) { return Promise.resolve(file); } -} - -const instance = new WebStorage(); +}; -export default instance; +export default webStorage; diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index 36383e7e4..38caa7c76 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -1,22 +1,17 @@ /** - * On native we can leave almost everything to AsyncStorage but should - * handle files. When we see that a file is saved we should move it to our "local space" (App Documents) - * so that it's not lost - image pickers and document pickers would move files to cache which - * can be cleared before we've uploaded them + * On native we can leave almost everything to AsyncStorage but files. + * Before files are saved in our key/value storage they should first be copied to + * our "local space" (App Documents) so that they're not lost - image pickers and document + * pickers would move files to cache which can be cleared before we've uploaded them + * + * We don't actually save the file to our key/value store but only the reference to it */ import Storage from './providers/AsyncStorage'; import FileHandler from './providers/NativeFileHandler'; -/** - * @implements {StorageProvider} - */ -class NativeStorage extends Storage { - constructor() { - super(); - this.fs = new FileHandler(); - this.storeFileLocally = this.storeFileLocally.bind(this); - } +const nativeStorage = { + ...Storage, /** * On native we copy the file locally and return a reference to the new file @@ -26,10 +21,8 @@ class NativeStorage extends Storage { * @returns {Promise<{uri: string, name: string, type: string}>} */ storeFileLocally(file) { - return this.fs.storeLocally(file); + return FileHandler.storeLocally(file); } -} - -const instance = new NativeStorage(); +}; -export default instance; +export default nativeStorage; diff --git a/lib/storage/providers/AsyncStorage.js b/lib/storage/providers/AsyncStorage.js index 302f9093b..6d8bfe94a 100644 --- a/lib/storage/providers/AsyncStorage.js +++ b/lib/storage/providers/AsyncStorage.js @@ -6,58 +6,47 @@ import _ from 'underscore'; import AsyncStorage from '@react-native-async-storage/async-storage'; -class AsyncStorageProvider { - getAllKeys() { - return AsyncStorage.getAllKeys(); +/** + * Values other than null and undefined should be stringified before + * they are saved in storage + * @param {*} value + * @returns {string|null} + */ +function prepareValueForStorage(value) { + if (_.isUndefined(value) || _.isNull(value)) { + return value; } + return JSON.stringify(value); +} + +const provider = { getItem(key) { return AsyncStorage.getItem(key) .then((value) => { const parsed = value && JSON.parse(value); return parsed; }); - } - + }, multiGet(keys) { return AsyncStorage.multiGet(keys) .then(pairs => pairs.map(([key, value]) => [key, value && JSON.parse(value)])); - } - - removeItem(key) { - return AsyncStorage.removeItem(key); - } - + }, setItem(key, value) { - return AsyncStorage.setItem(key, this.prepareValueForStorage((value))); - } - + return AsyncStorage.setItem(key, prepareValueForStorage(value)); + }, multiSet(pairs) { - const stringPairs = pairs.map(([key, value]) => [key, this.prepareValueForStorage(value)]); + const stringPairs = pairs.map(([key, value]) => [key, prepareValueForStorage(value)]); return AsyncStorage.multiSet(stringPairs); - } - + }, multiMerge(pairs) { - const stringPairs = pairs.map(([key, value]) => [key, this.prepareValueForStorage(value)]); + const stringPairs = pairs.map(([key, value]) => [key, prepareValueForStorage(value)]); return AsyncStorage.multiMerge(stringPairs); - } + }, - clear() { - return AsyncStorage.clear(); - } - - /** - * @private - * @param {*} value - * @returns {string|null} - */ - prepareValueForStorage(value) { - if (_.isUndefined(value) || _.isNull(value)) { - return value; - } - - return JSON.stringify(value); - } -} + getAllKeys: AsyncStorage.getAllKeys, + removeItem: AsyncStorage.removeItem, + clear: AsyncStorage.clear, +}; -export default AsyncStorageProvider; +export default provider; diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 99116c4b4..303532945 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -8,31 +8,16 @@ import localforage from 'localforage'; import _ from 'underscore'; import lodashMerge from 'lodash/merge'; -class Storage { - constructor() { - /** @type {import('localforage').LocalForageDbMethods} */ - this.store = localforage.createInstance({ - name: 'OnyxDb' - }); - } - - clear() { - return this.store.clear(); - } - - getAllKeys() { - return this.store.keys(); - } - - getItem(key) { - return this.store.getItem(key); - } +localforage.config({ + name: 'OnyxDb' +}); +const provider = { multiGet(keys) { const pairs = []; const remainingKeys = new Set(keys); - return this.store.iterate((value, key) => { + return localforage.iterate((value, key) => { if (remainingKeys.has(key)) { remainingKeys.delete(key); pairs.push([key, value]); @@ -46,10 +31,9 @@ class Storage { return undefined; }) .then(() => pairs); - } - + }, multiMerge(pairs) { - const tasks = pairs.map(([key, delta]) => this.getItem(key) + const tasks = pairs.map(([key, delta]) => localforage.getItem(key) .then((existing) => { let merged = delta; @@ -59,24 +43,21 @@ class Storage { } } - return this.setItem(key, merged); + return localforage.setItem(key, merged); })); return Promise.all(tasks).then(() => Promise.resolve()); - } - + }, multiSet(pairs) { - const tasks = pairs.map(([key, value]) => this.setItem(key, value)); + const tasks = pairs.map(([key, value]) => localforage.setItem(key, value)); return Promise.all(tasks).then(() => Promise.resolve()); - } - - removeItem(key) { - return this.store.removeItem(key); - } + }, - setItem(key, value) { - return this.store.setItem(key, value).then(() => Promise.resolve()); - } -} + clear: localforage.clear, + getAllKeys: localforage.keys, + getItem: localforage.getItem, + removeItem: localforage.removeItem, + setItem: localforage.setItem, +}; -export default Storage; +export default provider; diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 685d8b0b3..034791d15 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -8,7 +8,16 @@ import {FileSystem} from 'react-native-unimodules'; const LOCAL_PATH = `${FileSystem.documentDirectory}onyx_files/`; -class NativeFileHandler { +/** + * @private + * @param {{ name: string }} file + * @returns {string} + */ +function getLocalDestination(file) { + return `${LOCAL_PATH}${file.name}`; +} + +const fileHandler = { /** * Create a local copy of a file * @param {{ uri: string, name: string }} file @@ -17,7 +26,7 @@ class NativeFileHandler { storeLocally(file) { // Todo: perhaps check size here and abort if the size is larger than 20MB - const destination = this.getLocalDestination(file); + const destination = getLocalDestination(file); const copyTask = FileSystem .copyAsync({from: file.uri, to: destination}) @@ -30,7 +39,7 @@ class NativeFileHandler { // Because the requirements/logic will be the same for web return copyTask; - } + }, /** * A list of all the files we have locally @@ -42,7 +51,7 @@ class NativeFileHandler { .then(result => console.debug('getInfoAsync: ', result)); return FileSystem.readDirectoryAsync(LOCAL_PATH); - } + }, /** * Remove the file from the local FS @@ -51,7 +60,7 @@ class NativeFileHandler { */ deleteLocally(file) { return FileSystem.deleteAsync(file.uri || file, {idempotent: true}); - } + }, /** * Check if the object is a File @@ -67,7 +76,7 @@ class NativeFileHandler { && file.name && file.type ); - } + }, /** * Check if a file is already saved locally @@ -75,18 +84,9 @@ class NativeFileHandler { * @returns {boolean} */ isAvailableLocally(file) { - const dest = this.getLocalDestination(file); + const dest = getLocalDestination(file); return dest === file.uri; - } - - /** - * @private - * @param {{ name: string }} file - * @returns {string} - */ - getLocalDestination(file) { - return `${LOCAL_PATH}${file.name}`; - } -} + }, +}; -export default NativeFileHandler; +export default fileHandler; From c4441b531761141ebbb44e1dbced7a6a5c4f0c08 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 15:27:27 +0300 Subject: [PATCH 19/47] remove unused methods from FileHandler --- lib/storage/providers/NativeFileHandler.js | 26 ---------------------- 1 file changed, 26 deletions(-) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 034791d15..a2e1aefd0 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -61,32 +61,6 @@ const fileHandler = { deleteLocally(file) { return FileSystem.deleteAsync(file.uri || file, {idempotent: true}); }, - - /** - * Check if the object is a File - * @param {object} file - * @returns {boolean} - */ - isFile(file) { - if (!file) { - return false; - } - return Boolean( - file.uri - && file.name - && file.type - ); - }, - - /** - * Check if a file is already saved locally - * @param {{ name: string, uri: string }} file - * @returns {boolean} - */ - isAvailableLocally(file) { - const dest = getLocalDestination(file); - return dest === file.uri; - }, }; export default fileHandler; From 449d8021940d3781f02a0549f7522f2a28148cc8 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 15:46:03 +0300 Subject: [PATCH 20/47] rename "storeFileLocally" to "prepareFile" Add documentation and expose through Onyx --- lib/Onyx.js | 3 +++ lib/storage/index.d.ts | 17 ++++++++++++++++- lib/storage/index.js | 2 +- lib/storage/index.native.js | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 8622ce3b0..0d22d0c80 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -726,6 +726,8 @@ function init({ }); } +const prepareFile = Storage.prepareFile; + const Onyx = { connect, disconnect, @@ -739,6 +741,7 @@ const Onyx = { addToEvictionBlockList, removeFromEvictionBlockList, isSafeEvictionKey, + prepareFile, }; /** diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts index 9cf89d4eb..da9127e26 100644 --- a/lib/storage/index.d.ts +++ b/lib/storage/index.d.ts @@ -7,7 +7,22 @@ interface StorageProvider { multiSet(pairs: Array<[string, T|null]>): Promise, multiMerge(pairs: Array<[string, T|null]>): Promise, clear(): Promise, - storeFileLocally(file: any): Promise<{uri: string, type: string, name: string}|File> + + /** + * Prepares a file so that it can be saved in Onyx. + * Use this method to make a File reference. + * Then save it as usual by Onyx.set or Onyx.merge + * @example + * + * Onyx.prepareFile(someFile) + * .then(preparedFile => { + * Onyx.merge('someKey', { + * attachment: preparedFile, + * hasAttachment: true, + * }) + * }) + */ + prepareFile(file: any): Promise<{uri: string, type: string, name: string}|File> } export = StorageProvider; diff --git a/lib/storage/index.js b/lib/storage/index.js index f76bdfdb2..305d3bb68 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -13,7 +13,7 @@ const webStorage = { * @param {File} file * @returns {Promise} */ - storeFileLocally(file) { + prepareFile(file) { return Promise.resolve(file); } }; diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index 38caa7c76..5fd90d938 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -20,7 +20,7 @@ const nativeStorage = { * @param {{ uri: string, name: string }} file * @returns {Promise<{uri: string, name: string, type: string}>} */ - storeFileLocally(file) { + prepareFile(file) { return FileHandler.storeLocally(file); } }; From ec22e2c10913f988ab717768d7c6ea2229fc5e20 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 16:07:00 +0300 Subject: [PATCH 21/47] Update prepareFile so it can be called sync --- lib/Onyx.js | 12 ++++++++++++ lib/storage/index.d.ts | 17 +---------------- lib/storage/index.js | 5 +++-- lib/storage/index.native.js | 16 +++++++++++++--- lib/storage/providers/NativeFileHandler.js | 19 +++++-------------- 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 0d22d0c80..a709bd57d 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -726,6 +726,18 @@ function init({ }); } +/** + * Prepares a file so that it can be saved in Onyx. + * Use this method to make a File reference. + * Then save it as usual by Onyx.set or Onyx.merge + * + * @example + * const preparedFile = Onyx.prepareFile(someFile); + * Onyx.merge('someKey', { + * attachment: preparedFile, + * hasAttachment: true, + * }); + */ const prepareFile = Storage.prepareFile; const Onyx = { diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts index da9127e26..2c6e81103 100644 --- a/lib/storage/index.d.ts +++ b/lib/storage/index.d.ts @@ -7,22 +7,7 @@ interface StorageProvider { multiSet(pairs: Array<[string, T|null]>): Promise, multiMerge(pairs: Array<[string, T|null]>): Promise, clear(): Promise, - - /** - * Prepares a file so that it can be saved in Onyx. - * Use this method to make a File reference. - * Then save it as usual by Onyx.set or Onyx.merge - * @example - * - * Onyx.prepareFile(someFile) - * .then(preparedFile => { - * Onyx.merge('someKey', { - * attachment: preparedFile, - * hasAttachment: true, - * }) - * }) - */ - prepareFile(file: any): Promise<{uri: string, type: string, name: string}|File> + prepareFile(file: any): {uri: string, type: string, name: string}|File } export = StorageProvider; diff --git a/lib/storage/index.js b/lib/storage/index.js index 305d3bb68..67c41f74b 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -11,10 +11,11 @@ const webStorage = { * On web we just return the passed file * We don't need to do anything as we can just save the File to LocalForage * @param {File} file - * @returns {Promise} + * @returns {File} */ prepareFile(file) { - return Promise.resolve(file); + // Todo: we can add some size considerations here and abort if necessary + return file; } }; diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index 5fd90d938..c02df04de 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -17,11 +17,21 @@ const nativeStorage = { * On native we copy the file locally and return a reference to the new file * This allows us to stringify and save the reference in our regular storage * e.g. as part of a persisted request or an optimistic report action - * @param {{ uri: string, name: string }} file - * @returns {Promise<{uri: string, name: string, type: string}>} + * @param {{uri: string, name: string, type: string}} file + * @returns {{uri: string, name: string, type: string}} */ prepareFile(file) { - return FileHandler.storeLocally(file); + // Todo: perhaps check size here and abort if the size is larger than 20MB + + // Create result optimistically so the method can called as sync method + const uri = FileHandler.getLocalDestination(file); + const optimisticResult = {...file, uri}; + + // Todo: do something about the error, e.g. run eviction logic if it's due to lack of space + FileHandler.storeLocally(file) + .catch(console.error); + + return optimisticResult; } }; diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index a2e1aefd0..e314ec924 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -9,8 +9,7 @@ import {FileSystem} from 'react-native-unimodules'; const LOCAL_PATH = `${FileSystem.documentDirectory}onyx_files/`; /** - * @private - * @param {{ name: string }} file + * @param {{name: string}} file * @returns {string} */ function getLocalDestination(file) { @@ -20,25 +19,15 @@ function getLocalDestination(file) { const fileHandler = { /** * Create a local copy of a file - * @param {{ uri: string, name: string }} file + * @param {{uri: string, name: string}} file * @returns {Promise<{uri: string, name: string, type: string}>} A reference to the file stored locally */ storeLocally(file) { - // Todo: perhaps check size here and abort if the size is larger than 20MB - const destination = getLocalDestination(file); - const copyTask = FileSystem + return FileSystem .copyAsync({from: file.uri, to: destination}) .then(() => ({...file, uri: destination})); - - // Todo: do something about the error, e.g. run eviction logic if it's due to lack of space - copyTask.catch(console.error); - - // Todo: it might be best to move the checks mentioned here to the caller of the method - // Because the requirements/logic will be the same for web - - return copyTask; }, /** @@ -61,6 +50,8 @@ const fileHandler = { deleteLocally(file) { return FileSystem.deleteAsync(file.uri || file, {idempotent: true}); }, + + getLocalDestination, }; export default fileHandler; From 577091f2fea9f7033e51bc9e3ba3499599b19f5b Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Sat, 28 Aug 2021 16:46:13 +0300 Subject: [PATCH 22/47] Native Storage stats --- lib/storage/providers/NativeFileHandler.js | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index e314ec924..e5301c28c 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -31,15 +31,22 @@ const fileHandler = { }, /** - * A list of all the files we have locally - * @returns {Promise} + * Information about all the files we store locally + * @returns {Promise<{size: number, sizeMB: number, files: string[]}>} */ - getLocalFileList() { - // Todo: remove this - FileSystem.getInfoAsync(LOCAL_PATH, {size: true}) - .then(result => console.debug('getInfoAsync: ', result)); - - return FileSystem.readDirectoryAsync(LOCAL_PATH); + storageDirStats() { + return Promise.all([ + FileSystem.getInfoAsync(LOCAL_PATH, {size: true}), + FileSystem.readDirectoryAsync(LOCAL_PATH), + ]) + .then(([dirInfo, fileNames]) => ({ + ...dirInfo, + sizeMB: dirInfo.size * (1024 ** 2), + files: fileNames.map(name => ({ + name, + uri: getLocalDestination({name}), + })) + })); }, /** From dcce126f78d956d762db89baa05629b7ceb718e2 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 30 Aug 2021 11:12:59 +0300 Subject: [PATCH 23/47] Create folder for the local path iOS would not create the folder automatically on copy --- lib/storage/providers/NativeFileHandler.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index e5301c28c..6806a3b01 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -8,6 +8,14 @@ import {FileSystem} from 'react-native-unimodules'; const LOCAL_PATH = `${FileSystem.documentDirectory}onyx_files/`; +// Create our storage folder +FileSystem.getInfoAsync(LOCAL_PATH) + .then((info) => { + if (!info.exists) { + FileSystem.makeDirectoryAsync(LOCAL_PATH); + } + }); + /** * @param {{name: string}} file * @returns {string} From 2968c30ca60eb2865f3b286530b5c0075c41f026 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 30 Aug 2021 13:09:57 +0300 Subject: [PATCH 24/47] Feat: synchronize IndexDB updates across different tabs --- lib/Onyx.js | 17 ++++++--------- lib/storage/index.d.ts | 1 + lib/storage/index.js | 32 ++++++++++++++++++++++++++++ lib/storage/index.native.js | 5 +++++ lib/storage/providers/LocalForage.js | 6 +++--- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index a709bd57d..51d584c8e 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -269,7 +269,7 @@ function keysChanged(collectionKey, collection) { * When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks * * @param {string} key - * @param {mixed} data + * @param {any} data */ function keyChanged(key, data) { // Add or remove this key from the recentlyAccessedKeys lists @@ -677,21 +677,20 @@ function mergeCollection(collectionKey, collection) { * (individual or collection patterns) that when provided to Onyx are flagged * as "safe" for removal. Any components subscribing to these keys must also * implement a canEvict option. See the README for more info. - * @param {function} registerStorageEventListener a callback when a storage event happens. - * This applies to web platforms where the local storage emits storage events - * across all open tabs and allows Onyx to stay in sync across all open tabs. * @param {Number} [options.maxCachedKeysCount=55] Sets how many recent keys should we try to keep in cache * Setting this to 0 would practically mean no cache * We try to free cache when we connect to a safe eviction key * @param {Boolean} [options.captureMetrics] Enables Onyx benchmarking and exposes the get/print/reset functions + * @param {Boolean} [options.synchronizeInstances] Auto synchronize storage events between multiple instances of Onyx + * running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop) */ function init({ keys, initialKeyStates, safeEvictionKeys, - registerStorageEventListener, maxCachedKeysCount = 55, captureMetrics = false, + synchronizeInstances = Boolean(global.localStorage), }) { if (captureMetrics) { // The code here is only bundled and applied when the captureMetrics is set @@ -719,11 +718,9 @@ function init({ ]) .then(deferredInitTask.resolve); - // Update any key whose value changes in storage - registerStorageEventListener((key, newValue) => { - cache.set(key, newValue); - keyChanged(key, newValue); - }); + if (synchronizeInstances) { + Storage.synchronizeInstances({keyChanged}); + } } /** diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts index 2c6e81103..2e1cf6f17 100644 --- a/lib/storage/index.d.ts +++ b/lib/storage/index.d.ts @@ -8,6 +8,7 @@ interface StorageProvider { multiMerge(pairs: Array<[string, T|null]>): Promise, clear(): Promise, prepareFile(file: any): {uri: string, type: string, name: string}|File + synchronizeInstances(config: { keyChanged: (key: string, data: any) => void }): void } export = StorageProvider; diff --git a/lib/storage/index.js b/lib/storage/index.js index 67c41f74b..eb2574ff1 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -7,6 +7,38 @@ import Storage from './providers/LocalForage'; const webStorage = { ...Storage, + /** + * Storage synchronization mechanism keeping all opened tabs in sync + * @param {object} config + * @param {function(key: string, data: any)} config.keyChanged + */ + synchronizeInstances(config) { + const SYNC_ONYX = 'SYNC_ONYX'; + + // Override `setItem` to raise storage events that we can intercept in other tabs + this.setItem = (key, value) => Storage.setItem(key, value) + .then(() => { + /** We make a temp write to storage just to raise the storage event (below) + * then remove the "dummy" value. + * Listeners would receive everything they need to read the new value from the DB */ + global.localStorage.setItem(SYNC_ONYX, key); + global.localStorage.removeItem(SYNC_ONYX); + }); + + // This event will be triggered on tabs other than the current tab + global.addEventListener('storage', (event) => { + if (!event.newValue) { + return; + } + + // Notify any listeners in case an Onyx key did change + if (event.key === SYNC_ONYX) { + Storage.getItem(event.newValue) + .then(value => config.keyChanged(event.newValue, value)); + } + }); + }, + /** * On web we just return the passed file * We don't need to do anything as we can just save the File to LocalForage diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index c02df04de..6afba3fdf 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -13,6 +13,11 @@ import FileHandler from './providers/NativeFileHandler'; const nativeStorage = { ...Storage, + /** + * On native it's a no-op because it's not possible to have multiple instances of Onyx (e.g. multiple tabs) + */ + synchronizeInstances() {}, + /** * On native we copy the file locally and return a reference to the new file * This allows us to stringify and save the reference in our regular storage diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 303532945..83f38c719 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -33,7 +33,7 @@ const provider = { .then(() => pairs); }, multiMerge(pairs) { - const tasks = pairs.map(([key, delta]) => localforage.getItem(key) + const tasks = pairs.map(([key, delta]) => this.getItem(key) .then((existing) => { let merged = delta; @@ -43,13 +43,13 @@ const provider = { } } - return localforage.setItem(key, merged); + return this.setItem(key, merged); })); return Promise.all(tasks).then(() => Promise.resolve()); }, multiSet(pairs) { - const tasks = pairs.map(([key, value]) => localforage.setItem(key, value)); + const tasks = pairs.map(([key, value]) => this.setItem(key, value)); return Promise.all(tasks).then(() => Promise.resolve()); }, From 0bffc81c8845269dedd14b06330255901825f982 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 30 Aug 2021 15:56:15 +0300 Subject: [PATCH 25/47] Update tests after changes --- .../async-storage.js | 1 + lib/storage/__mocks__/index.js | 3 - package-lock.json | 3300 ++++++++++++++++- package.json | 6 +- tests/setupAfterEnv.js | 1 - tests/unit/cacheEvictionTest.js | 2 +- tests/unit/onyxCacheTest.js | 40 +- 7 files changed, 3206 insertions(+), 147 deletions(-) create mode 100644 __mocks__/@react-native-async-storage/async-storage.js delete mode 100644 lib/storage/__mocks__/index.js delete mode 100644 tests/setupAfterEnv.js diff --git a/__mocks__/@react-native-async-storage/async-storage.js b/__mocks__/@react-native-async-storage/async-storage.js new file mode 100644 index 000000000..1051fa919 --- /dev/null +++ b/__mocks__/@react-native-async-storage/async-storage.js @@ -0,0 +1 @@ +export {default} from '@react-native-async-storage/async-storage/jest/async-storage-mock'; diff --git a/lib/storage/__mocks__/index.js b/lib/storage/__mocks__/index.js deleted file mode 100644 index 53221653a..000000000 --- a/lib/storage/__mocks__/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import * as Storage from '@react-native-async-storage/async-storage/jest/async-storage-mock'; - -export default Storage; diff --git a/package-lock.json b/package-lock.json index 271e4d30e..4cc2d3a94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1620,6 +1620,1745 @@ "strip-json-comments": "^3.1.1" } }, + "@expo/config": { + "version": "3.3.43", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-3.3.43.tgz", + "integrity": "sha512-5a78fQqTKk7RhgrW5XzHS8ylCo9YRjZrheLyVDNNfvwAD8YjeBz6bFWsItZPpAIoaDgkLh0a8uhc11DCmqoKpw==", + "dev": true, + "requires": { + "@babel/core": "7.9.0", + "@babel/plugin-proposal-class-properties": "~7.12.13", + "@babel/preset-env": "~7.12.13", + "@babel/preset-typescript": "~7.12.13", + "@expo/config-plugins": "1.0.33", + "@expo/config-types": "^40.0.0-beta.2", + "@expo/json-file": "8.2.30", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "slugify": "^1.3.4" + }, + "dependencies": { + "@babel/compat-data": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "dev": true + }, + "@babel/core": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", + "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", + "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.15.0", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", + "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.15.0", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", + "@babel/helper-split-export-declaration": "^7.14.5" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", + "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "regexpu-core": "^4.7.1" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", + "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/parser": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "dev": true + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-get-function-arity": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", + "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", + "dev": true, + "requires": { + "@babel/types": "^7.15.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-module-imports": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-plugin-utils": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", + "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-wrap-function": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-replace-supers": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", + "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.15.0", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/generator": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "dev": true, + "requires": { + "@babel/types": "^7.15.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "dev": true + }, + "@babel/traverse": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.0", + "@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.15.0", + "@babel/types": "^7.15.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-simple-access": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", + "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", + "dev": true, + "requires": { + "@babel/types": "^7.14.8" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", + "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", + "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/generator": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "dev": true, + "requires": { + "@babel/types": "^7.15.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "dev": true + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/traverse": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.0", + "@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.15.0", + "@babel/types": "^7.15.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", + "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.13.tgz", + "integrity": "sha512-8SCJ0Ddrpwv4T7Gwb33EmW1V9PY5lggTO+A8WjyIwxrSHDUyBw4MtF96ifn1n8H806YlxbVCoKXbbmzD6RD+cA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", + "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", + "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", + "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", + "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", + "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", + "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "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==", + "dev": true, + "requires": { + "@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", + "@babel/plugin-transform-parameters": "^7.14.5" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", + "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", + "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", + "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", + "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", + "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", + "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", + "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", + "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", + "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", + "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-destructuring": { + "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==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", + "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", + "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", + "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", + "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", + "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", + "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", + "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", + "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/generator": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "dev": true, + "requires": { + "@babel/types": "^7.15.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", + "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", + "@babel/helper-simple-access": "^7.14.8", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.9", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" + } + }, + "@babel/parser": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "dev": true + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/traverse": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.0", + "@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.15.0", + "@babel/types": "^7.15.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", + "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.15.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-simple-access": "^7.14.8", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/generator": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "dev": true, + "requires": { + "@babel/types": "^7.15.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", + "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", + "@babel/helper-simple-access": "^7.14.8", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.9", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" + } + }, + "@babel/parser": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "dev": true + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/traverse": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.0", + "@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.15.0", + "@babel/types": "^7.15.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", + "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/generator": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "dev": true, + "requires": { + "@babel/types": "^7.15.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", + "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", + "@babel/helper-simple-access": "^7.14.8", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.9", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" + } + }, + "@babel/parser": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "dev": true + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/traverse": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.0", + "@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.15.0", + "@babel/types": "^7.15.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", + "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/generator": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "dev": true, + "requires": { + "@babel/types": "^7.15.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", + "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", + "@babel/helper-simple-access": "^7.14.8", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.9", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" + } + }, + "@babel/parser": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "dev": true + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/traverse": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.0", + "@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.15.0", + "@babel/types": "^7.15.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", + "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", + "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", + "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", + "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", + "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", + "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", + "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", + "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", + "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", + "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", + "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", + "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz", + "integrity": "sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.15.0", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-typescript": "^7.14.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", + "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", + "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/preset-env": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.17.tgz", + "integrity": "sha512-9PMijx8zFbCwTHrd2P4PJR5nWGH3zWebx2OcpTjqQrHhCiL2ssSR2Sc9ko2BsI2VmVBfoaQmPrlMTCui4LmXQg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.13", + "@babel/helper-compilation-targets": "^7.12.17", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-validator-option": "^7.12.17", + "@babel/plugin-proposal-async-generator-functions": "^7.12.13", + "@babel/plugin-proposal-class-properties": "^7.12.13", + "@babel/plugin-proposal-dynamic-import": "^7.12.17", + "@babel/plugin-proposal-export-namespace-from": "^7.12.13", + "@babel/plugin-proposal-json-strings": "^7.12.13", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.13", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.13", + "@babel/plugin-proposal-numeric-separator": "^7.12.13", + "@babel/plugin-proposal-object-rest-spread": "^7.12.13", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.13", + "@babel/plugin-proposal-optional-chaining": "^7.12.17", + "@babel/plugin-proposal-private-methods": "^7.12.13", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.13", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.13", + "@babel/plugin-transform-arrow-functions": "^7.12.13", + "@babel/plugin-transform-async-to-generator": "^7.12.13", + "@babel/plugin-transform-block-scoped-functions": "^7.12.13", + "@babel/plugin-transform-block-scoping": "^7.12.13", + "@babel/plugin-transform-classes": "^7.12.13", + "@babel/plugin-transform-computed-properties": "^7.12.13", + "@babel/plugin-transform-destructuring": "^7.12.13", + "@babel/plugin-transform-dotall-regex": "^7.12.13", + "@babel/plugin-transform-duplicate-keys": "^7.12.13", + "@babel/plugin-transform-exponentiation-operator": "^7.12.13", + "@babel/plugin-transform-for-of": "^7.12.13", + "@babel/plugin-transform-function-name": "^7.12.13", + "@babel/plugin-transform-literals": "^7.12.13", + "@babel/plugin-transform-member-expression-literals": "^7.12.13", + "@babel/plugin-transform-modules-amd": "^7.12.13", + "@babel/plugin-transform-modules-commonjs": "^7.12.13", + "@babel/plugin-transform-modules-systemjs": "^7.12.13", + "@babel/plugin-transform-modules-umd": "^7.12.13", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13", + "@babel/plugin-transform-new-target": "^7.12.13", + "@babel/plugin-transform-object-super": "^7.12.13", + "@babel/plugin-transform-parameters": "^7.12.13", + "@babel/plugin-transform-property-literals": "^7.12.13", + "@babel/plugin-transform-regenerator": "^7.12.13", + "@babel/plugin-transform-reserved-words": "^7.12.13", + "@babel/plugin-transform-shorthand-properties": "^7.12.13", + "@babel/plugin-transform-spread": "^7.12.13", + "@babel/plugin-transform-sticky-regex": "^7.12.13", + "@babel/plugin-transform-template-literals": "^7.12.13", + "@babel/plugin-transform-typeof-symbol": "^7.12.13", + "@babel/plugin-transform-unicode-escapes": "^7.12.13", + "@babel/plugin-transform-unicode-regex": "^7.12.13", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.17", + "core-js-compat": "^3.8.0", + "semver": "^5.5.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@babel/preset-typescript": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.17.tgz", + "integrity": "sha512-T513uT4VSThRcmWeqcLkITKJ1oGQho9wfWuhQm10paClQkp1qyd0Wf8mvC8Se7UYssMyRSj4tZYpVTkCmAK/mA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-validator-option": "^7.12.17", + "@babel/plugin-transform-typescript": "^7.12.17" + } + }, + "@expo/config-plugins": { + "version": "1.0.33", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-1.0.33.tgz", + "integrity": "sha512-YQJop0c69LKD/6ZJJto7klS7TDmzgs44TI0Z5RBqesOjYlDwNFcQk2Rl2BaA1wlAYkH+rRrhN2+WjjSyD9HiPg==", + "dev": true, + "requires": { + "@expo/config-types": "^40.0.0-beta.2", + "@expo/configure-splash-screen": "0.4.0", + "@expo/image-utils": "0.3.14", + "@expo/json-file": "8.2.30", + "@expo/plist": "0.0.13", + "find-up": "~5.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "^0.4.23" + } + }, + "@expo/config-types": { + "version": "40.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-40.0.0-beta.2.tgz", + "integrity": "sha512-t9pHCQMXOP4nwd7LGXuHkLlFy0JdfknRSCAeVF4Kw2/y+5OBbR9hW9ZVnetpBf0kORrekgiI7K/qDaa3hh5+Qg==", + "dev": true + }, + "@expo/json-file": { + "version": "8.2.30", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.30.tgz", + "integrity": "sha512-vrgGyPEXBoFI5NY70IegusCSoSVIFV3T3ry4tjJg1MFQKTUlR7E0r+8g8XR6qC705rc2PawaZQjqXMAVtV6s2A==", + "dev": true, + "requires": { + "@babel/code-frame": "~7.10.4", + "fs-extra": "9.0.0", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "@expo/plist": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.13.tgz", + "integrity": "sha512-zGPSq9OrCn7lWvwLLHLpHUUq2E40KptUFXn53xyZXPViI0k9lbApcR9KlonQZ95C+ELsf0BQ3gRficwK92Ivcw==", + "dev": true, + "requires": { + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0", + "xmldom": "~0.5.0" + } + }, + "browserslist": { + "version": "4.16.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", + "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001251", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.811", + "escalade": "^3.1.1", + "node-releases": "^1.1.75" + } + }, + "caniuse-lite": { + "version": "1.0.30001252", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz", + "integrity": "sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "colorette": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.822", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.822.tgz", + "integrity": "sha512-k7jG5oYYHxF4jx6PcqwHX3JVME/OjzolqOZiIogi9xtsfsmTjTdie4x88OakYFPEa8euciTgCCzvVNwvmjHb1Q==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "node-releases": { + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "dev": true, + "requires": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + } + }, + "xmlbuilder": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", + "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", + "dev": true + } + } + }, "@expo/config-plugins": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-3.1.0.tgz", @@ -1818,6 +3557,143 @@ "integrity": "sha512-Rj02OMZke2MrGa/1Y/EScmR7VuWbDEHPJyvfFyyLbadUt+Yv6isCdeFzDt71I7gJlPR9T4fzixeYLrtXXOTq0w==", "dev": true }, + "@expo/configure-splash-screen": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@expo/configure-splash-screen/-/configure-splash-screen-0.4.0.tgz", + "integrity": "sha512-IDPnr2/DW1tYpDHqedFYNCDzRTf9HYinWFQ7fOelNZLuOCMoErLbSStA5zfkv46o69AgcCpteqgKHSoxsIBz5g==", + "dev": true, + "requires": { + "color-string": "^1.5.3", + "commander": "^5.1.0", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "lodash": "^4.17.15", + "pngjs": "^5.0.0", + "xcode": "^3.0.0", + "xml-js": "^1.6.11" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "dev": true + }, + "xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "dev": true, + "requires": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + } + } + } + }, + "@expo/image-utils": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.3.14.tgz", + "integrity": "sha512-n+JkLZ71CWuNKLVVsPTzMGRwmbeKiVQw/2b99Ro7znCKzJy3tyE5T2C6WBvYh/5h/hjg8TqEODjXXWucRIzMXA==", + "dev": true, + "requires": { + "@expo/spawn-async": "1.5.0", + "chalk": "^4.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "jimp": "0.12.1", + "mime": "^2.4.4", + "node-fetch": "^2.6.0", + "parse-png": "^2.1.0", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "tempy": "0.3.0" + }, + "dependencies": { + "fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true + } + } + }, "@expo/json-file": { "version": "8.2.33", "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.33.tgz", @@ -1844,32 +3720,92 @@ "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "@expo/plist": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.14.tgz", + "integrity": "sha512-bb4Ua1M/OdNgS8KiGdSDUjZ/bbPfv3xdPY/lz8Ctp/adlj/QgB8xA7tVPeqSSfJPZqFRwU0qLCnRhpUOnP51VQ==", + "dev": true, + "requires": { + "@xmldom/xmldom": "~0.7.0", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", + "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", + "dev": true + } + } + }, + "@expo/spawn-async": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.5.0.tgz", + "integrity": "sha512-LB7jWkqrHo+5fJHNrLAFdimuSXQ2MQ4lA7SQW5bf/HbsXuV2VrT/jN/M8f/KoWt0uJMGN4k/j7Opx4AvOOxSew==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.5" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } } } }, - "@expo/plist": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.14.tgz", - "integrity": "sha512-bb4Ua1M/OdNgS8KiGdSDUjZ/bbPfv3xdPY/lz8Ctp/adlj/QgB8xA7tVPeqSSfJPZqFRwU0qLCnRhpUOnP51VQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "~0.7.0", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - }, - "dependencies": { - "xmlbuilder": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", - "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", - "dev": true - } - } - }, "@hapi/hoek": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", @@ -2466,6 +4402,365 @@ "@types/yargs": "^13.0.0" } }, + "@jimp/bmp": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.12.1.tgz", + "integrity": "sha512-t16IamuBMv4GiGa1VAMzsgrVKVANxXG81wXECzbikOUkUv7pKJ2vHZDgkLBEsZQ9sAvFCneM1+yoSRpuENrfVQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1", + "bmp-js": "^0.1.0" + } + }, + "@jimp/core": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.12.1.tgz", + "integrity": "sha512-mWfjExYEjHxBal+1gPesGChOQBSpxO7WUQkrO9KM7orboitOdQ15G5UA75ce7XVZ+5t+FQPOLmVkVZzzTQSEJA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/custom": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.12.1.tgz", + "integrity": "sha512-bVClp8FEJ/11GFTKeRTrfH7NgUWvVO5/tQzO/68aOwMIhbz9BOYQGh533K9+mSy29VjZJo8jxZ0C9ZwYHuFwfA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.12.1" + } + }, + "@jimp/gif": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.12.1.tgz", + "integrity": "sha512-cGn/AcvMGUGcqR6ByClGSnrja4AYmTwsGVXTQ1+EmfAdTiy6ztGgZCTDpZ/tq4SpdHXwm9wDHez7damKhTrH0g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1", + "omggif": "^1.0.9" + } + }, + "@jimp/jpeg": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.12.1.tgz", + "integrity": "sha512-UoCUHbKLj2CDCETd7LrJnmK/ExDsSfJXmc1pKkfgomvepjXogdl2KTHf141wL6D+9CfSD2VBWQLC5TvjMvcr9A==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1", + "jpeg-js": "^0.4.0" + } + }, + "@jimp/plugin-blit": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.12.1.tgz", + "integrity": "sha512-VRBB6bx6EpQuaH0WX8ytlGNqUQcmuxXBbzL3e+cD0W6MluYibzQy089okvXcyUS72Q+qpSMmUDCVr3pDqLAsSA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-blur": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.12.1.tgz", + "integrity": "sha512-rTFY0yrwVJFNgNsAlYGn2GYCRLVEcPQ6cqAuhNylXuR/7oH3Acul+ZWafeKtvN8D8uMlth/6VP74gruXvwffZw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-circle": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.12.1.tgz", + "integrity": "sha512-+/OiBDjby7RBbQoDX8ZsqJRr1PaGPdTaaKUVGAsrE7KCNO9ODYNFAizB9lpidXkGgJ4Wx5R4mJy21i22oY/a4Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-color": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.12.1.tgz", + "integrity": "sha512-xlnK/msWN4uZ+Bu7+UrCs9oMzTSA9QE0jWFnF3h0aBsD8t1LGxozkckHe8nHtC/y/sxIa8BGKSfkiaW+r6FbnA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/plugin-contain": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.12.1.tgz", + "integrity": "sha512-WZ/D6G0jhnBh2bkBh610PEh/caGhAUIAxYLsQsfSSlOxPsDhbj3S6hMbFKRgnDvf0hsd5zTIA0j1B0UG4kh18A==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-cover": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.12.1.tgz", + "integrity": "sha512-ddWwTQO40GcabJ2UwUYCeuNxnjV4rBTiLprnjGMqAJCzdz3q3Sp20FkRf+H+E22k2v2LHss8dIOFOF4i6ycr9Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-crop": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.12.1.tgz", + "integrity": "sha512-CKjVkrNO8FDZKYVpMireQW4SgKBSOdF+Ip/1sWssHHe77+jGEKqOjhYju+VhT3dZJ3+75rJNI9II7Kethp+rTw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-displace": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.12.1.tgz", + "integrity": "sha512-MQAw2iuf1/bVJ6P95WWTLA+WBjvIZ7TeGBerkvBaTK8oWdj+NSLNRIYOIoyPbZ7DTL8f1SN4Vd6KD6BZaoWrwg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-dither": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.12.1.tgz", + "integrity": "sha512-mCrBHdx2ViTLJDLcrobqGLlGhZF/Mq41bURWlElQ2ArvrQ3/xR52We9DNDfC08oQ2JVb6q3v1GnCCdn0KNojGQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-fisheye": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.12.1.tgz", + "integrity": "sha512-CHvYSXtHNplzkkYzB44tENPDmvfUHiYCnAETTY+Hx58kZ0w8ERZ+OiLhUmiBcvH/QHm/US1iiNjgGUAfeQX6dg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-flip": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.12.1.tgz", + "integrity": "sha512-xi+Yayrnln8A/C9E3yQBExjxwBSeCkt/ZQg1CxLgszVyX/3Zo8+nkV8MJYpkTpj8LCZGTOKlsE05mxu/a3lbJQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-gaussian": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.12.1.tgz", + "integrity": "sha512-7O6eKlhL37hsLfV6WAX1Cvce7vOqSwL1oWbBveC1agutDlrtvcTh1s2mQ4Pde654hCJu55mq1Ur10+ote5j3qw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-invert": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.12.1.tgz", + "integrity": "sha512-JTAs7A1Erbxwl+7ph7tgcb2PZ4WzB+3nb2WbfiWU8iCrKj17mMDSc5soaCCycn8wfwqvgB1vhRfGpseOLWxsuQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-mask": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.12.1.tgz", + "integrity": "sha512-bnDdY0RO/x5Mhqoy+056SN1wEj++sD4muAKqLD2CIT8Zq5M/0TA4hkdf/+lwFy3H2C0YTK39PSE9xyb4jPX3kA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-normalize": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.12.1.tgz", + "integrity": "sha512-4kSaI4JLM/PNjHwbnAHgyh51V5IlPfPxYvsZyZ1US32pebWtocxSMaSuOaJUg7OGSkwSDBv81UR2h5D+Dz1b5A==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-print": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.12.1.tgz", + "integrity": "sha512-T0lNS3qU9SwCHOEz7AGrdp50+gqiWGZibOL3350/X/dqoFs1EvGDjKVeWncsGCyLlpfd7M/AibHZgu8Fx2bWng==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1", + "load-bmfont": "^1.4.0" + } + }, + "@jimp/plugin-resize": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.12.1.tgz", + "integrity": "sha512-sbNn4tdBGcgGlPt9XFxCuDl4ZOoxa8/Re8nAikyxYhRss2Dqz91ARbBQxOf1vlUGeicQMsjEuWbPQAogTSJRug==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-rotate": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.12.1.tgz", + "integrity": "sha512-RYkLzwG2ervG6hHy8iepbIVeWdT1kz4Qz044eloqo6c66MK0KAqp228YI8+CAKm0joQnVDC/A0FgRIj/K8uyAw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-scale": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.12.1.tgz", + "integrity": "sha512-zjNVI1fUj+ywfG78T1ZU33g9a5sk4rhEQkkhtny8koAscnVsDN2YaZEKoFli54kqaWh5kSS5DDL7a/9pEfXnFQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-shadow": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.12.1.tgz", + "integrity": "sha512-Z82IwvunXWQ2jXegd3W3TYUXpfJcEvNbHodr7Z+oVnwhM1OoQ5QC6RSRQwsj2qXIhbGffQjH8eguHgEgAV+u5w==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugin-threshold": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.12.1.tgz", + "integrity": "sha512-PFezt5fSk0q+xKvdpuv0eLggy2I7EgYotrK8TRZOT0jimuYFXPF0Z514c6szumoW5kEsRz04L1HkPT1FqI97Yg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1" + } + }, + "@jimp/plugins": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.12.1.tgz", + "integrity": "sha512-7+Yp29T6BbYo+Oqnc+m7A5AH+O+Oy5xnxvxlfmsp48+SuwEZ4akJp13Gu2PSmRlylENzR7MlWOxzhas5ERNlIg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/plugin-blit": "^0.12.1", + "@jimp/plugin-blur": "^0.12.1", + "@jimp/plugin-circle": "^0.12.1", + "@jimp/plugin-color": "^0.12.1", + "@jimp/plugin-contain": "^0.12.1", + "@jimp/plugin-cover": "^0.12.1", + "@jimp/plugin-crop": "^0.12.1", + "@jimp/plugin-displace": "^0.12.1", + "@jimp/plugin-dither": "^0.12.1", + "@jimp/plugin-fisheye": "^0.12.1", + "@jimp/plugin-flip": "^0.12.1", + "@jimp/plugin-gaussian": "^0.12.1", + "@jimp/plugin-invert": "^0.12.1", + "@jimp/plugin-mask": "^0.12.1", + "@jimp/plugin-normalize": "^0.12.1", + "@jimp/plugin-print": "^0.12.1", + "@jimp/plugin-resize": "^0.12.1", + "@jimp/plugin-rotate": "^0.12.1", + "@jimp/plugin-scale": "^0.12.1", + "@jimp/plugin-shadow": "^0.12.1", + "@jimp/plugin-threshold": "^0.12.1", + "timm": "^1.6.1" + } + }, + "@jimp/png": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.12.1.tgz", + "integrity": "sha512-tOUSJMJzcMAN82F9/Q20IToquIVWzvOe/7NIpVQJn6m+Lq6TtVmd7d8gdcna9AEFm2FIza5lhq2Kta6Xj0KXhQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.12.1", + "pngjs": "^3.3.3" + }, + "dependencies": { + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "dev": true + } + } + }, + "@jimp/tiff": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.12.1.tgz", + "integrity": "sha512-bzWDgv3202TKhaBGzV9OFF0PVQWEb4194h9kv5js348SSnbCusz/tzTE1EwKrnbDZThZPgTB1ryKs7D+Q9Mhmg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" + } + }, + "@jimp/types": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.12.1.tgz", + "integrity": "sha512-hg5OKXpWWeKGuDrfibrjWWhr7hqb7f552wqnPWSLQpVrdWgjH+hpOv6cOzdo9bsU78qGTelZJPxr0ERRoc+MhQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.12.1", + "@jimp/gif": "^0.12.1", + "@jimp/jpeg": "^0.12.1", + "@jimp/png": "^0.12.1", + "@jimp/tiff": "^0.12.1", + "timm": "^1.6.1" + } + }, + "@jimp/utils": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.12.1.tgz", + "integrity": "sha512-EjPkDQOzV/oZfbolEUgFT6SE++PtCccVBvjuACkttyCfl0P2jnpR49SwstyVLc2u8AwBAZEHHAw9lPYaMjtbXQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" + } + }, "@react-native-async-storage/async-storage": { "version": "1.15.5", "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.15.5.tgz", @@ -3303,10 +5598,28 @@ } } }, + "@unimodules/core": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.1.1.tgz", + "integrity": "sha512-Sa7X+WkrhZzcckavjuQu4mq6BTPWsio7OITfoNNzjL0CEmfHfo3DNWQWoVyj+wCgMnjGUT1l3+q3AQlI+CaCLA==", + "dev": true, + "requires": { + "compare-versions": "^3.4.0" + } + }, + "@unimodules/react-native-adapter": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@unimodules/react-native-adapter/-/react-native-adapter-6.2.2.tgz", + "integrity": "sha512-hBXL+IX3u+4TcAHu9lIItdycA7pYWZn3Tt7s5TTna9QKHjyrwo0zVss27LkpJ40tXRHyh/GJ8VzN2CD+0M5I2A==", + "dev": true, + "requires": { + "invariant": "^2.2.4" + } + }, "@xmldom/xmldom": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.2.tgz", - "integrity": "sha512-t/Zqo0ewes3iq6zGqEqJNUWI27Acr3jkmSUNp6E3nl0Z2XbtqAG5XYqPNLdYonILmhcxANsIidh69tHzjXtuRg==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.3.tgz", + "integrity": "sha512-8XmJdPut2XGtfFcsNsqEsvMUmAwk7xLq7m+E/GcsU9b5qyFFIsiX4Fvnb5UoQ4wo12Wlm07YFJERoyWUYdbIpw==", "dev": true }, "abab": { @@ -3452,6 +5765,12 @@ "color-convert": "^1.9.0" } }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", + "dev": true + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -4185,6 +6504,18 @@ "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", "dev": true }, + "blueimp-md5": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz", + "integrity": "sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q==", + "dev": true + }, + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=", + "dev": true + }, "bplist-creator": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", @@ -4250,6 +6581,44 @@ "node-int64": "^0.4.0" } }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4572,6 +6941,16 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "color-string": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", + "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "colorette": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", @@ -4611,6 +6990,12 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -4801,6 +7186,12 @@ "which": "^2.0.1" } }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -5013,6 +7404,12 @@ "esutils": "^2.0.2" } }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, "domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", @@ -5913,6 +8310,12 @@ } } }, + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=", + "dev": true + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -6149,6 +8552,37 @@ } } }, + "expo-asset": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-8.3.3.tgz", + "integrity": "sha512-qCm5d14tzswY8DcmRJ+0WkY9tc3OiVikBAiw2hCMC+bFpK/bEdqy4Zwfd69MFIAJ0taJpHWhdUoBRO0byQLlfg==", + "dev": true, + "requires": { + "blueimp-md5": "^2.10.0", + "invariant": "^2.2.4", + "md5-file": "^3.2.3", + "path-browserify": "^1.0.0", + "url-parse": "^1.4.4" + } + }, + "expo-constants": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-10.1.3.tgz", + "integrity": "sha512-Eq/xeshnhSoe4ok89d5lrHvI9jq3bMe1FhJUbiHVGcGmW8mGCotwbQBIfDkkMrAKnSOwQq/Qfyg0XBxnG2XFjw==", + "dev": true, + "requires": { + "@expo/config": "^3.3.35", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, "expo-file-system": { "version": "11.1.3", "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-11.1.3.tgz", @@ -6168,12 +8602,24 @@ } } }, + "expo-image-loader": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-2.1.1.tgz", + "integrity": "sha512-EeItNIsmw4g+FIb9S9AHE7FAWQkuiIguFMua/RQ2mFHKFZYa/BU32MGagY+e4LzasBVbDKWgd3NHO+EYC6XeEA==", + "dev": true + }, "expo-modules-core": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.2.0.tgz", "integrity": "sha512-inpfZ5X/BaTtbj2wG9PA9AC0MN8VyId6KSRlVuEg7+ziurHBy/kKDFxpOddUokhwiln2uhoYPSStJjR/tKypdw==", "dev": true }, + "expo-permissions": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/expo-permissions/-/expo-permissions-12.0.1.tgz", + "integrity": "sha512-TtypNPPLG4SdVEKBlrArLLZIyhlhE+3B4dhz2HaY1Mve2rcvKE0C7z/e1WoUVU8+LgcdKoNGwg/wRVeCkxeEhg==", + "dev": true + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6334,6 +8780,12 @@ "flat-cache": "^2.0.1" } }, + "file-type": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==", + "dev": true + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6674,6 +9126,16 @@ "is-glob": "^4.0.1" } }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -6898,6 +9360,12 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -7240,6 +9708,12 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, "is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", @@ -9075,6 +11549,19 @@ "integrity": "sha512-3Zi16h6L5tXDRQJTb221cnRoVG9/9OvreLdLU2/ZjRv/GILL+2Cemt0IKvkowwkDpvouAU1DQPOJ7qaiHeIdrw==", "dev": true }, + "jimp": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.12.1.tgz", + "integrity": "sha512-0soPJif+yjmzmOF+4cF2hyhxUWWpXpQntsm2joJXFFoRcQiPzsG4dbLKYqYPT3Fc6PjZ8MaLtCkDqqckVSfmRw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/custom": "^0.12.1", + "@jimp/plugins": "^0.12.1", + "@jimp/types": "^0.12.1", + "regenerator-runtime": "^0.13.3" + } + }, "joi": { "version": "17.4.0", "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.0.tgz", @@ -9088,6 +11575,12 @@ "@sideway/pinpoint": "^2.0.0" } }, + "jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==", + "dev": true + }, "jquery": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", @@ -9437,6 +11930,22 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "load-bmfont": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", + "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "dev": true, + "requires": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -9576,6 +12085,15 @@ "object-visit": "^1.0.0" } }, + "md5-file": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", + "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.1.0" + } + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -10106,6 +12624,15 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "requires": { + "dom-walk": "^0.1.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -10446,6 +12973,12 @@ "has": "^1.0.3" } }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==", + "dev": true + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -10634,6 +13167,12 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10643,6 +13182,34 @@ "callsites": "^3.0.0" } }, + "parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=", + "dev": true + }, + "parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=", + "dev": true + }, + "parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "dev": true, + "requires": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, + "parse-headers": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", + "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==", + "dev": true + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -10652,6 +13219,23 @@ "error-ex": "^1.2.0" } }, + "parse-png": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", + "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==", + "dev": true, + "requires": { + "pngjs": "^3.3.0" + }, + "dependencies": { + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "dev": true + } + } + }, "parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", @@ -10670,6 +13254,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -10709,6 +13299,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", + "dev": true + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -10730,6 +13326,23 @@ "node-modules-regexp": "^1.0.0" } }, + "pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", + "dev": true, + "requires": { + "pngjs": "^3.0.0" + }, + "dependencies": { + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "dev": true + } + } + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -10804,6 +13417,12 @@ "xmldom": "^0.5.0" } }, + "pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "dev": true + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -10851,6 +13470,12 @@ } } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -10920,6 +13545,12 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "ramda": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", @@ -11142,143 +13773,379 @@ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "react-native-codegen": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.6.tgz", + "integrity": "sha512-cMvrUelD81wiPitEPiwE/TCNscIVauXxmt4NTGcy18HrUd0WRWXfYzAQGXm0eI87u3NMudNhqFj2NISJenxQHg==", + "dev": true, + "requires": { + "flow-parser": "^0.121.0", + "jscodeshift": "^0.11.0", + "nullthrows": "^1.1.1" + } + }, + "react-native-performance": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-2.0.0.tgz", + "integrity": "sha512-jKM9Qg0SkL9D9ad377nxb1VV+OXJSyYyIrBHKmM6CABNxfrLVA5xkQMEibjmZQde7b0ndJOZoQAiObgJjjc4VQ==", + "dev": true + }, + "react-native-unimodules": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/react-native-unimodules/-/react-native-unimodules-0.13.3.tgz", + "integrity": "sha512-fjbNbAcvJHF8Ywqe77oveRW1WfaAKCQGV4a3Fxgpai17oNHq1LFwwKw0crFo0k7Njm5u7kCMVNbm9ZILNBfABQ==", + "dev": true, + "requires": { + "@unimodules/core": "~7.1.0", + "@unimodules/react-native-adapter": "~6.2.2", + "chalk": "^2.4.2", + "expo-asset": "~8.3.1", + "expo-constants": "~10.1.3", + "expo-file-system": "~11.0.2", + "expo-image-loader": "~2.1.1", + "expo-permissions": "~12.0.1", + "find-up": "~5.0.0", + "unimodules-app-loader": "~2.1.0", + "unimodules-barcode-scanner-interface": "~6.1.0", + "unimodules-camera-interface": "~6.1.0", + "unimodules-constants-interface": "~6.1.0", + "unimodules-face-detector-interface": "~6.1.0", + "unimodules-file-system-interface": "~6.1.0", + "unimodules-font-interface": "~6.1.0", + "unimodules-image-loader-interface": "~6.1.0", + "unimodules-permissions-interface": "~6.1.0", + "unimodules-sensors-interface": "~6.1.0", + "unimodules-task-manager-interface": "~6.1.0" + }, + "dependencies": { + "@expo/config-plugins": { + "version": "1.0.33", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-1.0.33.tgz", + "integrity": "sha512-YQJop0c69LKD/6ZJJto7klS7TDmzgs44TI0Z5RBqesOjYlDwNFcQk2Rl2BaA1wlAYkH+rRrhN2+WjjSyD9HiPg==", + "dev": true, + "requires": { + "@expo/config-types": "^40.0.0-beta.2", + "@expo/configure-splash-screen": "0.4.0", + "@expo/image-utils": "0.3.14", + "@expo/json-file": "8.2.30", + "@expo/plist": "0.0.13", + "find-up": "~5.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "^0.4.23" + } + }, + "@expo/config-types": { + "version": "40.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-40.0.0-beta.2.tgz", + "integrity": "sha512-t9pHCQMXOP4nwd7LGXuHkLlFy0JdfknRSCAeVF4Kw2/y+5OBbR9hW9ZVnetpBf0kORrekgiI7K/qDaa3hh5+Qg==", + "dev": true + }, + "@expo/json-file": { + "version": "8.2.30", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.30.tgz", + "integrity": "sha512-vrgGyPEXBoFI5NY70IegusCSoSVIFV3T3ry4tjJg1MFQKTUlR7E0r+8g8XR6qC705rc2PawaZQjqXMAVtV6s2A==", + "dev": true, + "requires": { + "@babel/code-frame": "~7.10.4", + "fs-extra": "9.0.0", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + } + }, + "@expo/plist": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.13.tgz", + "integrity": "sha512-zGPSq9OrCn7lWvwLLHLpHUUq2E40KptUFXn53xyZXPViI0k9lbApcR9KlonQZ95C+ELsf0BQ3gRficwK92Ivcw==", + "dev": true, + "requires": { + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0", + "xmldom": "~0.5.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "expo-file-system": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-11.0.2.tgz", + "integrity": "sha512-nodNvUVa+US4N4xnj5BFw8W9ZF/qCHJVC2t45cHWrBiwkVVxz45wjE7uSHUmkMWyWT7a/7AJuL3XJfYp7h90IQ==", + "dev": true, + "requires": { + "@expo/config-plugins": "^1.0.18", + "uuid": "^3.4.0" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "dev": true, - "requires": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - } + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", "dev": true }, - "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", "dev": true } } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } + "xmlbuilder": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", + "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", + "dev": true } } }, - "react-native-codegen": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.6.tgz", - "integrity": "sha512-cMvrUelD81wiPitEPiwE/TCNscIVauXxmt4NTGcy18HrUd0WRWXfYzAQGXm0eI87u3NMudNhqFj2NISJenxQHg==", - "dev": true, - "requires": { - "flow-parser": "^0.121.0", - "jscodeshift": "^0.11.0", - "nullthrows": "^1.1.1" - } - }, - "react-native-performance": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-2.0.0.tgz", - "integrity": "sha512-jKM9Qg0SkL9D9ad377nxb1VV+OXJSyYyIrBHKmM6CABNxfrLVA5xkQMEibjmZQde7b0ndJOZoQAiObgJjjc4VQ==", - "dev": true - }, "react-refresh": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", @@ -11579,12 +14446,24 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, "reselect": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", @@ -12075,6 +14954,23 @@ "plist": "^3.0.1" } }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, "simply-deferred": { "version": "git+https://github.com/Expensify/simply-deferred.git#77a08a95754660c7bd6e0b6979fdf84e8e831bf5", "from": "git+https://github.com/Expensify/simply-deferred.git#77a08a95754660c7bd6e0b6979fdf84e8e831bf5" @@ -12102,6 +14998,12 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "slugify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.0.tgz", + "integrity": "sha512-FkMq+MQc5hzYgM86nLuHI98Acwi3p4wX+a5BO9Hhw4JdK4L7WueIiZ4tXEobImPqBz2sVcV0+Mu3GRB30IGang==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -12673,6 +15575,31 @@ } } }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "tempy": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.3.0.tgz", + "integrity": "sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==", + "dev": true, + "requires": { + "temp-dir": "^1.0.0", + "type-fest": "^0.3.1", + "unique-string": "^1.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -12722,11 +15649,23 @@ "xtend": "~4.0.1" } }, + "timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==", + "dev": true + }, "tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" }, + "tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==", + "dev": true + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -12932,6 +15871,72 @@ "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", "dev": true }, + "unimodules-app-loader": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unimodules-app-loader/-/unimodules-app-loader-2.1.0.tgz", + "integrity": "sha512-W+D+hVXq6jOvBm7QVwODPENz6Lupj73QequNNG+6GCTkqn4ybq/lba9IQvJQT2QzdL3luVHin+eym18cDblMlg==", + "dev": true + }, + "unimodules-barcode-scanner-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-barcode-scanner-interface/-/unimodules-barcode-scanner-interface-6.1.0.tgz", + "integrity": "sha512-+McBDniXReXNS8PnGDjIyDikb+cRXSfsZMLsF0gohEEV0xdA6HhPvFA0ryv65j2NKOyIiWmEHjv+yDOoewDq3w==", + "dev": true + }, + "unimodules-camera-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-camera-interface/-/unimodules-camera-interface-6.1.0.tgz", + "integrity": "sha512-Rbszrh54kIB4vA+AzDWFXplBz1UrxQNR6Ls0eJDAKffbjDfyQIP6SgIPjUlzqGVnzknyZ1SMGiFFSFCM4BCOAw==", + "dev": true + }, + "unimodules-constants-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-constants-interface/-/unimodules-constants-interface-6.1.0.tgz", + "integrity": "sha512-uPLFGufbdefRQeINyUfkw2mVJJg+6kH23RR4ATfUAsrD6vGLuONwduHvRwh+rcL9fzPVM4jsfH6iATrolmiatg==", + "dev": true + }, + "unimodules-face-detector-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-face-detector-interface/-/unimodules-face-detector-interface-6.1.0.tgz", + "integrity": "sha512-L2E8a2OjMPxfVh/OGt6Y5HWbEaJ9h3Hkmvx02GCferBPKgN3dcxFMaI53d1BVV9QA3r4YuLBP6RrolG/qy/r7A==", + "dev": true + }, + "unimodules-file-system-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-file-system-interface/-/unimodules-file-system-interface-6.1.0.tgz", + "integrity": "sha512-iJGm6nWF+PhxqFbeqC2Ku4XjglbL9z7aofkSX5S7bZ3Oi4v1NO1UOe9nczU17Ps19sfYZJgkiD4FiQaFCmAnKg==", + "dev": true + }, + "unimodules-font-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-font-interface/-/unimodules-font-interface-6.1.0.tgz", + "integrity": "sha512-OfSeWx9ew2SNENj/HhctfPU7hqeW0bzVZYGGJ0M6RNcRRWzwA6ltawyYwtuvRe/EEU3LwrFUSKPMCi9867hLyw==", + "dev": true + }, + "unimodules-image-loader-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-image-loader-interface/-/unimodules-image-loader-interface-6.1.0.tgz", + "integrity": "sha512-o8hZI6J6DGYyo2xSH6J+ipxME0blNfmaWU3P2Y2AUVxbEPdgjT2sVmufRWMKGhrt7gaNW4xF/JUbF9lq4Rui7w==", + "dev": true + }, + "unimodules-permissions-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-permissions-interface/-/unimodules-permissions-interface-6.1.0.tgz", + "integrity": "sha512-jeJx/y+Vn/Cp1/4su5XJ06UBul83MpXkYEqIOAb2jwaikhmj6tNwko7HpKy9OhfGfrhddCzwtedlro8xxZUk9A==", + "dev": true + }, + "unimodules-sensors-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-sensors-interface/-/unimodules-sensors-interface-6.1.0.tgz", + "integrity": "sha512-tJDOo3p4q4wmhyuwapNjYeON7cd5OSPYr3qDfMgPPg9m6pYM/FdQJ1PKMNb1NJUckpDgQ67Dows2jAdqkNRZSw==", + "dev": true + }, + "unimodules-task-manager-interface": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/unimodules-task-manager-interface/-/unimodules-task-manager-interface-6.1.0.tgz", + "integrity": "sha512-wSsuX5fzd3oCCjHvrRFxysmCswhHZbJflVyAWzgSHtyMgxBOZobGN1C0UQ/plcu/JWY2+maTDPpE9OU6wzzzdg==", + "dev": true + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -12944,6 +15949,15 @@ "set-value": "^2.0.1" } }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -13011,6 +16025,16 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, + "url-parse": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", + "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -13026,6 +16050,15 @@ "object-assign": "^4.1.1" } }, + "utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "dev": true, + "requires": { + "pako": "^1.0.5" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -13309,12 +16342,39 @@ } } }, + "xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "dev": true, + "requires": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "dev": true, + "requires": { + "sax": "^1.2.4" + } + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=", + "dev": true + }, "xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", diff --git a/package.json b/package.json index 1885bd50d..a3e639691 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "babel-plugin-transform-class-properties": "^6.24.1", "eslint": "^7.6.0", "eslint-config-expensify": "^2.0.11", + "expo-file-system": "^11.1.3", "jest": "^26.5.2", "jest-cli": "^26.5.2", "localforage": "^1.10.0", @@ -42,10 +43,12 @@ "react": "^17.0.2", "react-native": "0.64.1", "react-native-performance": "^2.0.0", + "react-native-unimodules": "^0.13.3", "react-test-renderer": "16.13.1" }, "peerDependencies": { "@react-native-async-storage/async-storage": "^1.15.5", + "expo-file-system": "^11.1.3", "localforage": "^1.10.0", "react": "^17.0.2", "react-native-performance": "^2.0.0", @@ -79,8 +82,7 @@ "timers": "fake", "testEnvironment": "jsdom", "setupFilesAfterEnv": [ - "@testing-library/jest-native/extend-expect", - "/tests/setupAfterEnv.js" + "@testing-library/jest-native/extend-expect" ] } } diff --git a/tests/setupAfterEnv.js b/tests/setupAfterEnv.js deleted file mode 100644 index 4cdababc4..000000000 --- a/tests/setupAfterEnv.js +++ /dev/null @@ -1 +0,0 @@ -jest.mock('../lib/storage'); diff --git a/tests/unit/cacheEvictionTest.js b/tests/unit/cacheEvictionTest.js index 59ada4077..67291dc69 100644 --- a/tests/unit/cacheEvictionTest.js +++ b/tests/unit/cacheEvictionTest.js @@ -14,7 +14,7 @@ test('Cache eviction', () => { const collection = {}; // Given an evictable key previously set in storage - return Storage.setItem(`${ONYX_KEYS.COLLECTION.TEST_KEY}${RECORD_TO_EVICT}`, JSON.stringify({test: 'evict'})) + return Storage.setItem(`${ONYX_KEYS.COLLECTION.TEST_KEY}${RECORD_TO_EVICT}`, {test: 'evict'}) .then(() => { // When we initialize Onyx and mark the set collection key as a safeEvictionKey Onyx.init({ diff --git a/tests/unit/onyxCacheTest.js b/tests/unit/onyxCacheTest.js index c82e24382..7891f1bf6 100644 --- a/tests/unit/onyxCacheTest.js +++ b/tests/unit/onyxCacheTest.js @@ -394,7 +394,7 @@ describe('Onyx', () => { describe('Onyx with Cache', () => { let Onyx; let withOnyx; - let StorageMock; + let AsyncStorageMock; /** @type OnyxCache */ let cache; @@ -411,7 +411,7 @@ describe('Onyx', () => { const OnyxModule = require('../../index'); Onyx = OnyxModule.default; withOnyx = OnyxModule.withOnyx; - StorageMock = require('../../lib/storage').default; + AsyncStorageMock = require('@react-native-async-storage/async-storage').default; cache = require('../../lib/OnyxCache').default; Onyx.init({ @@ -443,8 +443,8 @@ describe('Onyx', () => { })(ViewWithText); // GIVEN some string value for that key exists in storage - StorageMock.getItem.mockResolvedValue('"mockValue"'); - StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); + AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); + AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); return initOnyx() .then(() => { // WHEN multiple components are rendered @@ -459,7 +459,7 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called only once - expect(StorageMock.getItem).toHaveBeenCalledTimes(1); + expect(AsyncStorageMock.getItem).toHaveBeenCalledTimes(1); }); }); @@ -474,8 +474,8 @@ describe('Onyx', () => { // GIVEN some string value for that key exists in storage return initOnyx() .then(() => { - StorageMock.getItem.mockResolvedValue('"mockValue"'); - StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); + AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); + AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); // WHEN multiple components are rendered render( @@ -489,14 +489,14 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called only once - expect(StorageMock.getAllKeys).toHaveBeenCalledTimes(1); + expect(AsyncStorageMock.getAllKeys).toHaveBeenCalledTimes(1); }); }); it('Should keep recently accessed items in cache', () => { // GIVEN Storage with 10 different keys - StorageMock.getItem.mockResolvedValue('"mockValue"'); - StorageMock.getAllKeys.mockResolvedValue( + AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); + AsyncStorageMock.getAllKeys.mockResolvedValue( _.range(10).map(number => `${ONYX_KEYS.COLLECTION.MOCK_COLLECTION}${number}`) ); let connections; @@ -542,8 +542,8 @@ describe('Onyx', () => { })(ViewWithText); // GIVEN some string value for that key exists in storage - StorageMock.getItem.mockResolvedValue('"mockValue"'); - StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); + AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); + AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY]); return initOnyx() .then(() => { @@ -561,7 +561,7 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called twice - expect(StorageMock.getItem).toHaveBeenCalledTimes(2); + expect(AsyncStorageMock.getItem).toHaveBeenCalledTimes(2); }); }); @@ -580,9 +580,9 @@ describe('Onyx', () => { })(ViewWithText); // GIVEN some values exist in storage - StorageMock.setItem(ONYX_KEYS.TEST_KEY, JSON.stringify({ID: 15, data: 'mock object with ID'})); - StorageMock.setItem(ONYX_KEYS.ANOTHER_TEST, JSON.stringify('mock text')); - StorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY, ONYX_KEYS.ANOTHER_TEST]); + AsyncStorageMock.setItem(ONYX_KEYS.TEST_KEY, JSON.stringify({ID: 15, data: 'mock object with ID'})); + AsyncStorageMock.setItem(ONYX_KEYS.ANOTHER_TEST, JSON.stringify('mock text')); + AsyncStorageMock.getAllKeys.mockResolvedValue([ONYX_KEYS.TEST_KEY, ONYX_KEYS.ANOTHER_TEST]); return initOnyx() .then(() => { // WHEN the components are rendered multiple times @@ -596,8 +596,8 @@ describe('Onyx', () => { .then(waitForPromisesToResolve) .then(() => { // THEN Async storage `getItem` should be called exactly two times (once for each key) - expect(StorageMock.getItem).toHaveBeenCalledTimes(2); - expect(StorageMock.getItem.mock.calls).toEqual([ + expect(AsyncStorageMock.getItem).toHaveBeenCalledTimes(2); + expect(AsyncStorageMock.getItem.mock.calls).toEqual([ [ONYX_KEYS.TEST_KEY], [ONYX_KEYS.ANOTHER_TEST] ]); @@ -606,8 +606,8 @@ describe('Onyx', () => { it('Should clean cache when connections to eviction keys happen', () => { // GIVEN storage with some data - StorageMock.getItem.mockResolvedValue('"mockValue"'); - StorageMock.getAllKeys.mockResolvedValue(_.range(1, 10).map(n => `key${n}`)); + AsyncStorageMock.getItem.mockResolvedValue('"mockValue"'); + AsyncStorageMock.getAllKeys.mockResolvedValue(_.range(1, 10).map(n => `key${n}`)); jest.useFakeTimers(); From 449e4ba36e784c4ed31f2add83fc23872a41c15c Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 30 Aug 2021 16:04:00 +0300 Subject: [PATCH 26/47] Update docs --- lib/storage/index.d.ts | 4 ++++ lib/storage/index.native.js | 2 +- lib/storage/providers/NativeFileHandler.js | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts index 2e1cf6f17..821b01449 100644 --- a/lib/storage/index.d.ts +++ b/lib/storage/index.d.ts @@ -1,3 +1,7 @@ +/** + * Storage interaction interface used by Onyx internally + * It's used to hook Onyx to different storage layers + */ interface StorageProvider { getAllKeys(): Promise, getItem(key: string): Promise, diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index 6afba3fdf..0efb20fd5 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -1,5 +1,5 @@ /** - * On native we can leave almost everything to AsyncStorage but files. + * On native we can leave almost everything to AsyncStorage, but files need to be prepared. * Before files are saved in our key/value storage they should first be copied to * our "local space" (App Documents) so that they're not lost - image pickers and document * pickers would move files to cache which can be cleared before we've uploaded them diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 6806a3b01..76abcda2d 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -1,6 +1,6 @@ /** * The native FS handler - * We storage images in our app's directory space, which does not require special + * We store files in our app's directory space, which does not require special * permission */ From b6ad24440fe0b07b314373c1a4cfdf7914febc3f Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 30 Aug 2021 18:41:20 +0300 Subject: [PATCH 27/47] Use a hidden folder `.onyx_files` --- lib/storage/providers/NativeFileHandler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 76abcda2d..5cebdf673 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -6,7 +6,7 @@ import {FileSystem} from 'react-native-unimodules'; -const LOCAL_PATH = `${FileSystem.documentDirectory}onyx_files/`; +const LOCAL_PATH = `${FileSystem.documentDirectory}.onyx_files/`; // Create our storage folder FileSystem.getInfoAsync(LOCAL_PATH) From dac932ea16d8b50b62416de9b84bc1af96036cc7 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 13:22:43 +0200 Subject: [PATCH 28/47] Delete storage typings index --- lib/storage/index.d.ts | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 lib/storage/index.d.ts diff --git a/lib/storage/index.d.ts b/lib/storage/index.d.ts deleted file mode 100644 index 821b01449..000000000 --- a/lib/storage/index.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Storage interaction interface used by Onyx internally - * It's used to hook Onyx to different storage layers - */ -interface StorageProvider { - getAllKeys(): Promise, - getItem(key: string): Promise, - multiGet(keys: string[]): Promise>, - removeItem(key: string): Promise, - setItem(key: string, value: T): Promise, - multiSet(pairs: Array<[string, T|null]>): Promise, - multiMerge(pairs: Array<[string, T|null]>): Promise, - clear(): Promise, - prepareFile(file: any): {uri: string, type: string, name: string}|File - synchronizeInstances(config: { keyChanged: (key: string, data: any) => void }): void -} - -export = StorageProvider; From 81af8f7079a2aa6cfb5bc3c16e215d17658a1296 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 17:52:06 +0200 Subject: [PATCH 29/47] Address part of the requested changes (comments and clarification changes) --- lib/Onyx.js | 20 +++++++++++-------- lib/storage/index.js | 30 ++++++++++------------------ lib/storage/index.native.js | 17 ++++++++-------- lib/storage/providers/LocalForage.js | 5 +++-- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 0bf194944..3272a8a67 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -304,8 +304,8 @@ function keysChanged(collectionKey, collection) { * When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks * * @private - * @param {string} key - * @param {any} data + * @param {String} key + * @param {*} data */ function keyChanged(key, data) { // Add or remove this key from the recentlyAccessedKeys lists @@ -769,7 +769,7 @@ function mergeCollection(collectionKey, collection) { * Setting this to 0 would practically mean no cache * We try to free cache when we connect to a safe eviction key * @param {Boolean} [options.captureMetrics] Enables Onyx benchmarking and exposes the get/print/reset functions - * @param {Boolean} [options.synchronizeInstances] Auto synchronize storage events between multiple instances of Onyx + * @param {Boolean} [options.shouldSyncMultipleInstances] Auto synchronize storage events between multiple instances of Onyx * running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop) * * @example @@ -786,7 +786,7 @@ function init({ safeEvictionKeys = [], maxCachedKeysCount = 55, captureMetrics = false, - synchronizeInstances = Boolean(global.localStorage), + shouldSyncMultipleInstances = Boolean(global.localStorage), } = {}) { if (captureMetrics) { // The code here is only bundled and applied when the captureMetrics is set @@ -814,15 +814,17 @@ function init({ ]) .then(deferredInitTask.resolve); - if (synchronizeInstances) { - Storage.synchronizeInstances({keyChanged}); + if (shouldSyncMultipleInstances) { + Storage.useAutoInstanceSync(keyChanged); } } /** * Prepares a file so that it can be saved in Onyx. - * Use this method to make a File reference. + * Use this method to get an updated File reference. * Then save it as usual by Onyx.set or Onyx.merge + * @param {File} file + * @returns {File} * * @example * const preparedFile = Onyx.prepareFile(someFile); @@ -831,7 +833,9 @@ function init({ * hasAttachment: true, * }); */ -const prepareFile = Storage.prepareFile; +function prepareFile(file) { + return Storage.prepareFile(file); +} const Onyx = { connect, diff --git a/lib/storage/index.js b/lib/storage/index.js index eb2574ff1..4141a63eb 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -1,7 +1,3 @@ -/** - * On Web and Desktop it's enough to leave everything to localforage - */ - import Storage from './providers/LocalForage'; const webStorage = { @@ -9,44 +5,38 @@ const webStorage = { /** * Storage synchronization mechanism keeping all opened tabs in sync - * @param {object} config - * @param {function(key: string, data: any)} config.keyChanged + * @param {function(key: String, data: *)} onStorageKeyChanged */ - synchronizeInstances(config) { + useAutoInstanceSync(onStorageKeyChanged) { const SYNC_ONYX = 'SYNC_ONYX'; // Override `setItem` to raise storage events that we can intercept in other tabs this.setItem = (key, value) => Storage.setItem(key, value) .then(() => { - /** We make a temp write to storage just to raise the storage event (below) - * then remove the "dummy" value. - * Listeners would receive everything they need to read the new value from the DB */ + // We raise an event thorough `localStorage` to let other tabs know a value changed global.localStorage.setItem(SYNC_ONYX, key); global.localStorage.removeItem(SYNC_ONYX); }); - // This event will be triggered on tabs other than the current tab + // This listener will only be triggered by events coming from other tabs global.addEventListener('storage', (event) => { - if (!event.newValue) { + // Ignore events that don't originate from the SYNC_ONYX logic above + if (event.key !== SYNC_ONYX || !event.newValue) { return; } - // Notify any listeners in case an Onyx key did change - if (event.key === SYNC_ONYX) { - Storage.getItem(event.newValue) - .then(value => config.keyChanged(event.newValue, value)); - } + const onyxKey = event.newValue; + Storage.getItem(onyxKey) + .then(value => onStorageKeyChanged(onyxKey, value)); }); }, /** - * On web we just return the passed file - * We don't need to do anything as we can just save the File to LocalForage * @param {File} file * @returns {File} */ prepareFile(file) { - // Todo: we can add some size considerations here and abort if necessary + // Storing files in IndexedDB (localforage) doesn't require any preparation return file; } }; diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index 0efb20fd5..b3b2a672a 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -9,6 +9,7 @@ import Storage from './providers/AsyncStorage'; import FileHandler from './providers/NativeFileHandler'; +import {logAlert} from '../Logger'; const nativeStorage = { ...Storage, @@ -19,22 +20,20 @@ const nativeStorage = { synchronizeInstances() {}, /** - * On native we copy the file locally and return a reference to the new file - * This allows us to stringify and save the reference in our regular storage - * e.g. as part of a persisted request or an optimistic report action - * @param {{uri: string, name: string, type: string}} file - * @returns {{uri: string, name: string, type: string}} + * Prepares a file so that it can be referenced in Onyx key/value storage + * @param {{uri: String, name: String, type: String}} file + * @returns {{uri: String, name: String, type: String}} */ prepareFile(file) { - // Todo: perhaps check size here and abort if the size is larger than 20MB - // Create result optimistically so the method can called as sync method const uri = FileHandler.getLocalDestination(file); const optimisticResult = {...file, uri}; - // Todo: do something about the error, e.g. run eviction logic if it's due to lack of space FileHandler.storeLocally(file) - .catch(console.error); + .catch((error) => { + logAlert(`Failed to store file locally: ${error.message}`); + throw error; + }); return optimisticResult; } diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 83f38c719..99b4ff71d 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -9,7 +9,7 @@ import _ from 'underscore'; import lodashMerge from 'lodash/merge'; localforage.config({ - name: 'OnyxDb' + name: 'OnyxDB' }); const provider = { @@ -23,7 +23,6 @@ const provider = { pairs.push([key, value]); } - // Exist early (don't iterate all keys) if we've mapped everything if (remainingKeys.size === 0) { return true; } @@ -46,9 +45,11 @@ const provider = { return this.setItem(key, merged); })); + // We're returning Promise.resolve, otherwise the array of task results will be returned to the caller return Promise.all(tasks).then(() => Promise.resolve()); }, multiSet(pairs) { + // We're returning Promise.resolve, otherwise the array of task results will be returned to the caller const tasks = pairs.map(([key, value]) => this.setItem(key, value)); return Promise.all(tasks).then(() => Promise.resolve()); }, From 6f4abd38e5f4e9a821b46523006a04f1c7371b55 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 20:40:43 +0200 Subject: [PATCH 30/47] Get rid of empty `synchronizeInstances` method in index.native.js --- lib/Onyx.js | 4 ++-- lib/storage/index.js | 2 +- lib/storage/index.native.js | 7 +------ 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 3272a8a67..d72a2d6bc 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -814,8 +814,8 @@ function init({ ]) .then(deferredInitTask.resolve); - if (shouldSyncMultipleInstances) { - Storage.useAutoInstanceSync(keyChanged); + if (shouldSyncMultipleInstances && _.isFunction(Storage.keepInstancesSync)) { + Storage.keepInstancesSync(keyChanged); } } diff --git a/lib/storage/index.js b/lib/storage/index.js index 4141a63eb..ac5015273 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -7,7 +7,7 @@ const webStorage = { * Storage synchronization mechanism keeping all opened tabs in sync * @param {function(key: String, data: *)} onStorageKeyChanged */ - useAutoInstanceSync(onStorageKeyChanged) { + keepInstancesSync(onStorageKeyChanged) { const SYNC_ONYX = 'SYNC_ONYX'; // Override `setItem` to raise storage events that we can intercept in other tabs diff --git a/lib/storage/index.native.js b/lib/storage/index.native.js index b3b2a672a..5a3279c34 100644 --- a/lib/storage/index.native.js +++ b/lib/storage/index.native.js @@ -14,18 +14,13 @@ import {logAlert} from '../Logger'; const nativeStorage = { ...Storage, - /** - * On native it's a no-op because it's not possible to have multiple instances of Onyx (e.g. multiple tabs) - */ - synchronizeInstances() {}, - /** * Prepares a file so that it can be referenced in Onyx key/value storage * @param {{uri: String, name: String, type: String}} file * @returns {{uri: String, name: String, type: String}} */ prepareFile(file) { - // Create result optimistically so the method can called as sync method + // Create result optimistically so the method can be called synchronously const uri = FileHandler.getLocalDestination(file); const optimisticResult = {...file, uri}; From c6a5d69117f05ae84bfa7be5a141c322467c7f26 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 20:41:57 +0200 Subject: [PATCH 31/47] LocalForage Simplify multiGet implementation Iterating over the keys might be preferable if we expect to iterate nearly all the keys, but since we know exactly which keys we want to read it seems the way to go is to request just them --- lib/storage/providers/LocalForage.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 99b4ff71d..9f0bb0d7a 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -14,22 +14,13 @@ localforage.config({ const provider = { multiGet(keys) { - const pairs = []; - const remainingKeys = new Set(keys); + const pairs = _.map( + keys, + key => localforage.getItem(key) + .then(value => [key, value]) + ); - return localforage.iterate((value, key) => { - if (remainingKeys.has(key)) { - remainingKeys.delete(key); - pairs.push([key, value]); - } - - if (remainingKeys.size === 0) { - return true; - } - - return undefined; - }) - .then(() => pairs); + return Promise.all(pairs); }, multiMerge(pairs) { const tasks = pairs.map(([key, delta]) => this.getItem(key) From f409c689e74fb3ffbe00bcd4e7122a922ab9975a Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 20:54:39 +0200 Subject: [PATCH 32/47] LocalForage apply multiMerge suggested changes, use underscore --- lib/Onyx.js | 4 ++-- lib/storage/index.js | 2 +- lib/storage/providers/LocalForage.js | 18 +++++++----------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index d72a2d6bc..1096fa0b1 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -769,8 +769,8 @@ function mergeCollection(collectionKey, collection) { * Setting this to 0 would practically mean no cache * We try to free cache when we connect to a safe eviction key * @param {Boolean} [options.captureMetrics] Enables Onyx benchmarking and exposes the get/print/reset functions - * @param {Boolean} [options.shouldSyncMultipleInstances] Auto synchronize storage events between multiple instances of Onyx - * running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop) + * @param {Boolean} [options.shouldSyncMultipleInstances] Auto synchronize storage events between multiple instances + * of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop) * * @example * Onyx.init({ diff --git a/lib/storage/index.js b/lib/storage/index.js index ac5015273..1cafa27af 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -10,7 +10,7 @@ const webStorage = { keepInstancesSync(onStorageKeyChanged) { const SYNC_ONYX = 'SYNC_ONYX'; - // Override `setItem` to raise storage events that we can intercept in other tabs + // Override `setItem` to raise storage events that we intercept in other tabs this.setItem = (key, value) => Storage.setItem(key, value) .then(() => { // We raise an event thorough `localStorage` to let other tabs know a value changed diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 9f0bb0d7a..93582cf4b 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -23,17 +23,13 @@ const provider = { return Promise.all(pairs); }, multiMerge(pairs) { - const tasks = pairs.map(([key, delta]) => this.getItem(key) - .then((existing) => { - let merged = delta; + const tasks = _.map(pairs, ([key, partialValue]) => this.getItem(key) + .then((existingValue) => { + const newValue = _.isObject(existingValue) + ? lodashMerge(existingValue, partialValue) + : partialValue; - if (existing) { - if (_.isObject(existing)) { - merged = lodashMerge(existing, delta); - } - } - - return this.setItem(key, merged); + return this.setItem(key, newValue); })); // We're returning Promise.resolve, otherwise the array of task results will be returned to the caller @@ -41,7 +37,7 @@ const provider = { }, multiSet(pairs) { // We're returning Promise.resolve, otherwise the array of task results will be returned to the caller - const tasks = pairs.map(([key, value]) => this.setItem(key, value)); + const tasks = _.map(pairs, ([key, value]) => this.setItem(key, value)); return Promise.all(tasks).then(() => Promise.resolve()); }, From 35c2281fcc85cf254101144c5ef70bed7790a9ac Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 21:29:23 +0200 Subject: [PATCH 33/47] NativeFIleHandler: Apply review suggestion --- lib/storage/providers/NativeFileHandler.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 5cebdf673..fbbb7737e 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -5,15 +5,19 @@ */ import {FileSystem} from 'react-native-unimodules'; +import {logAlert} from '../../Logger'; const LOCAL_PATH = `${FileSystem.documentDirectory}.onyx_files/`; // Create our storage folder FileSystem.getInfoAsync(LOCAL_PATH) .then((info) => { - if (!info.exists) { - FileSystem.makeDirectoryAsync(LOCAL_PATH); + if (info.exists) { + return; } + + FileSystem.makeDirectoryAsync(LOCAL_PATH) + .catch(error => logAlert(`Failed to create app storage dir: ${error.message}`)); }); /** From cb7a8c0c256bf75fdc86233192f107a08d94dbee Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 21:30:34 +0200 Subject: [PATCH 34/47] Document provider methods --- lib/storage/providers/AsyncStorage.js | 45 +++++++++++++++++++++++++++ lib/storage/providers/LocalForage.js | 45 +++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/lib/storage/providers/AsyncStorage.js b/lib/storage/providers/AsyncStorage.js index 6d8bfe94a..c86a1fae1 100644 --- a/lib/storage/providers/AsyncStorage.js +++ b/lib/storage/providers/AsyncStorage.js @@ -21,6 +21,11 @@ function prepareValueForStorage(value) { } const provider = { + /** + * Get the value of a given key or return `null` if it's not available in storage + * @param {String} key + * @return {Promise<*>} + */ getItem(key) { return AsyncStorage.getItem(key) .then((value) => { @@ -28,24 +33,64 @@ const provider = { return parsed; }); }, + + /** + * Get multiple key-value pairs for the give array of keys in a batch + * @param {String[]} keys + * @return {Promise>} + */ multiGet(keys) { return AsyncStorage.multiGet(keys) .then(pairs => pairs.map(([key, value]) => [key, value && JSON.parse(value)])); }, + + /** + * Sets the value for a given key. The only requirement is that the value should be serializable to JSON string + * @param {String} key + * @param {*} value + * @return {Promise} + */ setItem(key, value) { return AsyncStorage.setItem(key, prepareValueForStorage(value)); }, + + /** + * Stores multiple key-value pairs in a batch + * @param {Array<[key, value]>} pairs + * @return {Promise} + */ multiSet(pairs) { const stringPairs = pairs.map(([key, value]) => [key, prepareValueForStorage(value)]); return AsyncStorage.multiSet(stringPairs); }, + + /** + * Multiple merging of existing and new values in a batch + * @param {Array<[key, value]>} pairs + * @return {Promise} + */ multiMerge(pairs) { const stringPairs = pairs.map(([key, value]) => [key, prepareValueForStorage(value)]); return AsyncStorage.multiMerge(stringPairs); }, + /** + * Returns all keys available in storage + * @returns {Promise} + */ getAllKeys: AsyncStorage.getAllKeys, + + /** + * Remove given key and it's value from storage + * @param {String} key + * @returns {Promise} + */ removeItem: AsyncStorage.removeItem, + + /** + * Clear absolutely everything from storage + * @returns {Promise} + */ clear: AsyncStorage.clear, }; diff --git a/lib/storage/providers/LocalForage.js b/lib/storage/providers/LocalForage.js index 93582cf4b..3a8c4634a 100644 --- a/lib/storage/providers/LocalForage.js +++ b/lib/storage/providers/LocalForage.js @@ -13,6 +13,11 @@ localforage.config({ }); const provider = { + /** + * Get multiple key-value pairs for the give array of keys in a batch + * @param {String[]} keys + * @return {Promise>} + */ multiGet(keys) { const pairs = _.map( keys, @@ -22,6 +27,12 @@ const provider = { return Promise.all(pairs); }, + + /** + * Multiple merging of existing and new values in a batch + * @param {Array<[key, value]>} pairs + * @return {Promise} + */ multiMerge(pairs) { const tasks = _.map(pairs, ([key, partialValue]) => this.getItem(key) .then((existingValue) => { @@ -35,16 +46,50 @@ const provider = { // We're returning Promise.resolve, otherwise the array of task results will be returned to the caller return Promise.all(tasks).then(() => Promise.resolve()); }, + + /** + * Stores multiple key-value pairs in a batch + * @param {Array<[key, value]>} pairs + * @return {Promise} + */ multiSet(pairs) { // We're returning Promise.resolve, otherwise the array of task results will be returned to the caller const tasks = _.map(pairs, ([key, value]) => this.setItem(key, value)); return Promise.all(tasks).then(() => Promise.resolve()); }, + /** + * Clear absolutely everything from storage + * @returns {Promise} + */ clear: localforage.clear, + + /** + * Returns all keys available in storage + * @returns {Promise} + */ getAllKeys: localforage.keys, + + /** + * Get the value of a given key or return `null` if it's not available in storage + * @param {String} key + * @return {Promise<*>} + */ getItem: localforage.getItem, + + /** + * Remove given key and it's value from storage + * @param {String} key + * @returns {Promise} + */ removeItem: localforage.removeItem, + + /** + * Sets the value for a given key. The only requirement is that the value should be serializable to JSON string + * @param {String} key + * @param {*} value + * @return {Promise} + */ setItem: localforage.setItem, }; From 273080f2d1a6fb75205d5cc0690a84e5c973077c Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 21:34:28 +0200 Subject: [PATCH 35/47] NativeFileHandler extract bytesToMB, use underscore --- lib/storage/providers/NativeFileHandler.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index fbbb7737e..7caecda14 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -5,6 +5,7 @@ */ import {FileSystem} from 'react-native-unimodules'; +import _ from 'underscore'; import {logAlert} from '../../Logger'; const LOCAL_PATH = `${FileSystem.documentDirectory}.onyx_files/`; @@ -28,6 +29,14 @@ function getLocalDestination(file) { return `${LOCAL_PATH}${file.name}`; } +/** + * @param{Number} size + * @returns {Number} + */ +function bytesToMB(size) { + return size * (1024 ** 2); +} + const fileHandler = { /** * Create a local copy of a file @@ -53,8 +62,8 @@ const fileHandler = { ]) .then(([dirInfo, fileNames]) => ({ ...dirInfo, - sizeMB: dirInfo.size * (1024 ** 2), - files: fileNames.map(name => ({ + sizeMB: bytesToMB(dirInfo.size), + files: _.map(fileNames, name => ({ name, uri: getLocalDestination({name}), })) From 6429c70ceb200c0234f7deda3a0d2cdd5b4b8447 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 21:54:25 +0200 Subject: [PATCH 36/47] Remove empty `prepareFile` and add a check in Onyx --- lib/Onyx.js | 7 ++++++- lib/storage/index.js | 9 --------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 1096fa0b1..9b1a80c92 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -834,7 +834,12 @@ function init({ * }); */ function prepareFile(file) { - return Storage.prepareFile(file); + // Some storage providers need to prepare the files others can directly save the file + if (_.isFunction(Storage.prepareFile)) { + return Storage.prepareFile(file); + } + + return file; } const Onyx = { diff --git a/lib/storage/index.js b/lib/storage/index.js index 1cafa27af..12afd6c94 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -30,15 +30,6 @@ const webStorage = { .then(value => onStorageKeyChanged(onyxKey, value)); }); }, - - /** - * @param {File} file - * @returns {File} - */ - prepareFile(file) { - // Storing files in IndexedDB (localforage) doesn't require any preparation - return file; - } }; export default webStorage; From 029a7a9da448f5b8a582055eda034e187a57d80a Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 22:14:42 +0200 Subject: [PATCH 37/47] Replace index.native with Platform.select --- .../{index.native.js => NativeStorage.js} | 0 lib/storage/WebStorage.js | 35 +++++++++++++++++ lib/storage/__mocks__/index.js | 3 ++ lib/storage/index.js | 39 +++---------------- 4 files changed, 44 insertions(+), 33 deletions(-) rename lib/storage/{index.native.js => NativeStorage.js} (100%) create mode 100644 lib/storage/WebStorage.js create mode 100644 lib/storage/__mocks__/index.js diff --git a/lib/storage/index.native.js b/lib/storage/NativeStorage.js similarity index 100% rename from lib/storage/index.native.js rename to lib/storage/NativeStorage.js diff --git a/lib/storage/WebStorage.js b/lib/storage/WebStorage.js new file mode 100644 index 000000000..12afd6c94 --- /dev/null +++ b/lib/storage/WebStorage.js @@ -0,0 +1,35 @@ +import Storage from './providers/LocalForage'; + +const webStorage = { + ...Storage, + + /** + * Storage synchronization mechanism keeping all opened tabs in sync + * @param {function(key: String, data: *)} onStorageKeyChanged + */ + keepInstancesSync(onStorageKeyChanged) { + const SYNC_ONYX = 'SYNC_ONYX'; + + // Override `setItem` to raise storage events that we intercept in other tabs + this.setItem = (key, value) => Storage.setItem(key, value) + .then(() => { + // We raise an event thorough `localStorage` to let other tabs know a value changed + global.localStorage.setItem(SYNC_ONYX, key); + global.localStorage.removeItem(SYNC_ONYX); + }); + + // This listener will only be triggered by events coming from other tabs + global.addEventListener('storage', (event) => { + // Ignore events that don't originate from the SYNC_ONYX logic above + if (event.key !== SYNC_ONYX || !event.newValue) { + return; + } + + const onyxKey = event.newValue; + Storage.getItem(onyxKey) + .then(value => onStorageKeyChanged(onyxKey, value)); + }); + }, +}; + +export default webStorage; diff --git a/lib/storage/__mocks__/index.js b/lib/storage/__mocks__/index.js new file mode 100644 index 000000000..c7d082958 --- /dev/null +++ b/lib/storage/__mocks__/index.js @@ -0,0 +1,3 @@ +import WebStorage from '../WebStorage'; + +export default WebStorage; diff --git a/lib/storage/index.js b/lib/storage/index.js index 12afd6c94..f5a621f46 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -1,35 +1,8 @@ -import Storage from './providers/LocalForage'; +import {Platform} from 'react-native'; -const webStorage = { - ...Storage, +const Storage = Platform.select({ + default: () => require('./WebStorage').default, + native: () => require('./NativeStorage').default, +})(); - /** - * Storage synchronization mechanism keeping all opened tabs in sync - * @param {function(key: String, data: *)} onStorageKeyChanged - */ - keepInstancesSync(onStorageKeyChanged) { - const SYNC_ONYX = 'SYNC_ONYX'; - - // Override `setItem` to raise storage events that we intercept in other tabs - this.setItem = (key, value) => Storage.setItem(key, value) - .then(() => { - // We raise an event thorough `localStorage` to let other tabs know a value changed - global.localStorage.setItem(SYNC_ONYX, key); - global.localStorage.removeItem(SYNC_ONYX); - }); - - // This listener will only be triggered by events coming from other tabs - global.addEventListener('storage', (event) => { - // Ignore events that don't originate from the SYNC_ONYX logic above - if (event.key !== SYNC_ONYX || !event.newValue) { - return; - } - - const onyxKey = event.newValue; - Storage.getItem(onyxKey) - .then(value => onStorageKeyChanged(onyxKey, value)); - }); - }, -}; - -export default webStorage; +export default Storage; From abf0339badf8af0f26df73a743736b1bc828f97b Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 23:21:50 +0200 Subject: [PATCH 38/47] Update to expo-file-system 13 which does not require unimodules react-native-unimodules were removed from Expensify/App and we're trying to make the same change here --- lib/storage/providers/NativeFileHandler.js | 2 +- package-lock.json | 3321 +------------------- package.json | 8 +- 3 files changed, 143 insertions(+), 3188 deletions(-) diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js index 7caecda14..fc9d070c3 100644 --- a/lib/storage/providers/NativeFileHandler.js +++ b/lib/storage/providers/NativeFileHandler.js @@ -4,7 +4,7 @@ * permission */ -import {FileSystem} from 'react-native-unimodules'; +import * as FileSystem from 'expo-file-system'; import _ from 'underscore'; import {logAlert} from '../../Logger'; diff --git a/package-lock.json b/package-lock.json index 04675a230..f2688fe35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1620,1754 +1620,16 @@ "strip-json-comments": "^3.1.1" } }, - "@expo/config": { - "version": "3.3.43", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-3.3.43.tgz", - "integrity": "sha512-5a78fQqTKk7RhgrW5XzHS8ylCo9YRjZrheLyVDNNfvwAD8YjeBz6bFWsItZPpAIoaDgkLh0a8uhc11DCmqoKpw==", - "dev": true, - "requires": { - "@babel/core": "7.9.0", - "@babel/plugin-proposal-class-properties": "~7.12.13", - "@babel/preset-env": "~7.12.13", - "@babel/preset-typescript": "~7.12.13", - "@expo/config-plugins": "1.0.33", - "@expo/config-types": "^40.0.0-beta.2", - "@expo/json-file": "8.2.30", - "fs-extra": "9.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "slugify": "^1.3.4" - }, - "dependencies": { - "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", - "dev": true - }, - "@babel/core": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", - "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.0", - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helpers": "^7.9.0", - "@babel/parser": "^7.9.0", - "@babel/template": "^7.8.6", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", - "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", - "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.14.5", - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", - "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", - "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-split-export-declaration": "^7.14.5" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", - "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "regexpu-core": "^4.7.1" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", - "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", - "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-get-function-arity": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", - "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-hoist-variables": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", - "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", - "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-module-imports": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", - "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", - "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", - "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-wrap-function": "^7.14.5", - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-replace-supers": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", - "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@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.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-simple-access": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", - "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", - "dev": true, - "requires": { - "@babel/types": "^7.14.8" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", - "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", - "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", - "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@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.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", - "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.13.tgz", - "integrity": "sha512-8SCJ0Ddrpwv4T7Gwb33EmW1V9PY5lggTO+A8WjyIwxrSHDUyBw4MtF96ifn1n8H806YlxbVCoKXbbmzD6RD+cA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", - "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", - "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", - "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", - "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", - "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", - "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "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==", - "dev": true, - "requires": { - "@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", - "@babel/plugin-transform-parameters": "^7.14.5" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", - "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", - "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", - "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", - "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", - "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", - "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", - "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", - "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", - "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-destructuring": { - "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==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", - "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", - "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", - "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", - "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", - "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", - "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", - "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", - "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@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.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", - "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.14.8", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@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.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", - "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.5", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@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.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", - "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@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.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - } - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", - "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", - "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", - "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", - "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", - "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", - "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", - "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", - "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", - "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", - "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", - "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", - "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-typescript": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz", - "integrity": "sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.15.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-typescript": "^7.14.5" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", - "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", - "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/preset-env": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.17.tgz", - "integrity": "sha512-9PMijx8zFbCwTHrd2P4PJR5nWGH3zWebx2OcpTjqQrHhCiL2ssSR2Sc9ko2BsI2VmVBfoaQmPrlMTCui4LmXQg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.12.13", - "@babel/helper-compilation-targets": "^7.12.17", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-proposal-async-generator-functions": "^7.12.13", - "@babel/plugin-proposal-class-properties": "^7.12.13", - "@babel/plugin-proposal-dynamic-import": "^7.12.17", - "@babel/plugin-proposal-export-namespace-from": "^7.12.13", - "@babel/plugin-proposal-json-strings": "^7.12.13", - "@babel/plugin-proposal-logical-assignment-operators": "^7.12.13", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.13", - "@babel/plugin-proposal-numeric-separator": "^7.12.13", - "@babel/plugin-proposal-object-rest-spread": "^7.12.13", - "@babel/plugin-proposal-optional-catch-binding": "^7.12.13", - "@babel/plugin-proposal-optional-chaining": "^7.12.17", - "@babel/plugin-proposal-private-methods": "^7.12.13", - "@babel/plugin-proposal-unicode-property-regex": "^7.12.13", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.12.13", - "@babel/plugin-transform-arrow-functions": "^7.12.13", - "@babel/plugin-transform-async-to-generator": "^7.12.13", - "@babel/plugin-transform-block-scoped-functions": "^7.12.13", - "@babel/plugin-transform-block-scoping": "^7.12.13", - "@babel/plugin-transform-classes": "^7.12.13", - "@babel/plugin-transform-computed-properties": "^7.12.13", - "@babel/plugin-transform-destructuring": "^7.12.13", - "@babel/plugin-transform-dotall-regex": "^7.12.13", - "@babel/plugin-transform-duplicate-keys": "^7.12.13", - "@babel/plugin-transform-exponentiation-operator": "^7.12.13", - "@babel/plugin-transform-for-of": "^7.12.13", - "@babel/plugin-transform-function-name": "^7.12.13", - "@babel/plugin-transform-literals": "^7.12.13", - "@babel/plugin-transform-member-expression-literals": "^7.12.13", - "@babel/plugin-transform-modules-amd": "^7.12.13", - "@babel/plugin-transform-modules-commonjs": "^7.12.13", - "@babel/plugin-transform-modules-systemjs": "^7.12.13", - "@babel/plugin-transform-modules-umd": "^7.12.13", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13", - "@babel/plugin-transform-new-target": "^7.12.13", - "@babel/plugin-transform-object-super": "^7.12.13", - "@babel/plugin-transform-parameters": "^7.12.13", - "@babel/plugin-transform-property-literals": "^7.12.13", - "@babel/plugin-transform-regenerator": "^7.12.13", - "@babel/plugin-transform-reserved-words": "^7.12.13", - "@babel/plugin-transform-shorthand-properties": "^7.12.13", - "@babel/plugin-transform-spread": "^7.12.13", - "@babel/plugin-transform-sticky-regex": "^7.12.13", - "@babel/plugin-transform-template-literals": "^7.12.13", - "@babel/plugin-transform-typeof-symbol": "^7.12.13", - "@babel/plugin-transform-unicode-escapes": "^7.12.13", - "@babel/plugin-transform-unicode-regex": "^7.12.13", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.12.17", - "core-js-compat": "^3.8.0", - "semver": "^5.5.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "@babel/preset-typescript": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.17.tgz", - "integrity": "sha512-T513uT4VSThRcmWeqcLkITKJ1oGQho9wfWuhQm10paClQkp1qyd0Wf8mvC8Se7UYssMyRSj4tZYpVTkCmAK/mA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-transform-typescript": "^7.12.17" - } - }, - "@expo/config-plugins": { - "version": "1.0.33", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-1.0.33.tgz", - "integrity": "sha512-YQJop0c69LKD/6ZJJto7klS7TDmzgs44TI0Z5RBqesOjYlDwNFcQk2Rl2BaA1wlAYkH+rRrhN2+WjjSyD9HiPg==", - "dev": true, - "requires": { - "@expo/config-types": "^40.0.0-beta.2", - "@expo/configure-splash-screen": "0.4.0", - "@expo/image-utils": "0.3.14", - "@expo/json-file": "8.2.30", - "@expo/plist": "0.0.13", - "find-up": "~5.0.0", - "fs-extra": "9.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "^0.4.23" - } - }, - "@expo/config-types": { - "version": "40.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-40.0.0-beta.2.tgz", - "integrity": "sha512-t9pHCQMXOP4nwd7LGXuHkLlFy0JdfknRSCAeVF4Kw2/y+5OBbR9hW9ZVnetpBf0kORrekgiI7K/qDaa3hh5+Qg==", - "dev": true - }, - "@expo/json-file": { - "version": "8.2.30", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.30.tgz", - "integrity": "sha512-vrgGyPEXBoFI5NY70IegusCSoSVIFV3T3ry4tjJg1MFQKTUlR7E0r+8g8XR6qC705rc2PawaZQjqXMAVtV6s2A==", - "dev": true, - "requires": { - "@babel/code-frame": "~7.10.4", - "fs-extra": "9.0.0", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "@expo/plist": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.13.tgz", - "integrity": "sha512-zGPSq9OrCn7lWvwLLHLpHUUq2E40KptUFXn53xyZXPViI0k9lbApcR9KlonQZ95C+ELsf0BQ3gRficwK92Ivcw==", - "dev": true, - "requires": { - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0", - "xmldom": "~0.5.0" - } - }, - "browserslist": { - "version": "4.16.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", - "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001251", - "colorette": "^1.3.0", - "electron-to-chromium": "^1.3.811", - "escalade": "^3.1.1", - "node-releases": "^1.1.75" - } - }, - "caniuse-lite": { - "version": "1.0.30001252", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz", - "integrity": "sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "colorette": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", - "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.822", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.822.tgz", - "integrity": "sha512-k7jG5oYYHxF4jx6PcqwHX3JVME/OjzolqOZiIogi9xtsfsmTjTdie4x88OakYFPEa8euciTgCCzvVNwvmjHb1Q==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "node-releases": { - "version": "1.1.75", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", - "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true - }, - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", - "dev": true - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", - "dev": true, - "requires": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" - } - }, - "xmlbuilder": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", - "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", - "dev": true - } - } - }, "@expo/config-plugins": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-3.1.0.tgz", - "integrity": "sha512-V5qxaxCAExBM0TXmbU1QKiZcAGP3ecu7KXede8vByT15cro5PkcWu2sSdJCYbHQ/gw6Vf/i8sr8gKlN8V8TSLg==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.0.6.tgz", + "integrity": "sha512-K/KQaw/CU8uLQgk7sFnZC54YGHoGucKFfdjYeZx5ds2eyzbuMAiKzGFcxZ/S+1dVBZ8QHzwowsVBW3kuYhnQ3Q==", "dev": true, "requires": { - "@expo/config-types": "^42.0.0", + "@expo/config-types": "^43.0.1", "@expo/json-file": "8.2.33", - "@expo/plist": "0.0.14", + "@expo/plist": "0.0.15", + "@react-native/normalize-color": "^2.0.0", "chalk": "^4.1.2", "debug": "^4.3.1", "find-up": "~5.0.0", @@ -3378,9 +1640,15 @@ "semver": "^7.3.5", "slash": "^3.0.0", "xcode": "^3.0.1", - "xml2js": "^0.4.23" + "xml2js": "0.4.23" }, "dependencies": { + "@react-native/normalize-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-2.0.0.tgz", + "integrity": "sha512-Wip/xsc5lw8vsBlmY2MO/gFLp3MvuZ2baBZjDeTjjndMgM0h5sxz7AZR62RDPGgstp8Np7JzjvVqVT7tpFZqsw==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -3552,148 +1820,11 @@ } }, "@expo/config-types": { - "version": "42.0.0", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-42.0.0.tgz", - "integrity": "sha512-Rj02OMZke2MrGa/1Y/EScmR7VuWbDEHPJyvfFyyLbadUt+Yv6isCdeFzDt71I7gJlPR9T4fzixeYLrtXXOTq0w==", + "version": "43.0.1", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-43.0.1.tgz", + "integrity": "sha512-EtllpCGDdB/UdwAIs5YXJwBLpbFQNdlLLrxIvoILA9cXrpQMWkeDCT9lQPJzFRMFcLUaMuGvkzX2tR4tx5EQFQ==", "dev": true }, - "@expo/configure-splash-screen": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@expo/configure-splash-screen/-/configure-splash-screen-0.4.0.tgz", - "integrity": "sha512-IDPnr2/DW1tYpDHqedFYNCDzRTf9HYinWFQ7fOelNZLuOCMoErLbSStA5zfkv46o69AgcCpteqgKHSoxsIBz5g==", - "dev": true, - "requires": { - "color-string": "^1.5.3", - "commander": "^5.1.0", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "lodash": "^4.17.15", - "pngjs": "^5.0.0", - "xcode": "^3.0.0", - "xml-js": "^1.6.11" - }, - "dependencies": { - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", - "dev": true - }, - "xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", - "dev": true, - "requires": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" - } - } - } - }, - "@expo/image-utils": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.3.14.tgz", - "integrity": "sha512-n+JkLZ71CWuNKLVVsPTzMGRwmbeKiVQw/2b99Ro7znCKzJy3tyE5T2C6WBvYh/5h/hjg8TqEODjXXWucRIzMXA==", - "dev": true, - "requires": { - "@expo/spawn-async": "1.5.0", - "chalk": "^4.0.0", - "fs-extra": "9.0.0", - "getenv": "^1.0.0", - "jimp": "0.12.1", - "mime": "^2.4.4", - "node-fetch": "^2.6.0", - "parse-png": "^2.1.0", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "tempy": "0.3.0" - }, - "dependencies": { - "fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true - } - } - }, "@expo/json-file": { "version": "8.2.33", "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.33.tgz", @@ -3728,9 +1859,9 @@ } }, "@expo/plist": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.14.tgz", - "integrity": "sha512-bb4Ua1M/OdNgS8KiGdSDUjZ/bbPfv3xdPY/lz8Ctp/adlj/QgB8xA7tVPeqSSfJPZqFRwU0qLCnRhpUOnP51VQ==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.15.tgz", + "integrity": "sha512-LDxiS0KNZAGJu4fIJhbEKczmb+zeftl1NU0LE0tj0mozoMI5HSKdMUchgvnBm35bwBl8ekKkAfJJ0ONxljWQjQ==", "dev": true, "requires": { "@xmldom/xmldom": "~0.7.0", @@ -3739,70 +1870,10 @@ }, "dependencies": { "xmlbuilder": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", - "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", - "dev": true - } - } - }, - "@expo/spawn-async": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.5.0.tgz", - "integrity": "sha512-LB7jWkqrHo+5fJHNrLAFdimuSXQ2MQ4lA7SQW5bf/HbsXuV2VrT/jN/M8f/KoWt0uJMGN4k/j7Opx4AvOOxSew==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.5" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", + "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, @@ -4402,365 +2473,6 @@ "@types/yargs": "^13.0.0" } }, - "@jimp/bmp": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.12.1.tgz", - "integrity": "sha512-t16IamuBMv4GiGa1VAMzsgrVKVANxXG81wXECzbikOUkUv7pKJ2vHZDgkLBEsZQ9sAvFCneM1+yoSRpuENrfVQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1", - "bmp-js": "^0.1.0" - } - }, - "@jimp/core": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.12.1.tgz", - "integrity": "sha512-mWfjExYEjHxBal+1gPesGChOQBSpxO7WUQkrO9KM7orboitOdQ15G5UA75ce7XVZ+5t+FQPOLmVkVZzzTQSEJA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1", - "any-base": "^1.1.0", - "buffer": "^5.2.0", - "exif-parser": "^0.1.12", - "file-type": "^9.0.0", - "load-bmfont": "^1.3.1", - "mkdirp": "^0.5.1", - "phin": "^2.9.1", - "pixelmatch": "^4.0.2", - "tinycolor2": "^1.4.1" - } - }, - "@jimp/custom": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.12.1.tgz", - "integrity": "sha512-bVClp8FEJ/11GFTKeRTrfH7NgUWvVO5/tQzO/68aOwMIhbz9BOYQGh533K9+mSy29VjZJo8jxZ0C9ZwYHuFwfA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/core": "^0.12.1" - } - }, - "@jimp/gif": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.12.1.tgz", - "integrity": "sha512-cGn/AcvMGUGcqR6ByClGSnrja4AYmTwsGVXTQ1+EmfAdTiy6ztGgZCTDpZ/tq4SpdHXwm9wDHez7damKhTrH0g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1", - "omggif": "^1.0.9" - } - }, - "@jimp/jpeg": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.12.1.tgz", - "integrity": "sha512-UoCUHbKLj2CDCETd7LrJnmK/ExDsSfJXmc1pKkfgomvepjXogdl2KTHf141wL6D+9CfSD2VBWQLC5TvjMvcr9A==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1", - "jpeg-js": "^0.4.0" - } - }, - "@jimp/plugin-blit": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.12.1.tgz", - "integrity": "sha512-VRBB6bx6EpQuaH0WX8ytlGNqUQcmuxXBbzL3e+cD0W6MluYibzQy089okvXcyUS72Q+qpSMmUDCVr3pDqLAsSA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-blur": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.12.1.tgz", - "integrity": "sha512-rTFY0yrwVJFNgNsAlYGn2GYCRLVEcPQ6cqAuhNylXuR/7oH3Acul+ZWafeKtvN8D8uMlth/6VP74gruXvwffZw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-circle": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.12.1.tgz", - "integrity": "sha512-+/OiBDjby7RBbQoDX8ZsqJRr1PaGPdTaaKUVGAsrE7KCNO9ODYNFAizB9lpidXkGgJ4Wx5R4mJy21i22oY/a4Q==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-color": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.12.1.tgz", - "integrity": "sha512-xlnK/msWN4uZ+Bu7+UrCs9oMzTSA9QE0jWFnF3h0aBsD8t1LGxozkckHe8nHtC/y/sxIa8BGKSfkiaW+r6FbnA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1", - "tinycolor2": "^1.4.1" - } - }, - "@jimp/plugin-contain": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.12.1.tgz", - "integrity": "sha512-WZ/D6G0jhnBh2bkBh610PEh/caGhAUIAxYLsQsfSSlOxPsDhbj3S6hMbFKRgnDvf0hsd5zTIA0j1B0UG4kh18A==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-cover": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.12.1.tgz", - "integrity": "sha512-ddWwTQO40GcabJ2UwUYCeuNxnjV4rBTiLprnjGMqAJCzdz3q3Sp20FkRf+H+E22k2v2LHss8dIOFOF4i6ycr9Q==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-crop": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.12.1.tgz", - "integrity": "sha512-CKjVkrNO8FDZKYVpMireQW4SgKBSOdF+Ip/1sWssHHe77+jGEKqOjhYju+VhT3dZJ3+75rJNI9II7Kethp+rTw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-displace": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.12.1.tgz", - "integrity": "sha512-MQAw2iuf1/bVJ6P95WWTLA+WBjvIZ7TeGBerkvBaTK8oWdj+NSLNRIYOIoyPbZ7DTL8f1SN4Vd6KD6BZaoWrwg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-dither": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.12.1.tgz", - "integrity": "sha512-mCrBHdx2ViTLJDLcrobqGLlGhZF/Mq41bURWlElQ2ArvrQ3/xR52We9DNDfC08oQ2JVb6q3v1GnCCdn0KNojGQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-fisheye": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.12.1.tgz", - "integrity": "sha512-CHvYSXtHNplzkkYzB44tENPDmvfUHiYCnAETTY+Hx58kZ0w8ERZ+OiLhUmiBcvH/QHm/US1iiNjgGUAfeQX6dg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-flip": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.12.1.tgz", - "integrity": "sha512-xi+Yayrnln8A/C9E3yQBExjxwBSeCkt/ZQg1CxLgszVyX/3Zo8+nkV8MJYpkTpj8LCZGTOKlsE05mxu/a3lbJQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-gaussian": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.12.1.tgz", - "integrity": "sha512-7O6eKlhL37hsLfV6WAX1Cvce7vOqSwL1oWbBveC1agutDlrtvcTh1s2mQ4Pde654hCJu55mq1Ur10+ote5j3qw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-invert": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.12.1.tgz", - "integrity": "sha512-JTAs7A1Erbxwl+7ph7tgcb2PZ4WzB+3nb2WbfiWU8iCrKj17mMDSc5soaCCycn8wfwqvgB1vhRfGpseOLWxsuQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-mask": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.12.1.tgz", - "integrity": "sha512-bnDdY0RO/x5Mhqoy+056SN1wEj++sD4muAKqLD2CIT8Zq5M/0TA4hkdf/+lwFy3H2C0YTK39PSE9xyb4jPX3kA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-normalize": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.12.1.tgz", - "integrity": "sha512-4kSaI4JLM/PNjHwbnAHgyh51V5IlPfPxYvsZyZ1US32pebWtocxSMaSuOaJUg7OGSkwSDBv81UR2h5D+Dz1b5A==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-print": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.12.1.tgz", - "integrity": "sha512-T0lNS3qU9SwCHOEz7AGrdp50+gqiWGZibOL3350/X/dqoFs1EvGDjKVeWncsGCyLlpfd7M/AibHZgu8Fx2bWng==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1", - "load-bmfont": "^1.4.0" - } - }, - "@jimp/plugin-resize": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.12.1.tgz", - "integrity": "sha512-sbNn4tdBGcgGlPt9XFxCuDl4ZOoxa8/Re8nAikyxYhRss2Dqz91ARbBQxOf1vlUGeicQMsjEuWbPQAogTSJRug==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-rotate": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.12.1.tgz", - "integrity": "sha512-RYkLzwG2ervG6hHy8iepbIVeWdT1kz4Qz044eloqo6c66MK0KAqp228YI8+CAKm0joQnVDC/A0FgRIj/K8uyAw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-scale": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.12.1.tgz", - "integrity": "sha512-zjNVI1fUj+ywfG78T1ZU33g9a5sk4rhEQkkhtny8koAscnVsDN2YaZEKoFli54kqaWh5kSS5DDL7a/9pEfXnFQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-shadow": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.12.1.tgz", - "integrity": "sha512-Z82IwvunXWQ2jXegd3W3TYUXpfJcEvNbHodr7Z+oVnwhM1OoQ5QC6RSRQwsj2qXIhbGffQjH8eguHgEgAV+u5w==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugin-threshold": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.12.1.tgz", - "integrity": "sha512-PFezt5fSk0q+xKvdpuv0eLggy2I7EgYotrK8TRZOT0jimuYFXPF0Z514c6szumoW5kEsRz04L1HkPT1FqI97Yg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1" - } - }, - "@jimp/plugins": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.12.1.tgz", - "integrity": "sha512-7+Yp29T6BbYo+Oqnc+m7A5AH+O+Oy5xnxvxlfmsp48+SuwEZ4akJp13Gu2PSmRlylENzR7MlWOxzhas5ERNlIg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/plugin-blit": "^0.12.1", - "@jimp/plugin-blur": "^0.12.1", - "@jimp/plugin-circle": "^0.12.1", - "@jimp/plugin-color": "^0.12.1", - "@jimp/plugin-contain": "^0.12.1", - "@jimp/plugin-cover": "^0.12.1", - "@jimp/plugin-crop": "^0.12.1", - "@jimp/plugin-displace": "^0.12.1", - "@jimp/plugin-dither": "^0.12.1", - "@jimp/plugin-fisheye": "^0.12.1", - "@jimp/plugin-flip": "^0.12.1", - "@jimp/plugin-gaussian": "^0.12.1", - "@jimp/plugin-invert": "^0.12.1", - "@jimp/plugin-mask": "^0.12.1", - "@jimp/plugin-normalize": "^0.12.1", - "@jimp/plugin-print": "^0.12.1", - "@jimp/plugin-resize": "^0.12.1", - "@jimp/plugin-rotate": "^0.12.1", - "@jimp/plugin-scale": "^0.12.1", - "@jimp/plugin-shadow": "^0.12.1", - "@jimp/plugin-threshold": "^0.12.1", - "timm": "^1.6.1" - } - }, - "@jimp/png": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.12.1.tgz", - "integrity": "sha512-tOUSJMJzcMAN82F9/Q20IToquIVWzvOe/7NIpVQJn6m+Lq6TtVmd7d8gdcna9AEFm2FIza5lhq2Kta6Xj0KXhQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.12.1", - "pngjs": "^3.3.3" - }, - "dependencies": { - "pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "dev": true - } - } - }, - "@jimp/tiff": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.12.1.tgz", - "integrity": "sha512-bzWDgv3202TKhaBGzV9OFF0PVQWEb4194h9kv5js348SSnbCusz/tzTE1EwKrnbDZThZPgTB1ryKs7D+Q9Mhmg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "utif": "^2.0.1" - } - }, - "@jimp/types": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.12.1.tgz", - "integrity": "sha512-hg5OKXpWWeKGuDrfibrjWWhr7hqb7f552wqnPWSLQpVrdWgjH+hpOv6cOzdo9bsU78qGTelZJPxr0ERRoc+MhQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/bmp": "^0.12.1", - "@jimp/gif": "^0.12.1", - "@jimp/jpeg": "^0.12.1", - "@jimp/png": "^0.12.1", - "@jimp/tiff": "^0.12.1", - "timm": "^1.6.1" - } - }, - "@jimp/utils": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.12.1.tgz", - "integrity": "sha512-EjPkDQOzV/oZfbolEUgFT6SE++PtCccVBvjuACkttyCfl0P2jnpR49SwstyVLc2u8AwBAZEHHAw9lPYaMjtbXQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "regenerator-runtime": "^0.13.3" - } - }, "@react-native-async-storage/async-storage": { "version": "1.15.5", "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.15.5.tgz", @@ -5598,28 +3310,10 @@ } } }, - "@unimodules/core": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.1.1.tgz", - "integrity": "sha512-Sa7X+WkrhZzcckavjuQu4mq6BTPWsio7OITfoNNzjL0CEmfHfo3DNWQWoVyj+wCgMnjGUT1l3+q3AQlI+CaCLA==", - "dev": true, - "requires": { - "compare-versions": "^3.4.0" - } - }, - "@unimodules/react-native-adapter": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@unimodules/react-native-adapter/-/react-native-adapter-6.2.2.tgz", - "integrity": "sha512-hBXL+IX3u+4TcAHu9lIItdycA7pYWZn3Tt7s5TTna9QKHjyrwo0zVss27LkpJ40tXRHyh/GJ8VzN2CD+0M5I2A==", - "dev": true, - "requires": { - "invariant": "^2.2.4" - } - }, "@xmldom/xmldom": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.3.tgz", - "integrity": "sha512-8XmJdPut2XGtfFcsNsqEsvMUmAwk7xLq7m+E/GcsU9b5qyFFIsiX4Fvnb5UoQ4wo12Wlm07YFJERoyWUYdbIpw==", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", "dev": true }, "abab": { @@ -5782,12 +3476,6 @@ "color-convert": "^1.9.0" } }, - "any-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", - "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", - "dev": true - }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -6533,18 +4221,6 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "blueimp-md5": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.18.0.tgz", - "integrity": "sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q==", - "dev": true - }, - "bmp-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=", - "dev": true - }, "bplist-creator": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", @@ -6610,44 +4286,6 @@ "node-int64": "^0.4.0" } }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -7008,16 +4646,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "colorette": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", @@ -7349,12 +4977,6 @@ "which": "^2.0.1" } }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -7607,12 +5229,6 @@ "esutils": "^2.0.2" } }, - "dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", - "dev": true - }, "domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", @@ -8519,12 +6135,6 @@ } } }, - "exif-parser": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", - "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=", - "dev": true - }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -8761,45 +6371,14 @@ } } }, - "expo-asset": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-8.3.3.tgz", - "integrity": "sha512-qCm5d14tzswY8DcmRJ+0WkY9tc3OiVikBAiw2hCMC+bFpK/bEdqy4Zwfd69MFIAJ0taJpHWhdUoBRO0byQLlfg==", - "dev": true, - "requires": { - "blueimp-md5": "^2.10.0", - "invariant": "^2.2.4", - "md5-file": "^3.2.3", - "path-browserify": "^1.0.0", - "url-parse": "^1.4.4" - } - }, - "expo-constants": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-10.1.3.tgz", - "integrity": "sha512-Eq/xeshnhSoe4ok89d5lrHvI9jq3bMe1FhJUbiHVGcGmW8mGCotwbQBIfDkkMrAKnSOwQq/Qfyg0XBxnG2XFjw==", - "dev": true, - "requires": { - "@expo/config": "^3.3.35", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, "expo-file-system": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-11.1.3.tgz", - "integrity": "sha512-FBRcD6ojrkrZiTZ8O7Fbo833HhZtkhKtLDj4RNZIMpF1i+ZBD2bmeMcfLMeRHNYcBeJno9C4AVXoNQFqDCGQDg==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-13.0.3.tgz", + "integrity": "sha512-i65brB1Nd0upWigXMXrN4YSvj5cP77tB4hNCXoWYVaqRKpUnVlEku2FjQ/xVfIWLJMYrFHHC0Kgz/OKsNzQTpg==", "dev": true, "requires": { - "@expo/config-plugins": "^3.0.0", - "expo-modules-core": "~0.2.0", + "@expo/config-plugins": "^4.0.2", + "expo-modules-core": "~0.4.4", "uuid": "^3.4.0" }, "dependencies": { @@ -8811,23 +6390,15 @@ } } }, - "expo-image-loader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-2.1.1.tgz", - "integrity": "sha512-EeItNIsmw4g+FIb9S9AHE7FAWQkuiIguFMua/RQ2mFHKFZYa/BU32MGagY+e4LzasBVbDKWgd3NHO+EYC6XeEA==", - "dev": true - }, "expo-modules-core": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.2.0.tgz", - "integrity": "sha512-inpfZ5X/BaTtbj2wG9PA9AC0MN8VyId6KSRlVuEg7+ziurHBy/kKDFxpOddUokhwiln2uhoYPSStJjR/tKypdw==", - "dev": true - }, - "expo-permissions": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/expo-permissions/-/expo-permissions-12.0.1.tgz", - "integrity": "sha512-TtypNPPLG4SdVEKBlrArLLZIyhlhE+3B4dhz2HaY1Mve2rcvKE0C7z/e1WoUVU8+LgcdKoNGwg/wRVeCkxeEhg==", - "dev": true + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.4.7.tgz", + "integrity": "sha512-boEbB3tAYO7WkgcaXToQLY8IUeEGOZeDF+StTL38FA0l8jzJwwQLU7TaWjWEMGfxvvn7KP7V7kFudJKc7dak3g==", + "dev": true, + "requires": { + "compare-versions": "^3.4.0", + "invariant": "^2.2.4" + } }, "extend": { "version": "3.0.2", @@ -9007,12 +6578,6 @@ } } }, - "file-type": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", - "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==", - "dev": true - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -9376,16 +6941,6 @@ "is-glob": "^4.0.1" } }, - "global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dev": true, - "requires": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -9632,12 +7187,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -9980,12 +7529,6 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", - "dev": true - }, "is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", @@ -11821,19 +9364,6 @@ "integrity": "sha512-3Zi16h6L5tXDRQJTb221cnRoVG9/9OvreLdLU2/ZjRv/GILL+2Cemt0IKvkowwkDpvouAU1DQPOJ7qaiHeIdrw==", "dev": true }, - "jimp": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.12.1.tgz", - "integrity": "sha512-0soPJif+yjmzmOF+4cF2hyhxUWWpXpQntsm2joJXFFoRcQiPzsG4dbLKYqYPT3Fc6PjZ8MaLtCkDqqckVSfmRw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "@jimp/custom": "^0.12.1", - "@jimp/plugins": "^0.12.1", - "@jimp/types": "^0.12.1", - "regenerator-runtime": "^0.13.3" - } - }, "joi": { "version": "17.4.0", "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.0.tgz", @@ -11847,12 +9377,6 @@ "@sideway/pinpoint": "^2.0.0" } }, - "jpeg-js": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", - "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==", - "dev": true - }, "jquery": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", @@ -12311,22 +9835,6 @@ "uc.micro": "^1.0.1" } }, - "load-bmfont": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", - "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", - "dev": true, - "requires": { - "buffer-equal": "0.0.1", - "mime": "^1.3.4", - "parse-bmfont-ascii": "^1.0.3", - "parse-bmfont-binary": "^1.0.5", - "parse-bmfont-xml": "^1.1.4", - "phin": "^2.9.1", - "xhr": "^2.0.1", - "xtend": "^4.0.0" - } - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -12515,15 +10023,6 @@ "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", "dev": true }, - "md5-file": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", - "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.1.0" - } - }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -13060,15 +10559,6 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "requires": { - "dom-walk": "^0.1.0" - } - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -13425,13 +10915,7 @@ "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" - } - }, - "omggif": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", - "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==", - "dev": true + } }, "on-finished": { "version": "2.3.0", @@ -13621,12 +11105,6 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -13636,34 +11114,6 @@ "callsites": "^3.0.0" } }, - "parse-bmfont-ascii": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", - "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=", - "dev": true - }, - "parse-bmfont-binary": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", - "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=", - "dev": true - }, - "parse-bmfont-xml": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", - "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", - "dev": true, - "requires": { - "xml-parse-from-string": "^1.0.0", - "xml2js": "^0.4.5" - } - }, - "parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==", - "dev": true - }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -13673,23 +11123,6 @@ "error-ex": "^1.2.0" } }, - "parse-png": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", - "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==", - "dev": true, - "requires": { - "pngjs": "^3.3.0" - }, - "dependencies": { - "pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "dev": true - } - } - }, "parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", @@ -13708,12 +11141,6 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -13753,12 +11180,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "phin": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", - "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", - "dev": true - }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -13780,23 +11201,6 @@ "node-modules-regexp": "^1.0.0" } }, - "pixelmatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", - "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", - "dev": true, - "requires": { - "pngjs": "^3.0.0" - }, - "dependencies": { - "pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "dev": true - } - } - }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -13871,12 +11275,6 @@ "xmldom": "^0.5.0" } }, - "pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "dev": true - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -13924,12 +11322,6 @@ } } }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -13999,12 +11391,6 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "ramda": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", @@ -14221,385 +11607,149 @@ "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==", "dev": true }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "dev": true, - "requires": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "dev": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "react-native-codegen": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.6.tgz", - "integrity": "sha512-cMvrUelD81wiPitEPiwE/TCNscIVauXxmt4NTGcy18HrUd0WRWXfYzAQGXm0eI87u3NMudNhqFj2NISJenxQHg==", - "dev": true, - "requires": { - "flow-parser": "^0.121.0", - "jscodeshift": "^0.11.0", - "nullthrows": "^1.1.1" - } - }, - "react-native-performance": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-2.0.0.tgz", - "integrity": "sha512-jKM9Qg0SkL9D9ad377nxb1VV+OXJSyYyIrBHKmM6CABNxfrLVA5xkQMEibjmZQde7b0ndJOZoQAiObgJjjc4VQ==", - "dev": true - }, - "react-native-unimodules": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/react-native-unimodules/-/react-native-unimodules-0.13.3.tgz", - "integrity": "sha512-fjbNbAcvJHF8Ywqe77oveRW1WfaAKCQGV4a3Fxgpai17oNHq1LFwwKw0crFo0k7Njm5u7kCMVNbm9ZILNBfABQ==", - "dev": true, - "requires": { - "@unimodules/core": "~7.1.0", - "@unimodules/react-native-adapter": "~6.2.2", - "chalk": "^2.4.2", - "expo-asset": "~8.3.1", - "expo-constants": "~10.1.3", - "expo-file-system": "~11.0.2", - "expo-image-loader": "~2.1.1", - "expo-permissions": "~12.0.1", - "find-up": "~5.0.0", - "unimodules-app-loader": "~2.1.0", - "unimodules-barcode-scanner-interface": "~6.1.0", - "unimodules-camera-interface": "~6.1.0", - "unimodules-constants-interface": "~6.1.0", - "unimodules-face-detector-interface": "~6.1.0", - "unimodules-file-system-interface": "~6.1.0", - "unimodules-font-interface": "~6.1.0", - "unimodules-image-loader-interface": "~6.1.0", - "unimodules-permissions-interface": "~6.1.0", - "unimodules-sensors-interface": "~6.1.0", - "unimodules-task-manager-interface": "~6.1.0" - }, - "dependencies": { - "@expo/config-plugins": { - "version": "1.0.33", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-1.0.33.tgz", - "integrity": "sha512-YQJop0c69LKD/6ZJJto7klS7TDmzgs44TI0Z5RBqesOjYlDwNFcQk2Rl2BaA1wlAYkH+rRrhN2+WjjSyD9HiPg==", - "dev": true, - "requires": { - "@expo/config-types": "^40.0.0-beta.2", - "@expo/configure-splash-screen": "0.4.0", - "@expo/image-utils": "0.3.14", - "@expo/json-file": "8.2.30", - "@expo/plist": "0.0.13", - "find-up": "~5.0.0", - "fs-extra": "9.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "^0.4.23" - } - }, - "@expo/config-types": { - "version": "40.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-40.0.0-beta.2.tgz", - "integrity": "sha512-t9pHCQMXOP4nwd7LGXuHkLlFy0JdfknRSCAeVF4Kw2/y+5OBbR9hW9ZVnetpBf0kORrekgiI7K/qDaa3hh5+Qg==", - "dev": true - }, - "@expo/json-file": { - "version": "8.2.30", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.30.tgz", - "integrity": "sha512-vrgGyPEXBoFI5NY70IegusCSoSVIFV3T3ry4tjJg1MFQKTUlR7E0r+8g8XR6qC705rc2PawaZQjqXMAVtV6s2A==", - "dev": true, - "requires": { - "@babel/code-frame": "~7.10.4", - "fs-extra": "9.0.0", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - } - }, - "@expo/plist": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.13.tgz", - "integrity": "sha512-zGPSq9OrCn7lWvwLLHLpHUUq2E40KptUFXn53xyZXPViI0k9lbApcR9KlonQZ95C+ELsf0BQ3gRficwK92Ivcw==", - "dev": true, - "requires": { - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0", - "xmldom": "~0.5.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "expo-file-system": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-11.0.2.tgz", - "integrity": "sha512-nodNvUVa+US4N4xnj5BFw8W9ZF/qCHJVC2t45cHWrBiwkVVxz45wjE7uSHUmkMWyWT7a/7AJuL3XJfYp7h90IQ==", - "dev": true, - "requires": { - "@expo/config-plugins": "^1.0.18", - "uuid": "^3.4.0" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - } - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "p-locate": "^5.0.0" + "p-locate": "^4.1.0" } }, "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "yocto-queue": "^0.1.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "p-limit": "^3.0.2" + "p-limit": "^2.2.0" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" } }, - "xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" + "ansi-regex": "^4.1.0" }, "dependencies": { - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true } } }, - "xmlbuilder": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", - "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", - "dev": true + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } } } }, + "react-native-codegen": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.6.tgz", + "integrity": "sha512-cMvrUelD81wiPitEPiwE/TCNscIVauXxmt4NTGcy18HrUd0WRWXfYzAQGXm0eI87u3NMudNhqFj2NISJenxQHg==", + "dev": true, + "requires": { + "flow-parser": "^0.121.0", + "jscodeshift": "^0.11.0", + "nullthrows": "^1.1.1" + } + }, + "react-native-performance": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-2.0.0.tgz", + "integrity": "sha512-jKM9Qg0SkL9D9ad377nxb1VV+OXJSyYyIrBHKmM6CABNxfrLVA5xkQMEibjmZQde7b0ndJOZoQAiObgJjjc4VQ==", + "dev": true + }, "react-refresh": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", @@ -14972,24 +12122,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, "requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", @@ -15489,23 +12627,6 @@ "plist": "^3.0.1" } }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - } - } - }, "simply-deferred": { "version": "git+https://github.com/Expensify/simply-deferred.git#77a08a95754660c7bd6e0b6979fdf84e8e831bf5", "from": "git+https://github.com/Expensify/simply-deferred.git#77a08a95754660c7bd6e0b6979fdf84e8e831bf5" @@ -15533,12 +12654,6 @@ "is-fullwidth-code-point": "^2.0.0" } }, - "slugify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.0.tgz", - "integrity": "sha512-FkMq+MQc5hzYgM86nLuHI98Acwi3p4wX+a5BO9Hhw4JdK4L7WueIiZ4tXEobImPqBz2sVcV0+Mu3GRB30IGang==", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -16190,37 +13305,12 @@ } } }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true - }, "temp-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", "dev": true }, - "tempy": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.3.0.tgz", - "integrity": "sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==", - "dev": true, - "requires": { - "temp-dir": "^1.0.0", - "type-fest": "^0.3.1", - "unique-string": "^1.0.0" - }, - "dependencies": { - "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true - } - } - }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -16291,23 +13381,11 @@ "xtend": "~4.0.1" } }, - "timm": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", - "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==", - "dev": true - }, "tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" }, - "tinycolor2": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", - "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==", - "dev": true - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -16525,72 +13603,6 @@ "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", "dev": true }, - "unimodules-app-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unimodules-app-loader/-/unimodules-app-loader-2.1.0.tgz", - "integrity": "sha512-W+D+hVXq6jOvBm7QVwODPENz6Lupj73QequNNG+6GCTkqn4ybq/lba9IQvJQT2QzdL3luVHin+eym18cDblMlg==", - "dev": true - }, - "unimodules-barcode-scanner-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-barcode-scanner-interface/-/unimodules-barcode-scanner-interface-6.1.0.tgz", - "integrity": "sha512-+McBDniXReXNS8PnGDjIyDikb+cRXSfsZMLsF0gohEEV0xdA6HhPvFA0ryv65j2NKOyIiWmEHjv+yDOoewDq3w==", - "dev": true - }, - "unimodules-camera-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-camera-interface/-/unimodules-camera-interface-6.1.0.tgz", - "integrity": "sha512-Rbszrh54kIB4vA+AzDWFXplBz1UrxQNR6Ls0eJDAKffbjDfyQIP6SgIPjUlzqGVnzknyZ1SMGiFFSFCM4BCOAw==", - "dev": true - }, - "unimodules-constants-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-constants-interface/-/unimodules-constants-interface-6.1.0.tgz", - "integrity": "sha512-uPLFGufbdefRQeINyUfkw2mVJJg+6kH23RR4ATfUAsrD6vGLuONwduHvRwh+rcL9fzPVM4jsfH6iATrolmiatg==", - "dev": true - }, - "unimodules-face-detector-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-face-detector-interface/-/unimodules-face-detector-interface-6.1.0.tgz", - "integrity": "sha512-L2E8a2OjMPxfVh/OGt6Y5HWbEaJ9h3Hkmvx02GCferBPKgN3dcxFMaI53d1BVV9QA3r4YuLBP6RrolG/qy/r7A==", - "dev": true - }, - "unimodules-file-system-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-file-system-interface/-/unimodules-file-system-interface-6.1.0.tgz", - "integrity": "sha512-iJGm6nWF+PhxqFbeqC2Ku4XjglbL9z7aofkSX5S7bZ3Oi4v1NO1UOe9nczU17Ps19sfYZJgkiD4FiQaFCmAnKg==", - "dev": true - }, - "unimodules-font-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-font-interface/-/unimodules-font-interface-6.1.0.tgz", - "integrity": "sha512-OfSeWx9ew2SNENj/HhctfPU7hqeW0bzVZYGGJ0M6RNcRRWzwA6ltawyYwtuvRe/EEU3LwrFUSKPMCi9867hLyw==", - "dev": true - }, - "unimodules-image-loader-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-image-loader-interface/-/unimodules-image-loader-interface-6.1.0.tgz", - "integrity": "sha512-o8hZI6J6DGYyo2xSH6J+ipxME0blNfmaWU3P2Y2AUVxbEPdgjT2sVmufRWMKGhrt7gaNW4xF/JUbF9lq4Rui7w==", - "dev": true - }, - "unimodules-permissions-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-permissions-interface/-/unimodules-permissions-interface-6.1.0.tgz", - "integrity": "sha512-jeJx/y+Vn/Cp1/4su5XJ06UBul83MpXkYEqIOAb2jwaikhmj6tNwko7HpKy9OhfGfrhddCzwtedlro8xxZUk9A==", - "dev": true - }, - "unimodules-sensors-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-sensors-interface/-/unimodules-sensors-interface-6.1.0.tgz", - "integrity": "sha512-tJDOo3p4q4wmhyuwapNjYeON7cd5OSPYr3qDfMgPPg9m6pYM/FdQJ1PKMNb1NJUckpDgQ67Dows2jAdqkNRZSw==", - "dev": true - }, - "unimodules-task-manager-interface": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/unimodules-task-manager-interface/-/unimodules-task-manager-interface-6.1.0.tgz", - "integrity": "sha512-wSsuX5fzd3oCCjHvrRFxysmCswhHZbJflVyAWzgSHtyMgxBOZobGN1C0UQ/plcu/JWY2+maTDPpE9OU6wzzzdg==", - "dev": true - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -16603,15 +13615,6 @@ "set-value": "^2.0.1" } }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -16679,16 +13682,6 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, - "url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -16704,15 +13697,6 @@ "object-assign": "^4.1.1" } }, - "utif": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", - "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", - "dev": true, - "requires": { - "pako": "^1.0.5" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -17018,39 +14002,12 @@ } } }, - "xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", - "dev": true, - "requires": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "xml-js": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", - "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", - "dev": true, - "requires": { - "sax": "^1.2.4" - } - }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, - "xml-parse-from-string": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", - "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=", - "dev": true - }, "xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", diff --git a/package.json b/package.json index 0093a8bf3..dc6f11d19 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "babel-plugin-transform-class-properties": "^6.24.1", "eslint": "^7.6.0", "eslint-config-expensify": "^2.0.11", - "expo-file-system": "^11.1.3", + "expo-file-system": "^13.0.3", "jest": "^26.5.2", "jest-cli": "^26.5.2", "jsdoc-to-markdown": "^7.1.0", @@ -45,16 +45,14 @@ "react": "^17.0.2", "react-native": "0.64.1", "react-native-performance": "^2.0.0", - "react-native-unimodules": "^0.13.3", "react-test-renderer": "16.13.1" }, "peerDependencies": { "@react-native-async-storage/async-storage": "^1.15.5", - "expo-file-system": "^11.1.3", + "expo-file-system": "^13.0.3", "localforage": "^1.10.0", "react": "^17.0.2", - "react-native-performance": "^2.0.0", - "react-native-unimodules": "^0.13.3" + "react-native-performance": "^2.0.0" }, "peerDependenciesMeta": { "react-native-performance": { From 41bed4db8e627038add32a51b4636071a50ef01a Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 1 Nov 2021 23:35:34 +0200 Subject: [PATCH 39/47] Remove accidental JSON.stringify resulted from merge --- lib/Onyx.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 9b1a80c92..d7e6c7e2f 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -534,7 +534,7 @@ function set(key, value) { Promise.resolve().then(() => keyChanged(key, value)); // Write the thing to persistent storage, which will trigger a storage event for any other tabs open on this domain - return Storage.setItem(key, JSON.stringify(value)) + return Storage.setItem(key, value) .catch(error => evictStorageAndRetry(error, set, key, value)); } From fe0646c1b670eb5f6736ec2c2273668e1756bac4 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Tue, 2 Nov 2021 14:55:14 +0200 Subject: [PATCH 40/47] Remove NativeFileHandler, prepareFile and the expo-file-system package --- lib/Onyx.js | 24 -- lib/storage/NativeStorage.js | 36 +-- lib/storage/providers/NativeFileHandler.js | 85 ----- package-lock.json | 349 --------------------- package.json | 2 - 5 files changed, 1 insertion(+), 495 deletions(-) delete mode 100644 lib/storage/providers/NativeFileHandler.js diff --git a/lib/Onyx.js b/lib/Onyx.js index d7e6c7e2f..91f0846e1 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -819,29 +819,6 @@ function init({ } } -/** - * Prepares a file so that it can be saved in Onyx. - * Use this method to get an updated File reference. - * Then save it as usual by Onyx.set or Onyx.merge - * @param {File} file - * @returns {File} - * - * @example - * const preparedFile = Onyx.prepareFile(someFile); - * Onyx.merge('someKey', { - * attachment: preparedFile, - * hasAttachment: true, - * }); - */ -function prepareFile(file) { - // Some storage providers need to prepare the files others can directly save the file - if (_.isFunction(Storage.prepareFile)) { - return Storage.prepareFile(file); - } - - return file; -} - const Onyx = { connect, disconnect, @@ -855,7 +832,6 @@ const Onyx = { addToEvictionBlockList, removeFromEvictionBlockList, isSafeEvictionKey, - prepareFile, }; /** diff --git a/lib/storage/NativeStorage.js b/lib/storage/NativeStorage.js index 5a3279c34..a4aaade0e 100644 --- a/lib/storage/NativeStorage.js +++ b/lib/storage/NativeStorage.js @@ -1,37 +1,3 @@ -/** - * On native we can leave almost everything to AsyncStorage, but files need to be prepared. - * Before files are saved in our key/value storage they should first be copied to - * our "local space" (App Documents) so that they're not lost - image pickers and document - * pickers would move files to cache which can be cleared before we've uploaded them - * - * We don't actually save the file to our key/value store but only the reference to it - */ - import Storage from './providers/AsyncStorage'; -import FileHandler from './providers/NativeFileHandler'; -import {logAlert} from '../Logger'; - -const nativeStorage = { - ...Storage, - - /** - * Prepares a file so that it can be referenced in Onyx key/value storage - * @param {{uri: String, name: String, type: String}} file - * @returns {{uri: String, name: String, type: String}} - */ - prepareFile(file) { - // Create result optimistically so the method can be called synchronously - const uri = FileHandler.getLocalDestination(file); - const optimisticResult = {...file, uri}; - - FileHandler.storeLocally(file) - .catch((error) => { - logAlert(`Failed to store file locally: ${error.message}`); - throw error; - }); - - return optimisticResult; - } -}; -export default nativeStorage; +export default Storage; diff --git a/lib/storage/providers/NativeFileHandler.js b/lib/storage/providers/NativeFileHandler.js deleted file mode 100644 index fc9d070c3..000000000 --- a/lib/storage/providers/NativeFileHandler.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The native FS handler - * We store files in our app's directory space, which does not require special - * permission - */ - -import * as FileSystem from 'expo-file-system'; -import _ from 'underscore'; -import {logAlert} from '../../Logger'; - -const LOCAL_PATH = `${FileSystem.documentDirectory}.onyx_files/`; - -// Create our storage folder -FileSystem.getInfoAsync(LOCAL_PATH) - .then((info) => { - if (info.exists) { - return; - } - - FileSystem.makeDirectoryAsync(LOCAL_PATH) - .catch(error => logAlert(`Failed to create app storage dir: ${error.message}`)); - }); - -/** - * @param {{name: string}} file - * @returns {string} - */ -function getLocalDestination(file) { - return `${LOCAL_PATH}${file.name}`; -} - -/** - * @param{Number} size - * @returns {Number} - */ -function bytesToMB(size) { - return size * (1024 ** 2); -} - -const fileHandler = { - /** - * Create a local copy of a file - * @param {{uri: string, name: string}} file - * @returns {Promise<{uri: string, name: string, type: string}>} A reference to the file stored locally - */ - storeLocally(file) { - const destination = getLocalDestination(file); - - return FileSystem - .copyAsync({from: file.uri, to: destination}) - .then(() => ({...file, uri: destination})); - }, - - /** - * Information about all the files we store locally - * @returns {Promise<{size: number, sizeMB: number, files: string[]}>} - */ - storageDirStats() { - return Promise.all([ - FileSystem.getInfoAsync(LOCAL_PATH, {size: true}), - FileSystem.readDirectoryAsync(LOCAL_PATH), - ]) - .then(([dirInfo, fileNames]) => ({ - ...dirInfo, - sizeMB: bytesToMB(dirInfo.size), - files: _.map(fileNames, name => ({ - name, - uri: getLocalDestination({name}), - })) - })); - }, - - /** - * Remove the file from the local FS - * @param {string|{uri: string}} file - works with either a path or a file object - * @return {Promise} - */ - deleteLocally(file) { - return FileSystem.deleteAsync(file.uri || file, {idempotent: true}); - }, - - getLocalDestination, -}; - -export default fileHandler; diff --git a/package-lock.json b/package-lock.json index f2688fe35..687f15c10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1620,263 +1620,6 @@ "strip-json-comments": "^3.1.1" } }, - "@expo/config-plugins": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.0.6.tgz", - "integrity": "sha512-K/KQaw/CU8uLQgk7sFnZC54YGHoGucKFfdjYeZx5ds2eyzbuMAiKzGFcxZ/S+1dVBZ8QHzwowsVBW3kuYhnQ3Q==", - "dev": true, - "requires": { - "@expo/config-types": "^43.0.1", - "@expo/json-file": "8.2.33", - "@expo/plist": "0.0.15", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "fs-extra": "9.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.3.5", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.4.23" - }, - "dependencies": { - "@react-native/normalize-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-2.0.0.tgz", - "integrity": "sha512-Wip/xsc5lw8vsBlmY2MO/gFLp3MvuZ2baBZjDeTjjndMgM0h5sxz7AZR62RDPGgstp8Np7JzjvVqVT7tpFZqsw==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true - }, - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", - "dev": true - }, - "xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", - "dev": true, - "requires": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" - } - } - } - }, - "@expo/config-types": { - "version": "43.0.1", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-43.0.1.tgz", - "integrity": "sha512-EtllpCGDdB/UdwAIs5YXJwBLpbFQNdlLLrxIvoILA9cXrpQMWkeDCT9lQPJzFRMFcLUaMuGvkzX2tR4tx5EQFQ==", - "dev": true - }, - "@expo/json-file": { - "version": "8.2.33", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.33.tgz", - "integrity": "sha512-CDnhjdirUs6OdN5hOSTJ2y3i9EiJMk7Z5iDljC5xyCHCrUex7oyI8vbRsZEojAahxZccgL/PrO+CjakiFFWurg==", - "dev": true, - "requires": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - } - } - }, - "@expo/plist": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.15.tgz", - "integrity": "sha512-LDxiS0KNZAGJu4fIJhbEKczmb+zeftl1NU0LE0tj0mozoMI5HSKdMUchgvnBm35bwBl8ekKkAfJJ0ONxljWQjQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "~0.7.0", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - }, - "dependencies": { - "xmlbuilder": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", - "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", - "dev": true - } - } - }, "@hapi/hoek": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", @@ -3310,12 +3053,6 @@ } } }, - "@xmldom/xmldom": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", - "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", - "dev": true - }, "abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -3696,12 +3433,6 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -4764,12 +4495,6 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, - "compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -6371,35 +6096,6 @@ } } }, - "expo-file-system": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-13.0.3.tgz", - "integrity": "sha512-i65brB1Nd0upWigXMXrN4YSvj5cP77tB4hNCXoWYVaqRKpUnVlEku2FjQ/xVfIWLJMYrFHHC0Kgz/OKsNzQTpg==", - "dev": true, - "requires": { - "@expo/config-plugins": "^4.0.2", - "expo-modules-core": "~0.4.4", - "uuid": "^3.4.0" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "expo-modules-core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.4.7.tgz", - "integrity": "sha512-boEbB3tAYO7WkgcaXToQLY8IUeEGOZeDF+StTL38FA0l8jzJwwQLU7TaWjWEMGfxvvn7KP7V7kFudJKc7dak3g==", - "dev": true, - "requires": { - "compare-versions": "^3.4.0", - "invariant": "^2.2.4" - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6903,12 +6599,6 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, - "getenv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/getenv/-/getenv-1.0.0.tgz", - "integrity": "sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==", - "dev": true - }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -9948,15 +9638,6 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -14008,24 +13689,6 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "dependencies": { - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - } - } - }, "xmlbuilder": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", @@ -14071,12 +13734,6 @@ "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", @@ -14179,12 +13836,6 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true } } } diff --git a/package.json b/package.json index dc6f11d19..d859a0222 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "babel-plugin-transform-class-properties": "^6.24.1", "eslint": "^7.6.0", "eslint-config-expensify": "^2.0.11", - "expo-file-system": "^13.0.3", "jest": "^26.5.2", "jest-cli": "^26.5.2", "jsdoc-to-markdown": "^7.1.0", @@ -49,7 +48,6 @@ }, "peerDependencies": { "@react-native-async-storage/async-storage": "^1.15.5", - "expo-file-system": "^13.0.3", "localforage": "^1.10.0", "react": "^17.0.2", "react-native-performance": "^2.0.0" From 45ddac448fb76ab2ae4d56cebef1d04e84158daa Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Tue, 2 Nov 2021 19:17:31 +0200 Subject: [PATCH 41/47] WebStorage make keepInstancesSync handle removeItem and clear We need to raise storage events for key removals and when the whole storage is cleared --- lib/storage/WebStorage.js | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/storage/WebStorage.js b/lib/storage/WebStorage.js index 12afd6c94..11576163d 100644 --- a/lib/storage/WebStorage.js +++ b/lib/storage/WebStorage.js @@ -1,5 +1,17 @@ +import _ from 'underscore'; import Storage from './providers/LocalForage'; +const SYNC_ONYX = 'SYNC_ONYX'; + +/** + * Raise an event thorough `localStorage` to let other tabs know a value changed + * @param {String} onyxKey + */ +function raiseStorageSyncEvent(onyxKey) { + global.localStorage.setItem(SYNC_ONYX, onyxKey); + global.localStorage.removeItem(SYNC_ONYX, onyxKey); +} + const webStorage = { ...Storage, @@ -8,19 +20,21 @@ const webStorage = { * @param {function(key: String, data: *)} onStorageKeyChanged */ keepInstancesSync(onStorageKeyChanged) { - const SYNC_ONYX = 'SYNC_ONYX'; - - // Override `setItem` to raise storage events that we intercept in other tabs + // Override set, remove and clear to raise storage events that we intercept in other tabs this.setItem = (key, value) => Storage.setItem(key, value) - .then(() => { - // We raise an event thorough `localStorage` to let other tabs know a value changed - global.localStorage.setItem(SYNC_ONYX, key); - global.localStorage.removeItem(SYNC_ONYX); - }); + .then(() => raiseStorageSyncEvent(key)); + + this.removeItem = key => Storage.removeItem(key) + .then(() => raiseStorageSyncEvent(key)); + + // If we just call Storage.clear other tabs will have no idea which keys were available previously + // so that they can call keysChanged for them. That's why we iterate and remove keys one by one + this.clear = () => Storage.getAllKeys() + .then(keys => _.forEach(keys, key => this.removeItem(key))); // This listener will only be triggered by events coming from other tabs global.addEventListener('storage', (event) => { - // Ignore events that don't originate from the SYNC_ONYX logic above + // Ignore events that don't originate from the SYNC_ONYX logic if (event.key !== SYNC_ONYX || !event.newValue) { return; } From 4c941f8e5ec3b84110bf9a2c5a5a28fd5f724998 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Wed, 3 Nov 2021 22:15:59 +0200 Subject: [PATCH 42/47] WebStorage: wait for all remove calls to finish and then resolve clear In App there's logic that waits for clear and then writes some keys We need to make sure all deleting is over - Promise.all() --- lib/storage/WebStorage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/storage/WebStorage.js b/lib/storage/WebStorage.js index 11576163d..0d2d9d128 100644 --- a/lib/storage/WebStorage.js +++ b/lib/storage/WebStorage.js @@ -30,7 +30,8 @@ const webStorage = { // If we just call Storage.clear other tabs will have no idea which keys were available previously // so that they can call keysChanged for them. That's why we iterate and remove keys one by one this.clear = () => Storage.getAllKeys() - .then(keys => _.forEach(keys, key => this.removeItem(key))); + .then(keys => _.map(keys, key => this.removeItem(key))) + .then(tasks => Promise.all(tasks)); // This listener will only be triggered by events coming from other tabs global.addEventListener('storage', (event) => { From c738e7e6751e74cb15c8840f97a7f383fb561da1 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Wed, 3 Nov 2021 22:19:21 +0200 Subject: [PATCH 43/47] tab-sync cache fix - update cache as well as raise keyChanged We should put the incoming value in cache, because: 1. The original tab changed a value in storage/db 2. The current tab called keyChanged 3. Nothing updates the value in cache 4. If something connects to such a key it will connect to the value in cache --- lib/Onyx.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 91f0846e1..5828ebb14 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -815,7 +815,10 @@ function init({ .then(deferredInitTask.resolve); if (shouldSyncMultipleInstances && _.isFunction(Storage.keepInstancesSync)) { - Storage.keepInstancesSync(keyChanged); + Storage.keepInstancesSync((key, value) => { + cache.set(key, value); + keyChanged(key, value); + }); } } From 9b02f63db4ba6da9baef7de04d92506ed606e831 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Wed, 3 Nov 2021 22:23:02 +0200 Subject: [PATCH 44/47] Move `storage/__mocks__` to the root level mocks --- __mocks__/lib/storage/index.js | 3 +++ lib/storage/__mocks__/index.js | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 __mocks__/lib/storage/index.js delete mode 100644 lib/storage/__mocks__/index.js diff --git a/__mocks__/lib/storage/index.js b/__mocks__/lib/storage/index.js new file mode 100644 index 000000000..97de83c8e --- /dev/null +++ b/__mocks__/lib/storage/index.js @@ -0,0 +1,3 @@ +import WebStorage from '../../../lib/storage/WebStorage'; + +export default WebStorage; diff --git a/lib/storage/__mocks__/index.js b/lib/storage/__mocks__/index.js deleted file mode 100644 index c7d082958..000000000 --- a/lib/storage/__mocks__/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import WebStorage from '../WebStorage'; - -export default WebStorage; From 3d5a67536a5d30fe88f502cae53b6787c6891d51 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Wed, 3 Nov 2021 22:56:53 +0200 Subject: [PATCH 45/47] Small code style cleanup --- lib/Onyx.js | 6 +++--- lib/storage/providers/AsyncStorage.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 5828ebb14..6372e3f35 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -539,12 +539,12 @@ function set(key, value) { } /** - * AsyncStorage expects array like: [["@MyApp_user", "value_1"], ["@MyApp_key", "value_2"]] - * This method transforms an object like {'@MyApp_user': 'myUserValue', '@MyApp_key': 'myKeyValue'} + * Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]] + * This method transforms an object like {'@MyApp_user': myUserValue, '@MyApp_key': myKeyValue} * to an array of key-value pairs in the above format * @private * @param {Record} data - * @return {Array} an array of stringified key - value pairs + * @return {Array<[key, value]>} an array key - value pairs */ function prepareKeyValuePairsForStorage(data) { return _.map(data, (value, key) => [key, value]); diff --git a/lib/storage/providers/AsyncStorage.js b/lib/storage/providers/AsyncStorage.js index c86a1fae1..2e753e53d 100644 --- a/lib/storage/providers/AsyncStorage.js +++ b/lib/storage/providers/AsyncStorage.js @@ -41,7 +41,7 @@ const provider = { */ multiGet(keys) { return AsyncStorage.multiGet(keys) - .then(pairs => pairs.map(([key, value]) => [key, value && JSON.parse(value)])); + .then(pairs => _.map(pairs, ([key, value]) => [key, value && JSON.parse(value)])); }, /** @@ -60,7 +60,7 @@ const provider = { * @return {Promise} */ multiSet(pairs) { - const stringPairs = pairs.map(([key, value]) => [key, prepareValueForStorage(value)]); + const stringPairs = _.map(pairs, ([key, value]) => [key, prepareValueForStorage(value)]); return AsyncStorage.multiSet(stringPairs); }, @@ -70,7 +70,7 @@ const provider = { * @return {Promise} */ multiMerge(pairs) { - const stringPairs = pairs.map(([key, value]) => [key, prepareValueForStorage(value)]); + const stringPairs = _.map(pairs, ([key, value]) => [key, prepareValueForStorage(value)]); return AsyncStorage.multiMerge(stringPairs); }, From 3c8aa3f07041fc1f203ab1e3c5f6e9cd5e77a081 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Wed, 3 Nov 2021 22:58:27 +0200 Subject: [PATCH 46/47] package: remove localforage from dev dependencies --- package-lock.json | 24 ------------------------ package.json | 1 - 2 files changed, 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 687f15c10..41d7a7522 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6889,12 +6889,6 @@ "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==", "dev": true }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true - }, "import-fresh": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", @@ -9501,15 +9495,6 @@ "type-check": "~0.4.0" } }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "dev": true, - "requires": { - "immediate": "~3.0.5" - } - }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -9537,15 +9522,6 @@ "strip-bom": "^3.0.0" } }, - "localforage": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", - "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", - "dev": true, - "requires": { - "lie": "3.1.1" - } - }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", diff --git a/package.json b/package.json index d859a0222..c08ad27fd 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "jest": "^26.5.2", "jest-cli": "^26.5.2", "jsdoc-to-markdown": "^7.1.0", - "localforage": "^1.10.0", "metro-react-native-babel-preset": "^0.61.0", "prop-types": "^15.7.2", "react": "^17.0.2", From 5e95175ba9fe8a872328d6db658f69bea9ba008e Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Wed, 3 Nov 2021 23:30:35 +0200 Subject: [PATCH 47/47] docs: fix typo --- lib/Onyx.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Onyx.js b/lib/Onyx.js index 6372e3f35..216e69a23 100644 --- a/lib/Onyx.js +++ b/lib/Onyx.js @@ -544,7 +544,7 @@ function set(key, value) { * to an array of key-value pairs in the above format * @private * @param {Record} data - * @return {Array<[key, value]>} an array key - value pairs + * @return {Array<[key, value]>} an array of key - value pairs */ function prepareKeyValuePairsForStorage(data) { return _.map(data, (value, key) => [key, value]);