let defaultLocale: string | undefined; let defaultIsDevelopment: boolean | undefined; let _sessionId = NewSessionId(); let _lastTouched = new Date(); const isInBrowser = true; // Hosts const _hosts: { [server: string]: string } = { ZV: 'https://events.sudovanilla.org', SH: '', }; // export type ZalvenaOptions = { host?: string; apiUrl?: string; appVersion?: string; isDevelopment?: boolean; }; // Save Session ID export function InMemorySessionId(timeout: number): string { const diffInMs = new Date().getTime() - _lastTouched.getTime(); const diffInSec = Math.floor(diffInMs / 1000); if (diffInSec > timeout) { _sessionId = NewSessionId(); } _lastTouched = new Date(); return _sessionId; } // Create Session ID export function NewSessionId(): string { const epochInSeconds = Math.floor(Date.now() / 1000).toString(); const random = Math.floor(Math.random() * 100000000) .toString() .padStart(8, '0'); return epochInSeconds + random; } // Check if the app key is valid export function ValidateAppKey(appKey: string): boolean { const parts = appKey.split('-'); if (parts.length !== 3 || _hosts[parts[1]] === undefined) { console.warn(`The Zalvena App Key "${appKey}" is invalid. Tracking will be disabled.`); return false; } return true; } // Check if user is using selfhosted key, // then point both coditions to API path export function GetApiURL(appKey: string, options?: ZalvenaOptions): string | undefined { const server = appKey.split('-')[1]; if (server === 'SH') { if (!options?.host) { console.warn(`Host parameter must be defined when using Self-Hosted App Key. Tracking will be disabled.`); console.warn(`Add the 'host' option to your 'init' function. 'init('key', {host: ''})'.`); return; } return `${options.host}/api/v0/event`; } const host = options?.host ?? _hosts[server]; return `${host}/api/v0/event`; } // Event Function export async function SendEvent(opts: { apiUrl: string; appKey?: string; sessionId: string; locale?: string; isDevelopment?: boolean; appVersion?: string; sdkVersion: string; eventName: string; props?: Record; }): Promise { if (!isInBrowser) { console.warn( `Zalvena: trackEvent requires a browser environment. Event "${opts.eventName}" will be discarded.`, ); return; } if (!opts.appKey) { console.warn(`Zalvena: init must be called before trackEvent. Event "${opts.eventName}" will be discarded.`); return; } try { const response = await fetch(opts.apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'App-Key': opts.appKey, }, credentials: 'omit', body: JSON.stringify({ timestamp: new Date().toISOString(), sessionId: opts.sessionId, eventName: opts.eventName, systemProps: { locale: opts.locale ?? getBrowserLocale(), isDebug: opts.isDevelopment ?? getIsDevelopment(), appVersion: opts.appVersion ?? '', sdkVersion: opts.sdkVersion, }, props: opts.props, }), }); if (response.status >= 300) { const responseBody = await response.text(); console.warn(`Failed to send event "${opts.eventName}": ${response.status} ${responseBody}`); } } catch (e) { console.warn(`Failed to send event "${opts.eventName}"`); console.warn(e); } } // Browser Locale function getBrowserLocale(): string | undefined { if (defaultLocale) { return defaultLocale; } if (typeof navigator === 'undefined') { return undefined; } if (navigator.languages.length > 0) { defaultLocale = navigator.languages[0]; } else { defaultLocale = navigator.language; } return defaultLocale; } // If the environment is on the `localhost` URL, // send development data instead of production function getIsDevelopment(): boolean { if (location.hostname === 'localhost') { defaultIsDevelopment = true; return defaultIsDevelopment; } else { defaultIsDevelopment = false; return defaultIsDevelopment; } }