import { NativeModules } from 'react-native'
const { RNBranch } = NativeModules
/**
* Class for generating standard and custom events with the Branch SDK.
* @example
* new BranchEvent(BranchEvent.ViewEvent, buo).logEvent()
*/
export default class BranchEvent {
/**
* The event name. May be a standard event name or a custom event name.
* @type {string}
*/
name = null
/**
* Array containing any Branch Universal Objects associated with this event.
* @type {Object[]}
*/
contentItems = []
/**
* Transaction ID associated with this event
* @type {?string}
*/
transactionID = null
/**
* ISO currency identifier associated with this event
* @type {?string}
*/
currency = null
/**
* Revenue associated with this event
* @type {?(string|number)}
*/
revenue = null
/**
* Shipping cost associated with this event
* @type {?(string|number)}
*/
shipping = null
/**
* Tax associated with this event
* @type {?(string|number)}
*/
tax = null
/**
* Coupon associated with this event
* @type {?string}
*/
coupon = null
/**
* Affiliation associated with this event
* @type {?string}
*/
affiliation = null
/**
* Description of this event
* @type {?string}
*/
description = null
/**
* Search query associated with this event
* @type {?string}
*/
searchQuery = null
/**
* Optional object containing custom data to associate with this event.
* Values must be strings.
* @type {?Object}
*/
customData = null
/**
* Constructs a new BranchEvent from arguments
*
* @param {!string} name - The name of the event. May be a standard Branch event
* or a custom event name.
* @param {?(Object|Object[])} contentItems - One or more Branch Universal Objects associated with this event, or null.
* @param {?Object} params - Object containing params to be set in the constructor
* @param {?string} params.transactionID - Initial value for the transactionID property
* @param {?string} params.currency - Initial value for the currency property
* @param {?(string|number)} params.revenue - Initial value for the revenue property
* @param {?(string|number)} params.shipping - Initial value for the shipping property
* @param {?(string|number)} params.tax - Initial value for the tax property
* @param {?string} params.coupon - Initial value for the coupon property
* @param {?string} params.affiliation - Initial value for the affiliation property
* @param {?string} params.description - Initial value for the description property
* @param {?string} params.searchQuery - Initial value for the searchQuery property
* @param {?Object} params.customData - Initial value for the customData property
*/
constructor(name, contentItems = null, params = {}) {
this.name = name
if (Array.isArray(contentItems)) {
this.contentItems = contentItems
}
else if (contentItems) {
this.contentItems = [contentItems]
}
if (params.transactionID) this.transactionID = params.transactionID
if (params.currency) this.currency = params.currency
if (params.revenue) this.revenue = params.revenue
if (params.shipping) this.shipping = params.shipping
if (params.tax) this.tax = params.tax
if (params.coupon) this.coupon = params.coupon
if (params.affiliation) this.affiliation = params.affiliation
if (params.description) this.description = params.description
if (params.searchQuery) this.searchQuery = params.searchQuery
if (params.customData) this.customData = params.customData
}
/**
* Log this event. This method is always successful. It queues events to be
* transmitted whenever the service is available. It returns a promise that
* is resolved once the native logEvent call is complete. The promise always
* returns null.
*
* @return {null} Always returns null
*/
async logEvent() {
const idents = this.contentItems.map((b) => b.ident)
try {
return await RNBranch.logEvent(idents, this.name, this._convertParams())
}
catch (error) {
if (error.code != 'RNBranch::Error::BUONotFound') {
// This is the only reason this promise should ever be rejected,
// but in case anything else is ever thrown, throw it out to the
// caller.
throw error
}
// Native BUO not found (expired from cache). Find the JS instance and
// have it create a new native instance with a new ident.
const ident = this._identFromMessage(error.message)
const buo = this.contentItems.find((b) => b.ident == ident)
await buo._newIdent()
// Now that a fresh BUO has been created, call this method again.
return await this.logEvent()
}
}
// Parse the ident of the missing BUO out of the error text.
_identFromMessage(message) {
const match = /^.*ident\s([A-Fa-f0-9-]+).*$/.exec(message)
if (match) return match[1]
return null
}
_convertParams() {
let params = {}
if (this.transactionID) params.transactionID = this.transactionID
if (this.currency) params.currency = this.currency
// for the benefit of the NSDecimalNumber on iOS
if (this.revenue) params.revenue = '' + this.revenue
if (this.shipping) params.shipping = '' + this.shipping
if (this.tax) params.tax = '' + this.tax
if (this.coupon) params.coupon = this.coupon
if (this.affiliation) params.affiliation = this.affiliation
if (this.description) params.description = this.description
if (this.searchQuery) params.searchQuery = this.searchQuery
if (this.customData) {
params.customData = this.customData
for (const key in params.customData) {
const valueType = typeof params.customData[key]
if (valueType == 'string') continue
console.warn('[Branch] customMetadata values must be strings. Value for property ' + key + ' has type ' + valueType + '.')
// TODO: throw?
}
}
return params
}
}
// --- Standard event definitions ---
// Commerce events
/**
* Standard Add to Cart event
* @type {string}
*/
BranchEvent.AddToCart = RNBranch.STANDARD_EVENT_ADD_TO_CART
/**
* Standard Add to Wishlist event
* @type {string}
*/
BranchEvent.AddToWishlist = RNBranch.STANDARD_EVENT_ADD_TO_WISHLIST
/**
* Standard View Cart event
* @type {string}
*/
BranchEvent.ViewCart = RNBranch.STANDARD_EVENT_VIEW_CART
/**
* Standard Initiate Purchase event
* @type {string}
*/
BranchEvent.InitiatePurchase = RNBranch.STANDARD_EVENT_INITIATE_PURCHASE
/**
* Standard Add Payment Info event
* @type {string}
*/
BranchEvent.AddPaymentInfo = RNBranch.STANDARD_EVENT_ADD_PAYMENT_INFO
/**
* Standard Purchase event
* @type {string}
*/
BranchEvent.Purchase = RNBranch.STANDARD_EVENT_PURCHASE
/**
* Standard Spend Credits event
* @type {string}
*/
BranchEvent.SpendCredits = RNBranch.STANDARD_EVENT_SPEND_CREDITS
// Content events
/**
* Standard Search event
* @type {string}
*/
BranchEvent.Search = RNBranch.STANDARD_EVENT_SEARCH
/**
* Standard View Item event for a single Branch Universal Object
* @type {string}
*/
BranchEvent.ViewItem = RNBranch.STANDARD_EVENT_VIEW_ITEM
/**
* Standard View Items event for multiple Branch Universal Objects
* @type {string}
*/
BranchEvent.ViewItems = RNBranch.STANDARD_EVENT_VIEW_ITEMS
/**
* Standard Rate event
* @type {string}
*/
BranchEvent.Rate = RNBranch.STANDARD_EVENT_RATE
/**
* Standard Share event
* @type {string}
*/
BranchEvent.Share = RNBranch.STANDARD_EVENT_SHARE
// User Lifecycle Events
/**
* Standard Complete Registration event
* @type {string}
*/
BranchEvent.CompleteRegistration = RNBranch.STANDARD_EVENT_COMPLETE_REGISTRATION
/**
* Standard Complete Tutorial event
* @type {string}
*/
BranchEvent.CompleteTutorial = RNBranch.STANDARD_EVENT_COMPLETE_TUTORIAL
/**
* Standard Achieve Level event
* @type {string}
*/
BranchEvent.AchieveLevel = RNBranch.STANDARD_EVENT_ACHIEVE_LEVEL
/**
* Standard Unlock Achievement event
* @type {string}
*/
BranchEvent.UnlockAchievement = RNBranch.STANDARD_EVENT_UNLOCK_ACHIEVEMENT