UNPKG

@gamealytics/web-sdk

Version:

GameAlytics SDK for Web/Node.js - Cross-platform analytics for game developers

284 lines (283 loc) 9.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Environment = exports.UserConfig = exports.GameAlytics = exports.CustomEventBuilder = exports.SystemEventBuilder = exports.Ad = exports.Progression = exports.User = exports.IAP = exports.Gameplay = void 0; // Core types const DataValidator_1 = require("./validation/DataValidator"); const EventQueue_1 = require("./queue/EventQueue"); var Environment; (function (Environment) { Environment["DEVELOPMENT"] = "DEVELOPMENT"; Environment["PRODUCTION"] = "PRODUCTION"; })(Environment || (exports.Environment = Environment = {})); class UserConfigBuilder { setSessionId(sessionId) { this.sessionId = sessionId; return this; } setUserId(userId) { this.userId = userId; return this; } setAnonymous(anonymousId) { this.anonymousId = anonymousId; return this; } build() { if (!this.sessionId) { throw new Error('SessionId is required'); } if (!this.userId && !this.anonymousId) { throw new Error('Either userId or anonymousId must be provided'); } return new UserConfig(this.sessionId, this.userId, this.anonymousId); } } class UserConfig { constructor(sessionId, userId, anonymousId) { this.sessionId = sessionId; if (userId !== undefined) { this.userId = userId; } if (anonymousId !== undefined) { this.anonymousId = anonymousId; } } static builder() { return new UserConfigBuilder(); } } exports.UserConfig = UserConfig; class EventBuilderImpl { constructor(eventType, eventCategory, isCustom) { this.properties = {}; this.eventType = eventType; this.eventCategory = eventCategory; this.isCustom = isCustom; } setProperties(properties) { this.properties = Object.assign(Object.assign({}, this.properties), properties); return this; } async track() { GameAlytics.getInstance().trackEvent(this.isCustom ? 'CUSTOM' : 'SYSTEM', this.eventType, this.eventCategory, this.properties); } } class InitBuilder { constructor(apiKey, environment) { this.apiKey = apiKey; this.environment = environment; } userConfig(userConfig) { this.userConfigValue = userConfig; return this; } create() { if (!this.apiKey) { throw new Error('API key is required'); } if (!this.userConfigValue) { throw new Error('UserConfig is required'); } GameAlytics.instance = new GameAlytics(this.apiKey, this.environment, this.userConfigValue); return GameAlytics.instance; } } class GameAlytics { constructor(apiKey, environment, userConfig) { this.isInitialized = false; this.apiKey = apiKey; this.environment = environment; this.userConfig = userConfig; this.deviceInfo = this.autoFetchDeviceInfo(); this.baseUrl = environment === Environment.PRODUCTION ? 'https://client.gamealytics.click' : 'https://client.dev.gamealytics.click'; // Initialize event queue with base URL and API key injection this.eventQueue = new EventQueue_1.EventQueue(); window.__GA_BASE_URL__ = this.baseUrl; window.__GA_API_KEY__ = this.apiKey; this.isInitialized = true; } static init(apiKey, environment) { return new InitBuilder(apiKey, environment); } static getInstance() { if (!GameAlytics.instance) { throw new Error('GameAlytics must be initialized first. Call GameAlytics.init(...).create()'); } return GameAlytics.instance; } systemEvent() { return new SystemEventBuilder(); } customEvent() { return new CustomEventBuilder(); } autoFetchDeviceInfo() { try { const isBrowser = typeof window !== 'undefined'; return { platform: isBrowser ? 'Web' : 'Node.js', osVersion: this.getOSVersion(), deviceModel: isBrowser ? window.navigator.platform : 'Node.js', screenResolution: this.getScreenResolution(), deviceManufacturer: isBrowser ? window.navigator.vendor || 'Unknown' : 'Node.js', appVersion: '1.0.0' }; } catch (error) { // Silent failure for performance return { platform: 'Unknown', osVersion: 'Unknown', deviceModel: 'Unknown', screenResolution: 'Unknown', deviceManufacturer: 'Unknown', appVersion: '1.0.0' }; } } trackEvent(type, eventType, category, properties) { // Validate and sanitize properties const validationResult = DataValidator_1.DataValidator.validateProperties(properties, { maxLength: 100, allowHtml: false, allowedTypes: ['string', 'number', 'boolean'] }); // Log validation errors in development if (validationResult.errors.length > 0 && this.environment === Environment.DEVELOPMENT) { console.warn('GameAlytics validation warnings:', validationResult.errors); } const eventPayload = Object.assign(Object.assign({ type, value: eventType, category, properties: validationResult.sanitized }, this.deviceInfo), { timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, localDateTime: new Date().toISOString(), userId: this.userConfig.userId || '', anonymousId: this.userConfig.anonymousId || '', sessionId: this.userConfig.sessionId }); // Use event queue for reliable delivery this.eventQueue.enqueue(eventPayload); } getOSVersion() { if (typeof window === 'undefined') return 'Node.js'; const userAgent = window.navigator.userAgent; const platform = window.navigator.platform; const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K']; const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE']; const iosPlatforms = ['iPhone', 'iPad', 'iPod']; if (macosPlatforms.indexOf(platform) !== -1) return 'Mac OS'; if (iosPlatforms.indexOf(platform) !== -1) return 'iOS'; if (windowsPlatforms.indexOf(platform) !== -1) return 'Windows'; if (/Android/.test(userAgent)) return 'Android'; if (/Linux/.test(platform)) return 'Linux'; return 'Unknown'; } getScreenResolution() { if (typeof window !== 'undefined' && window.screen) { return `${window.screen.width}x${window.screen.height}`; } return 'unknown'; } ensureInitialized() { if (!this.isInitialized) { throw new Error('GameAlytics must be initialized first. Call GameAlytics.init()'); } } } exports.GameAlytics = GameAlytics; GameAlytics.instance = null; // Event Category Classes class Gameplay { } exports.Gameplay = Gameplay; Gameplay.LEVEL_START = 'level_start'; Gameplay.LEVEL_END = 'level_end'; Gameplay.LEVEL_UP = 'level_up'; Gameplay.BOSS_FIGHT = 'boss_fight'; Gameplay.CHECKPOINT_REACHED = 'checkpoint_reached'; class IAP { } exports.IAP = IAP; IAP.PURCHASE = 'purchase'; IAP.PURCHASE_FAILED = 'purchase_failed'; IAP.PURCHASE_RESTORED = 'purchase_restored'; IAP.SUBSCRIPTION_STARTED = 'subscription_started'; IAP.SUBSCRIPTION_CANCELLED = 'subscription_cancelled'; class User { } exports.User = User; User.SESSION_START = 'session_start'; User.SESSION_END = 'session_end'; User.USER_LOGIN = 'user_login'; User.USER_LOGOUT = 'user_logout'; User.USER_REGISTER = 'user_register'; class Progression { } exports.Progression = Progression; Progression.TUTORIAL_COMPLETE = 'tutorial_complete'; Progression.ACHIEVEMENT_UNLOCKED = 'achievement_unlocked'; Progression.MILESTONE_REACHED = 'milestone_reached'; Progression.QUEST_COMPLETED = 'quest_completed'; class Ad { } exports.Ad = Ad; Ad.AD_VIEWED = 'ad_viewed'; Ad.AD_CLICKED = 'ad_clicked'; Ad.AD_REWARDED = 'ad_rewarded'; Ad.AD_FAILED = 'ad_failed'; // Event Builders class SystemEventBuilder { constructor() { this.properties = {}; } categoryClass(categoryClass) { this.category = categoryClass.constructor.name.toLowerCase(); return this; } eventType(type) { this.type = type; return this; } setProperties(properties) { this.properties = properties || {}; return this; } trigger() { if (!GameAlytics.instance) { throw new Error('GameAlytics must be initialized first'); } if (!this.category || !this.type) { throw new Error('Category and type are required'); } GameAlytics.instance.trackEvent('SYSTEM', this.type, this.category, this.properties); } } exports.SystemEventBuilder = SystemEventBuilder; class CustomEventBuilder { constructor() { this.properties = {}; } categoryName(category) { this.category = category; return this; } eventType(type) { this.type = type; return this; } setProperties(properties) { this.properties = properties || {}; return this; } trigger() { if (!GameAlytics.instance) { throw new Error('GameAlytics must be initialized first'); } if (!this.category || !this.type) { throw new Error('Category and type are required'); } GameAlytics.instance.trackEvent('CUSTOM', this.type, this.category, this.properties); } } exports.CustomEventBuilder = CustomEventBuilder; exports.default = GameAlytics;