UNPKG

@rudderstack/analytics-js-cookies

Version:
95 lines (85 loc) 8.05 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.rsaCookies = {})); })(this, (function (exports) { 'use strict'; /** * A function to check given value is null or not * @param value input value * @returns boolean */const isNull=value=>value===null;/** * A function to check given value is undefined * @param value input value * @returns boolean */const isUndefined=value=>typeof value==='undefined';/** * A function to check given value is null or undefined * @param value input value * @returns boolean */const isNullOrUndefined=value=>isNull(value)||isUndefined(value); // https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem /** * Converts a base64 encoded string to bytes array * @param base64Str base64 encoded string * @returns bytes array */const base64ToBytes=base64Str=>{const binString=globalThis.atob(base64Str);const bytes=binString.split('').map(char=>char.charCodeAt(0));return new Uint8Array(bytes);};/** * Converts a bytes array to base64 encoded string * @param bytes bytes array to be converted to base64 * @returns base64 encoded string */const bytesToBase64=bytes=>{const binString=Array.from(bytes,x=>String.fromCodePoint(x)).join('');return globalThis.btoa(binString);};/** * Encodes a string to base64 even with unicode characters * @param value input string * @returns base64 encoded string */const toBase64=value=>bytesToBase64(new TextEncoder().encode(value));/** * Decodes a base64 encoded string * @param value base64 encoded string * @returns decoded string */const fromBase64=value=>new TextDecoder().decode(base64ToBytes(value)); const CIRCULAR_REFERENCE_PLACEHOLDER='[Circular Reference]';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context // eslint-disable-next-line func-names return function(key,value){if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent. // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore-next-line while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){return CIRCULAR_REFERENCE_PLACEHOLDER;}ancestors.push(value);return value;};};/** * Utility method for JSON stringify object excluding null values & circular references * * @param {*} value input * @param {boolean} excludeNull if it should exclude nul or not * @param {function} logger optional logger methods for warning * @returns string */const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){return null;}}; /** * Encode. */const encode=(value,logger)=>{try{return encodeURIComponent(value);}catch(err){return undefined;}};/** * Decode */const decode=value=>{try{return decodeURIComponent(value);}catch(err){// Do nothing as non-RS SDK cookies may not be URI encoded return undefined;}};/** * Parse cookie `str` */const parse=str=>{const obj={};const pairs=str.split(/\s*;\s*/);let pair;if(!pairs[0]){return obj;}// TODO: Decode only the cookies that are needed by the SDK pairs.forEach(pairItem=>{pair=pairItem.split('=');const keyName=pair[0]?decode(pair[0]):undefined;if(keyName){obj[keyName]=pair[1]?decode(pair[1]):undefined;}});return obj;};/** * Set cookie `name` to `value` */const set=(name,value,optionsConfig,logger)=>{const options={...({})};let cookieString=`${encode(name)}=${encode(value)}`;if(isNull(value)){options.maxage=-1;}if(options.maxage){options.expires=new Date(+new Date()+options.maxage);}if(options.path){cookieString+=`; path=${options.path}`;}if(options.domain){cookieString+=`; domain=${options.domain}`;}if(options.expires){cookieString+=`; expires=${options.expires.toUTCString()}`;}if(options.samesite){cookieString+=`; samesite=${options.samesite}`;}if(options.secure){cookieString+=`; secure`;}globalThis.document.cookie=cookieString;};/** * Return all cookies */const all=()=>{const cookieStringValue=globalThis.document.cookie;return parse(cookieStringValue);};/** * Get cookie `name` */const get=name=>all()[name];/** * Set or get cookie `name` with `value` and `options` object */// eslint-disable-next-line func-names const cookie=function(name,value,options,logger){switch(arguments.length){case 4:case 3:case 2:return set(name,value);case 1:if(name){return get(name);}return all();default:return all();}}; const userIdKey='rl_user_id';const userTraitsKey='rl_trait';const anonymousUserIdKey='rl_anonymous_id';const groupIdKey='rl_group_id';const groupTraitsKey='rl_group_trait';const pageInitialReferrerKey='rl_page_init_referrer';const pageInitialReferringDomainKey='rl_page_init_referring_domain';const sessionInfoKey='rl_session';const authTokenKey='rl_auth_token';const COOKIE_KEYS={userId:userIdKey,userTraits:userTraitsKey,anonymousId:anonymousUserIdKey,groupId:groupIdKey,groupTraits:groupTraitsKey,initialReferrer:pageInitialReferrerKey,initialReferringDomain:pageInitialReferringDomainKey,sessionInfo:sessionInfoKey,authToken:authTokenKey};const ENCRYPTION_PREFIX_V3='RS_ENC_v3_'; const getEncryptedValueInternal=(value,encryptFn,debug)=>{const fallbackValue=null;try{const strValue=stringifyWithoutCircular(value,false);if(isNull(strValue)){return null;}return encryptFn(strValue);}catch(err){if(debug){console.error('Error occurred during encryption: ',err);}return fallbackValue;}};const getDecryptedValueInternal=(value,decryptFn,debug)=>{const fallbackValue=null;try{const decryptedVal=decryptFn(value);if(isNullOrUndefined(decryptedVal)){return fallbackValue;}return JSON.parse(decryptedVal);}catch(err){if(debug){console.error('Error occurred during decryption: ',err);}return fallbackValue;}};const encryptBrowser=value=>`${ENCRYPTION_PREFIX_V3}${toBase64(value)}`;const decryptBrowser=value=>{if(value?.startsWith(ENCRYPTION_PREFIX_V3)){return fromBase64(value.substring(ENCRYPTION_PREFIX_V3.length));}return value;};const getEncryptedValueBrowser=(value,debug=false)=>getEncryptedValueInternal(value,encryptBrowser,debug);const getDecryptedValueBrowser=(value,debug=false)=>getDecryptedValueInternal(value,decryptBrowser,debug);const getDecryptedCookieBrowser=(cookieKey,debug=false)=>{if(Object.values(COOKIE_KEYS).includes(cookieKey)){return getDecryptedValueBrowser(cookie(cookieKey),debug);}return null;};const encrypt=value=>`${ENCRYPTION_PREFIX_V3}${Buffer.from(value,'utf-8').toString('base64')}`;const decrypt=value=>{if(value?.startsWith(ENCRYPTION_PREFIX_V3)){return Buffer.from(value.substring(ENCRYPTION_PREFIX_V3.length),'base64').toString('utf-8');}return value;};const getDecryptedValue=(value,debug=false)=>getDecryptedValueInternal(value,decrypt,debug);const getEncryptedValue=(value,debug=false)=>getEncryptedValueInternal(value,encrypt,debug); exports.anonymousUserIdKey = anonymousUserIdKey; exports.authTokenKey = authTokenKey; exports.getDecryptedCookieBrowser = getDecryptedCookieBrowser; exports.getDecryptedValue = getDecryptedValue; exports.getDecryptedValueBrowser = getDecryptedValueBrowser; exports.getEncryptedValue = getEncryptedValue; exports.getEncryptedValueBrowser = getEncryptedValueBrowser; exports.groupIdKey = groupIdKey; exports.groupTraitsKey = groupTraitsKey; exports.pageInitialReferrerKey = pageInitialReferrerKey; exports.pageInitialReferringDomainKey = pageInitialReferringDomainKey; exports.sessionInfoKey = sessionInfoKey; exports.userIdKey = userIdKey; exports.userTraitsKey = userTraitsKey; Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); }));