import { reflect, string, storage } from '@amp-metrics/mt-metricskit-utils-private'; /* * src/helpers/constants.js * ae-client-kit-core * * Copyright © 2019 Apple Inc. All rights reserved. * */ var _allBaseFieldNames; var _environmentBaseFieldNames; function requiredEnvironmentBaseFieldNames() { return [ 'app', 'appVersion', 'hardwareFamily', 'hardwareModel', 'os', 'osBuildNumber', 'osLanguages', 'osVersion', 'resourceRevNum', 'screenHeight', 'screenWidth', 'userAgent' ]; } function optionalEnvironmentBaseFieldNames() { return ['delegateApp', 'hardwareBrand', 'storeFrontCountryCode', 'storeFrontHeader', 'storeFrontLanguage']; } function otherBaseFieldNames() { return [ 'baseVersion', 'clientEventId', 'connection', 'eventTime', 'eventType', 'eventVersion', 'timezoneOffset', 'xpPostFrequency', 'xpSendMethod' ]; } function environmentBaseFieldNames() { if (!_environmentBaseFieldNames) { _environmentBaseFieldNames = requiredEnvironmentBaseFieldNames().concat(optionalEnvironmentBaseFieldNames()); } return _environmentBaseFieldNames; } function allBaseFieldNames() { if (!_allBaseFieldNames) { _allBaseFieldNames = environmentBaseFieldNames().concat(otherBaseFieldNames()); } return _allBaseFieldNames; } /* * src/event_handlers/Base.js * ae-client-kit-core * * Copyright © 2018 Apple Inc. All rights reserved. * */ var attachDelegate = reflect.attachDelegate; var cryptoRandomBase62String = string.cryptoRandomBase62String; var exceptionString = string.exceptionString; var _prototypeInitialized; /** * Creates and returns an object (key/value data map (dictionary)) containing all of the "base" fields common to all metrics events. * To override any functionality in this class, use the "setDelegate() method in order to override the specific functions that need customization. * Kits can also extend this class and additional methods specific to their event model. * @example * // extend kit-core Base class * var MetricsKitBase = function MetricsKitBase() { * kitCore.eventHandlers.Base.apply(this, arguments); // invoke Base constructor * }; * MetricsKitBase.prototype = new kitCore.eventHandlers.Base(); * MetricsKitBase.prototype.constructor = MetricsKitBase; * * // set Kit-specific methods * MetricsKitBase.prototype.environment = function() { return metricsKit.system.environment; } * MetricsKitBase.prototype.eventRecorder = function() { return metricsKit.system.eventRecorder; } * MetricsKitBase.prototype.metricsData = function(pageId, pageType, pageContext, callerSuppliedFieldsMapsN) { ... } * MetricsKitBase.prototype.processMetricsData = function( ... ) { ... } * * // extend kit-core known fields * MetricsKitBase.prototype.knownFields = function knownFields() { * var parentKnownFields = Object.getPrototypeOf(MetricsKitBase.prototype).knownFields(); * return parentKnownFields.concat(['dsId', 'anotherUserExperienceOnlyField']); * }; * * // add Kit-specific accessor functions * MetricsKitBase.prototype.dsId = function dsId() { return this.environment().dsId(); }; * MetricsKitBase.prototype.anotherUserExperienceOnlyField = function() { ... }; * * // create a Kit-specific class instance * metricsKit.eventHandlers.base = new MetricsKitBase(metricsKit); * @param {MetricsKit/PerfKit/VPAFKit} kit * @delegatable * @constructor */ function Base(processor) { if (!reflect.isDefinedNonNull(processor)) { throw new Error('A processor instance is required for creating BaseEventHandler.'); } // @private this._processor = processor; if (!_prototypeInitialized) { _prototypeInitialized = true; environmentBaseFieldNames().forEach(function (fieldName) { Base.prototype[fieldName] = function (callerSuppliedEventFields) { var returnValue; if (callerSuppliedEventFields && callerSuppliedEventFields.hasOwnProperty(fieldName)) { returnValue = callerSuppliedEventFields[fieldName]; } else { returnValue = this.environment()[fieldName](); } return returnValue; }; }); } } Base._className = 'eventHandlers.base'; /** * Allows replacement of one or more of this class instance's functions * Any method on the passed-in object which matches a method that this class has will be called instead of the built-in class method. * To replace *all* methods of his class, simply have your delegate implement all the methods of this class * Your delegate can be a true object instance, an anonymous object, or a class object. * Your delegate is free to have as many additional non-matching methods as it likes (these methods will not be copied to the target object). * It can even act as a delegate for multiple MetricsKit objects, though that is not recommended. * * "setDelegate()" may be called repeatedly, with the functions in the most-recently set delegates replacing any functions matching those in the earlier delegates, as well as any as-yet unreplaced functions. * This allows callers to replace some number of methods that need custom implementations. * If, for example, a client wants to use the standard logger implementation with the exception of, say, the "debug" method, they can * call "setDelegate()" with their own delegate containing only a single method of "debug" as the delegate, which would leave all the other methods intact. * * NOTE: The delegate function will have a property called origFunction representing the original function that it replaced. * This allows the delegate to, essentially, call "super" before or after it does some work. * If a replaced method is overridden again with a subsequent "setDelegate()" call, the "origFunction" property will be the previous delegate's function. * @example: * To override one or more methods, in place: * base.setDelegate({ app: function() { return 'myApp'; }); * To override one or more methods with a separate object: * base.setDelegate(customBaseDelegate); * (where "customBaseDelegate" might be defined elsewhere as, e.g.: * var customBaseDelegate = { app: function() { return Device.appIdentifier; }; * appVersion: function() { return Device.appVersion; } }; * To override one or more methods with an instantiated object from a class definition: * base.setDelegate(new CustomBaseDelegate()); * (where "CustomBaseDelegate" might be defined elsewhere as, e.g.: * function CustomBaseDelegate() {} * CustomBaseDelegate.prototype.app = function app() { return Device.appIdentifier; }; * CustomBaseDelegate.prototype.appVersion = function appVersion() { return Device.appVersion; }; * To override one or more methods with a class object (with "static" methods): * base.setDelegate(CustomBaseDelegate); * (where "CustomBaseDelegate" might be defined elsewhere as, e.g.: * function CustomBaseDelegate() {} * CustomBaseDelegate.app = function app() { return Device.appIdentifier; }; * CustomBaseDelegate.appVersion = function appVersion() { return Device.appVersion; }; * @param {Object} delegate Object or Class with delegate method(s) to be called instead of default (built-in) methods. * @returns {Boolean} true if one or more methods on the delegate object match one or more methods on the default object, * otherwise returns false. */ Base.prototype.setDelegate = function setDelegate(delegate) { return attachDelegate(this, delegate); }; /** * The active environment class * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @see src/system/Environment * @return {Environment} * @overridable */ Base.prototype.environment = function environment() { // Don't wrap the throw in a helper function or the backtrace won't be as nice. throw exceptionString(Base._className, 'environment'); }; /** * The active eventRecorder * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @return {Object} an event recorder that implements a sendMethod() function * @overridable */ Base.prototype.eventRecorder = function eventRecorder() { // Don't wrap the throw in a helper function or the backtrace won't be as nice. throw exceptionString(Base._className, 'eventRecorder'); }; /** * Creates a simple map object (dictionary) with all the "base" fields required by AMP Analytics * Some fields can be derived by this class itself. * Some fields need to be provided by callers. * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @returns key/value pairs of all "base" fields required by AMP Analytics. * WARNING: May return "null" if metrics are disabled via the metrics.disabled config source value, or on error. * @overridable * * TODO: consider adding default implementation for shared Kit use */ Base.prototype.metricsData = function metricsData() { // Don't wrap the throw in a helper function or the backtrace won't be as nice. throw exceptionString(Base._className, 'metricsData'); }; /** * All of the various eventHandlers invoke this method to generate their metrics data * The data is a simple map object (dictionary) with all the fields required by AMP Analytics for that event * Some fields can be derived by this class itself. * This function typically expects to be called with the correct context * (e.g. base.processMetricsData.apply(this, arguments)) * @returns {Object} key/value pairs of all fields required by AMP Analytics. * WARNING: May return "null" if metrics and/or the specific eventType for this handler is disabled, or on error. * * TODO: consider adding default implementation for shared Kit use */ Base.prototype.processMetricsData = function processMetricsData() { // Don't wrap the throw in a helper function or the backtrace won't be as nice. throw exceptionString(Base._className, 'processMetricsData'); }; /** * @return {Array} all the fields that base eventHandlers know about */ Base.prototype.knownFields = function knownFields() { return allBaseFieldNames(); }; /** * ********************* ACCESSOR FUNCTIONS ********************* * We create accessor functions for every data field because: * 1. Cleans/simplifies all methods that use it. * 2. Facilitates writing test case shims * 3. Allows specific feature suppliers to be overridden (via setDelegate())) */ /** * The app identifier of the binary app * @param {Map} callerSuppliedEventFields * @returns {String} The app identifier of the binary app * @example "com.apple.appstore" or "com.apple.gamecenter" * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.app = function app(callerSuppliedEventFields) { }; /** * The version number of this application * @example "1.0", "5.43", etc. * @param {Map} callerSuppliedEventFields * @returns {String} the version number of this application * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.appVersion = function appVersion(callerSuppliedEventFields) { }; /** * The version of the set of base data to be sent up * @returns {number} the version of the set of base data to be sent up * @overridable */ Base.prototype.baseVersion = function baseVersion() { return 1; }; /** * A unique identifier for each event * @return {String} * @overridable */ Base.prototype.clientEventId = function clientEventId(callerSuppliedEventFields) { return (callerSuppliedEventFields && callerSuppliedEventFields.clientEventId) || cryptoRandomBase62String(true); }; /** * Type of internet connection. * Only applicable to devices * Beware that users on WiFi may actually be receiving 3G speeds (i.e. if device is tethered to a portable hotspot.) * @example "WiFi, "3G, etc. * @param {Map} callerSuppliedEventFields * @returns {String} type of internet connection * @overridable */ Base.prototype.connection = function connection(callerSuppliedEventFields) { return (callerSuppliedEventFields && callerSuppliedEventFields.connection) || this.environment().connectionType(); }; /** * The identifier of the process generating the event, if different from “app”, or blank otherwise. * @example 'web-experience-app' * @returns {String} * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.delegateApp = function delegateApp(callerSuppliedEventFields) { }; /** * The id of this user ("directory service id"). * This id will get mapped to a consumerId on the server. * @example 659261189 * @param {Map} callerSuppliedEventFields * @returns {String} * @overridable */ Base.prototype.dsId = function dsId(callerSuppliedEventFields) { return (callerSuppliedEventFields && callerSuppliedEventFields.dsId) || this.environment().dsId(); }; /** * The time (UTC) in milliseconds at which this event happened. * This field is central to determining the sequence of user events * Use online epoch converter to test your values. * @example 1437356433388 (http://www.epochconverter.com converts that to: July 19, 2015 at 6:40:33 PM PDT GMT-7:00 DST) * @param {Map} callerSuppliedEventFields * @returns {number} the time (UTC) in milliseconds at which this event happened * @overridable */ Base.prototype.eventTime = function eventTime(callerSuppliedEventFields) { return (callerSuppliedEventFields && callerSuppliedEventFields.eventTime) || Date.now(); }; /** * The version of the set of data to be sent up * @return {Number} * @overridable */ Base.prototype.eventVersion = function eventVersion(callerSuppliedEventFields) { return (callerSuppliedEventFields && callerSuppliedEventFields.eventVersion) || null; }; /** * The hardware brand of the device. Not required for Apple devices. * @example "Samsung", "LG", "Google" * @param {Map} callerSuppliedEventFields * @returns {String} * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.hardwareBrand = function hardwareBrand(callerSuppliedEventFields) { }; /** * The hardware family of the device * @example "iPhone", "Macbook Pro" * @param {Map} callerSuppliedEventFields * @returns {String} * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.hardwareFamily = function hardwareFamily(callerSuppliedEventFields) { }; /** * The model of the device * @example "iPhone10,2", "MacbookPro11,5" * @returns {String} * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.hardwareModel = function hardwareModel(callerSuppliedEventFields) { }; /** * The name of the OS * @example "ios", "macos", "windows" * @param {Map} callerSuppliedEventFields * @returns {String} * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.os = function os(callerSuppliedEventFields) { }; /** * The build number of the OS * @example "15D60", "17E192" * @param {Map} callerSuppliedEventFields * @returns {String} * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.osBuildNumber = function osBuildNumber(callerSuppliedEventFields) { }; /** * A string array of language IDs, ordered in descending preference * @example ["en-US", "fr-CA"] * @param {Map} callerSuppliedEventFields * @returns {Array} * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.osLanguages = function osLanguages(callerSuppliedEventFields) { }; /** * The full OS version number * In ITML, the value can be retrieved via Device.systemVersion * @example "8.2.1" (iOS) "10.10.3" (Desktop) * @param {Map} callerSuppliedEventFields * @returns {String} the full OS version number * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.osVersion = function osVersion(callerSuppliedEventFields) { }; /** * The HTML resources revision number * @example 2C97 or 8.4.0.0.103 * @param {Map} callerSuppliedEventFields * @returns {String} the HTML resources revision number * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.resourceRevNum = function resourceRevNum(callerSuppliedEventFields) { }; /** * The client screen height in pixels * @example 568 * @param {Map} callerSuppliedEventFields * @returns {number} the client screen height in pixels * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.screenHeight = function screenHeight(callerSuppliedEventFields) { }; /** * The client screen width in pixels * @example 320 * @param {Map} callerSuppliedEventFields * @returns {number} the client screen width in pixels * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.screenWidth = function screenWidth(callerSuppliedEventFields) { }; /** * ISO 3166 Country Code. Apps that cannot provide a storeFrontHeader should provide a storeFrontCountryCode instead * @example US * @param {Map} callerSuppliedEventFields * @returns {String} the store front country code * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.storeFrontCountryCode = function storeFrontCountryCode(callerSuppliedEventFields) { }; /** * The value contained in the X-Apple-Store-Front header value at the time the event is being created. * @example K143441-1,29 ab:rSwnYxS0 * @param {Map} callerSuppliedEventFields * @returns {String} the value contained in the X-Apple-Store-Front header value at the time the event is being created * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.storeFrontHeader = function storeFrontHeader(callerSuppliedEventFields) { }; /** * The difference, in minutes, between GMT (UTC) and timezone of event origin ("local time). * This means that the offset is positive if the local timezone is behind UTC and negative if it is ahead. * Daylight saving time prevents this value from being a constant, even for a given locale * @example 420 (PST, not -420) or -600 (Australian Eastern Standard Time, UTC+10) * @param {Map} callerSuppliedEventFields * @returns {number} the difference, in minutes, between GMT (UTC) and timezone of event origin ("local time). * @overridable */ Base.prototype.timezoneOffset = function timezoneOffset(callerSuppliedEventFields) { return (callerSuppliedEventFields && callerSuppliedEventFields.timezoneOffset) || new Date().getTimezoneOffset(); }; /** * The client’s user agent string. If the "app field is not provided, "userAgent may be used to derive the value of the "app field * @example AppStore/2.0 iOS/8.3 model/iPhone7,2 build/12F70 (6; dt:106) * @param {Map} callerSuppliedEventFields * @returns {String} the client’s user agent string. If the "app field is not provided, "userAgent may be used to derive the value of the "app field * @overridable */ // This prototype method is created dynamically upon instance initialization // Base.prototype.userAgent = function userAgent(callerSuppliedEventFields) { }; /** * How often, in milliseconds, batches of events should get sent to the server. * This field should be based on the client's most recent config value of "postFrequency". * This is valuable for problem analysis because it indicates if and how clients are honoring the "postFrequency" value * they were supplied with. * This cannot be a "passthrough" field, because it can change (via new config) during program execution, so the value * in effect at event creation time is what is needed. * @example 60000 * @param {Map} callerSuppliedEventFields * @returns {number} how often, in milliseconds, batches of events should get sent to the server * @overridable */ Base.prototype.xpPostFrequency = function xpPostFrequency(callerSuppliedEventFields) { return ( (callerSuppliedEventFields && callerSuppliedEventFields.xpPostFrequency) || this._processor.config.value('postFrequency') ); }; /** * The methodology being used by the eventRecorder to send batches of events to the server * This field should be hardcoded in the client based on what method it is using to encode and send its events to Figaro. * The three typical values are: * "itms" - use this value when/if JavaScript code enqueues events for sending via the "itms.recordEvent()" method in ITML. * "itunes" - use this value when/if JavaScript code enqueues events by calling the "iTunes.recordEvent()" method in Desktop Store apps. * "javascript" - use this value when/if JavaScript code enqueues events for sending via the JavaScript eventQueue management. This is typically only used by older clients which don't have the built-in functionality of itms or iTunes available to them. * @example "itms", "itunes", "javascript" * @param {Map} callerSuppliedEventFields * @returns {String} the methodology being used by the eventRecorder to send batches of events to the server * @overridable */ Base.prototype.xpSendMethod = function (callerSuppliedEventFields) { return (callerSuppliedEventFields && callerSuppliedEventFields.xpSendMethod) || this.eventRecorder().sendMethod(); }; /* * src/event_handlers/index.js * ae-client-kit-core * * Copyright © 2018 Apple Inc. All rights reserved. * */ var eventHandlers = { Base: Base }; /* * src/system/Environment.js * ae-client-kit-core * * Copyright © 2018 Apple Inc. All rights reserved. * */ var attachDelegate$1 = reflect.attachDelegate; var exceptionString$1 = string.exceptionString; var localStorageObject = storage.localStorageObject; var sessionStorageObject = storage.sessionStorageObject; var _prototypeInitialized$1; /** * Provides a set of environment-specific (platform-specific) functions which can be individually overridden for the needs * of the particular environment, or replaced en masse by providing a single replacement environment delegate object. * Kits can extend this class and additional methods specific to their event model. * @example * // MetricsKit code * * // extend kit-core Environment class * var MetricsKitEnvironment = function MetricsKitEnvironment() { * kitCore.system.Environment.apply(this, arguments); // invoke Environment constructor * }; * MetricsKitEnvironment.prototype = new kitCore.system.Environment(); * MetricsKitEnvironment.prototype.constructor = MetricsKitEnvironment; * * // add Kit-specific functions * MetricsKitEnvironment.prototype.dsId = function dsId() { * throw this._exceptionString(_utils.reflect.functionName()); * }; * MetricsKitEnvironment.prototype.anotherUserExperienceOnlyField = function() { ... }; * * // create a Kit-specific class instance * metricsKit.system.environment = new MetricsKitEnvironment(); * * // client app code remains unchanged: * var customEnvironmentDelegate = { * app: function() { return 'myAppName'; }, * appVersion: function() { ... } // etc. * }; * * metricsKit.system.environment.setDelegate(customEnvironmentDelegate); * * @constructor */ function Environment() { // consider moving this code into a separate init method if (!_prototypeInitialized$1) { _prototypeInitialized$1 = true; requiredEnvironmentBaseFieldNames().forEach(function (fieldName) { Environment.prototype[fieldName] = function () { throw exceptionString$1(Environment._className, fieldName); }; }); optionalEnvironmentBaseFieldNames().forEach(function (fieldName) { Environment.prototype[fieldName] = function () {}; }); } } Environment._className = 'system.environment'; /** * Allows replacement of one or more of this class instance's functions * Any method on the passed-in object which matches a method that this class has will be called instead of the built-in class method. * To replace *all* methods of his class, simply have your delegate implement all the methods of this class * Your delegate can be a true object instance, an anonymous object, or a class object. * Your delegate is free to have as many additional non-matching methods as it likes (these methods will not be copied to the target object). * It can even act as a delegate for multiple MetricsKit objects, though that is not recommended. * * "setDelegate()" may be called repeatedly, with the functions in the most-recently set delegates replacing any functions matching those in the earlier delegates, as well as any as-yet unreplaced functions. * This allows callers to replace some number of methods that need custom implementations. * If, for example, a client wants to use the standard logger implementation with the exception of, say, the "debug" method, they can * call "setDelegate()" with their own delegate containing only a single method of "debug" as the delegate, which would leave all the other methods intact. * * NOTE: The delegate function will have a property called origFunction representing the original function that it replaced. * This allows the delegate to, essentially, call "super" before or after it does some work. * If a replaced method is overridden again with a subsequent "setDelegate()" call, the "origFunction" property will be the previous delegate's function. * @example: * To override one or more methods, in place: * environment.setDelegate({ app: function() { return 'myApp'; }); * To override one or more methods with a separate object: * environment.setDelegate(customEnvironmentDelegate); * (where "customEnvironmentDelegate" might be defined elsewhere as, e.g.: * var customEnvironmentDelegate = { app: function() { return Device.appIdentifier; }, * appVersion: function() { return Device.appVersion; } }; * To override one or more methods with an instantiated object from a class definition: * environment.setDelegate(new CustomEnvironmentDelegate()); * (where "CustomEnvironmentDelegate" might be defined elsewhere as, e.g.: * function CustomEnvironmentDelegate() {} * CustomEnvironmentDelegate.prototype.app = function app() { return Device.appIdentifier; }; * CustomEnvironmentDelegate.prototype.appVersion = function appVersion() { return Device.appVersion; }; * To override one or more methods with a class object (with "static" methods): * environment.setDelegate(CustomEnvironmentDelegate); * (where "CustomEnvironmentDelegate" might be defined elsewhere as, e.g.: * function CustomEnvironmentDelegate() {} * CustomEnvironmentDelegate.app = function app() { return Device.appIdentifier; }; * CustomEnvironmentDelegate.appVersion = function appVersion() { return Device.appVersion; }; * @param {Object} delegate Object or Class with delegate method(s) to be called instead of default (built-in) methods. * @returns {Boolean} true if one or more methods on the delegate object match one or more methods on the default object, * otherwise returns false. */ Environment.prototype.setDelegate = function setDelegate(delegate) { return attachDelegate$1(this, delegate); }; /** * The app identifier of the binary app * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "com.apple.appstore" or "com.apple.gamecenter" * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.app = function app() { }; /** * The version number of this application * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "1.0", "5.43", etc. * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.appVersion = function appVersion() { }; /** * Type of internet connection. * Only applicable to devices * Beware that users on WiFi may actually be receiving 3G speeds (i.e. if device is tethered to a portable hotspot.) * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "WiFi, "3G, etc. * @returns {String} */ Environment.prototype.connectionType = function connectionType() { // Don't wrap the throw in a helper function or the backtrace won't be as nice. // TODO: use a constant instead of a hardcoded string throw exceptionString$1(Environment._className, 'connectionType'); }; /** * The identifier of the process generating the event, if different from “app”, or blank otherwise. * NO DEFAULT IMPLEMENTATION... HOWEVER: these fields are not required, so an exception will not be thrown if they * are omitted. * @example 'web-experience-app' * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.delegateApp = function delegateApp(callerSuppliedEventFields) { }; /** * The id of this user ("directory service id"). * This id will get mapped to a consumerId on the server. * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example 659261189 * @returns {String} */ // This prototype method is created dynamically upon instance initialization Environment.prototype.dsId = function dsId() { // Don't throw an exception to avoid breaking minor version backwards compatibility. // Consider adding an exception in the next major version. }; /** * The hardware brand of the device. Not required for Apple devices. * NO DEFAULT IMPLEMENTATION... HOWEVER: these fields are not required, so an exception will not be thrown if they * are omitted. * @example "Samsung", "LG", "Google" * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.hardwareBrand = function hardwareBrand() { }; /** * The hardware family of the device * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "iPhone", "Macbook Pro" * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.hardwareFamily = function hardwareFamily() { }; /** * The model of the device * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "iPhone10,2", "MacbookPro11,5" * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.hardwareModel = function hardwareModel() { }; /** * The name of the OS * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "ios", "macos", "windows" * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.os = function os() { }; /** * The build number of the OS * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "15D60", "17E192" * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.osBuildNumber = function osBuildNumber() { }; /** * A string array of language IDs, ordered in descending preference * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example ["en-US", "fr-CA"] * @returns {Array} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.osLanguages = function osLanguages() { }; /** * The full OS version number * In ITML, the value can be retrieved via Device.systemVersion * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example "8.2.1" (iOS) "10.10.3" (Desktop) * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.osVersion = function osVersion() { }; /** * HTML resources revision number * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example 2C97 or 8.4.0.0.103 * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.resourceRevNum = function resourceRevNum() { }; /** * Client screen height in pixels * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example 568 * @returns {number} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.screenHeight = function screenHeight() { }; /** * Client screen width in pixels * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example 320 * @returns {number} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.screenWidth = function screenWidth() { }; /** * ISO 3166 Country Code. Apps that cannot provide a storeFrontHeader should provide a storeFrontCountryCode instead * NO DEFAULT IMPLEMENTATION... Either this method or storeFrontHeader must be replaced. * are omitted. * @example US * @param {Map} callerSuppliedEventFields * @returns {String} the store front country code * @overridable */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.storeFrontCountryCode = function storeFrontCountryCode(callerSuppliedEventFields) { }; /** * The value contained in the X-Apple-Store-Front header value at the time the event is being created. * NO DEFAULT IMPLEMENTATION... Either this method or storeFrontHeader must be replaced. * @example K143441-1,29 ab:rSwnYxS0 * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.storeFrontHeader = function storeFrontHeader() { }; /** * Client’s user agent string. If the "app field is not provided, "userAgent may be used to derive the value of the "app field * NO DEFAULT IMPLEMENTATION... THIS METHOD MUST BE REPLACED * @example AppStore/2.0 iOS/8.3 model/iPhone7,2 build/12F70 (6; dt:106) * @returns {String} */ // This prototype method is created dynamically upon instance initialization // Environment.prototype.userAgent = function userAgent() { }; /** * Some clients have platform-specific implementations of these objects (e.g. iTunes.sessionStorage), * so we cover them in case they need to be overridden. */ Environment.prototype.localStorageObject = localStorageObject; Environment.prototype.sessionStorageObject = sessionStorageObject; /** * Fetching identifier entity from AMS Metrics Identifier API * @param {String} idNamespace - The id namespace that is defined under 'metricsIdentifier' in the bag * @param {'userid' | 'clientid'} idType - The identifier type (userid or clientid) * @param {Boolean} crossDeviceSync - The boolean flag to indicate whether the identifier is synced across devices * @returns {Promise} * @overridable */ Environment.prototype.platformIdentifier = function platformIdentifier() {}; /* * src/system/index.js * ae-client-kit-core * * Copyright © 2018 Apple Inc. All rights reserved. * */ var system = { Environment: Environment }; /* * src/helpers/MetricsData.js * ae-client-kit-core * * Copyright © 2018 Apple Inc. All rights reserved. * */ /** * Creates and returns a MetricsData instance with APIs to store event data and create and send events to AMP Analytics * @delegatable * @constructor * @return {MetricsData} */ function MetricsData() { // @private this._eventData = {}; // this data may be unclean; it should be cleaned before being enqueued as an event } /** ************************************ PUBLIC METHODS/IVARS ************************************ */ /** * Add event data to this metricsData object * This data may be unclean; it should be cleaned before being enqueued as an event * @param {Object} callerSuppliedEventFieldsMapN a variable number of Object arguments from 0-N, * each containing key/value pairs representing event fields to include when sending the event. * Later objects take precedence over earlier ones, overriding any field value that may have already been there. * @overridable */ MetricsData.prototype.updateData = function updateData(/* callerSuppliedEventFieldsMapN(varargs) */) { reflect.extend.apply(null, [this._eventData].concat(Array.prototype.slice.call(arguments))); }; /* * src/helpers/index.js * ae-client-kit-core * * Copyright © 2018 Apple Inc. All rights reserved. * */ var helpers = { MetricsData: MetricsData }; export { eventHandlers, helpers, system };