diff --git a/README.md b/README.md index 22d9ecf6..4fea8668 100644 --- a/README.md +++ b/README.md @@ -50,14 +50,24 @@ The hassle-free way to add Segment analytics to your React-Native app. ## Installation -Install `@segment/analytics-react-native`, [`@segment/sovran-react-native`](https://github.com/segmentio/sovran-react-native), [`react-native-get-random-values`](https://github.com/LinusU/react-native-get-random-values) and [`react-native-async-storage/async-storage`](https://github.com/react-native-async-storage/async-storage): +Install `@segment/analytics-react-native`, [`@segment/sovran-react-native`](https://github.com/segmentio/analytics-react-native/blob/master/packages/sovran) and [`react-native-get-random-values`](https://github.com/LinusU/react-native-get-random-values): ```sh -yarn add @segment/analytics-react-native @segment/sovran-react-native @react-native-async-storage/async-storage +yarn add @segment/analytics-react-native @segment/sovran-react-native react-native-get-random-values # or -npm install --save @segment/analytics-react-native @segment/sovran-react-native @react-native-async-storage/async-storage +npm install --save @segment/analytics-react-native @segment/sovran-react-native react-native-get-random-values ``` +If you want to use the default persistor for the Segment Analytics client, you also have to install [`react-native-async-storage/async-storage`](https://github.com/react-native-async-storage/async-storage). + +```sh +yarn add @react-native-async-storage/async-storage +# or +npm install --save @react-native-async-storage/async-storage +``` + +*Note: If you wish to use your own persistence layer you can use the `storePersistor` option when initializing the client. Read more [Client Options](#client-options)* + For iOS, install native modules with: ```sh @@ -119,7 +129,7 @@ You must pass at least the `writeKey`. Additional configuration options are list | `trackDeepLinks` | false | Enable automatic tracking for when the user opens the app via a deep link (Note: Requires additional setup on iOS, [see instructions](#ios-deep-link-tracking-setup)) | | `defaultSettings` | undefined | Settings that will be used if the request to get the settings from Segment fails. Type: [SegmentAPISettings](https://github.com/segmentio/analytics-react-native/blob/c0a5895c0c57375f18dd20e492b7d984393b7bc4/packages/core/src/types.ts#L293-L299) | | `autoAddSegmentDestination`| true | Set to false to skip adding the SegmentDestination plugin | -| `storePersistor` | undefined | A custom persistor for the store that `analytics-react-native` leverages. Must match `Persistor` interface exported from [sovran-react-native](https://github.com/segmentio/sovran-react-native).| +| `storePersistor` | undefined | A custom persistor for the store that `analytics-react-native` leverages. Must match [`Persistor`](https://github.com/segmentio/analytics-react-native/blob/master/packages/sovran/src/persistor/persistor.ts#L1-L18) interface exported from [sovran-react-native](https://github.com/segmentio/analytics-react-native/blob/master/packages/sovran).| | `proxy` | undefined | `proxy` is a batch url to post to instead of 'https://api.segment.io/v1/b'. | | `errorHandler` | undefined | Create custom actions when errors happen, see [Handling errors](#handling-errors) | diff --git a/jesttemplate b/jesttemplate index 9ff095a8..65f6dddc 100644 --- a/jesttemplate +++ b/jesttemplate @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/core/jest.config.js b/packages/core/jest.config.js index d373fe7e..674c48f5 100644 --- a/packages/core/jest.config.js +++ b/packages/core/jest.config.js @@ -2,4 +2,5 @@ module.exports = { preset: 'react-native', testPathIgnorePatterns: ['/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], + setupFiles: ['/src/__tests__/__helpers__/setup.ts'], }; diff --git a/packages/core/package.json b/packages/core/package.json index 2d70a9c1..49411a3f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -47,17 +47,22 @@ }, "homepage": "https://github.com/segmentio/analytics-react-native#readme", "dependencies": { - "@react-native-async-storage/async-storage": "^1.15.17", "@segment/sovran-react-native": "^0.4.5", "deepmerge": "^4.2.2", "js-base64": "^3.7.2", - "react-native-get-random-values": "^1.8.0", "uuid": "^9.0.0" }, "peerDependencies": { + "react-native-get-random-values": "1.x", + "@react-native-async-storage/async-storage": "1.x", "react": "*", "react-native": "*" }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + }, "devDependencies": { "@babel/core": "^7.12.9", "@babel/runtime": "^7.12.5", diff --git a/packages/core/src/__mocks__/@react-native-async-storage/async-storage.js b/packages/core/src/__mocks__/@react-native-async-storage/async-storage.js deleted file mode 100644 index dad97c78..00000000 --- a/packages/core/src/__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/packages/core/src/__mocks__/react-native-get-random-values.ts b/packages/core/src/__mocks__/react-native-get-random-values.ts new file mode 100644 index 00000000..a2ee33f6 --- /dev/null +++ b/packages/core/src/__mocks__/react-native-get-random-values.ts @@ -0,0 +1 @@ +jest.fn(); diff --git a/packages/core/src/__tests__/__helpers__/setup.ts b/packages/core/src/__tests__/__helpers__/setup.ts new file mode 100644 index 00000000..2526f450 --- /dev/null +++ b/packages/core/src/__tests__/__helpers__/setup.ts @@ -0,0 +1,8 @@ +// This is our basic setup for all JS Tests + +jest.mock('react-native'); +jest.mock('uuid'); +jest.mock('react-native-get-random-values'); +jest.mock('@react-native-async-storage/async-storage', () => + require('@react-native-async-storage/async-storage/jest/async-storage-mock') +); diff --git a/packages/core/src/storage/__tests__/sovranStorage.test.ts b/packages/core/src/storage/__tests__/sovranStorage.test.ts index e5499ed4..dbe7abe9 100644 --- a/packages/core/src/storage/__tests__/sovranStorage.test.ts +++ b/packages/core/src/storage/__tests__/sovranStorage.test.ts @@ -4,6 +4,7 @@ import { createCallbackManager as mockCreateCallbackManager } from '../../__test import { SovranStorage } from '../sovranStorage'; jest.mock('uuid'); +jest.mock('react-native-get-random-values'); jest.mock('@segment/sovran-react-native', () => ({ registerBridgeStore: jest.fn(), diff --git a/packages/plugins/plugin-adjust/jest.config.js b/packages/plugins/plugin-adjust/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-adjust/jest.config.js +++ b/packages/plugins/plugin-adjust/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-advertising-id/jest.config.js b/packages/plugins/plugin-advertising-id/jest.config.js index ca179a36..00a15a9e 100644 --- a/packages/plugins/plugin-advertising-id/jest.config.js +++ b/packages/plugins/plugin-advertising-id/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-amplitudeSession/jest.config.js b/packages/plugins/plugin-amplitudeSession/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-amplitudeSession/jest.config.js +++ b/packages/plugins/plugin-amplitudeSession/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-appsflyer/jest.config.js b/packages/plugins/plugin-appsflyer/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-appsflyer/jest.config.js +++ b/packages/plugins/plugin-appsflyer/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-branch/jest.config.js b/packages/plugins/plugin-branch/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-branch/jest.config.js +++ b/packages/plugins/plugin-branch/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-braze-middleware/jest.config.js b/packages/plugins/plugin-braze-middleware/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-braze-middleware/jest.config.js +++ b/packages/plugins/plugin-braze-middleware/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-braze/jest.config.js b/packages/plugins/plugin-braze/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-braze/jest.config.js +++ b/packages/plugins/plugin-braze/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-destination-filters/jest.config.js b/packages/plugins/plugin-destination-filters/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-destination-filters/jest.config.js +++ b/packages/plugins/plugin-destination-filters/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-facebook-app-events/jest.config.js b/packages/plugins/plugin-facebook-app-events/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-facebook-app-events/jest.config.js +++ b/packages/plugins/plugin-facebook-app-events/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-firebase/jest.config.js b/packages/plugins/plugin-firebase/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-firebase/jest.config.js +++ b/packages/plugins/plugin-firebase/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/plugins/plugin-idfa/jest.config.js b/packages/plugins/plugin-idfa/jest.config.js index 9ff095a8..65f6dddc 100644 --- a/packages/plugins/plugin-idfa/jest.config.js +++ b/packages/plugins/plugin-idfa/jest.config.js @@ -4,7 +4,7 @@ const { compilerOptions } = require('./tsconfig'); module.exports = { preset: 'react-native', roots: [''], - setupFiles: ['../../core/src/__tests__/__helpers__/setup.js'], + setupFiles: ['../../core/src/__tests__/__helpers__/setup.ts'], testPathIgnorePatterns: ['.../../core/src/__tests__/__helpers__/'], modulePathIgnorePatterns: ['/lib/'], transform: { diff --git a/packages/sovran/package.json b/packages/sovran/package.json index d0b89b69..ebcd03e8 100644 --- a/packages/sovran/package.json +++ b/packages/sovran/package.json @@ -88,11 +88,16 @@ ] }, "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x", "react": "*", "react-native": "*" }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + }, "dependencies": { - "@react-native-async-storage/async-storage": "^1.15.15", "ansi-regex": "5.0.1", "deepmerge": "^4.2.2", "shell-quote": "1.7.3" diff --git a/packages/sovran/src/__mocks__/@react-native-async-storage/async-storage.js b/packages/sovran/src/__mocks__/@react-native-async-storage/async-storage.js index dad97c78..9c1d1d7e 100644 --- a/packages/sovran/src/__mocks__/@react-native-async-storage/async-storage.js +++ b/packages/sovran/src/__mocks__/@react-native-async-storage/async-storage.js @@ -1 +1 @@ -export default from '@react-native-async-storage/async-storage/jest/async-storage-mock'; +export default '@react-native-async-storage/async-storage/jest/async-storage-mock'; diff --git a/packages/sovran/src/index.tsx b/packages/sovran/src/index.tsx index ebea1839..9aa15b0c 100644 --- a/packages/sovran/src/index.tsx +++ b/packages/sovran/src/index.tsx @@ -20,6 +20,11 @@ if (Sovran) { } else { console.warn(LINKING_ERROR); } -export { createStore, Store, Notify, Unsubscribe } from './store'; +export { + createStore, + type Store, + type Notify, + type Unsubscribe, +} from './store'; export { registerBridgeStore } from './bridge'; export * from './persistor'; diff --git a/packages/sovran/src/persistor/async-storage-persistor.ts b/packages/sovran/src/persistor/async-storage-persistor.ts index c69dbe42..5e4ce914 100644 --- a/packages/sovran/src/persistor/async-storage-persistor.ts +++ b/packages/sovran/src/persistor/async-storage-persistor.ts @@ -1,13 +1,23 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; import type { Persistor } from './persistor'; +let AsyncStorage: { + getItem: (key: string) => Promise; + setItem: (key: string, value: string) => Promise; +} | null; + +try { + AsyncStorage = require('@react-native-async-storage/async-storage'); +} catch (error) { + AsyncStorage = null; +} + /** * Persistor implementation using AsyncStorage */ export const AsyncStoragePersistor: Persistor = { get: async (key: string): Promise => { try { - const persistedStateJSON = await AsyncStorage.getItem(key); + const persistedStateJSON = await AsyncStorage?.getItem?.(key); if (persistedStateJSON !== null && persistedStateJSON !== undefined) { return JSON.parse(persistedStateJSON); } @@ -20,7 +30,7 @@ export const AsyncStoragePersistor: Persistor = { set: async (key: string, state: T): Promise => { try { - await AsyncStorage.setItem(key, JSON.stringify(state)); + await AsyncStorage?.setItem?.(key, JSON.stringify(state)); } catch (e) { console.error(e); } diff --git a/yarn.lock b/yarn.lock index 40fcdd96..3a3fec53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2261,7 +2261,7 @@ dependencies: "@octokit/openapi-types" "^12.10.0" -"@react-native-async-storage/async-storage@^1.15.15", "@react-native-async-storage/async-storage@^1.15.17": +"@react-native-async-storage/async-storage@^1.15.15": version "1.17.7" resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.17.7.tgz#f9213e8cc6202a8c29df5a4da1db588f3b0fa8a9" integrity sha512-mDtWhCcpxzrZhA95f6zi0pnBsjBEZW1LKZWfxVXG0UfaWpPxDBCKowNk2xjRTytckZeVhjmPJPtBU+8QNQcR0A== @@ -6130,11 +6130,6 @@ extract-zip@^1.6.6: mkdirp "^0.5.4" yauzl "^2.10.0" -fast-base64-decode@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418" - integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -10624,13 +10619,6 @@ react-native-fbsdk-next@^10.1.0: "@expo/config-plugins" "^4.1.5" xml2js "^0.4.23" -react-native-get-random-values@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.8.0.tgz#1cb4bd4bd3966a356e59697b8f372999fe97cb16" - integrity sha512-H/zghhun0T+UIJLmig3+ZuBCvF66rdbiWUfRSNS6kv5oDSpa1ZiVyvRWtuPesQpT8dXj+Bv7WJRQOUP+5TB1sA== - dependencies: - fast-base64-decode "^1.0.0" - react-native@^0.67.2: version "0.67.4" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.67.4.tgz#57a1503daa81f66a61f521ff67b259f126d87f9c"