diff --git a/App.tsx b/App.tsx index 8b4afad..77ef005 100644 --- a/App.tsx +++ b/App.tsx @@ -1,9 +1,9 @@ import App from './frontend' import { Buffer as SafeBuffer } from 'safe-buffer' -import SQLite from 'react-native-sqlite-storage' +// import SQLite from 'react-native-sqlite-storage' + +// SQLite.DEBUG(true) global.Buffer = SafeBuffer -SQLite.DEBUG(true) - export default App diff --git a/frontend/Components/ContactsPage/index.tsx b/frontend/Components/ContactsPage/index.tsx index 33820b5..051d356 100644 --- a/frontend/Components/ContactsPage/index.tsx +++ b/frontend/Components/ContactsPage/index.tsx @@ -14,7 +14,7 @@ import { import UserCard from '../UserCard' import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import Relay from '../../lib/nostr/Relay' -import { populatePets, tagToUser } from '../../Functions/RelayFunctions/Users' +import { populatePets } from '../../Functions/RelayFunctions/Users' export const ContactsPage: React.FC = () => { const { database } = useContext(AppContext) @@ -23,22 +23,27 @@ export const ContactsPage: React.FC = () => { const theme = useTheme() const [users, setUsers] = useState() const [refreshing, setRefreshing] = useState(true) - const [showAddContact, setShowAddContant] = useState(false) + const [showAddContact, setShowAddContact] = useState(false) const [contactInput, setContactInput] = useState() + const { t } = useTranslation('common') useEffect(() => { + loadUsers() + }, [lastEventId]) + + useEffect(() => { + subscribeContacts() + }, []) + + const loadUsers: () => void = () => { if (database && publicKey) { getUsers(database, { contacts: true }).then((results) => { if (users) setRefreshing(false) if (results) setUsers(results) }) } - }, [lastEventId]) - - useEffect(() => { - subscribeContacts() - }, []) + } const subscribeContacts: () => Promise = async () => { return await new Promise((resolve, _reject) => { @@ -47,10 +52,6 @@ export const ContactsPage: React.FC = () => { console.log('CONTACTS PAGE EVENT =======>', relay.url, event) if (database && event?.id && event.kind === EventKind.petNames) { insertUserContact(event, database).finally(() => setLastEventId(event?.id ?? '')) - relayPool?.subscribe('main-channel', { - kinds: [EventKind.meta], - authors: event.tags.map((tag) => tagToUser(tag).id), - }) relayPool?.removeOn('event', 'contacts') } }) @@ -68,7 +69,8 @@ export const ContactsPage: React.FC = () => { if (contactInput && relayPool && database && publicKey) { addContact(contactInput, database).then(() => { populatePets(relayPool, database, publicKey) - setShowAddContant(false) + setShowAddContact(false) + loadUsers() }) } } @@ -122,7 +124,7 @@ export const ContactsPage: React.FC = () => { style={styles.modal} visible={showAddContact} backdropStyle={styles.backdrop} - onBackdropPress={() => setShowAddContant(false)} + onBackdropPress={() => setShowAddContact(false)} > @@ -155,7 +157,7 @@ export const ContactsPage: React.FC = () => { backgroundColor: theme['color-warning-500'], borderRadius: 100, }} - onPress={() => setShowAddContant(true)} + onPress={() => setShowAddContact(true)} > diff --git a/frontend/Components/HomePage/index.tsx b/frontend/Components/HomePage/index.tsx index 2797d47..944a88d 100644 --- a/frontend/Components/HomePage/index.tsx +++ b/frontend/Components/HomePage/index.tsx @@ -33,34 +33,35 @@ export const HomePage: React.FC = () => { const calculateInitialNotes: () => Promise = async () => { return await new Promise((resolve) => { if (database && publicKey) { - getNotes(database, { limit: 1 }).then((notes) => { - getUsers(database, { contacts: true, includeIds: [publicKey] }).then((users) => { - setAuthors(users) - subscribeNotes(users, notes[0]?.created_at) - resolve() - }) + getUsers(database, { contacts: true, includeIds: [publicKey] }).then((users) => { + setAuthors(users) + subscribeNotes(users) + resolve() }) } }) } - const subscribeNotes: (users: User[], since?: number, until?: number) => void = ( + const subscribeNotes: (users: User[], past?: boolean) => void = ( users, - since, - until, + past ) => { - const message: RelayFilters = { - kinds: [EventKind.textNote, EventKind.recommendServer], - authors: users.map((user) => user.id), - limit: initialPageSize, - } - if (since) { - message.since = since - } - if (until) { - message.until = until - } - relayPool?.subscribe('main-channel', message) + if (!database || !publicKey) return + const limit = past ? pageSize : 1 + getNotes(database, { contacts: true, includeIds: [publicKey], limit }).then((results) => { + const message: RelayFilters = { + kinds: [EventKind.textNote, EventKind.recommendServer], + authors: users.map((user) => user.id), + limit: initialPageSize, + } + if (past) { + message.until = results[results.length - 1]?.created_at + } else { + message.since = results[0]?.created_at + } + + relayPool?.subscribe('main-channel', message) + }) } const loadNotes: () => void = () => { @@ -88,7 +89,7 @@ export const HomePage: React.FC = () => { useEffect(() => { if (pageSize > initialPageSize) { relayPool?.unsubscribeAll() - subscribeNotes(authors, undefined, notes[notes.length - 1]?.created_at) + subscribeNotes(authors, true) loadNotes() } }, [pageSize]) diff --git a/frontend/Components/LandingPage/Logger/index.tsx b/frontend/Components/LandingPage/Logger/index.tsx index 81259c0..1326431 100644 --- a/frontend/Components/LandingPage/Logger/index.tsx +++ b/frontend/Components/LandingPage/Logger/index.tsx @@ -22,13 +22,30 @@ export const Logger: React.FC = () => { const [loading, setLoading] = useState(false) const [status, setStatus] = useState(0) const [isPrivate, setIsPrivate] = useState(true) - const [totalPets, setTotalPets] = useState() + const [authors, setAuthors] = useState([]) const [inputValue, setInputValue] = useState('') const [loadedUsers, setLoadedUsers] = useState() + const [lastEventId, setLastEventId] = useState('') + + const onPress: () => void = () => { + if (inputValue && inputValue !== '') { + setLoading(true) + setStatus(1) + if (isPrivate) { + setPrivateKey(inputValue) + const publicKey: string = getPublickey(inputValue) + setPublicKey(publicKey) + SInfo.setItem('privateKey', inputValue, {}) + SInfo.setItem('publicKey', publicKey, {}) + } else { + setPublicKey(inputValue) + SInfo.setItem('publicKey', inputValue, {}) + } + } + } useEffect(() => { - if (!loadingRelayPool && publicKey) { - relayPool?.unsubscribeAll() + if (!loadingRelayPool && !loadingDb && publicKey) { setStatus(1) initEvents() relayPool?.subscribe('main-channel', { @@ -38,31 +55,16 @@ export const Logger: React.FC = () => { } }, [loadingRelayPool, publicKey, loadingDb]) - useEffect(() => { - if (status > 2) { - relayPool?.removeOn('event', 'landing') - goToPage('home', true) - } - }, [status]) - - useEffect(() => { - if (status > 1) { - const timer = setTimeout(() => setStatus(3), 8000) - return () => { - clearTimeout(timer) - } - } - }, [status]) - const initEvents: () => void = () => { relayPool?.on('event', 'landing', (_relay: Relay, _subId?: string, event?: Event) => { console.log('LANDING EVENT =======>', event) if (event && database) { + setLastEventId(event?.id ?? '') if (event.kind === EventKind.petNames) { loadPets(event) } else if (event.kind === EventKind.meta) { setLoadedUsers((prev) => (prev ? prev + 1 : 1)) - if (loadedUsers && loadedUsers - 1 === totalPets) setStatus(3) + if (loadedUsers && loadedUsers >= authors.length && status < 3) setStatus(3) } } }) @@ -70,14 +72,13 @@ export const Logger: React.FC = () => { const loadPets: (event: Event) => void = (event) => { if (database) { - setTotalPets(event.tags.length) if (event.tags.length > 0) { setStatus(2) insertUserContact(event, database).then(() => { requestUserData(event) }) } else { - setStatus(3) + setStatus(4) } } } @@ -85,6 +86,7 @@ export const Logger: React.FC = () => { const requestUserData: (event: Event) => void = (event) => { if (publicKey) { const authors: string[] = [publicKey, ...event.tags.map((tag) => tagToUser(tag).id)] + setAuthors(authors) relayPool?.subscribe('main-channel', { kinds: [EventKind.meta], authors, @@ -92,6 +94,25 @@ export const Logger: React.FC = () => { } } + useEffect(() => { + if (status > 3) { + relayPool?.removeOn('event', 'landing') + goToPage('home', true) + } else if (status === 2) { + relayPool?.subscribe('main-channel', { + kinds: [EventKind.textNote, EventKind.recommendServer], + authors, + limit: 15 + }) + } + if (status > 1) { + const timer = setTimeout(() => setStatus(status + 1), 5000) + return () => { + clearTimeout(timer) + } + } + }, [status, lastEventId]) + const randomKeyGenerator: () => JSX.Element = () => { if (!isPrivate) return <> @@ -119,28 +140,12 @@ export const Logger: React.FC = () => { ) } - const onPress: () => void = () => { - if (inputValue && inputValue !== '') { - setLoading(true) - setStatus(1) - if (isPrivate) { - setPrivateKey(inputValue) - const publicKey: string = getPublickey(inputValue) - setPublicKey(publicKey) - SInfo.setItem('privateKey', inputValue, {}) - SInfo.setItem('publicKey', publicKey, {}) - } else { - setPublicKey(inputValue) - SInfo.setItem('publicKey', inputValue, {}) - } - } - } - const statusName: { [status: number]: string } = { 0: t('landing.connect'), 1: t('landing.connecting'), 2: t('landing.loadingContacts'), - 3: t('landing.ready'), + 3: t('landing.loadingEvents'), + 4: t('landing.ready'), } const styles = StyleSheet.create({ inputsContainer: { diff --git a/frontend/Components/NoteCard/index.tsx b/frontend/Components/NoteCard/index.tsx index be246e3..7ea0b6e 100644 --- a/frontend/Components/NoteCard/index.tsx +++ b/frontend/Components/NoteCard/index.tsx @@ -61,7 +61,7 @@ export const NoteCard: React.FC = ({ note }) => { {note.content} - {moment.unix(note.created_at).format('DD-MM-YYYY HH:MM')} + {moment.unix(note.created_at).format('DD-MM-YY hh:mm')} diff --git a/frontend/Components/ProfilePage/index.tsx b/frontend/Components/ProfilePage/index.tsx index 488d641..76adf54 100644 --- a/frontend/Components/ProfilePage/index.tsx +++ b/frontend/Components/ProfilePage/index.tsx @@ -49,38 +49,22 @@ export const ProfilePage: React.FC = () => { const username = user?.name === '' ? user?.id : user?.name useEffect(() => { - if (page !== '') { - setContactsIds(undefined) - setNotes(undefined) - setUser(undefined) - loadProfile() - } - }, [page]) - - useEffect(() => { - loadUser() - loadNotes() - }, [lastEventId]) - - useEffect(() => { - if (pageSize > initialPageSize && notes) { - relayPool?.unsubscribeAll() - loadUser() - loadNotes() - subscribeNotes(undefined, notes[notes.length - 1]?.created_at) - } - }, [pageSize]) - - const onRefresh = useCallback(() => { setRefreshing(true) relayPool?.unsubscribeAll() - loadProfile().finally(() => setRefreshing(false)) - }, []) + setContactsIds(undefined) + setNotes(undefined) + setUser(undefined) + + loadUser() + loadNotes() + subscribeNotes() + }, [page]) const loadUser: () => void = () => { if (database) { getUser(userId, database).then((result) => { if (result) { + subscribeProfile() setUser(result) setIsContact(result?.contact) } @@ -88,6 +72,78 @@ export const ProfilePage: React.FC = () => { } } + const loadNotes: (past?: boolean) => void = (past) => { + if (database) { + getNotes(database, { filters: { pubkey: userId }, limit: pageSize }).then((results) => { + setNotes(results) + setRefreshing(false) + }) + } + } + + const subscribeNotes: (past?: boolean) => void = (past) => { + if (!database) return + const limit = past ? pageSize : 1 + getNotes(database, { filters: { pubkey: userId }, limit }).then((results) => { + const message: RelayFilters = { + kinds: [EventKind.textNote, EventKind.recommendServer], + authors: [userId], + limit: initialPageSize, + } + if (past) { + message.until = results[results.length - 1]?.created_at + } else { + message.since = results[0]?.created_at + } + + relayPool?.subscribe('main-channel', message) + }) + } + + const subscribeProfile: () => Promise = async () => { + return await new Promise((resolve) => { + relayPool?.subscribe('main-channel', { + kinds: [EventKind.meta, EventKind.petNames], + authors: [userId], + }) + relayPool?.on('event', 'profile', (_relay: Relay, _subId?: string, event?: Event) => { + console.log('PROFILE EVENT =======>', event) + if (database) { + if (event?.id && event.pubkey === userId) { + if (event.kind === EventKind.petNames) { + const ids = event.tags.map((tag) => tagToUser(tag).id) + setContactsIds(ids) + } else if (event.kind === EventKind.meta) { + storeEvent(event, database).then(() => setRefreshing(false)) + } + } + } + }) + resolve() + }) + } + + useEffect(() => { + if (notes) { + loadUser() + loadNotes() + } + }, [lastEventId]) + + useEffect(() => { + if (pageSize > initialPageSize && notes) { + loadUser() + loadNotes() + subscribeNotes(true) + } + }, [pageSize]) + + const onRefresh = useCallback(() => { + setRefreshing(true) + relayPool?.unsubscribeAll() + loadNotes(true) + }, []) + const removeAuthor: () => void = () => { if (relayPool && database && publicKey) { removeContact(userId, database).then(() => { @@ -156,69 +212,6 @@ export const ProfilePage: React.FC = () => { } } - const loadNotes: () => void = () => { - if (database) { - getNotes(database, { filters: { pubkey: userId }, limit: pageSize }).then((results) => { - if (results.length > 0) setNotes(results) - }) - } - } - - const subscribeNotes: (since?: number, until?: number) => void = (since, until) => { - const message: RelayFilters = { - kinds: [EventKind.textNote, EventKind.recommendServer], - authors: [userId], - limit: initialPageSize, - } - if (since) { - message.since = since - } - if (until) { - message.until = until - } - relayPool?.subscribe('main-channel', message) - } - - const calculateInitialNotes: () => void = () => { - if (database) { - getNotes(database, { filters: { pubkey: userId }, limit: pageSize }).then((results) => { - if (results) { - subscribeNotes(results[0]?.created_at) - } - }) - } - } - - const loadProfile: () => Promise = async () => { - return await new Promise((resolve) => { - relayPool?.subscribe('main-channel', { - kinds: [EventKind.meta, EventKind.petNames], - authors: [userId], - }) - relayPool?.on('event', 'profile', (_relay: Relay, _subId?: string, event?: Event) => { - console.log('PROFILE EVENT =======>', event) - if (database) { - if (event?.id && event.pubkey === userId) { - if (event.kind === EventKind.petNames) { - const ids = event.tags.map((tag) => tagToUser(tag).id) - setContactsIds(ids) - } else if (event.kind === EventKind.meta) { - storeEvent(event, database) - } - calculateInitialNotes() - } - } - }) - resolve() - }) - } - - const onScroll: (event: NativeSyntheticEvent) => void = (event) => { - if (handleInfinityScroll(event)) { - setPageSize(pageSize + initialPageSize) - } - } - const styles = StyleSheet.create({ list: { flex: 1, @@ -302,6 +295,13 @@ export const ProfilePage: React.FC = () => { return false } + const onScroll: (event: NativeSyntheticEvent) => void = (event) => { + if (handleInfinityScroll(event)) { + const newSize: number = notes?.length === pageSize ? pageSize + initialPageSize : pageSize + setPageSize(newSize) + } + } + const stats: () => JSX.Element = () => { if (contactsIds === undefined) { return ( @@ -339,7 +339,7 @@ export const ProfilePage: React.FC = () => { {user ? ( <> { /> {profile} - {notes ? ( + {notes && notes.length > 0 ? ( { if (publicKey && publicKey !== '') { - loadRelayPool() + if (!loadingRelayPool && page !== 'landing') { + goToPage('home', true) + } else { + loadRelayPool() + } } - }, [publicKey]) + }, [publicKey, loadingRelayPool]) useEffect(() => { if (!loadingDb) { SInfo.getItem('privateKey', {}).then((privateResult) => { if (privateResult && privateResult !== '') { - goToPage('home', true) setPrivateKey(privateResult) setPublicKey(getPublickey(privateResult)) } else { SInfo.getItem('publicKey', {}).then((publicResult) => { if (publicResult && publicResult !== '') { - goToPage('home', true) setPublicKey(publicResult) } else { goToPage('landing', true) diff --git a/frontend/Locales/en.json b/frontend/Locales/en.json index 0aec4f3..d571dcd 100644 --- a/frontend/Locales/en.json +++ b/frontend/Locales/en.json @@ -4,6 +4,7 @@ "connect": "Connect", "connecting": "Connecting", "loadingContacts": "Loading Contacts", + "loadingEvents": "Loading Events", "ready": "Ready", "privateKey": "Private Key", "publicKey": "Public Key" diff --git a/frontend/lib/nostr/RelayPool/intex.ts b/frontend/lib/nostr/RelayPool/intex.ts index 1b5d41f..83a90cb 100644 --- a/frontend/lib/nostr/RelayPool/intex.ts +++ b/frontend/lib/nostr/RelayPool/intex.ts @@ -1,3 +1,4 @@ +// import { spawnThread } from 'react-native-multithreading' import { signEvent, validateEvent, Event } from '../Events' import Relay, { RelayFilters, RelayOptions } from '../Relay' @@ -41,9 +42,9 @@ class RelayPool { Object.keys(this.onFunctions.open).forEach((id) => this.onFunctions.open[id](openRelay)) } relay.onEvent = (eventRelay, subId, event) => { - Object.keys(this.onFunctions.event).forEach((id) => - this.onFunctions.event[id](eventRelay, subId, event), - ) + Object.keys(this.onFunctions.event).forEach((id) => { + this.onFunctions.event[id](eventRelay, subId, event) + }) } relay.onEsoe = (eventRelay, subId) => { Object.keys(this.onFunctions.esoe).forEach((id) => diff --git a/package.json b/package.json index 8e4af3d..ddbbccb 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "react-native-bidirectional-infinite-scroll": "^0.3.3", "react-native-flash-message": "^0.3.1", "react-native-markdown-display": "^7.0.0-alpha.2", + "react-native-multithreading": "^1.1.1", + "react-native-reanimated": "^2.12.0", "react-native-securerandom": "^1.0.1", "react-native-sensitive-info": "^5.5.8", "react-native-sqlite-storage": "^6.0.1", diff --git a/yarn.lock b/yarn.lock index d2814fc..f0427ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -579,6 +579,13 @@ "@babel/helper-create-regexp-features-plugin" "^7.19.0" "@babel/helper-plugin-utils" "^7.19.0" +"@babel/plugin-transform-object-assign@^7.16.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.18.6.tgz#7830b4b6f83e1374a5afb9f6111bcfaea872cdd2" + integrity sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-transform-object-super@^7.0.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" @@ -700,7 +707,7 @@ "@babel/helper-validator-option" "^7.18.6" "@babel/plugin-transform-flow-strip-types" "^7.18.6" -"@babel/preset-typescript@^7.13.0": +"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.7": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== @@ -1427,6 +1434,11 @@ dependencies: "@types/node" "*" +"@types/invariant@^2.2.35": + version "2.2.35" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" + integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" @@ -4935,6 +4947,11 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + lodash.merge@^4.6.1, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -6106,6 +6123,24 @@ react-native-markdown-display@^7.0.0-alpha.2: prop-types "^15.7.2" react-native-fit-image "^1.5.5" +react-native-multithreading@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/react-native-multithreading/-/react-native-multithreading-1.1.1.tgz#e1522ecd56115993d444a69c21bca49ca123bf4e" + integrity sha512-ceJQRZAPjH5LfrDjb5svF4F18Ne7QR7QLQUFO0huAe+9w0hd2C3PR12ATxljo+590GXCzWRt2ruR9pY3EstFAQ== + +react-native-reanimated@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.12.0.tgz#5821eecfb1769b1617a67a2d4dec12fdeedb2b6e" + integrity sha512-nrlPyw+Hx9u4iJhZk9PoTvDo/QmVAd+bo7OK9Tv3hveNEF9++5oig/g3Uv9V93shy9avTYGsUprUvAEt/xdzeQ== + dependencies: + "@babel/plugin-transform-object-assign" "^7.16.7" + "@babel/preset-typescript" "^7.16.7" + "@types/invariant" "^2.2.35" + invariant "^2.2.4" + lodash.isequal "^4.5.0" + setimmediate "^1.0.5" + string-hash-64 "^1.0.3" + react-native-securerandom@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/react-native-securerandom/-/react-native-securerandom-1.0.1.tgz#dc983cce980c80d1af62406e2ef2917ed0ada55f" @@ -6548,6 +6583,11 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" @@ -6773,6 +6813,11 @@ stream@^0.0.2: dependencies: emitter-component "^1.1.1" +string-hash-64@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322" + integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"