Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial feature gating and A/B testing integration (#3122)

* Add statsig dependency

* Add SDK provider

* Move to separate file, add tier and hashing

* Disable local storage for now

* Add initial gate testing fixture

* Fork for web just in case

* More WIP

* wip

* Rm test gate

* Add shim on native

* Clarify

authored by

dan and committed by
GitHub
eb298d2e 26fc0cf6

+259 -33
+2
package.json
··· 179 179 "react-responsive": "^9.0.2", 180 180 "rn-fetch-blob": "^0.12.0", 181 181 "sentry-expo": "~7.0.1", 182 + "statsig-react": "^1.36.0", 183 + "statsig-react-native-expo": "^4.6.1", 182 184 "tippy.js": "^6.3.7", 183 185 "tlds": "^1.234.0", 184 186 "use-deep-compare": "^1.1.0",
+18 -15
src/App.native.tsx
··· 43 43 import * as persisted from '#/state/persisted' 44 44 import {Splash} from '#/Splash' 45 45 import {Provider as PortalProvider} from '#/components/Portal' 46 + import {Provider as StatsigProvider} from '#/lib/statsig/statsig' 46 47 import {msg} from '@lingui/macro' 47 48 import {useLingui} from '@lingui/react' 48 49 import {useIntentHandler} from 'lib/hooks/useIntentHandler' ··· 77 78 <React.Fragment 78 79 // Resets the entire tree below when it changes: 79 80 key={currentAccount?.did}> 80 - <LoggedOutViewProvider> 81 - <SelectedFeedProvider> 82 - <UnreadNotifsProvider> 83 - <ThemeProvider theme={theme}> 84 - {/* All components should be within this provider */} 85 - <RootSiblingParent> 86 - <GestureHandlerRootView style={s.h100pct}> 87 - <TestCtrls /> 88 - <Shell /> 89 - </GestureHandlerRootView> 90 - </RootSiblingParent> 91 - </ThemeProvider> 92 - </UnreadNotifsProvider> 93 - </SelectedFeedProvider> 94 - </LoggedOutViewProvider> 81 + <StatsigProvider> 82 + <LoggedOutViewProvider> 83 + <SelectedFeedProvider> 84 + <UnreadNotifsProvider> 85 + <ThemeProvider theme={theme}> 86 + {/* All components should be within this provider */} 87 + <RootSiblingParent> 88 + <GestureHandlerRootView style={s.h100pct}> 89 + <TestCtrls /> 90 + <Shell /> 91 + </GestureHandlerRootView> 92 + </RootSiblingParent> 93 + </ThemeProvider> 94 + </UnreadNotifsProvider> 95 + </SelectedFeedProvider> 96 + </LoggedOutViewProvider> 97 + </StatsigProvider> 95 98 </React.Fragment> 96 99 </Splash> 97 100 </Alf>
+18 -15
src/App.web.tsx
··· 32 32 import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread' 33 33 import * as persisted from '#/state/persisted' 34 34 import {Provider as PortalProvider} from '#/components/Portal' 35 + import {Provider as StatsigProvider} from '#/lib/statsig/statsig' 35 36 import {useIntentHandler} from 'lib/hooks/useIntentHandler' 36 37 37 38 function InnerApp() { ··· 54 55 <React.Fragment 55 56 // Resets the entire tree below when it changes: 56 57 key={currentAccount?.did}> 57 - <LoggedOutViewProvider> 58 - <SelectedFeedProvider> 59 - <UnreadNotifsProvider> 60 - <ThemeProvider theme={theme}> 61 - {/* All components should be within this provider */} 62 - <RootSiblingParent> 63 - <SafeAreaProvider> 64 - <Shell /> 65 - </SafeAreaProvider> 66 - </RootSiblingParent> 67 - <ToastContainer /> 68 - </ThemeProvider> 69 - </UnreadNotifsProvider> 70 - </SelectedFeedProvider> 71 - </LoggedOutViewProvider> 58 + <StatsigProvider> 59 + <LoggedOutViewProvider> 60 + <SelectedFeedProvider> 61 + <UnreadNotifsProvider> 62 + <ThemeProvider theme={theme}> 63 + {/* All components should be within this provider */} 64 + <RootSiblingParent> 65 + <SafeAreaProvider> 66 + <Shell /> 67 + </SafeAreaProvider> 68 + </RootSiblingParent> 69 + <ToastContainer /> 70 + </ThemeProvider> 71 + </UnreadNotifsProvider> 72 + </SelectedFeedProvider> 73 + </LoggedOutViewProvider> 74 + </StatsigProvider> 72 75 </React.Fragment> 73 76 </Alf> 74 77 )
+11
src/lib/statsig/statsig.tsx
··· 1 + import React from 'react' 2 + 3 + export function useGate(_gateName: string) { 4 + // Not enabled for native yet. 5 + return false 6 + } 7 + 8 + export function Provider({children}: {children: React.ReactNode}) { 9 + // Not enabled for native yet. 10 + return children 11 + }
+51
src/lib/statsig/statsig.web.tsx
··· 1 + import React from 'react' 2 + import {StatsigProvider, useGate as useStatsigGate} from 'statsig-react' 3 + import {useSession} from '../../state/session' 4 + import {sha256} from 'js-sha256' 5 + 6 + const statsigOptions = { 7 + environment: { 8 + tier: process.env.NODE_ENV === 'development' ? 'development' : 'production', 9 + }, 10 + // Don't block on waiting for network. The fetched config will kick in on next load. 11 + // This ensures the UI is always consistent and doesn't update mid-session. 12 + // Note this makes cold load (no local storage) and private mode return `false` for all gates. 13 + initTimeoutMs: 1, 14 + } 15 + 16 + export function useGate(gateName: string) { 17 + const {isLoading, value} = useStatsigGate(gateName) 18 + if (isLoading) { 19 + // This should not happen because of waitForInitialization={true}. 20 + console.error('Did not expected isLoading to ever be true.') 21 + } 22 + return value 23 + } 24 + 25 + function toStatsigUser(did: string | undefined) { 26 + let userID: string | undefined 27 + if (did) { 28 + userID = sha256(did) 29 + } 30 + return {userID} 31 + } 32 + 33 + export function Provider({children}: {children: React.ReactNode}) { 34 + const {currentAccount} = useSession() 35 + const currentStatsigUser = React.useMemo( 36 + () => toStatsigUser(currentAccount?.did), 37 + [currentAccount?.did], 38 + ) 39 + return ( 40 + <StatsigProvider 41 + sdkKey="client-SXJakO39w9vIhl3D44u8UupyzFl4oZ2qPIkjwcvuPsV" 42 + mountKey={currentStatsigUser.userID} 43 + user={currentStatsigUser} 44 + // This isn't really blocking due to short initTimeoutMs above. 45 + // However, it ensures `isLoading` is always `false`. 46 + waitForInitialization={true} 47 + options={statsigOptions}> 48 + {children} 49 + </StatsigProvider> 50 + ) 51 + }
+159 -3
yarn.lock
··· 3115 3115 xcode "^3.0.1" 3116 3116 xml2js "0.6.0" 3117 3117 3118 + "@expo/config-plugins@~5.0.3": 3119 + version "5.0.4" 3120 + resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-5.0.4.tgz#216fea6558fe66615af1370de55193f4181cb23e" 3121 + integrity sha512-vzUcVpqOMs3h+hyRdhGwk+eGIOhXa5xYdd92yO17RMNHav3v/+ekMbs7XA2c3lepMO8Yd4/5hqmRw9ZTL6jGzg== 3122 + dependencies: 3123 + "@expo/config-types" "^47.0.0" 3124 + "@expo/json-file" "8.2.36" 3125 + "@expo/plist" "0.0.18" 3126 + "@expo/sdk-runtime-versions" "^1.0.0" 3127 + "@react-native/normalize-color" "^2.0.0" 3128 + chalk "^4.1.2" 3129 + debug "^4.3.1" 3130 + find-up "~5.0.0" 3131 + getenv "^1.0.0" 3132 + glob "7.1.6" 3133 + resolve-from "^5.0.0" 3134 + semver "^7.3.5" 3135 + slash "^3.0.0" 3136 + xcode "^3.0.1" 3137 + xml2js "0.4.23" 3138 + 3118 3139 "@expo/config-plugins@~7.8.2": 3119 3140 version "7.8.2" 3120 3141 resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.8.2.tgz#c00ce93c4d6c2cb9e345ed9cd56ceeea05ab8ddb" ··· 3138 3159 xcode "^3.0.1" 3139 3160 xml2js "0.6.0" 3140 3161 3162 + "@expo/config-types@^47.0.0": 3163 + version "47.0.0" 3164 + resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-47.0.0.tgz#99eeabe0bba7a776e0f252b78beb0c574692c38d" 3165 + integrity sha512-r0pWfuhkv7KIcXMUiNACJmJKKwlTBGMw9VZHNdppS8/0Nve8HZMTkNRFQzTHW1uH3pBj8jEXpyw/2vSWDHex9g== 3166 + 3141 3167 "@expo/config-types@^50.0.0", "@expo/config-types@^50.0.0-alpha.1": 3142 3168 version "50.0.0" 3143 3169 resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-50.0.0.tgz#b534d3ec997ec60f8af24f6ad56244c8afc71a0b" ··· 3160 3186 slugify "^1.3.4" 3161 3187 sucrase "^3.20.0" 3162 3188 3189 + "@expo/config@~7.0.0": 3190 + version "7.0.3" 3191 + resolved "https://registry.yarnpkg.com/@expo/config/-/config-7.0.3.tgz#c9c634e76186de25e296485e51418f1e52966e6e" 3192 + integrity sha512-joVtB5o+NF40Tmsdp65UzryRtbnCuMbXkVO4wJnNJO4aaK0EYLdHCYSewORVqNcDfGN0LphQr8VTG2npbd9CJA== 3193 + dependencies: 3194 + "@babel/code-frame" "~7.10.4" 3195 + "@expo/config-plugins" "~5.0.3" 3196 + "@expo/config-types" "^47.0.0" 3197 + "@expo/json-file" "8.2.36" 3198 + getenv "^1.0.0" 3199 + glob "7.1.6" 3200 + require-from-string "^2.0.2" 3201 + resolve-from "^5.0.0" 3202 + semver "7.3.2" 3203 + slugify "^1.3.4" 3204 + sucrase "^3.20.0" 3205 + 3163 3206 "@expo/config@~8.5.0": 3164 3207 version "8.5.0" 3165 3208 resolved "https://registry.yarnpkg.com/@expo/config/-/config-8.5.0.tgz#c618e016c3272335e33fec02fb7fd67e4dcc3342" ··· 3259 3302 semver "7.3.2" 3260 3303 tempy "0.3.0" 3261 3304 3305 + "@expo/json-file@8.2.36": 3306 + version "8.2.36" 3307 + resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.36.tgz#62a505cb7f30a34d097386476794680a3f7385ff" 3308 + integrity sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ== 3309 + dependencies: 3310 + "@babel/code-frame" "~7.10.4" 3311 + json5 "^1.0.1" 3312 + write-file-atomic "^2.3.0" 3313 + 3262 3314 "@expo/json-file@^8.2.37": 3263 3315 version "8.2.37" 3264 3316 resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049" ··· 3327 3379 npm-package-arg "^7.0.0" 3328 3380 split "^1.0.1" 3329 3381 sudo-prompt "9.1.1" 3382 + 3383 + "@expo/plist@0.0.18": 3384 + version "0.0.18" 3385 + resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.18.tgz#9abcde78df703a88f6d9fa1a557ee2f045d178b0" 3386 + integrity sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w== 3387 + dependencies: 3388 + "@xmldom/xmldom" "~0.7.0" 3389 + base64-js "^1.2.3" 3390 + xmlbuilder "^14.0.0" 3330 3391 3331 3392 "@expo/plist@^0.1.0": 3332 3393 version "0.1.0" ··· 4750 4811 dependencies: 4751 4812 merge-options "^3.0.4" 4752 4813 4814 + "@react-native-async-storage/async-storage@^1.15.2": 4815 + version "1.22.0" 4816 + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.22.0.tgz#202a9afd15a5b829c39b709d0ca3942612441efc" 4817 + integrity sha512-b5KD010iiZnot86RbAaHpLuHwmPW2qA3SSN/OSZhd1kBoINEQEVBuv+uFtcaTxAhX27bT0wd13GOb2IOSDUXSA== 4818 + dependencies: 4819 + merge-options "^3.0.4" 4820 + 4753 4821 "@react-native-camera-roll/camera-roll@^5.2.2": 4754 4822 version "5.7.2" 4755 4823 resolved "https://registry.yarnpkg.com/@react-native-camera-roll/camera-roll/-/camera-roll-5.7.2.tgz#db11525ae26c8a61630c424aebd323a7c784a921" ··· 8124 8192 resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" 8125 8193 integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== 8126 8194 8127 - "@xmldom/xmldom@~0.7.7": 8195 + "@xmldom/xmldom@~0.7.0", "@xmldom/xmldom@~0.7.7": 8128 8196 version "0.7.13" 8129 8197 resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.13.tgz#ff34942667a4e19a9f4a0996a76814daac364cf3" 8130 8198 integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g== ··· 11737 11805 dependencies: 11738 11806 invariant "^2.2.4" 11739 11807 11808 + expo-constants@^13.0.2: 11809 + version "13.2.4" 11810 + resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-13.2.4.tgz#eab4a553f074b2c60ad7a158d3b82e3484a94606" 11811 + integrity sha512-Zobau8EuTk2GgafwkfGnWM6CmSLB7X8qnQXVuXe0nd3v92hfQUmRWGhJwH88uxXj3LrfqctM6PaJ8taG1vxfBw== 11812 + dependencies: 11813 + "@expo/config" "~7.0.0" 11814 + uuid "^3.3.2" 11815 + 11740 11816 expo-constants@~15.4.0: 11741 11817 version "15.4.1" 11742 11818 resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-15.4.1.tgz#f76f347cf687b6630e1e3b9a385a4e42771671a4" ··· 11786 11862 expo-dev-menu-interface "1.7.2" 11787 11863 semver "^7.5.3" 11788 11864 11865 + expo-device@~4.1.1: 11866 + version "4.1.1" 11867 + resolved "https://registry.yarnpkg.com/expo-device/-/expo-device-4.1.1.tgz#5de94144113ffb7fa0f37fa3d70e452113954c10" 11868 + integrity sha512-It0SGtKcvzQSf+Co6zdPdB63zZvG2/rDolB1lqswMNKj03Y7KVU41s5tcQCqNczj7tmeN3CJy7A8YhYGKdb7gA== 11869 + dependencies: 11870 + ua-parser-js "^0.7.19" 11871 + 11789 11872 expo-device@~5.9.2: 11790 11873 version "5.9.2" 11791 11874 resolved "https://registry.yarnpkg.com/expo-device/-/expo-device-5.9.2.tgz#697e96f52d213a141b6f265f1e274e9d5e98c92c" ··· 14978 15061 dependencies: 14979 15062 easy-stack "^1.0.1" 14980 15063 15064 + js-sha256@^0.10.1: 15065 + version "0.10.1" 15066 + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.10.1.tgz#b40104ba1368e823fdd5f41b66b104b15a0da60d" 15067 + integrity sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw== 15068 + 15069 + js-sha256@^0.11.0: 15070 + version "0.11.0" 15071 + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.11.0.tgz#256a921d9292f7fe98905face82e367abaca9576" 15072 + integrity sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q== 15073 + 14981 15074 js-sha256@^0.9.0: 14982 15075 version "0.9.0" 14983 15076 resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" ··· 15162 15255 resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 15163 15256 integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== 15164 15257 15165 - json5@^1.0.2: 15258 + json5@^1.0.1, json5@^1.0.2: 15166 15259 version "1.0.2" 15167 15260 resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" 15168 15261 integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== ··· 18503 18596 lodash "^4.17.21" 18504 18597 prop-types "^15.7.2" 18505 18598 18599 + react-native-get-random-values@^1.6.0: 18600 + version "1.10.0" 18601 + resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.10.0.tgz#c2c5f12a4ef8b1175145347b4a4b9f9a40d9ffc8" 18602 + integrity sha512-gZ1zbXhbb8+Jy9qYTV8c4Nf45/VB4g1jmXuavY5rPfUn7x3ok9Vl3FTl0dnE92Z4FFtfbUNNwtSfcmomdtWg+A== 18603 + dependencies: 18604 + fast-base64-decode "^1.0.0" 18605 + 18506 18606 react-native-get-random-values@~1.8.0: 18507 18607 version "1.8.0" 18508 18608 resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.8.0.tgz#1cb4bd4bd3966a356e59697b8f372999fe97cb16" ··· 19976 20076 resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" 19977 20077 integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== 19978 20078 20079 + statsig-js@4.45.1: 20080 + version "4.45.1" 20081 + resolved "https://registry.yarnpkg.com/statsig-js/-/statsig-js-4.45.1.tgz#b1f5b9c52adc4a8aece376fb011416c89227932f" 20082 + integrity sha512-h94RzFQsJCQCNwQXpZ9OBXcvCxDnkXF6OrCekd81ySvY2l4JSowpxMWX3Iw6IDFzfTfKdER9JQzFLhMSQbT+YQ== 20083 + dependencies: 20084 + js-sha256 "^0.10.1" 20085 + uuid "^8.3.2" 20086 + 20087 + statsig-js@4.49.0: 20088 + version "4.49.0" 20089 + resolved "https://registry.yarnpkg.com/statsig-js/-/statsig-js-4.49.0.tgz#8470a9ac218a93d36f4b7b306ff9377e48064740" 20090 + integrity sha512-N4drx6fzI168Q4NndFY3IJbSDqpWSBWvS290H/RnT/g3Et58SvtXzG5qqgzmqy4CwcmwH+IL8K15pL7hPnfvUQ== 20091 + dependencies: 20092 + js-sha256 "^0.11.0" 20093 + uuid "^8.3.2" 20094 + 20095 + statsig-react-native-expo@^4.6.1: 20096 + version "4.6.1" 20097 + resolved "https://registry.yarnpkg.com/statsig-react-native-expo/-/statsig-react-native-expo-4.6.1.tgz#0bdf49fee7112f7f28bff2405f4ba0c1727bb3d6" 20098 + integrity sha512-rB60c+WSrQPmjW9j75d+acUtwSOe38PE2KTDHiOv1Mf+0TCcFtGYlJmKCibWvbeXR7ZAyjjGeroh23bCSEZauQ== 20099 + dependencies: 20100 + "@react-native-async-storage/async-storage" "^1.15.2" 20101 + expo-constants "^13.0.2" 20102 + expo-device "~4.1.1" 20103 + js-sha256 "^0.9.0" 20104 + react-native-get-random-values "^1.6.0" 20105 + statsig-react "^1.21.1" 20106 + uuid "^8.3.2" 20107 + 20108 + statsig-react@^1.21.1: 20109 + version "1.35.0" 20110 + resolved "https://registry.yarnpkg.com/statsig-react/-/statsig-react-1.35.0.tgz#ad5730b83f564c640623e954fcbcbe848e939946" 20111 + integrity sha512-KLN7dhq6FvAl25Z0QN6IINFBgM3yn0GMafoE698tYZqRf911xvevFaR7qUXiTz3W9vmFYrmFRouqVMfCv7DW0A== 20112 + dependencies: 20113 + statsig-js "4.45.1" 20114 + 20115 + statsig-react@^1.36.0: 20116 + version "1.36.0" 20117 + resolved "https://registry.yarnpkg.com/statsig-react/-/statsig-react-1.36.0.tgz#c2171268a6c76eee534849ec9556b836baba04b6" 20118 + integrity sha512-QcTHla3ypfn2RvrnHGNlqWbiC2W/ZjcMM5LT6ExNV4skH7Xhspto3dMS3JVzBhOb74OEDZK4DbxQj9Wdz6XW0w== 20119 + dependencies: 20120 + statsig-js "4.49.0" 20121 + 19979 20122 statuses@2.0.1: 19980 20123 version "2.0.1" 19981 20124 resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" ··· 20919 21062 version "5.3.3" 20920 21063 resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" 20921 21064 integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== 21065 + 21066 + ua-parser-js@^0.7.19: 21067 + version "0.7.37" 21068 + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz#e464e66dac2d33a7a1251d7d7a99d6157ec27832" 21069 + integrity sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA== 20922 21070 20923 21071 ua-parser-js@^0.7.33: 20924 21072 version "0.7.35" ··· 21201 21349 resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 21202 21350 integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 21203 21351 21204 - uuid@^3.0.1: 21352 + uuid@^3.0.1, uuid@^3.3.2: 21205 21353 version "3.4.0" 21206 21354 resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 21207 21355 integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== ··· 21952 22100 version "4.0.0" 21953 22101 resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" 21954 22102 integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== 22103 + 22104 + xml2js@0.4.23: 22105 + version "0.4.23" 22106 + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" 22107 + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== 22108 + dependencies: 22109 + sax ">=0.6.0" 22110 + xmlbuilder "~11.0.0" 21955 22111 21956 22112 xml2js@0.6.0: 21957 22113 version "0.6.0"