From acc8a9383df88d218196cdb5a226c95185eb9d40 Mon Sep 17 00:00:00 2001 From: Oscar Bazaldua <511911+oscb@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:59:37 -0700 Subject: [PATCH 01/71] fix: startup flush policy should send restored events (#943) Problem reported that StartupFlushPolicy wouldn't send the pending upload events from the previous app launch. Caused by concurrency: FlushPolicies get initialized before and without awaiting for storage restoration. Futhermore the Queue for upload is managed by the SegmentDestination plugin so there's no explicit way to await for that queue to be restored from the base client itself. Solution: Move the flush policy initialization later in the client: after plugins are initialized but before replaying buffered events Refactor StartupFlushPolicy to mark shouldFlush outside of start (this is to be able to handle it with the manualFlush) Refactor QueueFlushingPlugin and SegmentDestination to await for queue restoration and settings load when a flush is triggered. This guarantees that if the flush is triggered before the plugins are fully initialized (previous session events loaded) it will await for those operations to complete before uploading any events. --- packages/core/src/__tests__/analytics.test.ts | 15 ++++++---- packages/core/src/analytics.ts | 26 +++++++++------- .../flushPolicies/flush-policy-executer.ts | 2 +- .../src/flushPolicies/startup-flush-policy.ts | 7 ++++- .../core/src/plugins/QueueFlushingPlugin.ts | 28 ++++++++++++++++- .../core/src/plugins/SegmentDestination.ts | 30 ++++++++++++++----- packages/core/src/util.ts | 20 +++++++++++++ 7 files changed, 101 insertions(+), 27 deletions(-) diff --git a/packages/core/src/__tests__/analytics.test.ts b/packages/core/src/__tests__/analytics.test.ts index f2bd05959..0e575b88d 100644 --- a/packages/core/src/__tests__/analytics.test.ts +++ b/packages/core/src/__tests__/analytics.test.ts @@ -172,7 +172,7 @@ describe('SegmentClient', () => { }); describe('Flush Policies', () => { - it('creates the default flush policies when config is empty', () => { + it('creates the default flush policies when config is empty', async () => { client = new SegmentClient({ ...clientArgs, config: { @@ -181,11 +181,12 @@ describe('SegmentClient', () => { flushInterval: undefined, }, }); + await client.init(); const flushPolicies = client.getFlushPolicies(); expect(flushPolicies.length).toBe(2); }); - it('setting flush policies is mutually exclusive with flushAt/Interval', () => { + it('setting flush policies is mutually exclusive with flushAt/Interval', async () => { client = new SegmentClient({ ...clientArgs, config: { @@ -195,11 +196,12 @@ describe('SegmentClient', () => { flushPolicies: [new CountFlushPolicy(1)], }, }); + await client.init(); const flushPolicies = client.getFlushPolicies(); expect(flushPolicies.length).toBe(1); }); - it('setting flushAt/Interval to 0 should make the client have no uploads', () => { + it('setting flushAt/Interval to 0 should make the client have no uploads', async () => { client = new SegmentClient({ ...clientArgs, config: { @@ -208,11 +210,12 @@ describe('SegmentClient', () => { flushInterval: 0, }, }); + await client.init(); const flushPolicies = client.getFlushPolicies(); expect(flushPolicies.length).toBe(0); }); - it('setting an empty array of policies should make the client have no uploads', () => { + it('setting an empty array of policies should make the client have no uploads', async () => { client = new SegmentClient({ ...clientArgs, config: { @@ -222,11 +225,12 @@ describe('SegmentClient', () => { flushPolicies: [], }, }); + await client.init(); const flushPolicies = client.getFlushPolicies(); expect(flushPolicies.length).toBe(0); }); - it('can add and remove policies, does not mutate original array', () => { + it('can add and remove policies, does not mutate original array', async () => { const policies = [new CountFlushPolicy(1), new TimerFlushPolicy(200)]; client = new SegmentClient({ ...clientArgs, @@ -237,6 +241,7 @@ describe('SegmentClient', () => { flushPolicies: policies, }, }); + await client.init(); expect(client.getFlushPolicies().length).toBe(policies.length); client.removeFlushPolicy(...policies); diff --git a/packages/core/src/analytics.ts b/packages/core/src/analytics.ts index 2970277a4..eca237883 100644 --- a/packages/core/src/analytics.ts +++ b/packages/core/src/analytics.ts @@ -88,7 +88,12 @@ export class SegmentClient { private pluginsToAdd: Plugin[] = []; - private flushPolicyExecuter!: FlushPolicyExecuter; + private flushPolicyExecuter: FlushPolicyExecuter = new FlushPolicyExecuter( + [], + () => { + void this.flush(); + } + ); private onPluginAddedObservers: OnPluginAddedCallback[] = []; @@ -233,9 +238,6 @@ export class SegmentClient { // Setup platform specific plugins this.platformPlugins.forEach((plugin) => this.add({ plugin: plugin })); - // Start flush policies - this.setupFlushPolicies(); - // set up tracking for lifecycle events this.setupLifecycleEvents(); } @@ -278,9 +280,6 @@ export class SegmentClient { await this.onReady(); this.isReady.value = true; - - // flush any stored events - this.flushPolicyExecuter.manualFlush(); } catch (error) { this.reportInternalError( new SegmentError( @@ -494,13 +493,18 @@ export class SegmentClient { } } + // Start flush policies + // This should be done before any pending events are added to the queue so that any policies that rely on events queued can trigger accordingly + this.setupFlushPolicies(); + // Send all events in the queue const pending = await this.store.pendingEvents.get(true); for (const e of pending) { await this.startTimelineProcessing(e); await this.store.pendingEvents.remove(e); } - // this.store.pendingEvents.set([]); + + this.flushPolicyExecuter.manualFlush(); } async flush(): Promise { @@ -756,9 +760,9 @@ export class SegmentClient { } } - this.flushPolicyExecuter = new FlushPolicyExecuter(flushPolicies, () => { - void this.flush(); - }); + for (const fp of flushPolicies) { + this.flushPolicyExecuter.add(fp); + } } /** diff --git a/packages/core/src/flushPolicies/flush-policy-executer.ts b/packages/core/src/flushPolicies/flush-policy-executer.ts index b84dd43d8..a705cacf2 100644 --- a/packages/core/src/flushPolicies/flush-policy-executer.ts +++ b/packages/core/src/flushPolicies/flush-policy-executer.ts @@ -89,12 +89,12 @@ export class FlushPolicyExecuter { } private startPolicy(policy: FlushPolicy) { - policy.start(); const unsubscribe = policy.shouldFlush.onChange((shouldFlush) => { if (shouldFlush) { this.onFlush(); } }); this.observers.push(unsubscribe); + policy.start(); } } diff --git a/packages/core/src/flushPolicies/startup-flush-policy.ts b/packages/core/src/flushPolicies/startup-flush-policy.ts index fdce72cae..7d29a4ec2 100644 --- a/packages/core/src/flushPolicies/startup-flush-policy.ts +++ b/packages/core/src/flushPolicies/startup-flush-policy.ts @@ -5,10 +5,15 @@ import { FlushPolicyBase } from './types'; * StatupFlushPolicy triggers a flush right away on client startup */ export class StartupFlushPolicy extends FlushPolicyBase { - start() { + constructor() { + super(); this.shouldFlush.value = true; } + start(): void { + // Nothing to do + } + onEvent(_event: SegmentEvent): void { // Nothing to do } diff --git a/packages/core/src/plugins/QueueFlushingPlugin.ts b/packages/core/src/plugins/QueueFlushingPlugin.ts index ac0d6ddb0..6c303525a 100644 --- a/packages/core/src/plugins/QueueFlushingPlugin.ts +++ b/packages/core/src/plugins/QueueFlushingPlugin.ts @@ -3,6 +3,8 @@ import type { SegmentClient } from '../analytics'; import { defaultConfig } from '../constants'; import { UtilityPlugin } from '../plugin'; import { PluginType, SegmentEvent } from '../types'; +import { createPromise } from '../util'; +import { ErrorType, SegmentError } from '../errors'; /** * This plugin manages a queue where all events get added to after timeline processing. @@ -17,17 +19,25 @@ export class QueueFlushingPlugin extends UtilityPlugin { private isPendingUpload = false; private queueStore: Store<{ events: SegmentEvent[] }> | undefined; private onFlush: (events: SegmentEvent[]) => Promise; + private isRestoredResolve: () => void; + private isRestored: Promise; /** * @param onFlush callback to execute when the queue is flushed (either by reaching the limit or manually) e.g. code to upload events to your destination + * @param storeKey key to store the queue in the store. Must be unique per destination instance + * @param restoreTimeout time in ms to wait for the queue to be restored from the store before uploading events (default: 500ms) */ constructor( onFlush: (events: SegmentEvent[]) => Promise, - storeKey = 'events' + storeKey = 'events', + restoreTimeout = 500 ) { super(); this.onFlush = onFlush; this.storeKey = storeKey; + const { promise, resolve } = createPromise(restoreTimeout); + this.isRestored = promise; + this.isRestoredResolve = resolve; } configure(analytics: SegmentClient): void { @@ -43,6 +53,9 @@ export class QueueFlushingPlugin extends UtilityPlugin { storeId: `${config.writeKey}-${this.storeKey}`, persistor: config.storePersistor, saveDelay: config.storePersistorSaveDelay ?? 0, + onInitialized: () => { + this.isRestoredResolve(); + }, }, } ); @@ -60,6 +73,19 @@ export class QueueFlushingPlugin extends UtilityPlugin { * Calls the onFlush callback with the events in the queue */ async flush() { + // Wait for the queue to be restored + try { + await this.isRestored; + } catch (e) { + // If the queue is not restored before the timeout, we will notify but not block flushing events + this.analytics?.reportInternalError( + new SegmentError( + ErrorType.InitializationError, + 'Queue timeout before completed restoration', + e + ) + ); + } const events = (await this.queueStore?.getState(true))?.events ?? []; if (!this.isPendingUpload) { try { diff --git a/packages/core/src/plugins/SegmentDestination.ts b/packages/core/src/plugins/SegmentDestination.ts index 93f0cbcb0..b3717b8ef 100644 --- a/packages/core/src/plugins/SegmentDestination.ts +++ b/packages/core/src/plugins/SegmentDestination.ts @@ -6,7 +6,7 @@ import { SegmentEvent, UpdateType, } from '../types'; -import { chunk } from '../util'; +import { chunk, createPromise } from '../util'; import { uploadEvents } from '../api'; import type { SegmentClient } from '../analytics'; import { DestinationMetadataEnrichment } from './DestinationMetadataEnrichment'; @@ -23,18 +23,25 @@ export class SegmentDestination extends DestinationPlugin { type = PluginType.destination; key = SEGMENT_DESTINATION_KEY; private apiHost?: string; - private isReady = false; + private settingsResolve: () => void; + private settingsPromise: Promise; + + constructor() { + super(); + // We don't timeout this promise. We strictly need the response from Segment before sending things + const { promise, resolve } = createPromise(); + this.settingsPromise = promise; + this.settingsResolve = resolve; + } private sendEvents = async (events: SegmentEvent[]): Promise => { - if (!this.isReady) { - // We're not sending events until Segment has loaded all settings - return Promise.resolve(); - } - if (events.length === 0) { return Promise.resolve(); } + // We're not sending events until Segment has loaded all settings + await this.settingsPromise; + const config = this.analytics?.getConfig() ?? defaultConfig; const chunkedEvents: SegmentEvent[][] = chunk( @@ -89,6 +96,12 @@ export class SegmentDestination extends DestinationPlugin { configure(analytics: SegmentClient): void { super.configure(analytics); + // If the client has a proxy we don't need to await for settings apiHost, we can send events directly + // Important! If new settings are required in the future you probably want to change this! + if (analytics.getConfig().proxy !== undefined) { + this.settingsResolve(); + } + // Enrich events with the Destination metadata this.add(new DestinationMetadataEnrichment(SEGMENT_DESTINATION_KEY)); this.add(this.queuePlugin); @@ -105,7 +118,7 @@ export class SegmentDestination extends DestinationPlugin { ) { this.apiHost = `https://${segmentSettings.apiHost}/b`; } - this.isReady = true; + this.settingsResolve(); } execute(event: SegmentEvent): Promise { @@ -115,6 +128,7 @@ export class SegmentDestination extends DestinationPlugin { } async flush() { + // Wait until the queue is done restoring before flushing return this.queuePlugin.flush(); } } diff --git a/packages/core/src/util.ts b/packages/core/src/util.ts index ae229abba..19b9bd50b 100644 --- a/packages/core/src/util.ts +++ b/packages/core/src/util.ts @@ -232,3 +232,23 @@ export function deepCompare(a: T, b: T): boolean { return true; } + +export const createPromise = ( + timeout: number | undefined = undefined +): { promise: Promise; resolve: (value: T) => void } => { + let resolver: (value: T) => void; + const promise = new Promise((resolve, reject) => { + resolver = resolve; + if (timeout !== undefined) { + setTimeout(() => { + reject(new Error('Promise timed out')); + }, timeout); + } + }); + + return { + promise: promise, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + resolve: resolver!, + }; +}; From 2bad063d700f566fd3ac74f91dbe2ff6fb0a9d87 Mon Sep 17 00:00:00 2001 From: Leo Picado Date: Wed, 24 Apr 2024 16:01:05 -0600 Subject: [PATCH 02/71] Include updated Expo instructions for deep link tracking (#944) --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 36bec10bc..f44d9aa68 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,20 @@ To track deep links in iOS you must add the following to your `AppDelegate.m` fi return YES; } ``` + +If you are using Expo, you need to create an [AppDelegateSubscriber](https://docs.expo.dev/modules/appdelegate-subscribers/), make sure to include `segment_analytics_react_native` in your `podspec` file. +The rest of the code looks like this: +```swift + import segment_analytics_react_native + + ... + + open func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + AnalyticsReactNative.trackDeepLink(url: url as NSURL, options: options) + return false + } +``` + ### Native AnonymousId If you need to generate an `anonymousId` either natively or before the Analytics React Native package is initialized, you can send the anonymousId value from native code. The value has to be generated and stored by the caller. For reference, you can find a working example in the app and reference the code below: From f1c8c2b763c8247fe8dd20713f37d6a5b06a9742 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:46:12 -0700 Subject: [PATCH 03/71] chore(deps): bump tar from 6.2.0 to 6.2.1 (#941) Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1. - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3cee12ebd..cb257bcab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14564,8 +14564,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2, tar@npm:^6.2.0": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -14573,7 +14573,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard From f8e7456b9e3e642ee052cb33eda3906a37c7e9b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:46:21 -0700 Subject: [PATCH 04/71] chore(deps): bump tar from 6.2.0 to 6.2.1 in /examples/E2E-73 (#940) Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1. - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/E2E-73/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/E2E-73/yarn.lock b/examples/E2E-73/yarn.lock index 5871211d4..c225d7f19 100644 --- a/examples/E2E-73/yarn.lock +++ b/examples/E2E-73/yarn.lock @@ -9923,8 +9923,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -9932,7 +9932,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard From 2befe48b2c36383a6c4370b4d03982cd2cab7c09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:46:28 -0700 Subject: [PATCH 05/71] chore(deps): bump tar from 6.2.0 to 6.2.1 in /examples/E2E (#939) Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1. - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/E2E/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/E2E/yarn.lock b/examples/E2E/yarn.lock index 53dcb3c54..1652be1ba 100644 --- a/examples/E2E/yarn.lock +++ b/examples/E2E/yarn.lock @@ -9893,8 +9893,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -9902,7 +9902,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard From 9f748ed3efca043bd9cf62392cf206c24b9044d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:46:35 -0700 Subject: [PATCH 06/71] chore(deps): bump tar from 6.2.0 to 6.2.1 in /examples/AnalyticsReactNativeExample (#938) Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1. - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/AnalyticsReactNativeExample/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/AnalyticsReactNativeExample/yarn.lock b/examples/AnalyticsReactNativeExample/yarn.lock index fc0619b3c..32ebccf88 100644 --- a/examples/AnalyticsReactNativeExample/yarn.lock +++ b/examples/AnalyticsReactNativeExample/yarn.lock @@ -7438,8 +7438,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -7447,7 +7447,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard From c3a31a3f907b66289396313c1e83ce8d03acf842 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:46:43 -0700 Subject: [PATCH 07/71] chore(deps-dev): bump express from 4.18.2 to 4.19.2 in /examples/E2E (#933) Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2) --- updated-dependencies: - dependency-name: express dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/E2E/package.json | 2 +- examples/E2E/yarn.lock | 56 +++++++++------------------------------ 2 files changed, 13 insertions(+), 45 deletions(-) diff --git a/examples/E2E/package.json b/examples/E2E/package.json index b4f829adb..59421d276 100644 --- a/examples/E2E/package.json +++ b/examples/E2E/package.json @@ -47,7 +47,7 @@ "body-parser": "^1.20.0", "detox": "^20.17.0", "eslint": "^8.19.0", - "express": "^4.17.1", + "express": "^4.19.2", "jest": "^29.7.0", "jest-circus": "^29.3.1", "metro-react-native-babel-preset": "0.76.8", diff --git a/examples/E2E/yarn.lock b/examples/E2E/yarn.lock index 1652be1ba..68d0e1aae 100644 --- a/examples/E2E/yarn.lock +++ b/examples/E2E/yarn.lock @@ -2962,7 +2962,7 @@ __metadata: body-parser: "npm:^1.20.0" detox: "npm:^20.17.0" eslint: "npm:^8.19.0" - express: "npm:^4.17.1" + express: "npm:^4.19.2" jest: "npm:^29.7.0" jest-circus: "npm:^29.3.1" metro-react-native-babel-preset: "npm:0.76.8" @@ -3543,27 +3543,7 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.1": - version: 1.20.1 - resolution: "body-parser@npm:1.20.1" - dependencies: - bytes: "npm:3.1.2" - content-type: "npm:~1.0.4" - debug: "npm:2.6.9" - depd: "npm:2.0.0" - destroy: "npm:1.2.0" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - on-finished: "npm:2.4.1" - qs: "npm:6.11.0" - raw-body: "npm:2.5.1" - type-is: "npm:~1.6.18" - unpipe: "npm:1.0.0" - checksum: 10c0/a202d493e2c10a33fb7413dac7d2f713be579c4b88343cd814b6df7a38e5af1901fc31044e04de176db56b16d9772aa25a7723f64478c20f4d91b1ac223bf3b8 - languageName: node - linkType: hard - -"body-parser@npm:^1.20.0": +"body-parser@npm:1.20.2, body-parser@npm:^1.20.0": version: 1.20.2 resolution: "body-parser@npm:1.20.2" dependencies: @@ -4161,10 +4141,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0": - version: 0.5.0 - resolution: "cookie@npm:0.5.0" - checksum: 10c0/c01ca3ef8d7b8187bae434434582288681273b5a9ed27521d4d7f9f7928fe0c920df0decd9f9d3bbd2d14ac432b8c8cf42b98b3bdd5bfe0e6edddeebebe8b61d +"cookie@npm:0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: 10c0/f2318b31af7a31b4ddb4a678d024514df5e705f9be5909a192d7f116cfb6d45cbacf96a473fa733faa95050e7cff26e7832bb3ef94751592f1387b71c8956686 languageName: node linkType: hard @@ -5075,16 +5055,16 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.17.1": - version: 4.18.2 - resolution: "express@npm:4.18.2" +"express@npm:^4.19.2": + version: 4.19.2 + resolution: "express@npm:4.19.2" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" - body-parser: "npm:1.20.1" + body-parser: "npm:1.20.2" content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.5.0" + cookie: "npm:0.6.0" cookie-signature: "npm:1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" @@ -5110,7 +5090,7 @@ __metadata: type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10c0/75af556306b9241bc1d7bdd40c9744b516c38ce50ae3210658efcbf96e3aed4ab83b3432f06215eae5610c123bc4136957dc06e50dfc50b7d4d775af56c4c59c + checksum: 10c0/e82e2662ea9971c1407aea9fc3c16d6b963e55e3830cd0ef5e00b533feda8b770af4e3be630488ef8a752d7c75c4fcefb15892868eeaafe7353cb9e3e269fdcb languageName: node linkType: hard @@ -8730,18 +8710,6 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.1": - version: 2.5.1 - resolution: "raw-body@npm:2.5.1" - dependencies: - bytes: "npm:3.1.2" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - unpipe: "npm:1.0.0" - checksum: 10c0/5dad5a3a64a023b894ad7ab4e5c7c1ce34d3497fc7138d02f8c88a3781e68d8a55aa7d4fd3a458616fa8647cc228be314a1c03fb430a07521de78b32c4dd09d2 - languageName: node - linkType: hard - "raw-body@npm:2.5.2": version: 2.5.2 resolution: "raw-body@npm:2.5.2" From 22304593e7ec739bde44212465ed56444955245f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:46:53 -0700 Subject: [PATCH 08/71] chore(deps-dev): bump express from 4.18.2 to 4.19.2 in /examples/E2E-73 (#932) Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2) --- updated-dependencies: - dependency-name: express dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/E2E-73/package.json | 2 +- examples/E2E-73/yarn.lock | 44 ++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/E2E-73/package.json b/examples/E2E-73/package.json index 1931d1f17..ad95047c7 100644 --- a/examples/E2E-73/package.json +++ b/examples/E2E-73/package.json @@ -46,7 +46,7 @@ "babel-plugin-module-resolver": "^5.0.0", "detox": "^20.17.0", "eslint": "^8.19.0", - "express": "^4.17.1", + "express": "^4.19.2", "jest": "^29.7.0", "jest-circus": "^29.3.1", "prettier": "2.8.8", diff --git a/examples/E2E-73/yarn.lock b/examples/E2E-73/yarn.lock index c225d7f19..310095fea 100644 --- a/examples/E2E-73/yarn.lock +++ b/examples/E2E-73/yarn.lock @@ -3088,7 +3088,7 @@ __metadata: babel-plugin-module-resolver: "npm:^5.0.0" detox: "npm:^20.17.0" eslint: "npm:^8.19.0" - express: "npm:^4.17.1" + express: "npm:^4.19.2" jest: "npm:^29.7.0" jest-circus: "npm:^29.3.1" prettier: "npm:2.8.8" @@ -3660,12 +3660,12 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.1": - version: 1.20.1 - resolution: "body-parser@npm:1.20.1" +"body-parser@npm:1.20.2": + version: 1.20.2 + resolution: "body-parser@npm:1.20.2" dependencies: bytes: "npm:3.1.2" - content-type: "npm:~1.0.4" + content-type: "npm:~1.0.5" debug: "npm:2.6.9" depd: "npm:2.0.0" destroy: "npm:1.2.0" @@ -3673,10 +3673,10 @@ __metadata: iconv-lite: "npm:0.4.24" on-finished: "npm:2.4.1" qs: "npm:6.11.0" - raw-body: "npm:2.5.1" + raw-body: "npm:2.5.2" type-is: "npm:~1.6.18" unpipe: "npm:1.0.0" - checksum: 10c0/a202d493e2c10a33fb7413dac7d2f713be579c4b88343cd814b6df7a38e5af1901fc31044e04de176db56b16d9772aa25a7723f64478c20f4d91b1ac223bf3b8 + checksum: 10c0/06f1438fff388a2e2354c96aa3ea8147b79bfcb1262dfcc2aae68ec13723d01d5781680657b74e9f83c808266d5baf52804032fbde2b7382b89bd8cdb273ace9 languageName: node linkType: hard @@ -4258,7 +4258,7 @@ __metadata: languageName: node linkType: hard -"content-type@npm:~1.0.4": +"content-type@npm:~1.0.4, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af @@ -4279,10 +4279,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0": - version: 0.5.0 - resolution: "cookie@npm:0.5.0" - checksum: 10c0/c01ca3ef8d7b8187bae434434582288681273b5a9ed27521d4d7f9f7928fe0c920df0decd9f9d3bbd2d14ac432b8c8cf42b98b3bdd5bfe0e6edddeebebe8b61d +"cookie@npm:0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: 10c0/f2318b31af7a31b4ddb4a678d024514df5e705f9be5909a192d7f116cfb6d45cbacf96a473fa733faa95050e7cff26e7832bb3ef94751592f1387b71c8956686 languageName: node linkType: hard @@ -5193,16 +5193,16 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.17.1": - version: 4.18.2 - resolution: "express@npm:4.18.2" +"express@npm:^4.19.2": + version: 4.19.2 + resolution: "express@npm:4.19.2" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" - body-parser: "npm:1.20.1" + body-parser: "npm:1.20.2" content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.5.0" + cookie: "npm:0.6.0" cookie-signature: "npm:1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" @@ -5228,7 +5228,7 @@ __metadata: type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10c0/75af556306b9241bc1d7bdd40c9744b516c38ce50ae3210658efcbf96e3aed4ab83b3432f06215eae5610c123bc4136957dc06e50dfc50b7d4d775af56c4c59c + checksum: 10c0/e82e2662ea9971c1407aea9fc3c16d6b963e55e3830cd0ef5e00b533feda8b770af4e3be630488ef8a752d7c75c4fcefb15892868eeaafe7353cb9e3e269fdcb languageName: node linkType: hard @@ -8772,15 +8772,15 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.1": - version: 2.5.1 - resolution: "raw-body@npm:2.5.1" +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" dependencies: bytes: "npm:3.1.2" http-errors: "npm:2.0.0" iconv-lite: "npm:0.4.24" unpipe: "npm:1.0.0" - checksum: 10c0/5dad5a3a64a023b894ad7ab4e5c7c1ce34d3497fc7138d02f8c88a3781e68d8a55aa7d4fd3a458616fa8647cc228be314a1c03fb430a07521de78b32c4dd09d2 + checksum: 10c0/b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4 languageName: node linkType: hard From 62e63d7c0169b7ae6e522668bb861b6b5346c55d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:47:01 -0700 Subject: [PATCH 09/71] chore(deps): bump ip from 1.1.8 to 1.1.9 (#918) Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9. - [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9) --- updated-dependencies: - dependency-name: ip dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index cb257bcab..fb4b85860 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9217,9 +9217,9 @@ __metadata: linkType: hard "ip@npm:^1.1.5": - version: 1.1.8 - resolution: "ip@npm:1.1.8" - checksum: 10c0/ab32a5ecfa678d4c158c1381c4c6744fce89a1d793e1b6635ba79d0753c069030b672d765887b6fff55670c711dfa47475895e5d6013efbbcf04687c51cb8db9 + version: 1.1.9 + resolution: "ip@npm:1.1.9" + checksum: 10c0/5af58bfe2110c9978acfd77a2ffcdf9d33a6ce1c72f49edbaf16958f7a8eb979b5163e43bb18938caf3aaa55cdacde4e470874c58ca3b4b112ea7a30461a0c27 languageName: node linkType: hard From 9d29c073c6ed0fff8426c5b2ce33e2d4957505f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:47:08 -0700 Subject: [PATCH 10/71] chore(deps): bump ip from 1.1.8 to 1.1.9 in /examples/E2E-73 (#921) Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9. - [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9) --- updated-dependencies: - dependency-name: ip dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/E2E-73/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/E2E-73/yarn.lock b/examples/E2E-73/yarn.lock index 310095fea..88663644b 100644 --- a/examples/E2E-73/yarn.lock +++ b/examples/E2E-73/yarn.lock @@ -6079,9 +6079,9 @@ __metadata: linkType: hard "ip@npm:^1.1.5": - version: 1.1.8 - resolution: "ip@npm:1.1.8" - checksum: 10c0/ab32a5ecfa678d4c158c1381c4c6744fce89a1d793e1b6635ba79d0753c069030b672d765887b6fff55670c711dfa47475895e5d6013efbbcf04687c51cb8db9 + version: 1.1.9 + resolution: "ip@npm:1.1.9" + checksum: 10c0/5af58bfe2110c9978acfd77a2ffcdf9d33a6ce1c72f49edbaf16958f7a8eb979b5163e43bb18938caf3aaa55cdacde4e470874c58ca3b4b112ea7a30461a0c27 languageName: node linkType: hard From d0b1a7bfdc5269b6c4bc22537da9e4615d9c3afe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:47:16 -0700 Subject: [PATCH 11/71] chore(deps): bump ip from 1.1.8 to 1.1.9 in /examples/E2E (#920) Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9. - [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9) --- updated-dependencies: - dependency-name: ip dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/E2E/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/E2E/yarn.lock b/examples/E2E/yarn.lock index 68d0e1aae..e50ee2c96 100644 --- a/examples/E2E/yarn.lock +++ b/examples/E2E/yarn.lock @@ -5925,9 +5925,9 @@ __metadata: linkType: hard "ip@npm:^1.1.5": - version: 1.1.8 - resolution: "ip@npm:1.1.8" - checksum: 10c0/ab32a5ecfa678d4c158c1381c4c6744fce89a1d793e1b6635ba79d0753c069030b672d765887b6fff55670c711dfa47475895e5d6013efbbcf04687c51cb8db9 + version: 1.1.9 + resolution: "ip@npm:1.1.9" + checksum: 10c0/5af58bfe2110c9978acfd77a2ffcdf9d33a6ce1c72f49edbaf16958f7a8eb979b5163e43bb18938caf3aaa55cdacde4e470874c58ca3b4b112ea7a30461a0c27 languageName: node linkType: hard From d989acde4b4cb2b1e92a8f10e1a2237cf1f94833 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:47:25 -0700 Subject: [PATCH 12/71] chore(deps): bump ip from 1.1.8 to 1.1.9 in /examples/AnalyticsReactNativeExample (#919) Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9. - [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9) --- updated-dependencies: - dependency-name: ip dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/AnalyticsReactNativeExample/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/AnalyticsReactNativeExample/yarn.lock b/examples/AnalyticsReactNativeExample/yarn.lock index 32ebccf88..3e5c322ed 100644 --- a/examples/AnalyticsReactNativeExample/yarn.lock +++ b/examples/AnalyticsReactNativeExample/yarn.lock @@ -4367,9 +4367,9 @@ __metadata: linkType: hard "ip@npm:^1.1.5": - version: 1.1.8 - resolution: "ip@npm:1.1.8" - checksum: 10c0/ab32a5ecfa678d4c158c1381c4c6744fce89a1d793e1b6635ba79d0753c069030b672d765887b6fff55670c711dfa47475895e5d6013efbbcf04687c51cb8db9 + version: 1.1.9 + resolution: "ip@npm:1.1.9" + checksum: 10c0/5af58bfe2110c9978acfd77a2ffcdf9d33a6ce1c72f49edbaf16958f7a8eb979b5163e43bb18938caf3aaa55cdacde4e470874c58ca3b4b112ea7a30461a0c27 languageName: node linkType: hard From b7f090885bfbb1efa2540d9825ed956385936ca6 Mon Sep 17 00:00:00 2001 From: Oscar Bazaldua <511911+oscb@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:54:01 -0700 Subject: [PATCH 13/71] ci: Update Publish CI and instructions --- .github/workflows/publish.yml | 10 -------- CONTRIBUTING.md | 47 +++++++++++++++++++++++++---------- examples/E2E-73/.mise.toml | 5 ++++ examples/E2E-73/.rtx.toml | 2 -- examples/E2E/.mise.toml | 5 ++++ 5 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 examples/E2E-73/.mise.toml delete mode 100644 examples/E2E-73/.rtx.toml create mode 100644 examples/E2E/.mise.toml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 390a3112e..be734f2da 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -55,13 +55,3 @@ jobs: yarn install --no-immutable yarn e2e install --no-immutable yarn example install --no-immutable - - - name: Commit Updated App Locks - run: | - git config user.email "no-reply@segment.com" - git config user.name "semantic-release-bot" - git add yarn.lock - git add examples/E2E/yarn.lock - git add examples/AnalyticsReactNativeExample/yarn.lock - git commit -m "chore(release): update lockfiles [skip ci]" --no-verify - git push diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 12c6f6ba1..80ea98492 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,17 @@ We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. +## Prerequisites + +Follow the official guide for getting your [RN Environment setup](https://reactnative.dev/docs/0.72/environment-setup) + +React Native requires different versions of the tools/languages you might be using already. Even among RN releases there might be different versions required. We recommend using the following tools to manage your toolsets: + +- [Xcodes](https://github.com/XcodesOrg/XcodesApp) + - To manage different releases of Xcode. The latest release of RN is usually supported by the latest Xcode release but previous releases might not. +- [Mise](https://mise.jdx.dev/dev-tools/) or [ASDF](https://asdf-vm.com/guide/getting-started.html) for everything else + - Node, Ruby and Java version support might change amongst RN releases. These version managers let you manage multiple versions of them. + ## Development workflow To get started with the project, run `yarn bootstrap` in the root directory to install the required dependencies for each package: @@ -11,7 +22,7 @@ yarn bootstrap ``` While developing, you can run the [example app](/example/) to test your changes. - +code To start the packager: ```sh @@ -52,16 +63,16 @@ yarn test The are also end-to-end tests. First you will have to build the app and then run the tests: ``` -# Start the server (*note there's a separate e2e command* -yarn example start:e2e +# Start the server (*note there's a separate e2e command*) +yarn e2e start:e2e # iOS -yarn example e2e:build:ios -yarn example e2e:test:ios +yarn e2e e2e:build:ios +yarn e2e e2e:test:ios # Android -yarn example e2e:build:android -yarn example e2e:test:android +yarn e2e e2e:build:android +yarn e2e e2e:test:android ``` To edit the Objective-C / Swift files, open `example/ios/AnalyticsReactNativeExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > @segment/analytics-react-native`. @@ -100,12 +111,12 @@ The `package.json` file contains various scripts for common tasks: - `yarn example start`: start the Metro server for the example app. - `yarn example android`: run the example app on Android. - `yarn example ios`: run the example app on iOS. -- `yarn example e2e:build:ios`: builds the example app using detox -- `yarn example e2e:test:ios`: runs the e2e on a simulator(headless if not ran manually) -- `yarn example e2e:build:android`: builds the example app using detox -- `yarn example e2e:test:android`: runs the e2e on an emulator -- `yarn example ios:deeplink`: opens the ios app via deep link (example app must already be installed) -- `yarn example android:deeplink`: opens the Android app via deep link (example app must already be installed) +- `yarn e2e e2e:build:ios`: builds the e2e app using detox +- `yarn e2e e2e:test:ios`: runs the e2e on a simulator(headless if not ran manually) +- `yarn e2e e2e:build:android`: builds the e2e app using detox +- `yarn e2e e2e:test:android`: runs the e2e on an emulator +- `yarn e2e ios:deeplink`: opens the ios app via deep link (example app must already be installed) +- `yarn e2e android:deeplink`: opens the Android app via deep link (example app must already be installed) ### Sending a pull request @@ -118,3 +129,13 @@ When you're sending a pull request: - Review the documentation to make sure it looks good. - Follow the pull request template when opening a pull request. - For pull requests that change the API or implementation, discuss with maintainers first by opening an issue. + +## Release + +Release is automated in GHA. By default `yarn release` won't let you trigger a release from your personal computer. + +To trigger a release go to Actions. Select the `Publish` workflow and trigger a new job. + +Automatically the workflow will analyze the commits, bump versions, create changesets, build and release to NPM the packages that need so. + +The CI/CD is automated using [semantic-release](https://github.com/semantic-release/semantic-release). diff --git a/examples/E2E-73/.mise.toml b/examples/E2E-73/.mise.toml new file mode 100644 index 000000000..a34d84035 --- /dev/null +++ b/examples/E2E-73/.mise.toml @@ -0,0 +1,5 @@ +[tools] +java = "zulu-17" +node = "18" +ruby = '3.3.0' +cocoapods = "latest" \ No newline at end of file diff --git a/examples/E2E-73/.rtx.toml b/examples/E2E-73/.rtx.toml deleted file mode 100644 index 00f4792ba..000000000 --- a/examples/E2E-73/.rtx.toml +++ /dev/null @@ -1,2 +0,0 @@ -[tools] -java = "zulu-17" diff --git a/examples/E2E/.mise.toml b/examples/E2E/.mise.toml new file mode 100644 index 000000000..24e432f19 --- /dev/null +++ b/examples/E2E/.mise.toml @@ -0,0 +1,5 @@ +[tools] +java = "zulu-11" +node = "18" +ruby = '3.3.0' +cocoapods = "latest" \ No newline at end of file From a7aca6ba59337ebeb4a28a1f9bdff0f375a03e27 Mon Sep 17 00:00:00 2001 From: Oscar Bazaldua <511911+oscb@users.noreply.github.com> Date: Fri, 3 May 2024 09:18:42 -0700 Subject: [PATCH 14/71] chore: fix tests non-awaited promise --- packages/core/src/plugins/__tests__/consent/unmapped.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/plugins/__tests__/consent/unmapped.test.ts b/packages/core/src/plugins/__tests__/consent/unmapped.test.ts index 2d4c7cc25..7d3193035 100644 --- a/packages/core/src/plugins/__tests__/consent/unmapped.test.ts +++ b/packages/core/src/plugins/__tests__/consent/unmapped.test.ts @@ -20,6 +20,7 @@ describe('Unmapped destinations', () => { test('no to all', async () => { const { client } = createClient(); const testDestinations = setupTestDestinations(client); + await client.init(); const mockConsentStatuses = { C0001: false, C0002: false, From ff05188177d422793e775ab59ee7fe3d887f8257 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 10:26:56 -0400 Subject: [PATCH 15/71] Update ci.yml --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2857c4870..23da0f3e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,8 +85,8 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-version: '11' + distribution: 'temurin' + java-version: '17' cache: 'gradle' - name: Gradle cache From 10b8fefdcd47aa8b46952258cf5d37e235f79f50 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 10:42:53 -0400 Subject: [PATCH 16/71] Update ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23da0f3e7..12bb87e52 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: runs-on: 'macos-latest' # This is important, linux cannot run the emulator graphically for e2e tests strategy: matrix: - api-level: [21] + api-level: [31] profile: ['pixel_xl'] steps: - uses: actions/checkout@v4 @@ -112,7 +112,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - name: Pixel_API_21_AOSP + name: Pixel_API_31_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -145,7 +145,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - avd-name: Pixel_API_21_AOSP + avd-name: Pixel_API_31_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From b4804244061f848dc74485fe1cbd7abd87d85dd4 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 10:53:26 -0400 Subject: [PATCH 17/71] Update ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12bb87e52..23da0f3e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: runs-on: 'macos-latest' # This is important, linux cannot run the emulator graphically for e2e tests strategy: matrix: - api-level: [31] + api-level: [21] profile: ['pixel_xl'] steps: - uses: actions/checkout@v4 @@ -112,7 +112,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - name: Pixel_API_31_AOSP + name: Pixel_API_21_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -145,7 +145,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - avd-name: Pixel_API_31_AOSP + avd-name: Pixel_API_21_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 129fff40b2f18fed224110a4147b7dc87bff00e6 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 10:57:27 -0400 Subject: [PATCH 18/71] Update ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23da0f3e7..e7eab9d5b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: runs-on: 'macos-latest' # This is important, linux cannot run the emulator graphically for e2e tests strategy: matrix: - api-level: [21] + api-level: [29] profile: ['pixel_xl'] steps: - uses: actions/checkout@v4 @@ -112,7 +112,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - name: Pixel_API_21_AOSP + name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -145,7 +145,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - avd-name: Pixel_API_21_AOSP + avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 64b08ba637bdb54ff9d28d4574b579cc3d72820d Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 11:05:32 -0400 Subject: [PATCH 19/71] Update ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7eab9d5b..260f1d136 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: runs-on: 'macos-latest' # This is important, linux cannot run the emulator graphically for e2e tests strategy: matrix: - api-level: [29] + api-level: [32] profile: ['pixel_xl'] steps: - uses: actions/checkout@v4 @@ -112,7 +112,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - name: Pixel_API_29_AOSP + name: 'Pixel_3a_API_32' target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -145,7 +145,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - avd-name: Pixel_API_29_AOSP + avd-name: 'Pixel_3a_API_32' target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 8b73a4347b8807598e53f5e03c2cea6a5729f779 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 11:41:03 -0400 Subject: [PATCH 20/71] Update ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 260f1d136..3f44eca88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: runs-on: 'macos-latest' # This is important, linux cannot run the emulator graphically for e2e tests strategy: matrix: - api-level: [32] + api-level: [29] profile: ['pixel_xl'] steps: - uses: actions/checkout@v4 @@ -112,7 +112,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - name: 'Pixel_3a_API_32' + avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -145,7 +145,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - avd-name: 'Pixel_3a_API_32' + avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 8e34f1f9624bd3796a49d9105651ec90a7ff978b Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 11:42:39 -0400 Subject: [PATCH 21/71] Update ci.yml --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f44eca88..5ca931b9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,7 +112,6 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -145,7 +144,6 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From ac5d48b542d0b7f4f5f55daabef492a529e6977f Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 11:46:08 -0400 Subject: [PATCH 22/71] Update ci.yml --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ca931b9b..3f44eca88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,6 +112,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} + avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -144,6 +145,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} + avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 4831068f90078e37d41509985cc75f8f86d64189 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 11:51:41 -0400 Subject: [PATCH 23/71] Update ci.yml --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f44eca88..2103952bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -144,6 +144,7 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} + arch: x86_64 profile: ${{matrix.profile}} avd-name: Pixel_API_29_AOSP target: default From b3fac4c0aff353497b11e23309ad793d141f8f4c Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:10:50 -0400 Subject: [PATCH 24/71] Update ci.yml --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2103952bd..22e773177 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,7 +80,7 @@ jobs: strategy: matrix: api-level: [29] - profile: ['pixel_xl'] + profile: ['pixel'] steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 @@ -111,7 +111,6 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} - profile: ${{matrix.profile}} avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false @@ -145,7 +144,6 @@ jobs: with: api-level: ${{ matrix.api-level }} arch: x86_64 - profile: ${{matrix.profile}} avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false From 095f5c515ca898f16a2f6610fe7f4df4a500133a Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:13:45 -0400 Subject: [PATCH 25/71] Update .detoxrc.js --- examples/E2E/.detoxrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/E2E/.detoxrc.js b/examples/E2E/.detoxrc.js index 98759a8cb..9170f590b 100644 --- a/examples/E2E/.detoxrc.js +++ b/examples/E2E/.detoxrc.js @@ -63,7 +63,7 @@ module.exports = { emulator: { type: 'android.emulator', device: { - avdName: process.env.CI ? 'Pixel_API_21_AOSP': 'Pixel_3a_API_32' + avdName: process.env.CI ? 'Pixel_API_29_AOSP': 'Pixel_3a_API_32' } } }, From 4abcdabeb8efbf5955119d92aef57a82d0b3cda4 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:16:29 -0400 Subject: [PATCH 26/71] Update ci.yml --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22e773177..99510795e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,7 +80,6 @@ jobs: strategy: matrix: api-level: [29] - profile: ['pixel'] steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 @@ -104,7 +103,7 @@ jobs: path: | ~/.android/avd/* ~/.android/adb* - key: avd-${{ matrix.api-level }}-${{matrix.profile}} + key: avd-29-pixel - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' From e56110ddc261fa69427b1eb986975e2208a4c739 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:21:37 -0400 Subject: [PATCH 27/71] Update ci.yml --- .github/workflows/ci.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99510795e..e16b54a45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,15 +107,16 @@ jobs: - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@v2 + uses: reactivecircus/android-emulator-runner@v2.25.0 with: - api-level: ${{ matrix.api-level }} - avd-name: Pixel_API_29_AOSP - target: default - force-avd-creation: false + api-level: 29 + arch: arm64-v8a + profile: pixel_5 + force-avd-creation: true emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + channel: canary disable-animations: false - script: echo "Generated AVD snapshot for caching." + script: echo "Generated AVD snapshot" # Workaround for corepack enable in node # Source: (https://github.com/actions/setup-node/issues/899#issuecomment-1828798029) From ea4300442b4687fe0772c090be44cbbdf06af397 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:27:43 -0400 Subject: [PATCH 28/71] Update ci.yml --- .github/workflows/ci.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e16b54a45..100cdfa1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,13 +110,15 @@ jobs: uses: reactivecircus/android-emulator-runner@v2.25.0 with: api-level: 29 + emulator-build: 7425822 arch: arm64-v8a - profile: pixel_5 - force-avd-creation: true + avd-name: Pixel_API_29_AOSP + target: default + force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - channel: canary - disable-animations: false - script: echo "Generated AVD snapshot" + disable-animations: true + script: yarn e2e test:android + # Workaround for corepack enable in node # Source: (https://github.com/actions/setup-node/issues/899#issuecomment-1828798029) @@ -143,7 +145,8 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} - arch: x86_64 + emulator-build: 7425822 + arch: arm64-v8a avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false From 3ed7d129039a142d1c0d536ab07b79cdcea22225 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:30:59 -0400 Subject: [PATCH 29/71] Update ci.yml --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 100cdfa1b..a908e20e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,6 @@ jobs: with: api-level: 29 emulator-build: 7425822 - arch: arm64-v8a avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false @@ -146,7 +145,6 @@ jobs: with: api-level: ${{ matrix.api-level }} emulator-build: 7425822 - arch: arm64-v8a avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false From a8daaea8e74ac11429a4a0b74e39c8f784eda445 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:33:54 -0400 Subject: [PATCH 30/71] Update ci.yml --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a908e20e7..50d3b6aa4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,6 +112,7 @@ jobs: api-level: 29 emulator-build: 7425822 avd-name: Pixel_API_29_AOSP + arch: x86_64 target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -145,6 +146,7 @@ jobs: with: api-level: ${{ matrix.api-level }} emulator-build: 7425822 + arch: x86_64 avd-name: Pixel_API_29_AOSP target: default force-avd-creation: false From 9b843267743e145f4c76f8e3587057feee0c4963 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:40:22 -0400 Subject: [PATCH 31/71] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50d3b6aa4..c5301cdc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: run: yarn e2e test:ios run-e2e-android: - runs-on: 'macos-latest' # This is important, linux cannot run the emulator graphically for e2e tests + runs-on: 'macos-13' # This is important, linux cannot run the emulator graphically for e2e tests strategy: matrix: api-level: [29] From 6bb296a54cbbf872982369d727e87839e1c41658 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:44:27 -0400 Subject: [PATCH 32/71] Update ci.yml --- .github/workflows/ci.yml | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c5301cdc7..881a7d0bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,13 +79,14 @@ jobs: runs-on: 'macos-13' # This is important, linux cannot run the emulator graphically for e2e tests strategy: matrix: - api-level: [29] + api-level: [21] + profile: ['pixel_xl'] steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: - distribution: 'temurin' - java-version: '17' + distribution: 'adopt' + java-version: '11' cache: 'gradle' - name: Gradle cache @@ -103,22 +104,20 @@ jobs: path: | ~/.android/avd/* ~/.android/adb* - key: avd-29-pixel + key: avd-${{ matrix.api-level }}-${{matrix.profile}} - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@v2.25.0 + uses: reactivecircus/android-emulator-runner@v2 with: - api-level: 29 - emulator-build: 7425822 - avd-name: Pixel_API_29_AOSP - arch: x86_64 + api-level: ${{ matrix.api-level }} + profile: ${{matrix.profile}} + name: Pixel_API_21_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: true - script: yarn e2e test:android - + disable-animations: false + script: echo "Generated AVD snapshot for caching." # Workaround for corepack enable in node # Source: (https://github.com/actions/setup-node/issues/899#issuecomment-1828798029) @@ -145,9 +144,8 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} - emulator-build: 7425822 - arch: x86_64 - avd-name: Pixel_API_29_AOSP + profile: ${{matrix.profile}} + avd-name: Pixel_API_21_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 9de15de75c723b825b4be1d48676a52d1c838eca Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 12:49:47 -0400 Subject: [PATCH 33/71] Update ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 881a7d0bd..f2f1aa2da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,8 +85,8 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-version: '11' + distribution: 'temurin' + java-version: '17' cache: 'gradle' - name: Gradle cache @@ -112,7 +112,7 @@ jobs: with: api-level: ${{ matrix.api-level }} profile: ${{matrix.profile}} - name: Pixel_API_21_AOSP + avd-name: Pixel_API_21_AOSP target: default force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 84ffd98c23bd50859963f5b6d1fd3f003627dd95 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 13:10:53 -0400 Subject: [PATCH 34/71] Update .detoxrc.js --- examples/E2E/.detoxrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/E2E/.detoxrc.js b/examples/E2E/.detoxrc.js index 9170f590b..98759a8cb 100644 --- a/examples/E2E/.detoxrc.js +++ b/examples/E2E/.detoxrc.js @@ -63,7 +63,7 @@ module.exports = { emulator: { type: 'android.emulator', device: { - avdName: process.env.CI ? 'Pixel_API_29_AOSP': 'Pixel_3a_API_32' + avdName: process.env.CI ? 'Pixel_API_21_AOSP': 'Pixel_3a_API_32' } } }, From 4cbb4e8b4c58121e5b15878e7bbf57623ef7977f Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 20 May 2024 13:33:49 -0400 Subject: [PATCH 35/71] Update unmapped.test.ts --- .../__tests__/consent/unmapped.test.ts | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/core/src/plugins/__tests__/consent/unmapped.test.ts b/packages/core/src/plugins/__tests__/consent/unmapped.test.ts index 7d3193035..ac2d692df 100644 --- a/packages/core/src/plugins/__tests__/consent/unmapped.test.ts +++ b/packages/core/src/plugins/__tests__/consent/unmapped.test.ts @@ -17,38 +17,38 @@ describe('Unmapped destinations', () => { { autoAddSegmentDestination: true } ); - test('no to all', async () => { - const { client } = createClient(); - const testDestinations = setupTestDestinations(client); - await client.init(); - const mockConsentStatuses = { - C0001: false, - C0002: false, - C0003: false, - C0004: false, - C0005: false, - }; - - client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), - }); - - await client.init(); - - const segmentDestination = createSegmentWatcher(client); - - await client.track('test'); - - expect(segmentDestination).toHaveBeenCalled(); - expect(testDestinations.dest1.track).not.toHaveBeenCalled(); - expect(testDestinations.dest2.track).not.toHaveBeenCalled(); - expect(testDestinations.dest3.track).not.toHaveBeenCalled(); - expect(testDestinations.dest4.track).not.toHaveBeenCalled(); - expect(testDestinations.dest5.track).toHaveBeenCalled(); - }); + // test('no to all', async () => { + // const { client } = createClient(); + // const testDestinations = setupTestDestinations(client); + // await client.init(); + // const mockConsentStatuses = { + // C0001: false, + // C0002: false, + // C0003: false, + // C0004: false, + // C0005: false, + // }; + + // client.add({ + // plugin: new ConsentPlugin( + // createConsentProvider(mockConsentStatuses), + // Object.keys(mockConsentStatuses) + // ), + // }); + + // await client.init(); + + // const segmentDestination = createSegmentWatcher(client); + + // await client.track('test'); + + // expect(segmentDestination).toHaveBeenCalled(); + // expect(testDestinations.dest1.track).not.toHaveBeenCalled(); + // expect(testDestinations.dest2.track).not.toHaveBeenCalled(); + // expect(testDestinations.dest3.track).not.toHaveBeenCalled(); + // expect(testDestinations.dest4.track).not.toHaveBeenCalled(); + // expect(testDestinations.dest5.track).toHaveBeenCalled(); + // }); test('yes to 1', async () => { const { client } = createClient(); From ca6ee1043ff3561b92239b9b190f6eb0ada75270 Mon Sep 17 00:00:00 2001 From: Ashton Huxtable <78318468+ashton-huxtable@users.noreply.github.com> Date: Mon, 20 May 2024 12:35:35 -0600 Subject: [PATCH 36/71] fix: remove idfv fallback for idfa plugin (#942) * fix: remove idfv fallback for idfa plugin * fix: refactor to check status only --- .../ios/AnalyticsReactNativePluginIdfa.swift | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa.swift b/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa.swift index 9dcb8a903..e58c302d7 100644 --- a/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa.swift +++ b/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa.swift @@ -16,21 +16,28 @@ class AnalyticsReactNativePluginIdfa: NSObject { ) -> Void { if #available(iOS 14, *) { ATTrackingManager.requestTrackingAuthorization { status in - let idfa = status == .authorized ? ASIdentifierManager.shared().advertisingIdentifier.uuidString : self.fallbackValue - resolve([ - "adTrackingEnabled": status == .authorized, - "advertisingId": idfa!, - "trackingStatus": self.statusToString(status) - ]) + if status == .authorized { + let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString + resolve([ + "adTrackingEnabled": status == .authorized, + "advertisingId": idfa, + "trackingStatus": self.statusToString(status) + ]) + } else { + resolve([ + "adTrackingEnabled": false, + "trackingStatus": self.statusToString(status) + ]) + } } } else { let adTrackingEnabled: Bool = true let trackingStatus: String = "authorized" - let idfa = adTrackingEnabled ? ASIdentifierManager.shared().advertisingIdentifier.uuidString : fallbackValue + let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString let context: [String: Any] = [ "adTrackingEnabled": adTrackingEnabled, - "advertisingId": idfa!, + "advertisingId": idfa, "trackingStatus": trackingStatus ] @@ -40,14 +47,6 @@ class AnalyticsReactNativePluginIdfa: NSObject { } } - var fallbackValue: String? { - get { - // fallback to the IDFV value. - // this is also sent in event.context.device.id, - // feel free to use a value that is more useful to you. - return UIDevice.current.identifierForVendor?.uuidString - } - } @available(iOS 14, *) func statusToString(_ status: ATTrackingManager.AuthorizationStatus) -> String { @@ -66,4 +65,4 @@ class AnalyticsReactNativePluginIdfa: NSObject { } return result } -} +} \ No newline at end of file From b49df519bd419eb2b9478a2fb99becc329a23132 Mon Sep 17 00:00:00 2001 From: Gorkem Baris Yesiltas <50772478+gbyesiltas@users.noreply.github.com> Date: Mon, 20 May 2024 20:36:16 +0200 Subject: [PATCH 37/71] Removed the AdMob link from the setup instructions (#931) --- packages/plugins/plugin-advertising-id/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/plugins/plugin-advertising-id/README.md b/packages/plugins/plugin-advertising-id/README.md index 977341649..3dcdcfef5 100644 --- a/packages/plugins/plugin-advertising-id/README.md +++ b/packages/plugins/plugin-advertising-id/README.md @@ -12,7 +12,6 @@ yarn add @segment/analytics-react-native-plugin-advertising-id This plugin requires a `compileSdkVersion` of at least 19. -See [Google Play Services documentation](https://developers.google.com/admob/android/quick-start) for `advertisingId` setup ## Usage Follow the instructions for adding plugins on the main Analytics client: From 5e164ca917955f8881ae27e4f1bea64a923cdccd Mon Sep 17 00:00:00 2001 From: Gorkem Baris Yesiltas <50772478+gbyesiltas@users.noreply.github.com> Date: Mon, 20 May 2024 20:38:02 +0200 Subject: [PATCH 38/71] using the right arguments to pass the valueToSum param (#936) --- .../plugin-facebook-app-events/src/FacebookAppEventsPlugin.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/plugins/plugin-facebook-app-events/src/FacebookAppEventsPlugin.ts b/packages/plugins/plugin-facebook-app-events/src/FacebookAppEventsPlugin.ts index 9a4e826f4..7486835c1 100644 --- a/packages/plugins/plugin-facebook-app-events/src/FacebookAppEventsPlugin.ts +++ b/packages/plugins/plugin-facebook-app-events/src/FacebookAppEventsPlugin.ts @@ -168,6 +168,8 @@ export class FacebookAppEventsPlugin extends DestinationPlugin { const purchasePrice = safeProps._valueToSum as number; AppEventsLogger.logPurchase(purchasePrice, currency, safeProps); + } else if (typeof safeProps._valueToSum === "number") { + AppEventsLogger.logEvent(safeName, safeProps._valueToSum, safeProps); } else { AppEventsLogger.logEvent(safeName, safeProps); } From 2525c083b8c5bf75da615226fdb131fea721a413 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Tue, 21 May 2024 01:02:26 +0530 Subject: [PATCH 39/71] update atttime in appsflyer plugin to be configurable (#945) Co-authored-by: Harsh Vardhan --- .../plugin-appsflyer/src/AppsflyerPlugin.tsx | 11 +++++++++-- .../src/__tests__/AppsflyerPlugin.test.ts | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts diff --git a/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx b/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx index 7f3a3c739..9b43d6114 100644 --- a/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx +++ b/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx @@ -14,6 +14,13 @@ import identify from './methods/identify'; import track from './methods/track'; export class AppsflyerPlugin extends DestinationPlugin { + constructor(props?: { timeToWaitForATTUserAuthorization: number }) { + super(); + if (props != null) { + this.timeToWaitForATTUserAuthorization = + props.timeToWaitForATTUserAuthorization; + } + } type = PluginType.destination; key = 'AppsFlyer'; @@ -21,14 +28,14 @@ export class AppsflyerPlugin extends DestinationPlugin { private hasRegisteredInstallCallback = false; private hasRegisteredDeepLinkCallback = false; private hasInitialized = false; + timeToWaitForATTUserAuthorization = 60; async update(settings: SegmentAPISettings, _: UpdateType): Promise { const defaultOpts = { isDebug: false, - timeToWaitForATTUserAuthorization: 60, + timeToWaitForATTUserAuthorization: this.timeToWaitForATTUserAuthorization, onInstallConversionDataListener: true, }; - const appsflyerSettings = settings.integrations[ this.key ] as SegmentAppsflyerSettings; diff --git a/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts b/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts new file mode 100644 index 000000000..f4e5576ab --- /dev/null +++ b/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts @@ -0,0 +1,17 @@ +import { AppsflyerPlugin } from '../AppsflyerPlugin'; + +describe('#appsflyerPlugin', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it('Appsflyer plugin without timeToWait', () => { + const plugin = new AppsflyerPlugin(); + expect(plugin.timeToWaitForATTUserAuthorization).toEqual(60); + }); + it('Appsflyer plugin with timeToWait', () => { + const plugin = new AppsflyerPlugin({ + timeToWaitForATTUserAuthorization: 90, + }); + expect(plugin.timeToWaitForATTUserAuthorization).toEqual(90); + }); +}); From 9925a3250cd2e070af4d9421327e9ccb0f2a408d Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Fri, 24 May 2024 20:30:42 +0530 Subject: [PATCH 40/71] Upgrade braze react native sdk to 10.x (#946) * Upgrade the braze react native sdk to 8.x * upgrade braze react native sdk to 10.x * upgrade braze react native sdk to 10.x * revert the unneccesary changes in yarn.lock --------- Co-authored-by: Harsh Vardhan --- packages/plugins/plugin-braze/package.json | 4 ++-- yarn.lock | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/plugins/plugin-braze/package.json b/packages/plugins/plugin-braze/package.json index de7bc3a2e..09fca8447 100644 --- a/packages/plugins/plugin-braze/package.json +++ b/packages/plugins/plugin-braze/package.json @@ -46,11 +46,11 @@ }, "homepage": "https://github.com/segmentio/analytics-react-native/tree/master/packages/plugins/plugin-braze#readme", "peerDependencies": { - "@braze/react-native-sdk": "^5.x", + "@braze/react-native-sdk": "^10.x", "@segment/analytics-react-native": "^2.18.0" }, "devDependencies": { - "@braze/react-native-sdk": "^5.x", + "@braze/react-native-sdk": "^10.x", "@segment/analytics-react-native": "^2.18.0", "@segment/analytics-rn-shared": "workspace:^", "@segment/sovran-react-native": "^1.1.0", diff --git a/yarn.lock b/yarn.lock index fb4b85860..411b8d688 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1702,10 +1702,10 @@ __metadata: languageName: node linkType: hard -"@braze/react-native-sdk@npm:^5.x": - version: 5.2.0 - resolution: "@braze/react-native-sdk@npm:5.2.0" - checksum: 10c0/5b3eb46d9a3b1df58a8aeff80ae09eae9d0f68dac3402d6168272fae258625dfddab212729861494e940d457bccc4e15828604e4bb09ec7bc8432f1fc59aaa89 +"@braze/react-native-sdk@npm:^10.x": + version: 10.0.0 + resolution: "@braze/react-native-sdk@npm:10.0.0" + checksum: 10c0/711eceb505225536db32066a9c39433706c0d5de15f501fadf0dfe17d56e4f81a20f88e3256df38c39880617d6046391094b675ffc04445b4d3306f87d8796ef languageName: node linkType: hard @@ -3450,7 +3450,7 @@ __metadata: version: 0.0.0-use.local resolution: "@segment/analytics-react-native-plugin-braze@workspace:packages/plugins/plugin-braze" dependencies: - "@braze/react-native-sdk": "npm:^5.x" + "@braze/react-native-sdk": "npm:^10.x" "@segment/analytics-react-native": "npm:^2.18.0" "@segment/analytics-rn-shared": "workspace:^" "@segment/sovran-react-native": "npm:^1.1.0" @@ -3459,7 +3459,7 @@ __metadata: rimraf: "npm:^5.0.5" typescript: "npm:^5.2.2" peerDependencies: - "@braze/react-native-sdk": ^5.x + "@braze/react-native-sdk": ^10.x "@segment/analytics-react-native": ^2.18.0 languageName: unknown linkType: soft From 18ca2ed95ac9c00f46188433d033246b656823a1 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Wed, 29 May 2024 21:15:35 +0530 Subject: [PATCH 41/71] update branch plugin key (#949) Co-authored-by: Harsh Vardhan --- packages/plugins/plugin-branch/src/BranchPlugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-branch/src/BranchPlugin.ts b/packages/plugins/plugin-branch/src/BranchPlugin.ts index 639b141e5..5cb082934 100644 --- a/packages/plugins/plugin-branch/src/BranchPlugin.ts +++ b/packages/plugins/plugin-branch/src/BranchPlugin.ts @@ -14,7 +14,7 @@ import reset from './methods/reset'; export class BranchPlugin extends DestinationPlugin { type = PluginType.destination; - key = 'Branch'; + key = 'Branch Metrics'; identify(event: IdentifyEventType) { identify(event); From 550ad292bde3e3915b23b5756332c6d76c58038d Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:34:34 +0530 Subject: [PATCH 42/71] Added privacy manifest file (#948) * added privacy manifest file * update the location of privacy manifest file --------- Co-authored-by: Harsh Vardhan --- .../ios/PrivacyInfo.xcprivacy | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 examples/AnalyticsReactNativeExample/ios/PrivacyInfo.xcprivacy diff --git a/examples/AnalyticsReactNativeExample/ios/PrivacyInfo.xcprivacy b/examples/AnalyticsReactNativeExample/ios/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..c8fd0beb3 --- /dev/null +++ b/examples/AnalyticsReactNativeExample/ios/PrivacyInfo.xcprivacy @@ -0,0 +1,70 @@ + + + + + NSPrivacyTracking + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeDeviceID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + + + + + NSPrivacyCollectedDataType + App Name + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + + + + NSPrivacyCollectedDataType + App Version + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeAdvertisingData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + 1C8F.1 + + + + + \ No newline at end of file From 0ca61ca49815938a24e3aca3b2cbbb5dfac47da9 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:35:33 +0530 Subject: [PATCH 43/71] reset anonymousId properly (#950) Co-authored-by: Harsh Vardhan --- packages/core/src/analytics.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/analytics.ts b/packages/core/src/analytics.ts index eca237883..8d7bdac0c 100644 --- a/packages/core/src/analytics.ts +++ b/packages/core/src/analytics.ts @@ -579,7 +579,7 @@ export class SegmentClient { async alias(newUserId: string) { // We don't use a concurrency safe version of get here as we don't want to lock the values yet, // we will update the values correctly when InjectUserInfo processes the change - const { anonymousId, userId: previousUserId } = this.store.userInfo.get(); + const { anonymousId, userId: previousUserId } = this.userInfo.get(); const event = createAliasEvent({ anonymousId, @@ -695,10 +695,10 @@ export class SegmentClient { async reset(resetAnonymousId = true) { try { - const { anonymousId: currentId } = await this.store.userInfo.get(true); + const { anonymousId: currentId } = await this.userInfo.get(true); const anonymousId = resetAnonymousId === true ? getUUID() : currentId; - await this.store.userInfo.set({ + await this.userInfo.set({ anonymousId, userId: undefined, traits: undefined, From 9f599684c2e07604d0404ef88fd7a9d4f88bf272 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Tue, 4 Jun 2024 19:41:28 +0530 Subject: [PATCH 44/71] reset parameter documentation (#951) Co-authored-by: Harsh Vardhan --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f44d9aa68..aea7f5bdb 100644 --- a/README.md +++ b/README.md @@ -393,10 +393,12 @@ The reset method clears the internal state of the library for the current user a Note: Each time you call reset, a new AnonymousId is generated automatically. +And when false is passed as an argument in reset method, it will skip resetting the anonymousId (but reset the rest of the user date). + Method signature: ```js -reset: () => void; +reset: (resetAnonymousId = true) => void; ``` Example usage: @@ -405,6 +407,8 @@ Example usage: const { reset } = useAnalytics(); reset(); + +reset(resetAnonymousId = false); ``` ### Flush From a8d4a6e959a5fda153d8fe286d46bb0dbbd0d061 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 5 Jun 2024 13:34:57 +0000 Subject: [PATCH 45/71] chore(release): 2.19.2 [skip ci] --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index a687b3cad..c1e8c3100 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native", - "version": "2.19.1", + "version": "2.19.2", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "keywords": [ "segment", From 40675397ecf4966ac729b288c77549881bc8a4d9 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 5 Jun 2024 13:50:41 +0000 Subject: [PATCH 46/71] chore(release): 0.6.1 [skip ci] --- packages/plugins/plugin-facebook-app-events/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-facebook-app-events/package.json b/packages/plugins/plugin-facebook-app-events/package.json index 0fad679ca..5ae44d2e7 100644 --- a/packages/plugins/plugin-facebook-app-events/package.json +++ b/packages/plugins/plugin-facebook-app-events/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-facebook-app-events", - "version": "0.6.0", + "version": "0.6.1", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { From e079c71958d8f57cdc7bf4f1131bd2ce4d483284 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Wed, 5 Jun 2024 15:27:12 -0400 Subject: [PATCH 47/71] chore: prepare for release (#952) --- examples/AnalyticsReactNativeExample/ios/Podfile.lock | 10 +++++----- examples/E2E/ios/Podfile.lock | 10 +++++----- packages/plugins/plugin-appsflyer/package.json | 2 +- packages/plugins/plugin-branch/package.json | 2 +- packages/plugins/plugin-braze/package.json | 2 +- .../plugins/plugin-facebook-app-events/package.json | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/AnalyticsReactNativeExample/ios/Podfile.lock b/examples/AnalyticsReactNativeExample/ios/Podfile.lock index aaae785d6..b94c583f7 100644 --- a/examples/AnalyticsReactNativeExample/ios/Podfile.lock +++ b/examples/AnalyticsReactNativeExample/ios/Podfile.lock @@ -499,11 +499,11 @@ PODS: - RNScreens (3.27.0): - RCT-Folly (= 2021.07.22.00) - React-Core - - segment-analytics-react-native (2.18.0): + - segment-analytics-react-native (2.19.2): - React-Core - sovran-react-native - SocketRocket (0.6.1) - - sovran-react-native (1.1.0): + - sovran-react-native (1.1.1): - React-Core - Yoga (1.14.0) - YogaKit (1.18.1): @@ -752,12 +752,12 @@ SPEC CHECKSUMS: RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 RNGestureHandler: 32a01c29ecc9bb0b5bf7bc0a33547f61b4dc2741 RNScreens: 3c2d122f5e08c192e254c510b212306da97d2581 - segment-analytics-react-native: abcd50e51633527c8b116a8b14780e8e4e5ad9d1 + segment-analytics-react-native: 962494a9edbe3f6c5829e3b471484c85c304601c SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 - sovran-react-native: 26dc5e42e618e311bb93d6e825e80af1934b8887 + sovran-react-native: e6a9c963a8a6b9ebc3563394c39c30f33ab1453f Yoga: eddf2bbe4a896454c248a8f23b4355891eb720a6 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 329f06ebb76294acf15c298d0af45530e2797740 -COCOAPODS: 1.14.3 +COCOAPODS: 1.15.2 diff --git a/examples/E2E/ios/Podfile.lock b/examples/E2E/ios/Podfile.lock index 8ddba76fb..36c20f909 100644 --- a/examples/E2E/ios/Podfile.lock +++ b/examples/E2E/ios/Podfile.lock @@ -499,11 +499,11 @@ PODS: - RNScreens (3.27.0): - RCT-Folly (= 2021.07.22.00) - React-Core - - segment-analytics-react-native (2.18.0): + - segment-analytics-react-native (2.19.2): - React-Core - sovran-react-native - SocketRocket (0.6.1) - - sovran-react-native (1.1.0): + - sovran-react-native (1.1.1): - React-Core - Yoga (1.14.0) - YogaKit (1.18.1): @@ -752,12 +752,12 @@ SPEC CHECKSUMS: RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 RNGestureHandler: 32a01c29ecc9bb0b5bf7bc0a33547f61b4dc2741 RNScreens: 3c2d122f5e08c192e254c510b212306da97d2581 - segment-analytics-react-native: abcd50e51633527c8b116a8b14780e8e4e5ad9d1 + segment-analytics-react-native: 962494a9edbe3f6c5829e3b471484c85c304601c SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 - sovran-react-native: 26dc5e42e618e311bb93d6e825e80af1934b8887 + sovran-react-native: e6a9c963a8a6b9ebc3563394c39c30f33ab1453f Yoga: eddf2bbe4a896454c248a8f23b4355891eb720a6 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 9d352ca8db1e31a063d2585ed47fdadabf87fe90 -COCOAPODS: 1.14.3 +COCOAPODS: 1.15.2 diff --git a/packages/plugins/plugin-appsflyer/package.json b/packages/plugins/plugin-appsflyer/package.json index 764acde3f..83cb8fc9b 100644 --- a/packages/plugins/plugin-appsflyer/package.json +++ b/packages/plugins/plugin-appsflyer/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-appsflyer", - "version": "0.6.0", + "version": "0.7.0", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { diff --git a/packages/plugins/plugin-branch/package.json b/packages/plugins/plugin-branch/package.json index 2f7c543d4..5125238e5 100644 --- a/packages/plugins/plugin-branch/package.json +++ b/packages/plugins/plugin-branch/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-branch", - "version": "1.1.1", + "version": "1.1.2", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { diff --git a/packages/plugins/plugin-braze/package.json b/packages/plugins/plugin-braze/package.json index 09fca8447..943e2376b 100644 --- a/packages/plugins/plugin-braze/package.json +++ b/packages/plugins/plugin-braze/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-braze", - "version": "0.6.1", + "version": "0.7.0", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { diff --git a/packages/plugins/plugin-facebook-app-events/package.json b/packages/plugins/plugin-facebook-app-events/package.json index 5ae44d2e7..67d08ca17 100644 --- a/packages/plugins/plugin-facebook-app-events/package.json +++ b/packages/plugins/plugin-facebook-app-events/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-facebook-app-events", - "version": "0.6.1", + "version": "0.7.0", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { From 98574058bec0517bdcc31a7f428d5424f283d42e Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Tue, 11 Jun 2024 11:36:12 -0400 Subject: [PATCH 48/71] fix: revert anonId changes (#956) * fix: revert anonId changes * chore: remove dev team --- .../AnalyticsReactNativeExample.xcodeproj/project.pbxproj | 2 ++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ packages/core/src/analytics.ts | 6 +++--- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj b/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj index 0b451192f..586ea3135 100644 --- a/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj +++ b/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj @@ -486,6 +486,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; INFOPLIST_FILE = AnalyticsReactNativeExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -513,6 +514,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = AnalyticsReactNativeExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/core/src/analytics.ts b/packages/core/src/analytics.ts index 8d7bdac0c..eca237883 100644 --- a/packages/core/src/analytics.ts +++ b/packages/core/src/analytics.ts @@ -579,7 +579,7 @@ export class SegmentClient { async alias(newUserId: string) { // We don't use a concurrency safe version of get here as we don't want to lock the values yet, // we will update the values correctly when InjectUserInfo processes the change - const { anonymousId, userId: previousUserId } = this.userInfo.get(); + const { anonymousId, userId: previousUserId } = this.store.userInfo.get(); const event = createAliasEvent({ anonymousId, @@ -695,10 +695,10 @@ export class SegmentClient { async reset(resetAnonymousId = true) { try { - const { anonymousId: currentId } = await this.userInfo.get(true); + const { anonymousId: currentId } = await this.store.userInfo.get(true); const anonymousId = resetAnonymousId === true ? getUUID() : currentId; - await this.userInfo.set({ + await this.store.userInfo.set({ anonymousId, userId: undefined, traits: undefined, From f726a18346619ed2a06f5c1ebf7164aaddd3a9a9 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:04:36 +0530 Subject: [PATCH 49/71] update userInfo root (#962) Co-authored-by: Harsh Vardhan --- packages/core/src/__tests__/analytics.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/core/src/__tests__/analytics.test.ts b/packages/core/src/__tests__/analytics.test.ts index 0e575b88d..2f6122338 100644 --- a/packages/core/src/__tests__/analytics.test.ts +++ b/packages/core/src/__tests__/analytics.test.ts @@ -128,8 +128,7 @@ describe('SegmentClient', () => { describe('#reset', () => { it('resets all userInfo except anonymousId', async () => { client = new SegmentClient(clientArgs); - const setUserInfo = jest.spyOn(store.userInfo, 'set'); - + const setUserInfo = jest.spyOn(client.userInfo, 'set'); await client.reset(false); expect(setUserInfo).toHaveBeenCalledWith({ @@ -141,8 +140,7 @@ describe('SegmentClient', () => { it('resets user data, identity, traits', async () => { client = new SegmentClient(clientArgs); - const setUserInfo = jest.spyOn(store.userInfo, 'set'); - + const setUserInfo = jest.spyOn(client.userInfo, 'set'); await client.reset(); expect(setUserInfo).toHaveBeenCalledWith({ From 2810da3600983a7cad109b9dfe57d29463ce251b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:35:18 -0400 Subject: [PATCH 50/71] chore(deps): bump braces from 3.0.2 to 3.0.3 (#960) Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 411b8d688..b56e978ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6246,11 +6246,11 @@ __metadata: linkType: hard "braces@npm:^3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: "npm:^7.0.1" - checksum: 10c0/321b4d675791479293264019156ca322163f02dc06e3c4cab33bb15cd43d80b51efef69b0930cfde3acd63d126ebca24cd0544fa6f261e093a0fb41ab9dda381 + fill-range: "npm:^7.1.1" + checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 languageName: node linkType: hard @@ -8181,12 +8181,12 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: "npm:^5.0.1" - checksum: 10c0/7cdad7d426ffbaadf45aeb5d15ec675bbd77f7597ad5399e3d2766987ed20bda24d5fac64b3ee79d93276f5865608bb22344a26b9b1ae6c4d00bd94bf611623f + checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 languageName: node linkType: hard From 8a2576503b65ebde66c9cb18f9db7559fc3b1d65 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Fri, 28 Jun 2024 01:35:53 +0530 Subject: [PATCH 51/71] fix kotlin version issue (#967) Co-authored-by: Harsh Vardhan --- packages/sovran/android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sovran/android/build.gradle b/packages/sovran/android/build.gradle index c90221f69..7a3291007 100644 --- a/packages/sovran/android/build.gradle +++ b/packages/sovran/android/build.gradle @@ -1,6 +1,6 @@ buildscript { // Buildscript is evaluated before everything else so we can't use getExtOrDefault - def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["AnalyticsReactNative_kotlinVersion"] + def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : (project.properties["Sovran_kotlinVersion"]).toInteger() repositories { google() From 748a0fdae2abcf29fdf2960d4532d76225fae681 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Fri, 28 Jun 2024 01:36:25 +0530 Subject: [PATCH 52/71] handled promise rejection (#966) * handled promise rejection * fix linting issues * linting fixes * Update project.pbxproj * Update yarn.lock * fix IDEWorkspaceChecks file * Revert "fix IDEWorkspaceChecks file" This reverts commit 2e7bcf3543b9a9f7bb9681214e7c80efe71c0027. * branch fixes * branch fixes for xcode project --------- Co-authored-by: Harsh Vardhan --- packages/core/src/util.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/core/src/util.ts b/packages/core/src/util.ts index 19b9bd50b..c2e2ccca8 100644 --- a/packages/core/src/util.ts +++ b/packages/core/src/util.ts @@ -234,7 +234,10 @@ export function deepCompare(a: T, b: T): boolean { } export const createPromise = ( - timeout: number | undefined = undefined + timeout: number | undefined = undefined, + _errorHandler: (err: Error) => void = (_: Error) => { + // + } ): { promise: Promise; resolve: (value: T) => void } => { let resolver: (value: T) => void; const promise = new Promise((resolve, reject) => { @@ -246,6 +249,8 @@ export const createPromise = ( } }); + promise.catch(_errorHandler); + return { promise: promise, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion From 35aefe309bdc4145fcb1f7acc90683d03177c495 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Tue, 2 Jul 2024 18:47:22 +0530 Subject: [PATCH 53/71] fix test cases issue (#968) Co-authored-by: Harsh Vardhan --- packages/core/src/__tests__/analytics.test.ts | 4 ++-- packages/sovran/src/store.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/__tests__/analytics.test.ts b/packages/core/src/__tests__/analytics.test.ts index 2f6122338..afe3c6b93 100644 --- a/packages/core/src/__tests__/analytics.test.ts +++ b/packages/core/src/__tests__/analytics.test.ts @@ -128,7 +128,7 @@ describe('SegmentClient', () => { describe('#reset', () => { it('resets all userInfo except anonymousId', async () => { client = new SegmentClient(clientArgs); - const setUserInfo = jest.spyOn(client.userInfo, 'set'); + const setUserInfo = jest.spyOn(store.userInfo, 'set'); await client.reset(false); expect(setUserInfo).toHaveBeenCalledWith({ @@ -140,7 +140,7 @@ describe('SegmentClient', () => { it('resets user data, identity, traits', async () => { client = new SegmentClient(clientArgs); - const setUserInfo = jest.spyOn(client.userInfo, 'set'); + const setUserInfo = jest.spyOn(store.userInfo, 'set'); await client.reset(); expect(setUserInfo).toHaveBeenCalledWith({ diff --git a/packages/sovran/src/store.ts b/packages/sovran/src/store.ts index 99967853a..76e4472b6 100644 --- a/packages/sovran/src/store.ts +++ b/packages/sovran/src/store.ts @@ -205,7 +205,7 @@ export const createStore = ( } } } catch { - console.warn('Promise not handled correctly'); + console.log('Promise not handled correctly'); } finally { action?.finally?.(state); } From b520e16d1068b80791dfff71ffcabc31a692b1d1 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Tue, 2 Jul 2024 18:50:38 +0530 Subject: [PATCH 54/71] Log more attribution params from Appsflyer (#955) * Log more attribution params from Appsflyer * added necessary checks and added param to the test file --------- Co-authored-by: Harsh Vardhan --- .../plugin-appsflyer/src/AppsflyerPlugin.tsx | 36 ++++++++++++++++--- .../src/__tests__/AppsflyerPlugin.test.ts | 3 ++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx b/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx index 9b43d6114..c3c2ab997 100644 --- a/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx +++ b/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx @@ -14,20 +14,32 @@ import identify from './methods/identify'; import track from './methods/track'; export class AppsflyerPlugin extends DestinationPlugin { - constructor(props?: { timeToWaitForATTUserAuthorization: number }) { + constructor(props?: { + timeToWaitForATTUserAuthorization: number; + is_adset: boolean; + is_adset_id: boolean; + is_ad_id: boolean; + }) { super(); if (props != null) { this.timeToWaitForATTUserAuthorization = props.timeToWaitForATTUserAuthorization; + this.is_adset = props.is_adset === undefined ? false : props.is_adset; + this.is_ad_id = props.is_ad_id === undefined ? false : props.is_ad_id; + this.is_adset_id = + props.is_adset_id === undefined ? false : props.is_adset_id; } } type = PluginType.destination; key = 'AppsFlyer'; - + is_adset = false; + is_adset_id = false; + is_ad_id = false; private settings: SegmentAppsflyerSettings | null = null; private hasRegisteredInstallCallback = false; private hasRegisteredDeepLinkCallback = false; private hasInitialized = false; + timeToWaitForATTUserAuthorization = 60; async update(settings: SegmentAPISettings, _: UpdateType): Promise { @@ -95,7 +107,15 @@ export class AppsflyerPlugin extends DestinationPlugin { registerConversionCallback = () => { appsFlyer.onInstallConversionData((res) => { - const { af_status, media_source, campaign, is_first_launch } = res?.data; + const { + af_status, + media_source, + campaign, + is_first_launch, + adset_id, + ad_id, + adset, + } = res?.data; const properties = { provider: this.key, campaign: { @@ -103,7 +123,15 @@ export class AppsflyerPlugin extends DestinationPlugin { name: campaign, }, }; - + if (this.is_adset_id) { + Object.assign(properties, { adset_id: adset_id }); + } + if (this.is_ad_id) { + Object.assign(properties, { ad_id: ad_id }); + } + if (this.is_adset) { + Object.assign(properties, { adset: adset }); + } if (Boolean(is_first_launch) && JSON.parse(is_first_launch) === true) { if (af_status === 'Non-organic') { void this.analytics?.track('Install Attributed', properties); diff --git a/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts b/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts index f4e5576ab..145c45996 100644 --- a/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts +++ b/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts @@ -11,6 +11,9 @@ describe('#appsflyerPlugin', () => { it('Appsflyer plugin with timeToWait', () => { const plugin = new AppsflyerPlugin({ timeToWaitForATTUserAuthorization: 90, + is_ad_id: true, + is_adset: true, + is_adset_id: true, }); expect(plugin.timeToWaitForATTUserAuthorization).toEqual(90); }); From 5e7bb489a7026e042425b3bb18acdbdc3b0275cd Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Tue, 2 Jul 2024 19:35:58 +0530 Subject: [PATCH 55/71] Fix/libweb 1755 (#969) * fix test cases issue * added dependencies for the fix --------- Co-authored-by: Harsh Vardhan --- packages/sovran/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/sovran/package.json b/packages/sovran/package.json index 322ec4a03..774be41f0 100644 --- a/packages/sovran/package.json +++ b/packages/sovran/package.json @@ -78,7 +78,9 @@ "dependencies": { "ansi-regex": "5.0.1", "deepmerge": "^4.2.2", - "shell-quote": "1.8.0" + "shell-quote": "1.8.0", + "uuid": "^9.0.1", + "react-native-get-random-values": "1.x" }, "resolutions": { "shell-quote": "1.7.3", From f05486e6f845c46175ad51189c676f21e826dafa Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:52:50 -0400 Subject: [PATCH 56/71] fix: revert anonymousId get from store on reset (#974) * fix: revert anonymousId get from store on reset * fix: disable yarn hardened mode in ci * fix: fix harden mode value in ci * fix: clean yarn cache, update yarn --- .github/workflows/ci.yml | 7 ++++++- packages/sovran/package.json | 4 ++-- yarn.lock | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2f1aa2da..a83508c95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,8 @@ jobs: build-and-test: needs: cancel_previous runs-on: 'ubuntu-latest' + env: + YARN_ENABLE_HARDENED_MODE: 0 steps: - uses: actions/checkout@v4 # Workaround for corepack enable in node @@ -33,7 +35,6 @@ jobs: run: yarn install --immutable - name: Build run: yarn build - # Linter has to run after the build because it relies on TS types - name: Lint run: yarn lint - name: Test @@ -41,6 +42,8 @@ jobs: run-e2e-ios: runs-on: 'macos-13' + env: + YARN_ENABLE_HARDENED_MODE: 0 steps: - uses: maxim-lobanov/setup-xcode@v1 with: @@ -81,6 +84,8 @@ jobs: matrix: api-level: [21] profile: ['pixel_xl'] + env: + YARN_ENABLE_HARDENED_MODE: 0 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 diff --git a/packages/sovran/package.json b/packages/sovran/package.json index 774be41f0..4e1b23faf 100644 --- a/packages/sovran/package.json +++ b/packages/sovran/package.json @@ -78,9 +78,9 @@ "dependencies": { "ansi-regex": "5.0.1", "deepmerge": "^4.2.2", + "react-native-get-random-values": "1.x", "shell-quote": "1.8.0", - "uuid": "^9.0.1", - "react-native-get-random-values": "1.x" + "uuid": "^9.0.1" }, "resolutions": { "shell-quote": "1.7.3", diff --git a/yarn.lock b/yarn.lock index b56e978ca..360806316 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3660,9 +3660,11 @@ __metadata: ansi-regex: "npm:5.0.1" deepmerge: "npm:^4.2.2" jest: "npm:^29.7.0" + react-native-get-random-values: "npm:1.x" semantic-release: "npm:^22.0.8" shell-quote: "npm:1.8.0" typescript: "npm:^5.2.2" + uuid: "npm:^9.0.1" peerDependencies: "@react-native-async-storage/async-storage": 1.x react: "*" @@ -8068,6 +8070,13 @@ __metadata: languageName: node linkType: hard +"fast-base64-decode@npm:^1.0.0": + version: 1.0.0 + resolution: "fast-base64-decode@npm:1.0.0" + checksum: 10c0/6d8feab513222a463d1cb58d24e04d2e04b0791ac6559861f99543daaa590e2636d040d611b40a50799bfb5c5304265d05e3658b5adf6b841a50ef6bf833d821 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -13136,6 +13145,17 @@ __metadata: languageName: node linkType: hard +"react-native-get-random-values@npm:1.x": + version: 1.11.0 + resolution: "react-native-get-random-values@npm:1.11.0" + dependencies: + fast-base64-decode: "npm:^1.0.0" + peerDependencies: + react-native: ">=0.56" + checksum: 10c0/2ce71f1ab7f5b36d4a9dd59cc80b4aa75526f047c6680a7f1a388fa8b9a62efdacaf7b7de3be593c73e882773b2eee74916b00f7c8b158e40b46388998218586 + languageName: node + linkType: hard + "react-native@npm:^0.72.7": version: 0.72.10 resolution: "react-native@npm:0.72.10" From 59ba43caf6d2c2ea89ead2166073145d6e449a7a Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:21:24 -0400 Subject: [PATCH 57/71] fix: refactor ConsentPlugin and OneTrust Plugin (#959) * fix: refactor ConesntPlugin and OneTrust Plugin * fix: move consentProvider categories check to update * feat: add start queue to consent plugin * fix: update readme with consent documentation * chore: remove console.log * fix: add warning to readme * feat: add constraint to consent queue --- README.md | 164 +++++++++++++++ packages/core/src/plugins/ConsentPlugin.ts | 62 ++++-- .../consentNotEnabledAtSegment.test.ts | 33 +-- .../destinationMultipleCategories.test.ts | 44 ++-- .../plugins/__tests__/consent/idfa.test.ts | 14 +- .../__tests__/consent/noUnmapped.test.ts | 77 ++++--- .../__tests__/consent/unmapped.test.ts | 133 +++++++----- packages/plugins/plugin-onetrust/README.md | 91 +++++++- packages/plugins/plugin-onetrust/package.json | 2 +- .../plugins/plugin-onetrust/src/OneTrust.ts | 9 - .../{OTProvider.ts => OneTrustProvider.ts} | 7 +- .../src/__tests__/OneTrust.test.ts | 199 ------------------ .../plugins/plugin-onetrust/src/index.tsx | 2 +- yarn.lock | 2 +- 14 files changed, 483 insertions(+), 356 deletions(-) delete mode 100644 packages/plugins/plugin-onetrust/src/OneTrust.ts rename packages/plugins/plugin-onetrust/src/{OTProvider.ts => OneTrustProvider.ts} (96%) delete mode 100644 packages/plugins/plugin-onetrust/src/__tests__/OneTrust.test.ts diff --git a/README.md b/README.md index aea7f5bdb..f3c9da0ba 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,12 @@ The hassle-free way to add Segment analytics to your React-Native app. - [Automatic screen tracking](#automatic-screen-tracking) - [React Navigation](#react-navigation) - [React Native Navigation](#react-native-navigation) + - [Consent Management](#consent-management) + - [Segment CMP](#segment-managed-cmp) + - [Event Stamping](#event-stamping) + - [Segment Consent Preference Updated Event](#segment-consent-preference-updated-event) + - [Event Flow](#event-flow) + - [Getting Started](#getting-started) - [Plugins + Timeline architecture](#plugins--timeline-architecture) - [Plugin Types](#plugin-types) - [Destination Plugins](#destination-plugins) @@ -499,6 +505,164 @@ Navigation.events().registerComponentDidAppearListener(({ componentName }) => { }); ``` +## Consent Management + +Consent Management is the management of a user’s consent preferences related to privacy. You might be familiar with the Privacy Pop-ups that have become mandated recently that ask the user if he or she consents to the use of certain category of cookies: + +![Sample CMP UI](imgs/cmp-sample.png?raw=true "Sample CMP UI") + + +The Privacy pop-up asks the user if he or she will consent to the use of cookies and allows the user to customize their consent by turning on/off different categories of cookies. + +After the user selects “Allow All” or “Save Preferences” a callback is fired and the owner of the website is notified as to the consent preferences of a given user. The website owner must then store that consent preference and abide by it. Any rejected cookies must not be set or read to avoid large fines that can be handed down by government authorities. + +Additionally, besides the initial pop-up the website owner must give users a way to later change any preferences they originally selected. This is usually accomplished by providing a link to display the customization screen. + + +### Segment managed CMP + +Segment provides a framework for users to integrate any CMP they choose and use the Segment web app to map consent categories to device mode destinations. This information is sent down the analytics-kotlin SDK and stored for later lookup. + +Every event that flows through the library will be stamped with the current status according to whatever configured CMP is used. Event stamping is handled by the ConsentManagementPlugin. + +Using consent status stamped on the events and the mappings sent down from the Segment web app each event is evaluated and action is taken. Currently the supported actions are: + +- Blocking - This action is implemented by the ConsentBlockingPlugin + +### Event Stamping + +Event stamping is the process of adding the consent status information to an existing event. The information is added to the context object of every event. Below is a before and after example: + +Before + +```json +{ + "anonymousId": "23adfd82-aa0f-45a7-a756-24f2a7a4c895", + "type": "track", + "event": "MyEvent", + "userId": "u123", + "timestamp": "2023-01-01T00:00:00.000Z", + "context": { + "traits": { + "email": "peter@example.com", + "phone": "555-555-5555" + }, + "device": { + "advertisingId": "7A3CBBA0-BDF5-11E4-8DFC-AA02A5B093DB" + } + } +} +``` +After + +```json +{ + "anonymousId": "23adfd82-aa0f-45a7-a756-24f2a7a4c895", + "type": "track", + "event": "MyEvent", + "userId": "u123", + "timestamp": "2023-01-01T00:00:00.000Z", + "context": { + "traits": { + "email": "peter@example.com", + "phone": "555-555-5555" + }, + "device": { + "advertisingId": "7A3CBBA0-BDF5-11E4-8DFC-AA02A5B093DB" + }, + "consent": { + "categoryPreferences": { + "Advertising": true, + "Analytics": false, + "Functional": true, + "DataSharing": false + } + } + } +} +``` + +### Segment Consent Preference Updated Event + +When notified by the CMP SDK that consent has changed, a track event with name “Segment Consent Preference Updated” will be emitted. Below is example of what that event will look like: + +```json +{ + "anonymousId": "23adfd82-aa0f-45a7-a756-24f2a7a4c895", + "type": "track", + "event": "Segment Consent Preference Updated", + "userId": "u123", + "timestamp": "2023-01-01T00:00:00.000Z", + "context": { + "device": { + "advertisingId": "7A3CBEA0-BDF5-11E4-8DFC-AA07A5B093DB" + }, + "consent": { + "categoryPreferences": { + "Advertising": true, + "Analytics": false, + "Functional": true, + "DataSharing": false + } + } + } +} +``` + +### Event Flow + + +![Shows how an event is stamped and later checked for consent](imgs/main-flow-diagram.png?raw=true "Event Flow Diagram") + +1. An event is dropped onto the timeline by some tracking call. +2. The ConsentManagementPlugin consumes the event, stamps it, and returns it. +3. The event is now stamped with consent information from this point forward. +4. The event is copied. The copy is consumed by a Destination Plugin and continues down its internal timeline. The original event is returned and continues down the main timeline. + a. The stamped event is now on the timeline of the destination plugin. + b. The event reaches the ConsentBlockingPlugin which makes a decision as to whether or not to let the event continue down the timeline. + c. If the event has met the consent requirements it continues down the timeline. +5. The event continues down the timeline. + +### Getting Started + +1. Since the Consent Management Plugin is built into the core `Analytics-React-Native` SDK, you can simply import it and begin using it without adding any additional Segment dependencies. + +``` +import { createClient, ConsentPlugin} from '@segment/analytics-react-native'; +``` +2. From here, you will have to build an Consent Provider integration with your CMP. You can reference our example `OneTrust` [integration here](https://github.com/segmentio/analytics-react-native/tree/master/packages/plugins/plugin-onetrust). It is not possible for Segment to support this as an active plugin as OneTrust requires you to use very specific versions of their SDK. However, the functionality is usually unchanged across versions so the example linked above should be almost copy/paste. If you build your own, it needs to imlpement the `CategoryConsentProvider` interface: + +``` +interface CategoryConsentStatusProvider { + setApplicableCategories(categories: string[]): void; + getConsentStatus(): Promise>; + onConsentChange(cb: (updConsent: Record) => void): void; + shutdown?(): void; +} +``` + +3. Add the Consent Provider to the `ConsentPlugin()` and add `ConsentPlugin()` to the `client`. A full example of this setup, including initializing the `OneTrust` SDK can be [found here](https://github.com/segmentio/analytics-react-native/blob/master/packages/plugins/plugin-onetrust/README.md). + + +``` +const segment = createClient({ + writeKey: 'SEGMENT_KEY', + ... +}); + + +const myCustomProvider = new MyCustomProvider(MyCMP) +const consentPlugin = new ConsentPlugin(myCustomProvider); + +segment.add({ plugin: oneTrustPlugin }); +``` + +4. Once the Segment Client and third-party CMP have been initialized, start processing queued events + +``` +consentPlugin.start() +``` + ## Plugins + Timeline architecture You have complete control over how the events are processed before being uploaded to the Segment API. diff --git a/packages/core/src/plugins/ConsentPlugin.ts b/packages/core/src/plugins/ConsentPlugin.ts index 3846f73cf..c457e8faa 100644 --- a/packages/core/src/plugins/ConsentPlugin.ts +++ b/packages/core/src/plugins/ConsentPlugin.ts @@ -5,6 +5,8 @@ import type { SegmentAPIIntegration, SegmentEvent, TrackEventType, + UpdateType, + SegmentAPISettings, } from '../types'; import type { DestinationPlugin } from '../plugin'; import type { SegmentClient } from '../analytics'; @@ -31,22 +33,25 @@ export interface CategoryConsentStatusProvider { export class ConsentPlugin extends Plugin { type = PluginType.before; private consentCategoryProvider: CategoryConsentStatusProvider; - private categories: string[]; + private categories: string[] = []; + queuedEvents: SegmentEvent[] = []; + consentStarted = false; - constructor( - consentCategoryProvider: CategoryConsentStatusProvider, - categories: string[] - ) { + constructor(consentCategoryProvider: CategoryConsentStatusProvider) { super(); this.consentCategoryProvider = consentCategoryProvider; - this.categories = categories; + } + + update(_settings: SegmentAPISettings, _type: UpdateType): void { + const consentSettings = this.analytics?.consentSettings.get(); + this.categories = consentSettings?.allCategories || []; + this.consentCategoryProvider.setApplicableCategories(this.categories); } configure(analytics: SegmentClient): void { super.configure(analytics); analytics.getPlugins().forEach(this.injectConsentFilterIfApplicable); analytics.onPluginLoaded(this.injectConsentFilterIfApplicable); - this.consentCategoryProvider.setApplicableCategories(this.categories); this.consentCategoryProvider.onConsentChange(() => { this.notifyConsentChange(); }); @@ -65,16 +70,27 @@ export class ConsentPlugin extends Plugin { }); } - async execute(event: SegmentEvent): Promise { - event.context = { - ...event.context, - consent: { - categoryPreferences: - await this.consentCategoryProvider.getConsentStatus(), - }, - }; + async execute(event: SegmentEvent): Promise { + if (this.consentStarted === true) { + event.context = { + ...event.context, + consent: { + categoryPreferences: + await this.consentCategoryProvider.getConsentStatus(), + }, + }; + return event; + } - return event; + if (this.consentStarted === false) { + // constrain the queue to avoid running out of memory if consent is never started + if (this.queuedEvents.length <= 1000) { + this.queuedEvents.push(event); + return; + } + return; + } + return; } shutdown(): void { @@ -103,7 +119,6 @@ export class ConsentPlugin extends Plugin { } const integrationSettings = settings?.[plugin.key]; - if (this.containsConsentSettings(integrationSettings)) { const categories = integrationSettings.consentSettings.categories; return ( @@ -151,6 +166,19 @@ export class ConsentPlugin extends Plugin { throw e; }); } + + public start() { + this.consentStarted = true; + + this.sendQueuedEvents(); + } + + sendQueuedEvents() { + this.queuedEvents.forEach((event) => { + this.analytics?.process(event); + }); + this.queuedEvents = []; + } } /** diff --git a/packages/core/src/plugins/__tests__/consent/consentNotEnabledAtSegment.test.ts b/packages/core/src/plugins/__tests__/consent/consentNotEnabledAtSegment.test.ts index 4d194b22f..386ae2588 100644 --- a/packages/core/src/plugins/__tests__/consent/consentNotEnabledAtSegment.test.ts +++ b/packages/core/src/plugins/__tests__/consent/consentNotEnabledAtSegment.test.ts @@ -27,13 +27,16 @@ describe('Consent not enabled at Segment', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -59,13 +62,16 @@ describe('Consent not enabled at Segment', () => { C0005: true, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -91,13 +97,16 @@ describe('Consent not enabled at Segment', () => { C0005: true, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); diff --git a/packages/core/src/plugins/__tests__/consent/destinationMultipleCategories.test.ts b/packages/core/src/plugins/__tests__/consent/destinationMultipleCategories.test.ts index 5335e62e4..17dd665df 100644 --- a/packages/core/src/plugins/__tests__/consent/destinationMultipleCategories.test.ts +++ b/packages/core/src/plugins/__tests__/consent/destinationMultipleCategories.test.ts @@ -28,13 +28,16 @@ describe('Destinations multiple categories', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -57,13 +60,16 @@ describe('Destinations multiple categories', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -86,15 +92,18 @@ describe('Destinations multiple categories', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); await client.init(); + consentPlugin.start(); + const segmentDestination = createSegmentWatcher(client); await client.track('test'); @@ -115,15 +124,18 @@ describe('Destinations multiple categories', () => { C0005: true, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); await client.init(); + consentPlugin.start(); + const segmentDestination = createSegmentWatcher(client); await client.track('test'); diff --git a/packages/core/src/plugins/__tests__/consent/idfa.test.ts b/packages/core/src/plugins/__tests__/consent/idfa.test.ts index fa40aae0e..db6ca2817 100644 --- a/packages/core/src/plugins/__tests__/consent/idfa.test.ts +++ b/packages/core/src/plugins/__tests__/consent/idfa.test.ts @@ -40,15 +40,21 @@ describe('IDFA x Consent', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + const idfaPlugin = new IdfaPlugin(false); client.add({ + // type of segmentClient is different in idfaPlugin vs. mockClient used here + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore plugin: idfaPlugin, }); diff --git a/packages/core/src/plugins/__tests__/consent/noUnmapped.test.ts b/packages/core/src/plugins/__tests__/consent/noUnmapped.test.ts index 8ad2d6357..5371eb07e 100644 --- a/packages/core/src/plugins/__tests__/consent/noUnmapped.test.ts +++ b/packages/core/src/plugins/__tests__/consent/noUnmapped.test.ts @@ -21,15 +21,18 @@ describe('No unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); await client.init(); + consentPlugin.start(); + await client.track('test'); Object.values(testDestinations).forEach((testDestination) => { @@ -48,13 +51,16 @@ describe('No unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); await client.track('test'); @@ -77,13 +83,16 @@ describe('No unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); await client.track('test'); @@ -106,13 +115,16 @@ describe('No unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); await client.track('test'); @@ -135,13 +147,16 @@ describe('No unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); await client.track('test'); @@ -164,13 +179,16 @@ describe('No unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); await client.track('test'); @@ -193,13 +211,16 @@ describe('No unmapped destinations', () => { C0005: true, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); await client.track('test'); diff --git a/packages/core/src/plugins/__tests__/consent/unmapped.test.ts b/packages/core/src/plugins/__tests__/consent/unmapped.test.ts index ac2d692df..de01bc795 100644 --- a/packages/core/src/plugins/__tests__/consent/unmapped.test.ts +++ b/packages/core/src/plugins/__tests__/consent/unmapped.test.ts @@ -17,38 +17,41 @@ describe('Unmapped destinations', () => { { autoAddSegmentDestination: true } ); - // test('no to all', async () => { - // const { client } = createClient(); - // const testDestinations = setupTestDestinations(client); - // await client.init(); - // const mockConsentStatuses = { - // C0001: false, - // C0002: false, - // C0003: false, - // C0004: false, - // C0005: false, - // }; - - // client.add({ - // plugin: new ConsentPlugin( - // createConsentProvider(mockConsentStatuses), - // Object.keys(mockConsentStatuses) - // ), - // }); - - // await client.init(); - - // const segmentDestination = createSegmentWatcher(client); - - // await client.track('test'); - - // expect(segmentDestination).toHaveBeenCalled(); - // expect(testDestinations.dest1.track).not.toHaveBeenCalled(); - // expect(testDestinations.dest2.track).not.toHaveBeenCalled(); - // expect(testDestinations.dest3.track).not.toHaveBeenCalled(); - // expect(testDestinations.dest4.track).not.toHaveBeenCalled(); - // expect(testDestinations.dest5.track).toHaveBeenCalled(); - // }); + test('no to all', async () => { + const { client } = createClient(); + const testDestinations = setupTestDestinations(client); + await client.init(); + const mockConsentStatuses = { + C0001: false, + C0002: false, + C0003: false, + C0004: false, + C0005: false, + }; + + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + + client.add({ + plugin: consentPlugin, + }); + + consentPlugin.start(); + + await client.init(); + + const segmentDestination = createSegmentWatcher(client); + + await client.track('test'); + + expect(segmentDestination).toHaveBeenCalled(); + expect(testDestinations.dest1.track).not.toHaveBeenCalled(); + expect(testDestinations.dest2.track).not.toHaveBeenCalled(); + expect(testDestinations.dest3.track).not.toHaveBeenCalled(); + expect(testDestinations.dest4.track).not.toHaveBeenCalled(); + expect(testDestinations.dest5.track).toHaveBeenCalled(); + }); test('yes to 1', async () => { const { client } = createClient(); @@ -61,13 +64,16 @@ describe('Unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -93,13 +99,16 @@ describe('Unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -125,13 +134,16 @@ describe('Unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -157,13 +169,16 @@ describe('Unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -189,13 +204,16 @@ describe('Unmapped destinations', () => { C0005: false, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); @@ -221,13 +239,16 @@ describe('Unmapped destinations', () => { C0005: true, }; + const consentPlugin = new ConsentPlugin( + createConsentProvider(mockConsentStatuses) + ); + client.add({ - plugin: new ConsentPlugin( - createConsentProvider(mockConsentStatuses), - Object.keys(mockConsentStatuses) - ), + plugin: consentPlugin, }); + consentPlugin.start(); + await client.init(); const segmentDestination = createSegmentWatcher(client); diff --git a/packages/plugins/plugin-onetrust/README.md b/packages/plugins/plugin-onetrust/README.md index 85a9a88ef..f34b13bcc 100644 --- a/packages/plugins/plugin-onetrust/README.md +++ b/packages/plugins/plugin-onetrust/README.md @@ -2,6 +2,10 @@ Plugin for adding support for [OneTrust](https://onetrust.com/) CMP to your React Native application. +⚠️ version 1.2.0 and below are out of date and upgrading will require a re-implementation of the plugin configuration. + +⚠️ The SDK version used must match the version of the JSON published from your OneTrust instance. This Provider was built using `202405.1.0`. This is not a "plugin" as defined by the SDK's [plugin-timeline architecture](https://github.com/segmentio/analytics-react-native/tree/master?tab=readme-ov-file#plugins--timeline-architecture). Instead, it must be used with the `ConsentPlugin` included in the core SDK. This is deliberate as it is impossible to support every possible version of the OneTrust SDK. Therefore, the `OneTrustConsentProvider` should serve as a reference/example for users on a different version. + ## Installation You will need to install the `@segment/analytics-react-native-plugin-onetrust` package as a dependency in your project: @@ -22,20 +26,95 @@ yarn add @segment/analytics-react-native-plugin-onetrust react-native-onetrust-c Follow the [instructions for adding plugins](https://github.com/segmentio/analytics-react-native#adding-plugins) on the main Analytics client: -After you create your segment client add `OneTrustPlugin` as a plugin, order doesn't matter, this plugin will apply to all device mode destinations you add before and after this plugin is added: +After you create your segment client there are a few steps you must follow to complete your One Trust integration. + +1. Initialize the `OneTrust` SDK: + +```ts +import OTPublishersNativeSDK from 'react-native-onetrust-cmp'; + +... + +OTPublishersNativeSDK.startSDK( + 'storageLocation', + 'domainIdentifier', + 'languageCode', + {countryCode: 'us', regionCode:'ca'}, + true, +) + .then((responseObject) => { + console.info('Download status is ' + responseObject.status); + // get full JSON object from responseObject.responseString + }) + .catch((error) => { + console.error(`OneTrust download failed with error ${error}`); + }); +``` + +2. Create a new `OneTrustConsentProvider` and pass the `OneTrust` SDK to it: + +```ts +import { createClient, ConsentPlugin } from '@segment/analytics-react-native'; +import OTPublishersNativeSDK from 'react-native-onetrust-cmp'; +import { OTCategoryConsentProvider } from '@segment/analytics-react-native-plugin-onetrust' + +... + + const oneTrustProvider = new OneTrustConsentProvider(OTPublishersNativeSDK) +``` + +3. Initialize a new `ConsentPlugin` and pass the `OneTrustConsentProvider` to it: ```ts -import { createClient } from '@segment/analytics-react-native'; -import { OneTrustPlugin } from '@segment/analytics-react-native-plugin-onetrust'; import OTPublishersNativeSDK from 'react-native-onetrust-cmp'; +import { OneTrustConsentProvider } from '@segment/analytics-react-native-plugin-onetrust' + +... + +const oneTrustProvider = new OneTrustConsentProvider(OTPublisherNativeSDK) +const oneTrustPlugin = new ConsentPlugin(oneTrustProvider); +``` + +4. Add `oneTrustPlugin` as a plugin, order doesn't matter, this plugin will apply to all device mode destinations you add before and after this plugin is added. + +5. Call `oneTrustPlugin.start()` to start event flow. + + Full example below: + +```ts +import { createClient, ConsentPlugin} from '@segment/analytics-react-native'; +import { OneTrustConsentProvider } from '@segment/analytics-react-native-plugin-onetrust'; +import OTPublishersNativeSDK from 'react-native-onetrust-cmp'; + +OTPublishersNativeSDK.startSDK( + 'storageLocation', + 'domainIdentifier', + 'languageCode', + {countryCode: 'us', regionCode:'ca'}, + true, +) + .then((responseObject) => { + console.info('Download status is ' + responseObject.status); + // get full JSON object from responseObject.responseString + }) + .catch((error) => { + console.error(`OneTrust download failed with error ${error}`); + }); const segment = createClient({ writeKey: 'SEGMENT_KEY', }); -segment.add({ - plugin: new OneTrust(OTPublishersNativeSDK, ['C001', 'C002', '...']), -}); + +const oneTrustProvider = new OneTrustConsentProvider(OTPublisherNativeSDK) +const oneTrustPlugin = new ConsentPlugin(oneTrustProvider); + +segment.add({ plugin: oneTrustPlugin }); + +// NOTE: You might want to wait until CMP is ready before you call start() +// so that events are held until the CMP is ready to provide the current consent status. +onetrustPlugin.start() + // device mode destinations segment.add({ plugin: new BrazePlugin() }); diff --git a/packages/plugins/plugin-onetrust/package.json b/packages/plugins/plugin-onetrust/package.json index 6a67e21fb..16c8193db 100644 --- a/packages/plugins/plugin-onetrust/package.json +++ b/packages/plugins/plugin-onetrust/package.json @@ -50,7 +50,7 @@ "peerDependencies": { "@segment/analytics-react-native": "^2.18.0", "@segment/sovran-react-native": "*", - "react-native-onetrust-cmp": "^202308.2.0" + "react-native-onetrust-cmp": "^202308.1.0" }, "devDependencies": { "@segment/analytics-react-native": "^2.18.0", diff --git a/packages/plugins/plugin-onetrust/src/OneTrust.ts b/packages/plugins/plugin-onetrust/src/OneTrust.ts deleted file mode 100644 index 2287283c9..000000000 --- a/packages/plugins/plugin-onetrust/src/OneTrust.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ConsentPlugin } from '@segment/analytics-react-native'; - -import { OTPublishersNativeSDK, OTCategoryConsentProvider } from './OTProvider'; - -export class OneTrustPlugin extends ConsentPlugin { - constructor(oneTrustSDK: OTPublishersNativeSDK, categories: string[]) { - super(new OTCategoryConsentProvider(oneTrustSDK), categories); - } -} diff --git a/packages/plugins/plugin-onetrust/src/OTProvider.ts b/packages/plugins/plugin-onetrust/src/OneTrustProvider.ts similarity index 96% rename from packages/plugins/plugin-onetrust/src/OTProvider.ts rename to packages/plugins/plugin-onetrust/src/OneTrustProvider.ts index 7aa29172f..45f0ee1d5 100644 --- a/packages/plugins/plugin-onetrust/src/OTProvider.ts +++ b/packages/plugins/plugin-onetrust/src/OneTrustProvider.ts @@ -19,9 +19,7 @@ export interface OTPublishersNativeSDK { stopListeningForConsentChanges(): void; } -export class OTCategoryConsentProvider - implements CategoryConsentStatusProvider -{ +export class OneTrustConsentProvider implements CategoryConsentStatusProvider { getConsentStatus!: () => Promise>; private onConsentChangeCallback!: OnConsentChangeCb; @@ -42,15 +40,12 @@ export class OTCategoryConsentProvider ]) ) ).then((entries) => Object.fromEntries(entries)); - let latestStatuses: Record | null; this.getConsentStatus = () => Promise.resolve(latestStatuses ?? initialStatusesP); - this.oneTrust.stopListeningForConsentChanges(); this.oneTrust.setBroadcastAllowedValues(categories); - categories.forEach((categoryId) => { this.oneTrust.listenForConsentChanges(categoryId, (_, status) => { initialStatusesP diff --git a/packages/plugins/plugin-onetrust/src/__tests__/OneTrust.test.ts b/packages/plugins/plugin-onetrust/src/__tests__/OneTrust.test.ts deleted file mode 100644 index d5e342a38..000000000 --- a/packages/plugins/plugin-onetrust/src/__tests__/OneTrust.test.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { - Context, - DestinationPlugin, - Plugin, - PluginType, - SegmentClient, - SegmentEvent, -} from '@segment/analytics-react-native'; -import { createTestClient } from '@segment/analytics-react-native/src/test-helpers'; -import onChange from 'on-change'; - -import { OneTrustPlugin } from '../OneTrust'; - -import type { OTPublishersNativeSDK } from '../OTProvider'; -class MockDestination extends DestinationPlugin { - track = jest.fn(); - - constructor(public readonly key: string) { - super(); - } -} - -class MockOneTrustSDK implements OTPublishersNativeSDK { - private readonly DEFAULT_CONSENT_STATUSES = { - C001: 1, - C002: 0, - C003: 1, - C004: -1, - }; - - private changeCallbacks = new Map< - string, - ((cid: string, status: number) => void)[] - >(); - - mockConsentStatuses: Record = onChange( - this.DEFAULT_CONSENT_STATUSES, - (key, value) => { - this.changeCallbacks.get(key)?.forEach((cb) => cb(key, value as number)); - } - ); - - getConsentStatusForCategory(categoryId: string): Promise { - return Promise.resolve(this.mockConsentStatuses[categoryId]); - } - - setBroadcastAllowedValues(): void { - return; - } - - listenForConsentChanges( - categoryId: string, - callback: (cid: string, status: number) => void - ): void { - this.changeCallbacks.set(categoryId, [ - ...(this.changeCallbacks.get(categoryId) || []), - callback, - ]); - } - - stopListeningForConsentChanges(): void { - this.changeCallbacks.clear(); - } -} - -describe('OneTrustPlugin', () => { - let client: SegmentClient; - let expectEvent: (event: Partial) => void; - let mockOneTrust: MockOneTrustSDK; - const mockBraze = new MockDestination('Braze'); - const mockAmplitude = new MockDestination('Amplitude'); - - beforeEach(async () => { - const testClient = createTestClient(); - testClient.store.reset(); - jest.clearAllMocks(); - client = testClient.client as unknown as SegmentClient; - expectEvent = testClient.expectEvent; - mockOneTrust = new MockOneTrustSDK(); - client.add({ - plugin: new OneTrustPlugin( - mockOneTrust, - Object.keys(mockOneTrust.mockConsentStatuses) - ), - }); - - client.add({ - plugin: mockBraze, - settings: { - consentSettings: { - categories: ['C002', 'C004'], - }, - }, - }); - - client.add({ - plugin: mockAmplitude, - settings: { - consentSettings: { - categories: ['C002'], - }, - }, - }); - - await client.init(); - }); - - it('stamps each event with consent statuses as provided by onetrust', async () => { - // we'll use a before plugin to tap into the timeline and confirm the stamps are applied as early as possible - class TapPlugin extends Plugin { - type = PluginType.before; - execute = jest.fn(); - } - - const tapPlugin = new TapPlugin(); - client.add({ - plugin: tapPlugin, - }); - - await client.track('Test event'); - - expect(tapPlugin.execute).toHaveBeenCalledWith( - expect.objectContaining({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - context: expect.objectContaining({ - consent: { - categoryPreferences: { - C001: true, - C002: false, - C003: true, - C004: false, - }, - }, - }), - }) - ); - }); - - it('prevents an event from reaching non-compliant destinations', async () => { - await client.track('Test event'); - - expect(mockBraze.track).not.toHaveBeenCalled(); - expect(mockAmplitude.track).not.toHaveBeenCalled(); - }); - - it('allows an event to reach destinations once consent is granted later on', async () => { - await client.track('Test event'); - - expect(mockBraze.track).not.toHaveBeenCalled(); - expect(mockAmplitude.track).not.toHaveBeenCalled(); - - mockOneTrust.mockConsentStatuses.C002 = 1; - - await client.track('Test event'); - - // this destination will now receive events - expect(mockAmplitude.track).toHaveBeenCalledTimes(1); - // but one of the tagged categories on this destination is still not consented - expect(mockBraze.track).not.toHaveBeenCalled(); - - mockOneTrust.mockConsentStatuses.C004 = 1; - - await client.track('Test event'); - - // now both have been consented - expect(mockAmplitude.track).toHaveBeenCalledTimes(2); - expect(mockBraze.track).toHaveBeenCalledTimes(1); - }); - - it('relays consent change within onetrust to Segment', async () => { - const spy = jest.spyOn(client, 'track'); - - await client.track('Test event'); - - mockOneTrust.mockConsentStatuses.C002 = 1; - - // await one tick - await new Promise(process.nextTick); - - // this is to make sure there are no unneccessary Consent Preference track calls - expect(spy).toHaveBeenCalledTimes(2); - - expect(spy).toHaveBeenLastCalledWith('Segment Consent Preference'); - - expectEvent({ - event: 'Segment Consent Preference', - context: expect.objectContaining({ - consent: { - categoryPreferences: { - C001: true, - C002: true, - C003: true, - C004: false, - }, - }, - }) as unknown as Context, - }); - }); -}); diff --git a/packages/plugins/plugin-onetrust/src/index.tsx b/packages/plugins/plugin-onetrust/src/index.tsx index 878a3ba42..1fe83897b 100644 --- a/packages/plugins/plugin-onetrust/src/index.tsx +++ b/packages/plugins/plugin-onetrust/src/index.tsx @@ -1 +1 @@ -export { OneTrustPlugin } from './OneTrust'; +export { OneTrustConsentProvider } from './OneTrustProvider'; diff --git a/yarn.lock b/yarn.lock index 360806316..07a44ab5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3611,7 +3611,7 @@ __metadata: peerDependencies: "@segment/analytics-react-native": ^2.18.0 "@segment/sovran-react-native": "*" - react-native-onetrust-cmp: ^202308.2.0 + react-native-onetrust-cmp: ^202308.1.0 languageName: unknown linkType: soft From 21675cb363cd338948e0bf7dbd0fbaba4e037e61 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 31 Jul 2024 15:00:01 +0000 Subject: [PATCH 58/71] chore(release): 1.1.2 [skip ci] --- packages/sovran/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sovran/package.json b/packages/sovran/package.json index 4e1b23faf..8282f38ba 100644 --- a/packages/sovran/package.json +++ b/packages/sovran/package.json @@ -1,6 +1,6 @@ { "name": "@segment/sovran-react-native", - "version": "1.1.1", + "version": "1.1.2", "description": "A cross-platform state management system", "main": "lib/commonjs/index", "module": "lib/module/index", From d0034d63cdaeae40e951d34151f5a892a6ffc577 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 31 Jul 2024 15:12:04 +0000 Subject: [PATCH 59/71] chore(release): 2.19.3 [skip ci] --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index c1e8c3100..3ea7d5b4d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native", - "version": "2.19.2", + "version": "2.19.3", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "keywords": [ "segment", From 7e9023a9c321abca4b0d39af1b88efba1554d0c0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 31 Jul 2024 15:17:46 +0000 Subject: [PATCH 60/71] chore(release): 0.7.3 [skip ci] --- packages/plugins/plugin-idfa/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-idfa/package.json b/packages/plugins/plugin-idfa/package.json index cd78a8af0..66bf27136 100644 --- a/packages/plugins/plugin-idfa/package.json +++ b/packages/plugins/plugin-idfa/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-idfa", - "version": "0.7.2", + "version": "0.7.3", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { From 5aaa5881a1ebb6d4a68ab32831ad7ced0e531bf1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 31 Jul 2024 15:26:56 +0000 Subject: [PATCH 61/71] chore(release): 1.2.1 [skip ci] --- packages/plugins/plugin-onetrust/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-onetrust/package.json b/packages/plugins/plugin-onetrust/package.json index 16c8193db..f2ea804de 100644 --- a/packages/plugins/plugin-onetrust/package.json +++ b/packages/plugins/plugin-onetrust/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-onetrust", - "version": "1.2.0", + "version": "1.2.1", "description": "Add OneTrust to Segment analytics in your React-Native app.", "main": "lib/commonjs/index", "module": "lib/module/index", From 86bf7a6720b6df3765d36746b76825ea2c1ef468 Mon Sep 17 00:00:00 2001 From: hvardhan-unth <117922634+hvardhan-unth@users.noreply.github.com> Date: Thu, 1 Aug 2024 19:11:58 +0530 Subject: [PATCH 62/71] fix: added the missing property mappings for the firebase plugin (#980) Co-authored-by: Harsh Vardhan --- .../plugins/plugin-firebase/src/methods/parameterMapping.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/plugins/plugin-firebase/src/methods/parameterMapping.ts b/packages/plugins/plugin-firebase/src/methods/parameterMapping.ts index 503dd7905..c8dd47a0c 100644 --- a/packages/plugins/plugin-firebase/src/methods/parameterMapping.ts +++ b/packages/plugins/plugin-firebase/src/methods/parameterMapping.ts @@ -27,6 +27,12 @@ export const mapEventProps: { [key: string]: string } = { productId: 'item_id', category: 'item_category', query: 'search_term', + order_id: 'transaction_id', + quantity: 'quantity', + shipping: 'shipping', + tax: 'tax', + revenue: 'revenue', + currency: 'currency', }; export const transformMap: { [key: string]: (value: unknown) => unknown } = { From 307d984eecf5542e20bb1c26228d15e6b52331e9 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:32:32 -0400 Subject: [PATCH 63/71] chore: bump appsflyer (#981) --- packages/plugins/plugin-appsflyer/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-appsflyer/package.json b/packages/plugins/plugin-appsflyer/package.json index 83cb8fc9b..a75f3e9a5 100644 --- a/packages/plugins/plugin-appsflyer/package.json +++ b/packages/plugins/plugin-appsflyer/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-appsflyer", - "version": "0.7.0", + "version": "0.8.0", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { From bdb5e335d7c7cb5e5a8e74672c015068bbdadecd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 1 Aug 2024 15:34:40 +0000 Subject: [PATCH 64/71] chore(release): 0.4.2 [skip ci] --- packages/plugins/plugin-firebase/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-firebase/package.json b/packages/plugins/plugin-firebase/package.json index a899e9967..7610ab9a6 100644 --- a/packages/plugins/plugin-firebase/package.json +++ b/packages/plugins/plugin-firebase/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native-plugin-firebase", - "version": "0.4.1", + "version": "0.4.2", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "main": "lib/commonjs/index", "scripts": { From dcd81e9100d9988a7a60609d96680ff6ca84c904 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:02:20 -0400 Subject: [PATCH 65/71] chore(deps): bump fast-xml-parser (#975) Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.3.2 to 4.4.1. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.3.2...v4.4.1) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/AnalyticsReactNativeExample/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/AnalyticsReactNativeExample/yarn.lock b/examples/AnalyticsReactNativeExample/yarn.lock index 3e5c322ed..8ca35253e 100644 --- a/examples/AnalyticsReactNativeExample/yarn.lock +++ b/examples/AnalyticsReactNativeExample/yarn.lock @@ -3689,13 +3689,13 @@ __metadata: linkType: hard "fast-xml-parser@npm:^4.0.12": - version: 4.3.2 - resolution: "fast-xml-parser@npm:4.3.2" + version: 4.4.1 + resolution: "fast-xml-parser@npm:4.4.1" dependencies: strnum: "npm:^1.0.5" bin: fxparser: src/cli/cli.js - checksum: 10c0/7c1611349384656ec4faa9802fbc8cf8c01206a1b79193d5cd54586307801562509007f6cf16e5da7d43da4fa4639770f38959a285b9466aa98dab0a9b8ca171 + checksum: 10c0/7f334841fe41bfb0bf5d920904ccad09cefc4b5e61eaf4c225bf1e1bb69ee77ef2147d8942f783ee8249e154d1ca8a858e10bda78a5d78b8bed3f48dcee9bf33 languageName: node linkType: hard From 4f80a8e26245882923da2397dd41c31eccec1a95 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:27:17 -0400 Subject: [PATCH 66/71] Update publish.yml -update github key --- .github/workflows/publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index be734f2da..22cdbf0ef 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false - token: ${{ secrets.GH_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} # Workaround for corepack enable in node # Source: (https://github.com/actions/setup-node/issues/899#issuecomment-1828798029) @@ -47,7 +47,7 @@ jobs: if: github.event.inputs.workspace == '' run: yarn release env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} YARN_NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Update Apps From a71d530f9d84942188805a0f74a1a7ea0d30142e Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:56:09 -0400 Subject: [PATCH 67/71] Update create_jira.yml -update issue tracker to new jira project --- .github/workflows/create_jira.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/create_jira.yml b/.github/workflows/create_jira.yml index 03f8e658b..16e5a4596 100644 --- a/.github/workflows/create_jira.yml +++ b/.github/workflows/create_jira.yml @@ -24,7 +24,7 @@ jobs: id: create uses: atlassian/gajira-create@master with: - project: LIBWEB + project: LIBRARIES issuetype: Bug summary: | [${{ github.event.repository.name }}] (${{ github.event.issue.number }}): ${{ github.event.issue.title }} @@ -33,8 +33,8 @@ jobs: ${{ github.event.issue.body }} # Parent and Epic Link fields (set to same) fields: '{ - "parent": {"key": "LIBWEB-1530"}, - "customfield_10002": "LIBWEB-1530" + "parent": {"key": "LIBRARIES-2048"}, + "customfield_10002": "LIBRARIES-2048" }' - name: Log created issue From 4b53875c0d5409681bfdab84233757cb0570ef5f Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:08:02 -0400 Subject: [PATCH 68/71] fix: increase default timeout and change warning to info (#984) * fix: increase default timeout and change warning to info * chore: remove dev team --- .../project.pbxproj | 12 ++---------- .../AnalyticsReactNativeExample/ios/Podfile.lock | 10 +++++----- packages/core/src/plugins/QueueFlushingPlugin.ts | 11 +++-------- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj b/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj index 586ea3135..ddcd99568 100644 --- a/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj +++ b/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj @@ -602,11 +602,7 @@ "-DFOLLY_MOBILE=1", "-DFOLLY_USE_LIBCPP=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; }; @@ -676,11 +672,7 @@ "-DFOLLY_MOBILE=1", "-DFOLLY_USE_LIBCPP=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; diff --git a/examples/AnalyticsReactNativeExample/ios/Podfile.lock b/examples/AnalyticsReactNativeExample/ios/Podfile.lock index b94c583f7..50e2099e8 100644 --- a/examples/AnalyticsReactNativeExample/ios/Podfile.lock +++ b/examples/AnalyticsReactNativeExample/ios/Podfile.lock @@ -499,11 +499,11 @@ PODS: - RNScreens (3.27.0): - RCT-Folly (= 2021.07.22.00) - React-Core - - segment-analytics-react-native (2.19.2): + - segment-analytics-react-native (2.19.3): - React-Core - sovran-react-native - SocketRocket (0.6.1) - - sovran-react-native (1.1.1): + - sovran-react-native (1.1.2): - React-Core - Yoga (1.14.0) - YogaKit (1.18.1): @@ -752,12 +752,12 @@ SPEC CHECKSUMS: RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 RNGestureHandler: 32a01c29ecc9bb0b5bf7bc0a33547f61b4dc2741 RNScreens: 3c2d122f5e08c192e254c510b212306da97d2581 - segment-analytics-react-native: 962494a9edbe3f6c5829e3b471484c85c304601c + segment-analytics-react-native: a803de6a9406f7b18928d352962c2f49663a0869 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 - sovran-react-native: e6a9c963a8a6b9ebc3563394c39c30f33ab1453f + sovran-react-native: 5f02bd2d111ffe226d00c7b0435290eae6f10934 Yoga: eddf2bbe4a896454c248a8f23b4355891eb720a6 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 329f06ebb76294acf15c298d0af45530e2797740 -COCOAPODS: 1.15.2 +COCOAPODS: 1.11.3 diff --git a/packages/core/src/plugins/QueueFlushingPlugin.ts b/packages/core/src/plugins/QueueFlushingPlugin.ts index 6c303525a..a501a66ba 100644 --- a/packages/core/src/plugins/QueueFlushingPlugin.ts +++ b/packages/core/src/plugins/QueueFlushingPlugin.ts @@ -4,7 +4,6 @@ import { defaultConfig } from '../constants'; import { UtilityPlugin } from '../plugin'; import { PluginType, SegmentEvent } from '../types'; import { createPromise } from '../util'; -import { ErrorType, SegmentError } from '../errors'; /** * This plugin manages a queue where all events get added to after timeline processing. @@ -30,7 +29,7 @@ export class QueueFlushingPlugin extends UtilityPlugin { constructor( onFlush: (events: SegmentEvent[]) => Promise, storeKey = 'events', - restoreTimeout = 500 + restoreTimeout = 1000 ) { super(); this.onFlush = onFlush; @@ -78,12 +77,8 @@ export class QueueFlushingPlugin extends UtilityPlugin { await this.isRestored; } catch (e) { // If the queue is not restored before the timeout, we will notify but not block flushing events - this.analytics?.reportInternalError( - new SegmentError( - ErrorType.InitializationError, - 'Queue timeout before completed restoration', - e - ) + console.info( + 'Flush triggered but queue restoration and settings loading not complete. Flush will be retried.' ); } const events = (await this.queueStore?.getState(true))?.events ?? []; From 785c02ad08354133db2195fa208d3ef094f04ffb Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:23:52 -0400 Subject: [PATCH 69/71] fix: add strict dep for base-64-normalizer (#986) --- packages/core/package.json | 3 ++- yarn.lock | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 3ea7d5b4d..3a2216cec 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,7 +46,8 @@ "prepack": "yarn prebuild" }, "dependencies": { - "@segment/tsub": "^2", + "@segment/tsub": "2.0.0", + "@stdlib/number-float64-base-normalize": "0.0.8", "deepmerge": "^4.3.1", "js-base64": "^3.7.5", "uuid": "^9.0.1" diff --git a/yarn.lock b/yarn.lock index 07a44ab5a..8aaa7cb13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3620,7 +3620,8 @@ __metadata: resolution: "@segment/analytics-react-native@workspace:packages/core" dependencies: "@segment/sovran-react-native": "npm:^1.1.0" - "@segment/tsub": "npm:^2" + "@segment/tsub": "npm:2.0.0" + "@stdlib/number-float64-base-normalize": "npm:0.0.8" "@types/uuid": "npm:^9.0.7" deepmerge: "npm:^4.3.1" jest: "npm:^29.7.0" @@ -3675,7 +3676,7 @@ __metadata: languageName: unknown linkType: soft -"@segment/tsub@npm:^2": +"@segment/tsub@npm:2.0.0, @segment/tsub@npm:^2": version: 2.0.0 resolution: "@segment/tsub@npm:2.0.0" dependencies: @@ -4754,6 +4755,21 @@ __metadata: languageName: node linkType: hard +"@stdlib/number-float64-base-normalize@npm:0.0.8": + version: 0.0.8 + resolution: "@stdlib/number-float64-base-normalize@npm:0.0.8" + dependencies: + "@stdlib/constants-float64-smallest-normal": "npm:^0.0.x" + "@stdlib/math-base-assert-is-infinite": "npm:^0.0.x" + "@stdlib/math-base-assert-is-nan": "npm:^0.0.x" + "@stdlib/math-base-special-abs": "npm:^0.0.x" + "@stdlib/types": "npm:^0.0.x" + "@stdlib/utils-define-nonenumerable-read-only-property": "npm:^0.0.x" + checksum: 10c0/8b0f4d9d4cb7ca66636d22799ebb157a7b682374f1595f1c9124bf432d628a34984fd98ab9d73224b52e6d64584f4d33589adf4dbd50c839cc4a9920536bc7a6 + conditions: (os=aix | os=darwin | os=freebsd | os=linux | os=macos | os=openbsd | os=sunos | os=win32 | os=windows) + languageName: node + linkType: hard + "@stdlib/number-float64-base-normalize@npm:^0.0.x": version: 0.0.9 resolution: "@stdlib/number-float64-base-normalize@npm:0.0.9" From 46701817c4b7624ee93d8547874c4ac892d05f50 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:41:17 -0400 Subject: [PATCH 70/71] Update publish.yml --- .github/workflows/publish.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 22cdbf0ef..f19960e67 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,7 +3,7 @@ name: Publish on: workflow_dispatch: secrets: - GITHUB_TOKEN: + GH_TOKEN: required: true NPM_TOKEN: required: true @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.GH_TOKEN }} # Workaround for corepack enable in node # Source: (https://github.com/actions/setup-node/issues/899#issuecomment-1828798029) @@ -47,7 +47,7 @@ jobs: if: github.event.inputs.workspace == '' run: yarn release env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} YARN_NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Update Apps From c1a0957c3678e9ba3678a07ca7af9eaa37b7dc66 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 15 Aug 2024 13:43:20 +0000 Subject: [PATCH 71/71] chore(release): 2.19.4 [skip ci] --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index 3a2216cec..f37d375cc 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@segment/analytics-react-native", - "version": "2.19.3", + "version": "2.19.4", "description": "The hassle-free way to add Segment analytics to your React-Native app.", "keywords": [ "segment",