From a89ea9be756d09dfa3d6861dfa4a31accde66885 Mon Sep 17 00:00:00 2001 From: Jade Date: Mon, 27 Oct 2025 07:37:38 +0000 Subject: [PATCH] feat: release --- CHANGELOG.md | 29 +++++++++++++ LICENSE | 4 +- MainSDK.js | 116 +++++++++++++++++++++++++++++++++++++++++++++++---- package.json | 6 +-- 4 files changed, 141 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f868e1..12b5f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,32 @@ +## 4.0.1 (2025-10-27) + + +* [DEV-359] feat!(main): support expo apps, rm native module. Kudos https://github.com/ahmetkuslular (dc9762c) + + +### Bug Fixes + +* **gcm:** message variability (544eb08) + + +### Features + +* **common:** bump version (ce7e70d) +* **sdk:** bump device-info (1d1f10e) +* **sdk:** getToken to use correct token (d07df14) +* **sdk:** in-app push notifications (#51) (6fa0296) +* **sdk:** include types for exclude_brands (#50) (cd1d301) +* **sdk:** rm jest (d0cce5d) +* **sdk:** sid token generation (4a34846) + + +### BREAKING CHANGES + +* rm react-native-device-info, dynamically import if +needed + + + ## 3.1.3 (2025-08-22) diff --git a/LICENSE b/LICENSE index 97ba533..383731e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2024 +Copyright (c) 2025 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/MainSDK.js b/MainSDK.js index 20ff20d..033b0cd 100644 --- a/MainSDK.js +++ b/MainSDK.js @@ -30,7 +30,6 @@ import { EventType } from '@notifee/react-native' import { AuthorizationStatus } from '@notifee/react-native' import { SDK_PUSH_CHANNEL } from './index' import Performer from './lib/performer' -import DeviceInfo from 'react-native-device-info' import { blankSearchRequest } from './utils' import { isOverOneWeekAgo } from './utils' @@ -46,6 +45,11 @@ import { isOverOneWeekAgo } from './utils' * @property {string} ["gcm.message_id"] */ +/** + * @typedef {Object} DeviceInfo + * @property {string} id + */ + /** * @typedef {Object} Data * @property {string} message_id @@ -74,7 +78,20 @@ import { isOverOneWeekAgo } from './utils' export var DEBUG = false class MainSDK extends Performer { - constructor(shop_id, stream, debug = false, autoSendPushToken = true) { + /** + * @param {string} shop_id + * @param {string} stream + * @param {boolean?} debug + * @param {boolean?} autoSendPushToken + * @param {DeviceInfo?} deviceInfo + */ + constructor( + shop_id, + stream, + debug = false, + autoSendPushToken = true, + deviceInfo = null + ) { let queue = [] super(queue) this.shop_id = shop_id @@ -86,12 +103,20 @@ class MainSDK extends Performer { this.lastMessageIds = [] this.autoSendPushToken = autoSendPushToken this.messaging = getMessaging() + this.deviceInfo = deviceInfo } + /** + * @param {Function} command + * @returns {void} + */ perform(command) { command() } + /** + * @returns {void} + */ init() { ;(async () => { try { @@ -121,11 +146,24 @@ class MainSDK extends Performer { response.sid = response.seance = generateSid() } } else { - const did = - Platform.OS === 'android' - ? await DeviceInfo.getAndroidId() - : (await DeviceInfo.syncUniqueId()) || '' - if (DEBUG) console.log('Device ID: ', did) + let did + + if (this.deviceInfo && this.deviceInfo.id) { + did = this.deviceInfo.id + } else { + try { + const DeviceInfo = await import('react-native-device-info') + did = + Platform.OS === 'android' + ? await DeviceInfo.getAndroidId() + : (await DeviceInfo.syncUniqueId()) || '' + } catch (e) { + console.error( + `Device ID is not present in init args, but also 'react-native-device-info' is not present: ${JSON.stringify(e, undefined, 2)}` + ) + did = '' + } + } response = await request('init', this.shop_id, { params: { @@ -153,8 +191,14 @@ class MainSDK extends Performer { })() } + /** + * @returns {boolean} + */ isInit = () => this.initialized + /** + * @returns {Promise} + */ getToken = () => { return this.initPushToken() .then((token) => { @@ -208,6 +252,11 @@ class MainSDK extends Performer { }) } + /** + * @param {string} event + * @param {Record} options + * @returns {void} + */ trackEvent(event, options) { this.push(async () => { try { @@ -278,6 +327,11 @@ class MainSDK extends Performer { }) } + /** + * @param {string} recommender_code + * @param {Record} options + * @returns {Promise} + */ recommend(recommender_code, options) { return new Promise((resolve, reject) => { this.push(() => { @@ -299,6 +353,9 @@ class MainSDK extends Performer { }) } + /** + * @returns {Promise} + */ cart() { return new Promise((resolve, reject) => { this.push(() => { @@ -347,12 +404,16 @@ class MainSDK extends Performer { /** * Executes a blank search. * - * @returns {Promise} - A promise with the request result. + * @returns {Promise} - A promise with the request result. */ searchBlank() { return blankSearchRequest(this.shop_id, this.stream) } + /** + * @param {Record} params + * @returns {void} + */ setProfile(params) { this.push(async () => { if ( @@ -381,6 +442,10 @@ class MainSDK extends Performer { } }) } + + /** + * @returns {Promise} + */ getProfile() { return new Promise((resolve, reject) => { this.push(() => { @@ -430,6 +495,10 @@ class MainSDK extends Performer { } } + /** + * @param {string} token + * @returns {void} + */ setPushTokenNotification(token) { this.push(async () => { try { @@ -461,6 +530,7 @@ class MainSDK extends Performer { } }) } + firebase_only(val) { this._push_type = val ? 'android' : null } @@ -504,6 +574,10 @@ class MainSDK extends Performer { } } + /** + * @param {boolean} removeOld + * @returns {Promise} + */ async initPushToken(removeOld = false) { let savedToken = await getSavedPushToken(this.shop_id) if (removeOld) { @@ -534,6 +608,9 @@ class MainSDK extends Performer { return pushToken } + /** + * @returns {Promise} + */ async initPushChannel() { await notifee.createChannel({ id: SDK_PUSH_CHANNEL, @@ -542,6 +619,9 @@ class MainSDK extends Performer { }) } + /** + * @returns {void} + */ initPushChannelAndToken() { this.push(async () => { const granted = await this.getPushPermission() @@ -710,6 +790,11 @@ class MainSDK extends Performer { }) } + /** + * @param {string} trigger_name + * @param {Record} data + * @returns {void} + */ triggers(trigger_name, data) { this.push(async () => { try { @@ -729,14 +814,29 @@ class MainSDK extends Performer { } }) } + + /** + * @returns {Promise} + */ async deleteToken() { return savePushToken(false, this.shop_id).then(async () => { await deleteToken(this.messaging) }) } + + /** + * @param {string} action + * @param {Record} data + * @returns {void} + */ subscriptions(action, data) { this.triggers(action, data) } + + /** + * @param {string} action + * @param {Record} data + */ segments(action, data) { return new Promise((resolve, reject) => { this.push(() => { diff --git a/package.json b/package.json index 27c09e3..2c35a67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@personaclick/rn-sdk", - "version": "3.1.3", + "version": "4.0.1", "description": "PersonaClick React Native SDK", "type": "module", "exports": { @@ -28,15 +28,13 @@ "conventional-changelog-cli": "5.0.0", "react": "^19.1.0", "react-native": "^0.81.0", - "react-native-device-info": "^14.0.4", "react-test-renderer": "^17.0.2" }, "peerDependencies": { "@notifee/react-native": "^9.1.8", "@react-native-async-storage/async-storage": "^1.23.1", "@react-native-firebase/app": "^23", - "@react-native-firebase/messaging": "^23", - "react-native-device-info": "^14.0.4" + "@react-native-firebase/messaging": "^23" }, "directories": { "lib": "lib"