UNPKG

@braze/web-sdk

Version:

Braze SDK for web sites and other JS platforms.

222 lines (221 loc) 6.37 kB
import { isArray as D, isDate as Nt, isObject as It, keys as C, } from "./code-utils.js"; import { getByteLength as rr } from "./string-utils.js"; import { logger as N } from "../../shared-lib/index.js"; import { toValidBackendTimeString as Lt } from "./date-utils.js"; import { BRAZE_ACTIONS as oo } from "./braze-actions.js"; import { SET_CUSTOM_USER_ATTRIBUTE_STRING as Ft } from "../common/constants.js"; export const CUSTOM_DATA_REGEX = /^[^\x00-\x1F\x22]+$/; export const CUSTOM_ATTRIBUTE_SPECIAL_CHARS_REGEX = /[$.]/; export const CUSTOM_ATTRIBUTE_RESERVED_OPERATORS = [ "$add", "$update", "$remove", "$identifier_key", "$identifier_value", "$new_object", "$time", "$google_ad_personalization", "$google_ad_user_data", ]; export const EMAIL_ADDRESS_REGEX = new RegExp(/^.+@.+\..+$/); export const CUSTOM_PROPERTIES_MAX_SIZE_BYTES = 51200; export const CUSTOM_PROPERTIES_MAX_SIZE_STRING = "50KB"; export const CUSTOM_ATTRIBUTES_MAX_SIZE_BYTES = 76800; export const CUSTOM_ATTRIBUTES_MAX_SIZE_STRING = "75KB"; export const CUSTOM_ATTRIBUTE_MAX_DEPTH = 50; export const BRAZE_ACTION_URI_REGEX = /^brazeActions:\/\/v\d+\//; export const VALID_UTF8_STRING_NO_WHITESPACES_REGEX = /^[^\s]+$/; export function validateCustomString(t, e, r) { const n = null != t && "string" == typeof t && ("" === t || null != t.match(CUSTOM_DATA_REGEX)); return n || N.error(`Cannot ${e} because ${r} "${t}" is invalid.`), n; } export function validateCustomAttributeKey(t) { return ( null != t && t.match(CUSTOM_ATTRIBUTE_SPECIAL_CHARS_REGEX) && -1 === CUSTOM_ATTRIBUTE_RESERVED_OPERATORS.indexOf(t) && N.warn("Custom attribute keys cannot contain '$' or '.'"), validateCustomString(t, "set custom user attribute", "the given key") ); } export function validatePropertyType(t) { const e = typeof t; return ( null == t || "number" === e || "boolean" === e || Nt(t) || "string" === e ); } export function _validateNestedProperties(t, e, r) { const n = -1 !== r; if (n && r > 50) return N.error("Nested attributes cannot be more than 50 levels deep."), !1; const o = n ? r + 1 : -1; if (D(t) && D(e)) { for (let r = 0; r < t.length && r < e.length; r++) if ( (Nt(t[r]) && (e[r] = Lt(t[r])), !_validateNestedProperties(t[r], e[r], o)) ) return !1; } else { if (!It(t)) return validatePropertyType(t); for (const r of C(t)) { const i = t[r]; if (n && !validateCustomAttributeKey(r)) return !1; if (Nt(i)) { e[r] = Lt(i); } if (!_validateNestedProperties(i, e[r], o)) return !1; } } return !0; } export function _validateEventPropertyValue(t, e, r, n, o) { let i; return ( (i = It(t) || D(t) ? _validateNestedProperties(t, e, o ? 1 : -1) : validatePropertyType(t)), i || N.error(`Cannot ${r} because ${n} "${t}" is invalid.`), i ); } export function validateStandardString(t, e, r, n = !1) { const o = "string" == typeof t || (null === t && n); return o || N.error(`Cannot ${e} because ${r} "${t}" is invalid.`), o; } export function validateCustomProperties(t, e, r, n, o) { if ((null == t && (t = {}), "object" != typeof t || D(t))) return ( N.error(`${e} requires that ${r} be an object. Ignoring ${o}.`), [!1, null] ); let i, a; e === Ft ? ((i = 76800), (a = "75KB")) : ((i = 51200), (a = "50KB")); const s = JSON.stringify(t); if (rr(s) > i) return ( N.error( `Could not ${n} because ${r} was greater than the max size of ${a}.`, ), [!1, null] ); let u; try { u = JSON.parse(s); } catch (t) { return ( N.error(`Could not ${n} because ${r} did not contain valid JSON.`), [!1, null] ); } for (const r in t) { if (e === Ft && !validateCustomAttributeKey(r)) return [!1, null]; if (!validateCustomString(r, n, `the ${o} property name`)) return [!1, null]; const i = t[r]; if (e !== Ft && null == i) { delete t[r], delete u[r]; continue; } Nt(i) && (u[r] = Lt(i)); if ( !_validateEventPropertyValue( i, u[r], n, `the ${o} property "${r}"`, e === Ft, ) ) return [!1, null]; } return [!0, u]; } export function validateCustomAttributeArrayType(t, e) { let r = !1, n = !1; const o = () => { N.error( "Custom attribute arrays must be either string arrays or object arrays.", ); }; for (const i of e) if ("string" == typeof i) { if (n) return o(), [!1, !1]; if ( !validateCustomString( i, `set custom user attribute "${t}"`, "the element in the given array", ) ) return [!1, !1]; r = !0; } else { if (!It(i)) return o(), [!1, !1]; if (r) return o(), [!1, !1]; if ( !validateCustomProperties( i, Ft, "attribute value", `set custom user attribute "${t}"`, "custom user attribute", ) ) return [!1, !1]; n = !0; } return [r, n]; } export function isValidEmail(t) { return ( "string" == typeof t && null != t.toLowerCase().match(EMAIL_ADDRESS_REGEX) ); } export function isValidBrazeActionJson(t) { if (!(oo.properties.type in t)) return !1; switch (t[oo.properties.type]) { case oo.types.io: if (oo.properties.eo in t) return !0; break; case oo.types.logCustomEvent: case oo.types.setEmailNotificationSubscriptionType: case oo.types.setPushNotificationSubscriptionType: case oo.types.setCustomUserAttribute: case oo.types.addToSubscriptionGroup: case oo.types.removeFromSubscriptionGroup: case oo.types.addToCustomAttributeArray: case oo.types.removeFromCustomAttributeArray: case oo.types.mo: case oo.types.uo: if (oo.properties.so in t) return !0; break; case oo.types.requestPushPermission: return !0; default: return !1; } return !1; } export function isValidBrazeActionType(t) { let e = !1; return ( Object.keys(oo.types).forEach((r) => { oo.types[r] !== t.toString() || (e = !0); }), e ); } export function isValidBannerPlacementId(t) { return VALID_UTF8_STRING_NO_WHITESPACES_REGEX.test(t); }