{"mappings":"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","names":["STRINGIFY_TYPES","SDKError","message","errorObject","ret","additionalInfo","key","assert","condition","message","SDKError","isStr","value","isNonEmptyString","isObject","isNonEmptyObj","isUrl","mandatoryFields","parsedUrl","f","isFunction","isStrIn","possibilities","caseSensitive","_isSameStrCaseInsensitive","str","cloneDefined","sources","result","SDKError","source","assert","isObject","isNonEmptyObj","key","value","cloneDeep","obj","urlMapper","url","urlMap","assert","isNonEmptyString","isNonEmptyObj","isUrl","config","ENDPOINTS","config","NAMESPACE","EventEmitter","webStorageWorks","storeProvider","store","randomKey","testValue","val","WebStorageCache","key","value","LiteralCache","maxExpiresIn","Cache","getObj","raw","obj","e","SDKError","expiresIn","expiresOn","serialize","obj","assert","isObject","key","defaultWindowFeatures","open","parentWindow","url","windowName","windowFeatures","isFunction","isUrl","height","width","mergedFeatures","cloneDefined","features","logString","msg","m","isObject","logFn","fn","encode","str","replace","match","globalFetch","RESTClient","_RESTClient","serverUrl","envDic","fetch","log","defaultParams","assert","mappedUrl","urlMapper","handledServerUrl","isFunction","method","headers","pathname","data","useDefaultParams","fetchOptions","isNonEmptyString","cloneDefined","fullUrl","response","SDKError","responseObject","err","isStr","query","handledPathname","url","params","p","RESTClient_default","emulate","global","isFunction","callbackName","data","version","version_default","registerGlobal","global","componentClassName","instance","prefixedName","HAS_SESSION_CACHE_KEY","SESSION_CALL_BLOCKED_CACHE_KEY","SESSION_CALL_BLOCKED_TTL","TAB_ID_KEY","TAB_ID","TAB_ID_TTL","globalWindow","Identity","EventEmitter","clientId","redirectUri","sessionDomain","env","log","window","callbackBeforeRedirect","assert","isNonEmptyString","isObject","isUrl","emulate","Cache","registerGlobal","tabId","url","isStr","RESTClient_default","urlMapper","ENDPOINTS","domain","client_sdrn","NAMESPACE","version_default","previous","current","options","expiresIn","sessionData","date","expires","cookie","baseDomain","SDKError","settings","_postProcess","_checkRedirectionNeed","sessionDataKeys","_getSession","cachedSession","err","user","cloneDeep","externalParty","optionalSuffix","pairId","_toHexDigest","hashBuffer","b","_getSha256Digest","data","message","msgUint8","it","sdrn","state","acrValues","scope","preferPopup","loginHint","tag","teaser","maxAge","locale","oneStepLogin","prompt","xDomainId","xEnvironmentId","originCampaign","open","isValidAcrValue","acrValue","isStrIn","params","loginParams","userData","queryParams","widgetUrl","prepareLoginParams","loginPrams","resolve","reject","initialParams","f","loginHandler","loginNotYouHandler","initHandler","cancelLoginHandler","simplifiedLoginWidget","EventEmitter","globalWindow","Monetization","EventEmitter","clientId","redirectUri","env","sessionDomain","window","emulate","assert","isNonEmptyString","Cache","isUrl","registerGlobal","url","isStr","RESTClient_default","urlMapper","ENDPOINTS","domain","client_sdrn","NAMESPACE","version_default","productIds","userId","SDKError","sortedIds","cacheKey","data","promise","expiresSeconds","globalWindow","Payment","clientId","redirectUri","env","publisher","window","emulate","assert","isNonEmptyString","registerGlobal","url","isStr","RESTClient_default","urlMapper","ENDPOINTS","paylink","preferPopup","isUrl","open","voucherCode","paylinkId","productId","campaignId","code","state"],"sources":["../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/SDKError.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/validate.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/object.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/url.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/config.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/identity.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/cache.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/popup.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/RESTClient.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/spidTalk.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/version.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/global-registry.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/monetization.js","../esm/npm/@schibsted/account-sdk-browser@5.2.6/node_modules/@schibsted/account-sdk-browser/src/payment.js"],"sourcesContent":["/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\n/*\n * Note: this module can't have any internal dependencies because it's used in ./validate which\n * in turn is used as a dependency to a lot of other modules. Doing so may create a circular\n * dependency that's hard to debug in Node.\n */\n\nconst STRINGIFY_TYPES = ['boolean', 'number', 'string'];\n\n/**\n * Represents a SDK error. This is returned from all rejected promises that are returned from an API\n * call. Constructs an SDK error ready to throw\n * @summary When the SDK throws an error, it's supposed to be an instance of this class\n * @private\n */\nexport default class SDKError extends Error {\n    /**\n     * @property {number} code - The HTTP error code\n     * @extends {Error}\n     * @param {string} message - The error message\n     * @param {object} [errorObject] - The error object that was returned from the server. Any\n     * property of errorObject object will be copied into this instance SDKError\n     */\n    constructor(message, errorObject) {\n        super(message);\n        this.name = 'SDKError';\n        if (typeof errorObject === 'object') {\n            try {\n                // At this point it doesn't matter if errorObject === null\n                Object.assign(this, errorObject);\n            } catch(err) {\n                // silent\n            }\n        }\n    }\n\n    /**\n     * Serializes the error printing any interesting additional info\n     * @private\n     * @return {String}\n     */\n    toString() {\n        const ret = `${this.name}: ${this.message}`;\n        const additionalInfo = Object.keys(this)\n            .filter(key =\u003e key !== 'name' \u0026\u0026 STRINGIFY_TYPES.includes(typeof this[key]))\n            .map(key =\u003e `    ${key}: ${this[key]}`)\n            .join('\\n');\n        return additionalInfo ? `${ret}\\n${additionalInfo}` : ret;\n    }\n}\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\nimport SDKError from './SDKError.js';\n\n/*\n * This module defines a set of validation functions which are used in the rest of the SDK.\n * Why make our own validation module?\n * 1. To implement the validations that we specifically need for the SDK\n * 2. To have one less dependency\n */\n\n/**\n * A utility function that throws an SDKError if an assertion fails. It's mostly useful for\n * validating function inputs.\n * @memberof core\n * @param {boolean} condition - The condition that we're asserting\n * @param {string} [message = Assertion failed] - The error message\n * @throws {SDKError} - If the condition is falsy it throws the appropriate error\n * @return {void}\n */\nexport function assert(condition, message = 'Assertion failed') {\n    if (!condition) {\n        throw new SDKError(message);\n    }\n}\n\n/**\n * Checks if a value is a string or not\n * @memberof core\n * @param {*} value - The value to check\n * @return {boolean}\n */\nexport function isStr(value) {\n    return typeof value === 'string';\n}\n\n/**\n * Checks if a value is a non-empty string\n * @memberof core\n * @param {*} value - The value to check\n * @return {boolean}\n */\nexport function isNonEmptyString(value) {\n    return typeof value === 'string' \u0026\u0026 value.length \u003e 0;\n}\n\n/**\n * checks if a given value is an object (but not null)\n * @memberof core\n * @param {*} value - The value to check\n * @return {boolean}\n */\nexport function isObject(value) {\n    return typeof value === 'object' \u0026\u0026 value !== null;\n}\n\n/**\n * Checks if a given value is an object with at least one own key\n * @memberof core\n * @param {*} value - The value to check\n * @return {boolean}\n */\nexport function isNonEmptyObj(value) {\n    return isObject(value) \u0026\u0026 Object.keys(value).length \u003e 0;\n}\n\n/**\n * Checks if a given string is a valid URL\n * @memberof core\n * @param {string} value - The string to be tested\n * @param {...string} mandatoryFields - A list of mandatory fields that should exist in the parsed\n * URL object\n * @return {boolean}\n */\nexport function isUrl(value, ...mandatoryFields) {\n    try {\n        const parsedUrl = new URL(value);\n        return mandatoryFields.every(f =\u003e parsedUrl[f]);\n    } catch (urlParsingError) {\n        return false;\n    }\n}\n\n/**\n * Checks if a given value is a function\n * @memberof core\n * @param {*} value - The value to check\n * @return {boolean}\n */\nexport function isFunction(value) {\n    return typeof value === 'function';\n}\n\n/**\n * Checks if a string matches any of the strings in a set of possibilities\n * @memberof core\n * @param {string} value\n * @param {string[]} possibilities - An array of strings that'll be used to check the string\n * inclusion. Note that for performance reasons, we don't validate this parameter.\n * @param {boolean} [caseSensitive=false] - Should the check be case sensitive\n * @return {boolean}\n */\nexport function isStrIn(value, possibilities, caseSensitive = false) {\n    const _isSameStrCaseInsensitive = str =\u003e\n        isStr(str) \u0026\u0026 value.toUpperCase() === str.toUpperCase();\n    if (!(isStr(value) \u0026\u0026 Array.isArray(possibilities))) {\n        return false;\n    }\n    if (caseSensitive) {\n        return possibilities.indexOf(value) !== -1;\n    }\n    return possibilities.some(_isSameStrCaseInsensitive);\n}\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\n/**\n * @summary Some routines that work on javascript objects\n * @private\n */\n\nimport { assert, isObject, isNonEmptyObj } from './validate.js';\nimport SDKError from './SDKError.js';\n\n/**\n * Similar to Object.assign({}, src) but only clones the keys of an object that have non-undefined\n * values.\n * Please note that the values in the rightmost parameters can overwrite the values of the earlier\n * parameters so the order of the parameters matters.\n * @memberof core\n * @example\n * cloneDefined({foo: 1, bar: 2}, {foo: 2}) // returns {foo: 2, bar: 2}\n *\n * @param {object} sources - one or more sources. Their defined properties will override the ones\n *        that came before it. For example if `source1.foo = 'bar'` and `source2.foo = 'baz'`, the\n *        result will include `{ foo: 'baz' }`\n * @return {object} a new object that is similar to src with all the key/values where the\n *         keys for undefined values are removed.\n */\nexport function cloneDefined(...sources) {\n    const result = {};\n    if (!(sources \u0026\u0026 sources.length)) {\n        throw new SDKError('No objects to clone');\n    }\n    sources.forEach(source =\u003e {\n        assert(isObject(source));\n        if (isNonEmptyObj(source)) {\n            Object.entries(source).forEach(([key, value]) =\u003e {\n                if (typeof value !== 'undefined' ) {\n                    result[key] = isObject(value) ? cloneDeep(value) : value;\n                }\n            });\n        }\n    });\n    return result;\n}\n\n/**\n * Deep copies an object. This is handy for immutability.\n * @memberof core\n * @param {object} obj - An object, array or null.\n * @return {object} - an exact copy of the object but deep copied\n * @throws {SDKError} - if the obj is not an accepted type or is not\n *         stringifiable by JSON for example if it has loops\n */\nexport function cloneDeep(obj) {\n    assert(typeof obj === 'object', `obj should be an object (even null) but it is ${obj}`);\n    return JSON.parse(JSON.stringify(obj)) || obj;\n}\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict'\n\nimport { assert, isNonEmptyString, isUrl, isNonEmptyObj } from './validate.js';\n\n/**\n * A simple utility function that allows looking up URLs from a dictionary\n * @memberof core\n * @param {string} url - A url like http://example.com, or a key used for lookup\n * @param {object\u003cstring,string\u003e} urlMap - A map of URLs like\n * `{ DEV: 'http://dev.example.com' }`\n * @throws {SDKError} - If the url is not an string or is an empty string\n * @return {string} The url that points to the server\n */\nexport function urlMapper(url, urlMap) {\n    assert(isNonEmptyString(url), `\"url\" param must be a non empty string: ${typeof url}`);\n    if (isNonEmptyObj(urlMap) \u0026\u0026 isUrl(urlMap[url])) {\n        return urlMap[url];\n    }\n    assert(isUrl(url, 'hostname'), `Bad URL given: '${url}'`);\n    return url;\n}\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\n/*\n * This file declares configs that are essentially part of how the SDK works and interacts with our\n * backend servers.\n *\n * What goes here?\n * - The configurations that are likely to change over time\n * - Constants that are otherwise obscure (for example 7000 for a TIMEOUT)\n *\n * What doesn't go here?\n * - options that the users of the SDK are supposed to set or provide as a parameter to functions\n *   and classes.\n */\n\n/**\n * Core configuration used by the SDK\n * @type {Object}\n * @memberof core\n * @prop {object} ENDPOINTS - URL to some of the services that users of this SDK may interact with\n * @prop {object} ENDPOINTS.SPiD - SPiD endpoints\n * @prop {string} ENDPOINTS.SPiD.LOCAL - Local endpoint (for Identity team)\n * @prop {string} ENDPOINTS.SPiD.DEV - Dev environment (for Identity team)\n * @prop {string} ENDPOINTS.SPiD.PRE - Staging environment\n * @prop {string} ENDPOINTS.SPiD.PRO - Production environment Sweden\n * @prop {string} ENDPOINTS.SPiD.PRO_NO - Production environment Norway\n * @prop {string} ENDPOINTS.SPiD.PRO_FI - Production environment Finland\n * @prop {string} ENDPOINTS.SPiD.PRO_DK - Production environment Denmark\n * @prop {object} ENDPOINTS.BFF - Endpoints used with new GDPR-compliant web flows\n * @prop {string} ENDPOINTS.BFF.LOCAL - Local endpoint (for Identity team)\n * @prop {string} ENDPOINTS.BFF.DEV - Dev environment (for Identity team)\n * @prop {string} ENDPOINTS.BFF.PRE - Staging environment\n * @prop {string} ENDPOINTS.BFF.PRO - Production environment Sweden\n * @prop {string} ENDPOINTS.BFF.PRO_NO - Production environment Norway\n * @prop {string} ENDPOINTS.BFF.PRO_FI - Production environment Finland\n * @prop {string} ENDPOINTS.BFF.PRO_DK - Production environment Denmark\n * @prop {object} ENDPOINTS.SESSION_SERVICE - Endpoints to check global user session data\n * @prop {string} ENDPOINTS.SESSION_SERVICE.LOCAL - Local endpoint (for Identity team)\n * @prop {string} ENDPOINTS.SESSION_SERVICE.DEV - Dev environment (for Identity team)\n * @prop {string} ENDPOINTS.SESSION_SERVICE.PRE - Staging environment\n * @prop {string} ENDPOINTS.SESSION_SERVICE.PRO - Production environment Sweden\n * @prop {string} ENDPOINTS.SESSION_SERVICE.PRO_NO - Production environment Norway\n * @prop {string} ENDPOINTS.SESSION_SERVICE.PRO_FI - Production environment Finland\n * @prop {string} ENDPOINTS.SESSION_SERVICE.PRO_DK - Production environment Denmark\n */\nconst config = {\n    ENDPOINTS: {\n        SPiD: {\n            LOCAL: 'http://id.localhost',\n            DEV: 'https://identity-dev.schibsted.com',\n            PRE: 'https://identity-pre.schibsted.com',\n            PRO: 'https://login.schibsted.com',\n            PRO_NO: 'https://payment.schibsted.no',\n            PRO_FI: 'https://login.schibsted.fi',\n            PRO_DK: 'https://login.schibsted.dk',\n        },\n        BFF: {\n            LOCAL: 'http://id.localhost/authn/',\n            DEV: 'https://identity-dev.schibsted.com/authn/',\n            PRE: 'https://identity-pre.schibsted.com/authn/',\n            PRO: 'https://login.schibsted.com/authn/',\n            PRO_NO: 'https://payment.schibsted.no/authn/',\n            PRO_FI: 'https://login.schibsted.fi/authn/',\n            PRO_DK: 'https://login.schibsted.dk/authn/',\n        },\n        SESSION_SERVICE: {\n            LOCAL: 'http://session-service.id.localhost',\n            DEV: 'https://session-service.identity-dev.schibsted.com',\n            PRE: 'https://session-service.identity-pre.schibsted.com',\n            PRO: 'https://session-service.login.schibsted.com',\n            PRO_NO: 'https://session-service.payment.schibsted.no',\n            PRO_FI: 'https://session-service.login.schibsted.fi',\n            PRO_DK: 'https://session-service.login.schibsted.dk',\n        },\n    },\n    NAMESPACE: {\n        LOCAL: 'id.localhost',\n        DEV: 'schibsted.com',\n        PRE: 'schibsted.com',\n        PRO: 'schibsted.com',\n        PRO_NO: 'spid.no',\n        PRO_FI: 'schibsted.fi',\n        PRO_DK: 'schibsted.dk',\n    }\n};\n\nexport default config;\nexport const ENDPOINTS = config.ENDPOINTS;\nexport const NAMESPACE = config.NAMESPACE;\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\nimport { assert, isStr, isNonEmptyString, isObject, isUrl, isStrIn } from './validate.js';\nimport { cloneDeep } from './object.js';\nimport { urlMapper } from './url.js';\nimport { ENDPOINTS, NAMESPACE } from './config.js';\nimport EventEmitter from 'tiny-emitter';\nimport Cache from './cache.js';\nimport * as popup from './popup.js';\nimport RESTClient from './RESTClient.js';\nimport SDKError from './SDKError.js';\nimport * as spidTalk from './spidTalk.js';\nimport version from './version.js';\nimport { registerGlobal } from './global-registry.js';\n\n/**\n * @typedef {object} LoginOptions\n * @property {string} state - An opaque value used by the client to maintain state between\n * the request and callback. It's also recommended to prevent CSRF {@link https://tools.ietf.org/html/rfc6749#section-10.12}\n * @property {string} [acrValues] - Authentication Context Class Reference Values. If\n * omitted, the user will be asked to authenticate using username+password.\n * For 2FA (Two-Factor Authentication) possible values are `sms`, `otp` (one time password),\n * `password` (will force password confirmation, even if user is already logged in), `eid`. Those values might\n * be mixed as space-separated string. To make sure that user has authenticated with 2FA you need\n * to verify AMR (Authentication Methods References) claim in ID token.\n * Might also be used to ensure additional acr (sms, otp) for already logged-in users.\n * Supported value is also 'otp-email' means one time password using email.\n * @property {string} [scope] - The OAuth scopes for the tokens. This is a list of\n * scopes, separated by space. If the list of scopes contains `openid`, the generated tokens\n * includes the id token which can be useful for getting information about the user. Omitting\n * scope is allowed, while `invalid_scope` is returned when the client asks for a scope you\n * aren’t allowed to request. {@link https://tools.ietf.org/html/rfc6749#section-3.3}\n * @property {string} [redirectUri] - Redirect uri that will receive the\n * code. Must exactly match a redirectUri from your client in self-service\n * @property {boolean} [preferPopup] - Should we try to open a popup window?\n * @property {string} [loginHint] - User email or UUID hint\n * @property {string} [tag] - Pulse tag\n * @property {string} [teaser] - Teaser slug. Teaser with given slug will be displayed\n * in place of default teaser\n * @property {number|string} [maxAge] - Specifies the allowable elapsed time in seconds since\n * the last time the End-User was actively authenticated. If last authentication time is more\n * than maxAge seconds in the past, re-authentication will be required. See the OpenID Connect\n * spec section 3.1.2.1 for more information\n * @property {string} [locale] - Optional parameter to overwrite client locale setting.\n * New flows supports nb_NO, fi_FI, sv_SE, en_US\n * @property {boolean} [oneStepLogin] - Display username and password on one screen\n * @property {string} [prompt] - String that specifies whether the Authorization Server prompts the\n * End-User for re-authentication or confirm account screen. Supported values: `select_account` or `login`\n * @property {string} [xDomainId] - Identifier for cross-domain tracking in Pulse\n * @property {string} [xEnvironmentId] - Environment for cross-domain tracking in Pulse\n * @property {string} [originCampaign] - Campaign identifier for tracking in Pulse\n */\n/**\n * @typedef {object} SimplifiedLoginWidgetLoginOptions\n * @property {string|function(): (string|Promise\u003cstring\u003e)} state - An opaque value used by the client to maintain state between\n * the request and callback. It's also recommended to prevent CSRF {@link https://tools.ietf.org/html/rfc6749#section-10.12}\n * @property {string} [acrValues] - Authentication Context Class Reference Values. If\n * omitted, the user will be asked to authenticate using username+password.\n * For 2FA (Two-Factor Authentication) possible values are `sms`, `otp` (one time password) and\n * `password` (will force password confirmation, even if user is already logged in). Those values might\n * be mixed as space-separated string. To make sure that user has authenticated with 2FA you need\n * to verify AMR (Authentication Methods References) claim in ID token.\n * Might also be used to ensure additional acr (sms, otp) for already logged-in users.\n * Supported value is also 'otp-email' means one time password using email.\n * @property {string} [scope] - The OAuth scopes for the tokens. This is a list of\n * scopes, separated by space. If the list of scopes contains `openid`, the generated tokens\n * includes the id token which can be useful for getting information about the user. Omitting\n * scope is allowed, while `invalid_scope` is returned when the client asks for a scope you\n * aren’t allowed to request. {@link https://tools.ietf.org/html/rfc6749#section-3.3}\n * @property {string} [redirectUri] - Redirect uri that will receive the\n * code. Must exactly match a redirectUri from your client in self-service\n * @property {boolean} [preferPopup] - Should we try to open a popup window?\n * @property {string} [loginHint] - User email or UUID hint\n * @property {string} [tag] - Pulse tag\n * @property {string} [teaser] - Teaser slug. Teaser with given slug will be displayed\n * in place of default teaser\n * @property {number|string} [maxAge] - Specifies the allowable elapsed time in seconds since\n * the last time the End-User was actively authenticated. If last authentication time is more\n * than maxAge seconds in the past, re-authentication will be required. See the OpenID Connect\n * spec section 3.1.2.1 for more information\n * @property {string} [locale] - Optional parameter to overwrite client locale setting.\n * New flows supports nb_NO, fi_FI, sv_SE, en_US\n * @property {boolean} [oneStepLogin] - Display username and password on one screen\n * @property {string} [prompt] - String that specifies whether the Authorization Server prompts the\n * End-User for reauthentication or confirm account screen. Supported values: `select_account` or `login`\n * @property {string} [xDomainId] - Identifier for cross-domain tracking in Pulse\n * @property {string} [xEnvironmentId] - Environment for cross-domain tracking in Pulse\n * @property {string} [originCampaign] - Campaign identifier for tracking in Pulse\n */\n\n/**\n * @typedef {object} HasSessionSuccessResponse\n * @property {boolean} result - Is the user connected to the merchant? (it means that the merchant\n * id is in the list of merchants listed of this user in the database)? Example: false\n * @property {string} userStatus - Example: 'notConnected' or 'connected'. Deprecated, use\n * `Identity.isConnected()`\n * @property {string} baseDomain - Example: 'localhost'\n * @property {string} id - Example: '58eca10fdbb9f6df72c3368f'. Obsolete\n * @property {number} userId - Example: 37162\n * @property {string} uuid - Example: 'b3b23aa7-34f2-5d02-a10e-5a3455c6ab2c'\n * @property {string} sp_id - Example: 'eyJjbGllbnRfaWQ...'\n * @property {number} expiresIn - Example: 30 * 60 * 1000 (for 30 minutes)\n * @property {number} serverTime - Example: 1506285759\n * @property {string} sig - Example: 'NCdzXaz4ZRb7...' The sig parameter is a concatenation of an\n * HMAC SHA-256 signature string, a dot (.) and a base64url encoded JSON object (session).\n * {@link http://techdocs.spid.no/sdks/js/response-signature-and-validation/}\n * @property {string} displayName - (Only for connected users) Example: 'batman'\n * @property {string} givenName - (Only for connected users) Example: 'Bruce'\n * @property {string} familyName - (Only for connected users) Example: 'Wayne'\n * @property {string} gender - (Only for connected users) Example: 'male', 'female', 'undisclosed'\n * @property {string} photo - (Only for connected users) Example:\n * 'http://www.srv.com/some/picture.jpg'\n * @property {boolean} tracking - (Only for connected users)\n * @property {boolean} clientAgreementAccepted - (Only for connected users)\n * @property {boolean} defaultAgreementAccepted - (Only for connected users)\n * @property {string} pairId\n * @property {string} sdrn\n */\n\n/**\n * Emitted when an error happens (useful for debugging)\n * @event Identity#error\n */\n\n/**\n * @typedef {object} HasSessionFailureResponse\n * @property {object} error\n * @property {number} error.code - Typically an HTTP response code. Example: 401\n * @property {string} error.description - Example: \"No session found!\"\n * @property {string} error.type - Example: \"UserException\"\n * @property {object} response\n * @property {string} response.baseDomain - Example: \"localhost\"\n * @property {number} response.expiresIn - Time span in milliseconds. Example: 30 * 60 * 1000 (for 30 minutes)\n * @property {boolean} response.result\n * @property {number} response.serverTime - Server time in seconds since the Unix Epoch. Example: 1506287788\n */\n\n/**\n * @typedef {object} SimplifiedLoginData\n * @property {string} identifier - Deprecated: User UUID, to be be used as `loginHint` for {@link Identity#login}\n * @property {string} display_text - Human-readable user identifier\n * @property {string} client_name - Client name\n */\n\n/**\n * @typedef {object} SimplifiedLoginWidgetOptions\n * @property {string} encoding - expected encoding of simplified login widget. Could be utf-8 (default), iso-8859-1 or iso-8859-15\n */\n\nconst HAS_SESSION_CACHE_KEY = 'hasSession-cache';\nconst SESSION_CALL_BLOCKED_CACHE_KEY = 'sessionCallBlocked-cache';\nconst SESSION_CALL_BLOCKED_TTL = 1000 * 60 * 5;\n\nconst TAB_ID_KEY = 'tab-id-cache';\nconst TAB_ID = Math.floor(Math.random() * 100000)\nconst TAB_ID_TTL = 1000 * 60 * 60 * 24 * 30;\n\nconst globalWindow = () =\u003e window;\n\n/**\n * Provides Identity functionalty to a web page\n */\nexport class Identity extends EventEmitter {\n    /**\n     * @param {object} options\n     * @param {string} options.clientId - Example: \"1234567890abcdef12345678\"\n     * @param {string} options.sessionDomain - Example: \"https://id.site.com\"\n     * @param {string} options.redirectUri - Example: \"https://site.com\"\n     * @param {string} [options.env=PRE] - Schibsted account environment: `PRE`, `PRO`, `PRO_NO`, `PRO_FI` or `PRO_DK`\n     * @param {function} [options.log] - A function that receives debug log information. If not set,\n     * no logging will be done\n     * @param {object} [options.window] - window object\n     * @param {function} [options.callbackBeforeRedirect] - callback triggered before session refresh redirect happen\n     * @throws {SDKError} - If any of options are invalid\n     */\n    constructor({\n        clientId,\n        redirectUri,\n        sessionDomain,\n        env = 'PRE',\n        log,\n        window = globalWindow(),\n        callbackBeforeRedirect = ()=\u003e{}\n    }) {\n        super();\n        assert(isNonEmptyString(clientId), 'clientId parameter is required');\n        assert(isObject(window), 'The reference to window is missing');\n        assert(!redirectUri || isUrl(redirectUri), 'redirectUri parameter is invalid');\n        assert(sessionDomain \u0026\u0026 isUrl(sessionDomain), 'sessionDomain parameter is not a valid URL');\n\n        spidTalk.emulate(window);\n        this._sessionInitiatedSent = false;\n        this.window = window;\n        this.clientId = clientId;\n        this.sessionStorageCache = new Cache(() =\u003e this.window \u0026\u0026 this.window.sessionStorage);\n        this.localStorageCache = new Cache(() =\u003e this.window \u0026\u0026 this.window.localStorage);\n        this.redirectUri = redirectUri;\n        this.env = env;\n        this.log = log;\n        this.callbackBeforeRedirect = callbackBeforeRedirect;\n        this._sessionDomain = sessionDomain;\n\n        // Internal hack: set to false to always refresh from hassession\n        this._enableSessionCaching = true;\n\n        // Old session\n        this._session = {};\n\n        this._setSessionServiceUrl(sessionDomain);\n        this._usedSessionServiceGetSessionEndpoint = this._sessionService.url.pathname \u0026\u0026 this._sessionService.url.pathname.length \u003c= 1 ? 'v2/session' : 'session';\n\n        this._setSpidServerUrl(env);\n        this._setBffServerUrl(env);\n        this._setOauthServerUrl(env);\n        this._setGlobalSessionServiceUrl(env);\n\n        this._unblockSessionCall();\n\n        registerGlobal(window, 'Identity', this);\n\n    }\n\n    /**\n     * Read tabId from session storage\n     * @returns {number}\n     * @private\n     */\n    _getTabId() {\n        if (this._enableSessionCaching) {\n            const tabId = this.sessionStorageCache.get(TAB_ID_KEY);\n            if (!tabId) {\n                this.sessionStorageCache.set(TAB_ID_KEY, TAB_ID, TAB_ID_TTL);\n                return TAB_ID;\n            }\n\n            return tabId;\n        }\n    }\n\n    /**\n     * Checks if getting session is blocked\n     * @private\n     *\n     * @returns {boolean|void}\n     */\n    _isSessionCallBlocked(){\n        return this.localStorageCache.get(SESSION_CALL_BLOCKED_CACHE_KEY);\n    }\n\n    /**\n     * Block calls to get session\n     * @private\n     *\n     * @returns {void}\n     */\n    _blockSessionCall(){\n        const SESSION_CALL_BLOCKED = true;\n\n        this.localStorageCache.set(\n            SESSION_CALL_BLOCKED_CACHE_KEY,\n            SESSION_CALL_BLOCKED,\n            SESSION_CALL_BLOCKED_TTL\n        );\n    }\n\n    /**\n     * Unblocks calls to get session\n     * @private\n     *\n     * @returns {void}\n     */\n    _unblockSessionCall(){\n        this.localStorageCache.delete(SESSION_CALL_BLOCKED_CACHE_KEY);\n    }\n\n    /**\n     * Set SPiD server URL\n     * @private\n     * @param {string} url - real URL or 'PRE' style key\n     * @returns {void}\n     */\n    _setSpidServerUrl(url) {\n        assert(isStr(url), `url parameter is invalid: ${url}`);\n        this._spid = new RESTClient({\n            serverUrl: urlMapper(url, ENDPOINTS.SPiD),\n            log: this.log,\n            defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n        });\n    }\n\n    /**\n     * Set OAuth server URL\n     * @private\n     * @param {string} url - real URL or 'PRE' style key\n     * @returns {void}\n     */\n    _setOauthServerUrl(url) {\n        assert(isStr(url), `url parameter is invalid: ${url}`);\n        this._oauthService = new RESTClient({\n            serverUrl: urlMapper(url, ENDPOINTS.SPiD),\n            log: this.log,\n            defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n        });\n    }\n\n    /**\n     * Set BFF server URL\n     * @private\n     * @param {string} url  - real URL or 'PRE' style key\n     * @returns {void}\n     */\n    _setBffServerUrl(url) {\n        assert(isStr(url), `url parameter is invalid: ${url}`);\n        this._bffService = new RESTClient({\n            serverUrl: urlMapper(url, ENDPOINTS.BFF),\n            log: this.log,\n            defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n        });\n    }\n\n    /**\n     * Set site-specific session-service domain\n     * @private\n     * @param {string} domain - real URL — (**not** 'PRE' style env key)\n     * @returns {void}\n     */\n    _setSessionServiceUrl(domain) {\n        assert(isStr(domain), `domain parameter is invalid: ${domain}`);\n        const client_sdrn = `sdrn:${NAMESPACE[this.env]}:client:${this.clientId}`;\n        this._sessionService = new RESTClient({\n            serverUrl: domain,\n            log: this.log,\n            defaultParams: { client_sdrn, redirect_uri: this.redirectUri, sdk_version: version },\n        });\n    }\n\n    /**\n     * Set global session-service server URL\n     * @private\n     * @param {string} url - real URL or 'PRE' style key\n     * @returns {void}\n     */\n    _setGlobalSessionServiceUrl(url) {\n        assert(isStr(url), `url parameter is invalid: ${url}`);\n        const client_sdrn = `sdrn:${NAMESPACE[this.env]}:client:${this.clientId}`;\n        this._globalSessionService = new RESTClient({\n            serverUrl: urlMapper(url, ENDPOINTS.SESSION_SERVICE),\n            log: this.log,\n            defaultParams: { client_sdrn, sdk_version: version },\n        });\n    }\n\n    /**\n     * Emits the relevant events based on the previous and new reply from hassession\n     * @private\n     * @param {object} previous\n     * @param {object} current\n     * @returns {void}\n     */\n    _emitSessionEvent(previous, current) {\n        /**\n         * Emitted when the user is logged in (This happens as a result of calling\n         * {@link Identity#hasSession}, so it is also emitted if the user was previously logged in)\n         * @event Identity#login\n         */\n        if (current.userId) {\n            this.emit('login', current);\n        }\n        /**\n         * Emitted when the user logged out\n         * @event Identity#logout\n         */\n        if (previous.userId \u0026\u0026 !current.userId) {\n            this.emit('logout', current);\n        }\n        /**\n         * Emitted when the user is changed. This happens as a result of calling\n         * {@link Identity#hasSession}, and is emitted if there was a user both before and after\n         * this invocation, and the userId has now changed\n         * @event Identity#userChange\n         */\n        if (previous.userId \u0026\u0026 current.userId \u0026\u0026 previous.userId !== current.userId) {\n            this.emit('userChange', current);\n        }\n        if (previous.userId || current.userId) {\n            /**\n             * Emitted when the session is changed. More accurately, this event is emitted if there\n             * was a logged-in user either before or after {@link Identity#hasSession} was called.\n             * In practice, this means the event is emitted a lot\n             * @event Identity#sessionChange\n             */\n            this.emit('sessionChange', current);\n        } else {\n            /**\n             * Emitted when there is no logged-in user. More specifically, it means that there was\n             * no logged-in user neither before nor after {@link Identity#hasSession} was called\n             * @event Identity#notLoggedin\n             */\n            this.emit('notLoggedin', current);\n        }\n        /**\n         * Emitted when the session is first created\n         * @event Identity#sessionInit\n         */\n        if (current.userId \u0026\u0026 !this._sessionInitiatedSent) {\n            this._sessionInitiatedSent = true;\n            this.emit('sessionInit', current);\n        }\n        /**\n         * Emitted when the user status changes. This happens as a result of calling\n         * {@link Identity#hasSession}\n         * @event Identity#statusChange\n         */\n        if (previous.userStatus !== current.userStatus) {\n            this.emit('statusChange', current);\n        }\n    }\n\n    /**\n     * Close this.popup if it exists and is open\n     * @private\n     * @returns {void}\n     */\n    _closePopup() {\n        if (this.popup) {\n            if (!this.popup.closed) {\n                this.popup.close();\n            }\n            this.popup = null;\n        }\n    }\n\n    /**\n     * Set the Varnish cookie (`SP_ID`) when hasSession() is called. Note that most browsers require\n     * that you are on a \"real domain\" for this to work — so, **not** `localhost`\n     * @param {object} [options]\n     * @param {number} [options.expiresIn] Override this to set number of seconds before the varnish\n     * cookie expires. The default is to use the same time that hasSession responses are cached for\n     * @param {string} [options.domain] Override cookie domain. E.g. «vg.no» instead of «www.vg.no»\n     * @returns {void}\n     */\n    enableVarnishCookie(options) {\n        let expiresIn = 0;\n        let domain;\n        if (Number.isInteger(options)) {\n            expiresIn = options;\n        }\n        else if (typeof options == 'object') {\n            expiresIn = options.expiresIn || expiresIn;\n            domain = options.domain || domain;\n        }\n\n        assert(Number.isInteger(expiresIn), `'expiresIn' must be an integer`);\n        assert(expiresIn \u003e= 0, `'expiresIn' cannot be negative`);\n        this.setVarnishCookie = true;\n        this.varnishExpiresIn = expiresIn;\n        this.varnishCookieDomain = domain;\n    }\n\n    /**\n     * Set the Varnish cookie if configured\n     * @private\n     * @param {HasSessionSuccessResponse} sessionData\n     * @returns {void}\n     */\n    _maybeSetVarnishCookie(sessionData) {\n        if (!this.setVarnishCookie) {\n            return;\n        }\n        const date = new Date();\n        const validExpires = this.varnishExpiresIn\n            || typeof sessionData.expiresIn === 'number' \u0026\u0026 sessionData.expiresIn \u003e 0;\n        if (validExpires) {\n            const expires = this.varnishExpiresIn || sessionData.expiresIn;\n            date.setTime(date.getTime() + (expires * 1000));\n        } else {\n            date.setTime(0);\n        }\n\n        // If the domain is missing or of the wrong type, we'll use document.domain\n        let domain = this.varnishCookieDomain ||\n            (typeof sessionData.baseDomain === 'string'\n                ? sessionData.baseDomain\n                : document.domain) ||\n            '';\n\n        const cookie = [\n            `SP_ID=${sessionData.sp_id}`,\n            `expires=${date.toUTCString()}`,\n            `path=/`,\n            `domain=.${domain}`\n        ].join('; ');\n        document.cookie = cookie;\n    }\n\n    /**\n     * Clear the Varnish cookie if configured\n     * @private\n     * @returns {void}\n     */\n    _maybeClearVarnishCookie() {\n        if (this.setVarnishCookie) {\n            this._clearVarnishCookie();\n        }\n    }\n\n    /**\n     * Clear the Varnish cookie\n     * @private\n     * @returns {void}\n     */\n    _clearVarnishCookie() {\n        const baseDomain =  this._session \u0026\u0026 typeof this._session.baseDomain === 'string'\n            ? this._session.baseDomain\n            : document.domain;\n\n        let domain = this.varnishCookieDomain ||\n            baseDomain ||\n            '';\n\n        document.cookie = `SP_ID=nothing; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`;\n    }\n\n    /**\n     * Log used settings and version\n     * @throws {SDKError} - If log method is not provided\n     * @return {void}\n     */\n    logSettings() {\n        if (!this.log \u0026\u0026 !window.console) {\n            throw new SDKError('You have to provide log method in constructor');\n        }\n\n        const log = this.log || console.log;\n\n        const settings = {\n            clientId: this.clientId,\n            redirectUri: this.redirectUri,\n            env: this.env,\n            sessionDomain: this._sessionDomain,\n            sdkVersion: version\n        }\n\n        log(`Schibsted account SDK for browsers settings: \\n${JSON.stringify(settings, null, 2)}`);\n    }\n\n    /**\n     * @summary Queries the hassession endpoint and returns information about the status of the user\n     * @description When we send a request to this endpoint, cookies sent along with the request\n     * determines the status of the user.\n     * @throws {SDKError} - If the call to the hasSession service fails in any way (this will happen\n     * if, say, the user is not logged in)\n     * @fires Identity#login\n     * @fires Identity#logout\n     * @fires Identity#userChange\n     * @fires Identity#sessionChange\n     * @fires Identity#notLoggedin\n     * @fires Identity#sessionInit\n     * @fires Identity#statusChange\n     * @fires Identity#error\n     * @return {Promise\u003cHasSessionSuccessResponse|HasSessionFailureResponse\u003e}\n     */\n    hasSession() {\n        const isSessionCallBlocked = this._isSessionCallBlocked()\n        if (isSessionCallBlocked) {\n            return this._session;\n        }\n\n        if (this._hasSessionInProgress) {\n            return this._hasSessionInProgress;\n        }\n\n        const _postProcess = (sessionData) =\u003e {\n            if (sessionData.error) {\n                throw new SDKError('HasSession failed', sessionData.error);\n            }\n            this._maybeSetVarnishCookie(sessionData);\n            this._emitSessionEvent(this._session, sessionData);\n            this._session = sessionData;\n            return sessionData;\n        };\n\n        const _checkRedirectionNeed = (sessionData={})=\u003e{\n            const sessionDataKeys = Object.keys(sessionData);\n\n            return sessionDataKeys.length === 1 \u0026\u0026\n                sessionDataKeys[0] === 'redirectURL';\n        }\n\n        const _getSession = async () =\u003e {\n            if (this._enableSessionCaching) {\n                // Try to resolve from cache (it has a TTL)\n                let cachedSession = this.sessionStorageCache.get(HAS_SESSION_CACHE_KEY);\n                if (cachedSession) {\n                    return _postProcess(cachedSession);\n                }\n            }\n            let sessionData = null;\n            try {\n                sessionData = await this._sessionService.get(this._usedSessionServiceGetSessionEndpoint, {tabId: this._getTabId()});\n            } catch (err) {\n                if (err \u0026\u0026 err.code === 400 \u0026\u0026 this._enableSessionCaching) {\n                    const expiresIn = 1000 * (err.expiresIn || 300);\n                    this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, { error: err }, expiresIn);\n                }\n                throw err;\n            }\n\n            if (sessionData){\n                // for expiring session and safari browser do full page redirect to gain new session\n                if(_checkRedirectionNeed(sessionData)){\n                    this._blockSessionCall();\n\n                    await this.callbackBeforeRedirect();\n\n                    return this._sessionService.makeUrl(sessionData.redirectURL, {tabId: this._getTabId()});\n                }\n\n                if (this._enableSessionCaching) {\n                    const expiresIn = 1000 * (sessionData.expiresIn || 300);\n                    this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, sessionData, expiresIn);\n                }\n            }\n\n            return _postProcess(sessionData);\n        };\n        this._hasSessionInProgress = _getSession()\n            .then(\n                sessionData =\u003e {\n                    this._hasSessionInProgress = false;\n\n                    if (isUrl(sessionData)) {\n                        return this.window.location.href = sessionData;\n                    }\n\n                    return sessionData;\n                },\n                err =\u003e {\n                    this.emit('error', err);\n                    this._hasSessionInProgress = false;\n                    throw new SDKError('HasSession failed', err);\n                }\n            );\n\n        return this._hasSessionInProgress;\n    }\n\n    /**\n     * @async\n     * @summary Allows the client app to check if the user is logged in to Schibsted account\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @return {Promise\u003cboolean\u003e}\n     */\n    async isLoggedIn() {\n        try {\n            const data = await this.hasSession();\n            return 'result' in data;\n        } catch (_) {\n            return false;\n        }\n    }\n\n    /**\n     * Removes the cached user session.\n     * @returns {void}\n     */\n    clearCachedUserSession() {\n        this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);\n    }\n\n    /**\n     * @async\n     * @summary Allows the caller to check if the current user is connected to the client_id in\n     * Schibsted account. Being connected means that the user has agreed for their account to be\n     * used by your web app and have accepted the required terms\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @summary Check if the user is connected to the client_id\n     * @return {Promise\u003cboolean\u003e}\n     */\n    async isConnected() {\n        try {\n            const data = await this.hasSession();\n            // if data is not an object, the promise will fail.\n            // if the result is present, it's boolean. But if it's not, it should be assumed false.\n            return !!data.result;\n        } catch (_) {\n            return false;\n        }\n    }\n\n    /**\n     * @async\n     * @summary Returns information about the user\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @throws {SDKError} If the user isn't connected to the merchant\n     * @throws {SDKError} If we couldn't get the user\n     * @return {Promise\u003cHasSessionSuccessResponse\u003e}\n     */\n    async getUser() {\n        const user = await this.hasSession();\n        if (!user.result) {\n            throw new SDKError('The user is not connected to this merchant');\n        }\n        return cloneDeep(user);\n    }\n\n    /**\n     * @async\n     * @summary\n     * In Schibsted account, there are multiple ways of identifying a user; the `userId`,\n     * `uuid` and `externalId` used for identifying a user-merchant pair (see {@link Identity#getExternalId}).\n     * There are reasons for them all to exist. The `userId` is a numeric identifier, but\n     * since Schibsted account is deployed separately in Norway and Sweden, there are a lot of\n     * duplicates. The `userId` was introduced early, so many sites still need to use them for\n     * legacy reasons. The `uuid` is universally unique, and so — if we could disregard a lot of\n     * Schibsted components depending on the numeric `userId` — it would be a good identifier to use\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @throws {SDKError} If the user isn't connected to the merchant\n     * @return {Promise\u003cstring\u003e} The `userId` field (not to be confused with the `uuid`)\n     */\n    async getUserId() {\n        const user = await this.hasSession();\n        if (user.userId \u0026\u0026 user.result) {\n            return user.userId;\n        }\n        throw new SDKError('The user is not connected to this merchant');\n    }\n\n    /**\n     * @async\n     * @function\n     * @summary\n     * Retrieves the external identifier (`externalId`) for the authenticated user.\n     *\n     * In Schibsted Account there are multiple ways of identifying users, however for integrations with\n     * third-parties it's recommended to use `externalId` as it does not disclose\n     * any critical data whilst allowing for user identification.\n     *\n     * `externalId` is merchant-scoped using a pairwise identifier (`pairId`),\n     * meaning the same user's ID will differ between merchants.\n     * Additionally, this identifier is bound to the external party provided as argument.\n     *\n     * @param {string} externalParty\n     * @param {string|null} optionalSuffix\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @throws {SDKError} If the `pairId` is missing in user session.\n     * @throws {SDKError} If the `externalParty` is not defined\n     * @return {Promise\u003cstring\u003e} The merchant- and 3rd-party-specific `externalId`\n     */\n    async getExternalId(externalParty, optionalSuffix = \"\") {\n        const { pairId } = await this.hasSession();\n\n        if (!pairId)\n            throw new SDKError('pairId missing in user session!');\n\n        if(!externalParty || externalParty.length === 0) {\n            throw new SDKError('externalParty cannot be empty');\n        }\n        const _toHexDigest = (hashBuffer) =\u003e{\n            // convert buffer to byte array\n            const hashArray = Array.from(new Uint8Array(hashBuffer));\n            // convert bytes to hex string\n            return hashArray.map(b =\u003e b.toString(16).padStart(2, '0')).join('');\n        }\n\n        const _getSha256Digest = (data) =\u003e {\n            return crypto.subtle.digest('SHA-256', data);\n        }\n\n        const _hashMessage = async (message) =\u003e {\n            const msgUint8 = new TextEncoder().encode(message);\n            return _getSha256Digest(msgUint8).then( (it) =\u003e _toHexDigest(it));\n        }\n\n        const _constructMessage = (pairId, externalParty, optionalSuffix) =\u003e {\n            return optionalSuffix\n                ? `${pairId}:${externalParty}:${optionalSuffix}`\n                : `${pairId}:${externalParty}`;\n        }\n\n        return _hashMessage(_constructMessage(pairId, externalParty, optionalSuffix))\n    }\n\n    /**\n     * @async\n     * @summary Enables brands to programmatically get the current the SDRN based on the user's session.\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @throws {SDKError} If the SDRN is missing in user session object.\n     * @returns {Promise\u003cstring\u003e}\n     */\n    async getUserSDRN() {\n        const { sdrn } = await this.hasSession();\n        if (sdrn) {\n            return sdrn;\n        }\n        throw new SDKError('Failed to get SDRN from user session');\n    }\n\n    /**\n     * @async\n     * @summary In Schibsted account, there are two ways of identifying a user; the `userId` and the\n     * `uuid`. There are reasons for them both existing. The `userId` is a numeric identifier, but\n     * since Schibsted account is deployed separately in Norway and Sweden, there are a lot of\n     * duplicates. The `userId` was introduced early, so many sites still need to use them for\n     * legacy reasons. The `uuid` is universally unique, and so — if we could disregard a lot of\n     * Schibsted components depending on the numeric `userId` — it would be a good identifier to use\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @throws {SDKError} If the user isn't connected to the merchant\n     * @return {Promise\u003cstring\u003e} The `uuid` field (not to be confused with the `userId`)\n     */\n    async getUserUuid() {\n        const user = await this.hasSession();\n        if (user.uuid \u0026\u0026 user.result) {\n            return user.uuid;\n        }\n        throw new SDKError('The user is not connected to this merchant');\n    }\n\n    /**\n     * @async\n     * @summary Get basic information about any user currently logged-in to their Schibsted account\n     * in this browser. Can be used to provide context in a continue-as prompt.\n     * @description This function relies on the global Schibsted account user session cookie, which\n     * is a third-party cookie and hence might be blocked by the browser (for example due to ITP in\n     * Safari). So there's no guarantee any data is returned, even though a user is logged-in in\n     * the current browser.\n     * @return {Promise\u003cSimplifiedLoginData|null\u003e}\n     */\n    async getUserContextData() {\n        try {\n            return await this._globalSessionService.get('user-context');\n        } catch (_) {\n            return null;\n        }\n    }\n\n    /**\n     * If a popup is desired, this function needs to be called in response to a user event (like\n     * click or tap) in order to work correctly. Otherwise the popup will be blocked by the\n     * browser's popup blockers and has to be explicitly authorized to be shown.\n     * @summary Perform a login, either using a full-page redirect or a popup\n     * @see https://tools.ietf.org/html/rfc6749#section-4.1.1\n     *\n     * @param {LoginOptions} options\n     * @param {string} options.state\n     * @param {string} [options.acrValues]\n     * @param {string} [options.scope=openid]\n     * @param {string} [options.redirectUri]\n     * @param {boolean} [options.preferPopup=false]\n     * @param {string} [options.loginHint]\n     * @param {string} [options.tag]\n     * @param {string} [options.teaser]\n     * @param {number|string} [options.maxAge]\n     * @param {string} [options.locale]\n     * @param {boolean} [options.oneStepLogin=false]\n     * @param {string} [options.prompt=select_account]\n     * @param {string} [options.xDomainId]\n     * @param {string} [options.xEnvironmentId]\n     * @param {string} [options.originCampaign]\n     * @return {Window|null} - Reference to popup window if created (or `null` otherwise)\n     */\n    login({\n        state,\n        acrValues = '',\n        scope = 'openid',\n        redirectUri = this.redirectUri,\n        preferPopup = false,\n        loginHint = '',\n        tag = '',\n        teaser = '',\n        maxAge = '',\n        locale = '',\n        oneStepLogin = false,\n        prompt = 'select_account',\n        xDomainId = '',\n        xEnvironmentId = '',\n        originCampaign = ''\n    }) {\n        this._closePopup();\n        this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);\n        const url = this.loginUrl({\n            state,\n            acrValues,\n            scope,\n            redirectUri,\n            loginHint,\n            tag,\n            teaser,\n            maxAge,\n            locale,\n            oneStepLogin,\n            prompt,\n            xDomainId,\n            xEnvironmentId,\n            originCampaign\n        });\n\n        if (preferPopup) {\n            this.popup =\n                popup.open(this.window, url, 'Schibsted account', { width: 360, height: 570 });\n            if (this.popup) {\n                return this.popup;\n            }\n        }\n        this.window.location.href = url;\n        return null;\n    }\n\n    /**\n     * @async\n     * @summary Retrieve the sp_id (Varnish ID)\n     * @description This function calls {@link Identity#hasSession} internally and thus has the side\n     * effect that it might perform an auto-login on the user\n     * @return {Promise\u003cstring|null\u003e} - The sp_id string or null (if the server didn't return it)\n     */\n    async getSpId() {\n        try {\n            const user = await this.hasSession();\n            return user.sp_id || null;\n        } catch (_) {\n            return null;\n        }\n    }\n\n    /**\n     * @summary Logs the user out from the Identity platform\n     * @param {string} redirectUri - Where to redirect the browser after logging out of Schibsted\n     * account\n     * @return {void}\n     */\n    logout(redirectUri = this.redirectUri) {\n        this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);\n        this._maybeClearVarnishCookie();\n        this.emit('logout');\n        this.window.location.href = this.logoutUrl(redirectUri);\n    }\n\n    /**\n     * Generates the link to the new login page that'll be used in the popup or redirect flow\n     * @param {LoginOptions} options\n     * @param {string} options.state\n     * @param {string} [options.acrValues]\n     * @param {string} [options.scope=openid]\n     * @param {string} [options.redirectUri]\n     * @param {string} [options.loginHint]\n     * @param {string} [options.tag]\n     * @param {string} [options.teaser]\n     * @param {number|string} [options.maxAge]\n     * @param {string} [options.locale]\n     * @param {boolean} [options.oneStepLogin=false]\n     * @param {string} [options.prompt=select_account]\n     * @param {string} [options.xDomainId]\n     * @param {string} [options.xEnvironmentId]\n     * @param {string} [options.originCampaign]\n     * @return {string} - The url\n     */\n    loginUrl({\n        state,\n        acrValues = '',\n        scope = 'openid',\n        redirectUri = this.redirectUri,\n        loginHint = '',\n        tag = '',\n        teaser = '',\n        maxAge = '',\n        locale = '',\n        oneStepLogin = false,\n        prompt = 'select_account',\n        xDomainId = '',\n        xEnvironmentId = '',\n        originCampaign = ''\n    }) {\n        if (typeof arguments[0] !== 'object') {\n            // backward compatibility\n            state = arguments[0];\n            acrValues = arguments[1];\n            scope = arguments[2] || scope;\n            redirectUri = arguments[3] || redirectUri;\n            loginHint = arguments[4] || loginHint;\n            tag = arguments[5] || tag;\n            teaser = arguments[6] || teaser;\n            maxAge = isNaN(arguments[7]) ? maxAge : arguments[7];\n        }\n        const isValidAcrValue = (acrValue) =\u003e isStrIn(acrValue, ['password', 'otp', 'sms', 'eid-dk', 'eid-no', 'eid-se', 'eid-fi', 'eid'], true);\n        assert(!acrValues || isStrIn(acrValues, ['', 'otp-email'], true) || acrValues.split(' ').every(isValidAcrValue),\n            `The acrValues parameter is not acceptable: ${acrValues}`);\n        assert(isUrl(redirectUri),\n            `loginUrl(): redirectUri must be a valid url but is ${redirectUri}`);\n        assert(isNonEmptyString(state),\n            `the state parameter should be a non empty string but it is ${state}`);\n\n        return this._oauthService.makeUrl('oauth/authorize', {\n            response_type: 'code',\n            redirect_uri: redirectUri,\n            scope,\n            state,\n            acr_values: acrValues,\n            login_hint: loginHint,\n            tag,\n            teaser,\n            max_age: maxAge,\n            locale,\n            one_step_login: oneStepLogin || '',\n            prompt: acrValues ? '' : prompt,\n            x_domain_id: xDomainId,\n            x_env_id: xEnvironmentId,\n            utm_campaign: originCampaign\n        });\n    }\n\n    /**\n     * The url for logging the user out\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} url\n     */\n    logoutUrl(redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `logoutUrl(): redirectUri is invalid`);\n        const params = { redirect_uri: redirectUri };\n        return this._sessionService.makeUrl('logout', params);\n    }\n\n    /**\n     * The account summary page url\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string}\n     */\n    accountUrl(redirectUri = this.redirectUri) {\n        return this._spid.makeUrl('profile-pages', {\n            response_type: 'code',\n            redirect_uri: redirectUri\n        });\n    }\n\n    /**\n     * The phone editing page url\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string}\n     */\n    phonesUrl(redirectUri = this.redirectUri) {\n        return this._spid.makeUrl('profile-pages/about-you/phone', {\n            response_type: 'code',\n            redirect_uri: redirectUri\n        });\n    }\n\n    /**\n     * Function responsible for loading and displaying simplified login widget. How often\n     * widget will be display is up to you. Preferred way would be to show it once per user,\n     * and store that info in localStorage. Widget will be display only if user is logged in to SSO.\n     *\n     * @async\n     * @param {SimplifiedLoginWidgetLoginOptions} loginParams - the same as `options` param for login function. Login will be called on user\n     * continue action. `state` might be string or async function.\n     * @param {SimplifiedLoginWidgetOptions} [options] - additional configuration of Simplified Login Widget\n     * @fires Identity#simplifiedLoginOpened\n     * @fires Identity#simplifiedLoginCancelled\n     * @return {Promise\u003cboolean|SDKError\u003e} - will resolve to true if widget will be display. Otherwise, will throw SDKError\n     */\n    async showSimplifiedLoginWidget(loginParams, options) {\n        // getUserContextData doesn't throw exception\n        const userData = await this.getUserContextData();\n\n        const queryParams = { client_id: this.clientId };\n        if (options \u0026\u0026 options.encoding) {\n            queryParams.encoding = options.encoding;\n        }\n        const widgetUrl = this._bffService.makeUrl('simplified-login-widget', queryParams, false);\n\n        const prepareLoginParams = async (loginPrams) =\u003e {\n            if (typeof loginPrams.state === 'function') {\n                loginPrams.state = await loginPrams.state();\n            }\n\n            return loginPrams;\n        }\n\n        return new Promise(\n            (resolve, reject) =\u003e {\n                if (!userData || !userData.display_text || !userData.identifier) {\n                    return reject(new SDKError('Missing user data'));\n                }\n\n                const initialParams = {\n                    displayText: userData.display_text,\n                    env: this.env,\n                    clientName: userData.client_name,\n                    clientId: this.clientId,\n                    providerId: userData.provider_id,\n                    windowWidth: () =\u003e window.innerWidth,\n                    windowOnResize: (f) =\u003e {\n                        window.onresize = f;\n                    },\n                };\n\n                if (options \u0026\u0026 options.locale) {\n                    initialParams.locale = options.locale;\n                }\n\n                const loginHandler = async () =\u003e {\n                    this.login(Object.assign(await prepareLoginParams(loginParams), {loginHint: userData.identifier}));\n                };\n\n                const loginNotYouHandler = async () =\u003e {\n                    this.login(Object.assign(await prepareLoginParams(loginParams), {loginHint: userData.identifier, prompt: 'login'}));\n                };\n\n                const initHandler = () =\u003e {\n                    /**\n                     * Emitted when the simplified login widget is displayed on the screen\n                     * @event Identity#simplifiedLoginOpened\n                     */\n                    this.emit('simplifiedLoginOpened');\n                }\n\n                const cancelLoginHandler = () =\u003e {\n                    /**\n                     * Emitted when the user closes the simplified login widget\n                     * @event Identity#simplifiedLoginCancelled\n                     */\n                    this.emit('simplifiedLoginCancelled');\n                }\n\n                if (window.openSimplifiedLoginWidget) {\n                    window.openSimplifiedLoginWidget(initialParams, loginHandler, loginNotYouHandler, initHandler, cancelLoginHandler);\n                    return resolve(true);\n                }\n\n                const simplifiedLoginWidget = document.createElement(\"script\");\n                simplifiedLoginWidget.type = \"text/javascript\";\n                simplifiedLoginWidget.src = widgetUrl;\n                simplifiedLoginWidget.onload = () =\u003e {\n                    window.openSimplifiedLoginWidget(initialParams, loginHandler, loginNotYouHandler, initHandler, cancelLoginHandler);\n                    resolve(true);\n                };\n                simplifiedLoginWidget.onerror = () =\u003e {\n                    reject(new SDKError('Error when loading simplified login widget content'));\n                };\n                document.getElementsByTagName('body')[0].appendChild(simplifiedLoginWidget);\n            });\n    }\n}\n\nexport default Identity;\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\nimport SDKError from './SDKError.js';\n\n/**\n * Check whether we are able to use web storage\n * @param {Storage} storeProvider - A function to return a WebStorage instance (either\n * `sessionStorage` or `localStorage` from a `Window` object)\n * @private\n * @returns {boolean}\n */\nfunction webStorageWorks(storeProvider) {\n    if (!storeProvider) {\n        return false;\n    }\n    try {\n        const store = storeProvider();\n        const randomKey = 'x-x-x-x'.replace(/x/g, () =\u003e Math.random());\n        const testValue = 'TEST-VALUE';\n        store.setItem(randomKey, testValue);\n        const val = store.getItem(randomKey);\n        store.removeItem(randomKey);\n        return (val === testValue);\n    } catch (e) {\n        return false;\n    }\n}\n\n/**\n * Will be used if web storage is available\n * @private\n */\nclass WebStorageCache {\n    /**\n     * Create web storage cache object\n     * @param {Storage} store - A reference to either `sessionStorage` or `localStorage` from a\n     * `Window` object\n     */\n    constructor(store) {\n        this.store = store;\n        this.get = (key) =\u003e this.store.getItem(key);\n        this.set = (key, value) =\u003e this.store.setItem(key, value);\n        this.delete = (key) =\u003e this.store.removeItem(key);\n    }\n}\n\n/**\n * Will be used if session storage is not available\n * @private\n */\nclass LiteralCache {\n    /**\n     * Create JS object literal cache object\n     */\n    constructor() {\n        this.store = {};\n        this.get = (key) =\u003e this.store[key];\n        this.set = (key, value) =\u003e this.store[key] = value;\n        this.delete = (key) =\u003e delete this.store[key];\n    }\n}\n\nconst maxExpiresIn = Math.pow(2, 31) - 1;\n\n/**\n * Cache class that attempts WebStorage (session/local storage), and falls back to JS object literal\n * @private\n */\nexport default class Cache {\n    /**\n     * @param {Storage} [storeProvider] - A function to return a WebStorage instance (either\n     * `sessionStorage` or `localStorage` from a `Window` object)\n     * @throws {SDKError} - If sessionStorage or localStorage are not accessible\n     */\n    constructor(storeProvider) {\n        if (webStorageWorks(storeProvider)) {\n            this.cache = new WebStorageCache(storeProvider());\n            this.type = 'WebStorage';\n        } else {\n            this.cache = new LiteralCache();\n            this.type = 'ObjectLiteralStorage';\n        }\n    }\n\n    /**\n     * Get a value from cache (checks that the object has not expired)\n     * @param {string} key\n     * @private\n     * @returns {*} - The value if it exists, otherwise null\n     */\n    get(key) {\n        /**\n         * JSON.parse safe wrapper\n         * @param {string} raw\n         * @returns {*} parsed value or null if failed to parse\n         */\n        function getObj(raw) {\n            try {\n                return JSON.parse(raw);\n            } catch (e) {\n                return null;\n            }\n        }\n\n        try {\n            const raw = this.cache.get(key);\n            let obj = getObj(raw);\n            if (obj \u0026\u0026 Number.isInteger(obj.expiresOn) \u0026\u0026 obj.expiresOn \u003e Date.now()) {\n                return obj.value;\n            }\n            this.delete(key);\n            return null;\n        } catch (e) {\n            throw new SDKError(e);\n        }\n    }\n\n    /**\n     * Set a cache entry\n     * @param {string} key\n     * @param {*} value\n     * @param {Number} expiresIn - Value in milliseconds until the entry expires\n     * @private\n     * @returns {void}\n     */\n    set(key, value, expiresIn = 0) {\n        if (expiresIn \u003c= 0) {\n            return;\n        }\n        expiresIn = Math.min(maxExpiresIn, expiresIn);\n\n        try {\n            const expiresOn = Math.floor(Date.now() + expiresIn);\n            this.cache.set(key, JSON.stringify({ expiresOn, value }));\n            setTimeout(() =\u003e this.delete(key), expiresIn);\n        } catch (e) {\n            throw new SDKError(e);\n        }\n    }\n\n    /**\n     * Delete a cache entry\n     * @param {string} key\n     * @private\n     * @returns {void}\n     */\n    delete(key) {\n        try {\n            this.cache.delete(key);\n        } catch (e) {\n            throw new SDKError(e);\n        }\n    }\n}\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\nimport { assert, isObject, isUrl, isFunction } from './validate.js';\nimport { cloneDefined } from './object.js';\n\n/**\n * Serializes an object to string.\n * @memberof core\n * @private\n * @param {object} obj - for example {a: 'b', c: 1}\n * @return {string} - for example 'a=b,c=1'\n */\nfunction serialize(obj) {\n    assert(isObject(obj), `Object must be an object but it is '${obj}'`);\n    return Object.keys(obj)\n        .map(key =\u003e `${key}=${obj[key]}`)\n        .join(',');\n}\n\nconst defaultWindowFeatures = {\n    scrollbars: 'yes',\n    location: 'yes',\n    status: 'no',\n    menubar: 'no',\n    toolbar: 'no',\n    resizable: 'yes'\n};\n\n/**\n * Opens a popup\n * @param {Window} parentWindow - A reference to the window that will open the popup\n * @param {string} url - The URL that the popup will open\n * @param {string} [windowName] - A name for the window\n * @param {object} [windowFeatures] - Window features for the popup (default ones are usually ok)\n * @returns {Window|null} - A reference to the popup window\n * @private\n */\nexport function open(parentWindow, url, windowName = '', windowFeatures = {}) {\n    assert(isObject(parentWindow), `window was supposed to be an object but it is ${parentWindow}`);\n    assert(isObject(parentWindow.screen),\n        `window should be a valid Window object but it lacks a 'screen' property`);\n    assert(isFunction(parentWindow.open),\n        `window should be a valid Window object but it lacks an 'open' function`);\n    assert(isUrl(url), 'Invalid URL for popup');\n\n    const { height, width } = parentWindow.screen;\n\n    let mergedFeatures = cloneDefined(defaultWindowFeatures, windowFeatures);\n    if (Number.isFinite(mergedFeatures.width) \u0026\u0026 Number.isFinite(width)) {\n        mergedFeatures.left = (width - mergedFeatures.width) / 2;\n    }\n    if (Number.isFinite(mergedFeatures.height) \u0026\u0026 Number.isFinite(height)) {\n        mergedFeatures.top = (height - mergedFeatures.height) / 2;\n    }\n    const features = serialize(mergedFeatures);\n    return parentWindow.open(url, windowName, features);\n}\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\nimport SDKError from './SDKError.js';\nimport { cloneDefined } from './object.js';\nimport { urlMapper } from './url.js';\nimport { assert, isObject, isFunction, isStr, isNonEmptyString } from './validate.js';\n\n/**\n * Converts a series of parameters of various types to a string that's suitable for logging.\n * @private\n * @param {Array.\u003c*\u003e} msg - a number of parameters from any type (including objects)\n * @return {string}\n */\nconst logString = (msg) =\u003e msg.map(m =\u003e isObject(m) ? JSON.stringify(m, null, 2) : m).join(' ');\n\n/**\n * Calls a log function passing a string\n * @private\n * @param {function} fn - the log function\n * @param {...*} msg - a series of message objects\n * @return {*} - The result of calling fn\n */\nconst logFn = (fn, ...msg) =\u003e (typeof fn === 'function') \u0026\u0026 fn(logString(msg));\n\n/**\n * Encode a string like URLSearchParams would do\n * @private\n * @param {string} str - The input\n * @returns {string} The encoded string\n */\nfunction encode(str) {\n    const replace = {\n        '!': '%21',\n        \"'\": '%27',\n        '(': '%28',\n        ')': '%29',\n        '~': '%7E',\n        '%20': '+',\n        '%00': '\\x00'\n    };\n    return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, match =\u003e replace[match]);\n}\n\nconst globalFetch = () =\u003e window.fetch \u0026\u0026 window.fetch.bind(window);\n\n/**\n * This class can be used for creating a wrapper around a server and all its endpoints.\n * Its functionality is extended by {@link JSONPClient}\n * Creates a client to a REST server. While useful stand-alone, it's also used for some other\n * types of client that change some functionalities.\n * @throws {SDKError} if any of options are invalid\n * @summary the simplest way to communicate to a REST endpoint without any\n *          special authentication\n * @memberof core\n * @private\n */\nexport class RESTClient {\n\n    /**\n     * @param {object} options\n     * @param {string} [options.serverUrl=PRE] - The URL to the server eg.\n     * https://login.schibsted.com or a URL key like 'DEV' in combination with {@link envDic}.\n     * @param {object} [options.envDic] - A dictionary that will be used for looking up\n     * {@link serverUrl} keys. If serverUrl is always a URL, you don't need this.\n     * @param {function} [options.fetch=window.fetch] - The fetch function to use. It can be native\n     * or a polyfill\n     * @param {function} [options.log] - A function that will be called with log messages about\n     * request and response\n     * @param {object} [options.defaultParams={}] - a set of parameters to add to every call custom.\n     *        As long as it supports the standard fetch API we're good.\n     */\n    constructor({ serverUrl = 'PRE', envDic, fetch = globalFetch(), log, defaultParams = {}}) {\n        assert(isObject(defaultParams), `defaultParams should be a non-null object`);\n\n        const mappedUrl = urlMapper(serverUrl, envDic);\n        const handledServerUrl = mappedUrl.endsWith('/') ? mappedUrl : `${mappedUrl}/`;\n        this.url = new URL(handledServerUrl);\n\n        this.defaultParams = defaultParams;\n\n        if (log) {\n            assert(isFunction(log), `log must be a function but it is ${log}`);\n            this.log = log;\n        }\n\n        if (fetch) {\n            assert(isFunction(fetch), 'Fetch should be a function');\n            this.fetch = fetch;\n        }\n    }\n\n    /**\n     * Makes the actual call to the server and deals with headers, data objects and the edge cases.\n     * Please note that this method expects the response to be in JSON format. However, it'll not\n     * parse the response if its code is not in the 200 range.\n     * @param {object} options - an obligatory options object\n     * @param {string} options.method - can be 'GET', 'POST', 'DELETE', etc. case sensitive.  To be\n     *        more specific, this can be one of the values that are passed to the `methods`\n     *        property of the constructor's `options` parameter.\n     * @param {string} options.pathname - the path to the endpoint like 'api/2/endpoint-name'\n     * @param {Object} [options.data={}] - data payload (depending on GET/DELETE or POST it may be a query\n     *        string or form body)\n     * @param {array} [options.headers] - fetch options headers\n     * @param {boolean} [options.useDefaultParams] - should we add the defaultParams to the query?\n     * @param {object} [options.fetchOptions] - fetch options\n     * @throws {SDKError} - if the call can't be made for whatever reason.\n     * @return {Promise\u003cobject\u003e} - A promise that will resolve to the call's response or reject if there\n     *         is an error before making the call or if the server returns a non-2xx error or\n     *         something that's not parsable as JSON.\n     */\n    async go({\n        method,\n        headers,\n        pathname,\n        data = {},\n        useDefaultParams = true,\n        fetchOptions = { method, credentials: 'include' }\n    }) {\n        assert(isFunction(this.fetch),\n            `Can't make a call. The reference to fetch is missing or not a function.`);\n        assert(isNonEmptyString(method), `Method must be a non empty string but it is \"${method}\"`);\n        assert(isNonEmptyString(pathname), `Pathname must be string but it is \"${pathname}\"`);\n        assert(isObject(data), `data must be a non-null object`);\n\n        fetchOptions.headers = isObject(headers) ? cloneDefined(headers) : {};\n        const fullUrl = this.makeUrl(pathname, data, useDefaultParams);\n\n        logFn(this.log, 'Request:', fetchOptions.method.toUpperCase(), fullUrl);\n        logFn(this.log, 'Request Headers:', fetchOptions.headers);\n        logFn(this.log, 'Request Body:', fetchOptions.body);\n        try {\n            const response = await this.fetch(fullUrl, fetchOptions);\n            logFn(this.log, 'Response Code:', response.status, response.statusText);\n            if (!response.ok) {\n                // status code not in range 200-299\n                throw new SDKError(response.statusText, { code: response.status });\n            }\n            const responseObject = await response.json();\n            logFn(this.log, 'Response Parsed:', responseObject);\n            return responseObject;\n        } catch (err) {\n            let msg = isStr(err) ? err : 'Unknown RESTClient error';\n            if (isObject(err) \u0026\u0026 isStr(err.message)) {\n                msg = err.message;\n            }\n            throw new SDKError(`Failed to '${method}' '${fullUrl}': '${msg}'`, err);\n        }\n    }\n\n    /**\n     * Creates a url that points to an endpoint in the server\n     * @param {string} [pathname=] - WHATWG pathname ie. 'api/2/endpoint-name'\n     * @param {object} [query={}] - WHATWG query. It's the data payload.\n     * @param {boolean} [useDefaultParams=true] - should we add the defaultParams to the query?\n     * @return {string} - the resulting url string ready to pass to fetch\n     */\n    makeUrl(pathname = '', query = {}, useDefaultParams = true) {\n        const handledPathname = pathname.startsWith('/') ? pathname.slice(1) : pathname;\n\n        const url = new URL(handledPathname, this.url);\n        url.search = RESTClient.search(query, useDefaultParams, this.defaultParams);\n        return url.href;\n    }\n\n    /**\n     * Make a GET request\n     * @param {string} pathname - WHATWG pathname ie. 'api/2/endpoint-name'\n     * @param {object} [data={}] - the data payload.\n     * @return {Promise}\n     */\n    get(pathname, data) {\n        return this.go({ method: 'get', pathname, data });\n    }\n\n    /**\n     * Construct query string for WHATWG urls\n     * @private\n     * @param {object} query - Object to generate query string from\n     * @param {boolean} useDefaultParams - Use defaultParams or not\n     * @param {object} defaultParams - Default params\n     * @returns {string} Query string\n     */\n    static search(query, useDefaultParams, defaultParams) {\n        const params = useDefaultParams ? cloneDefined(defaultParams, query) : cloneDefined(query);\n        return Object.keys(params).filter(p =\u003e params[p]!=='').map(p =\u003e `${encode(p)}=${encode(params[p])}`).join('\u0026');\n    }\n}\n\nexport default RESTClient;\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\n/**\n * A workaround for how Schibsted account handles JSONP calls in the browser\n * @private\n */\n\nimport { isFunction } from './validate.js';\n\n/**\n * This is a workaround for making the old SPiD/hassession on JSONP APIs compatible with more common\n * JSONP convention where the callback function is expected to exist in the global object.\n *\n * How does it work?\n * =================\n * The old SPiD JSONP APIs relied on SPiD.Talk.response(callbackName, data) but fetch-jsonp merely\n * calls window[callbackName](data) which is more common practice. This module simply acts as an\n * adapter to modernize the old mechanism until we support CORS. To see how the SPiD solution works,\n * try to run a simple JSONP request or debug it in netowrk tab. This module will be removed when\n * CORS is supported.\n * @memberof core\n * @param {object} global - a reference to the global object\n * @return {void}\n */\nexport function emulate(global) {\n    if (global.SPiD === null || typeof global.SPiD !== 'object') {\n        global.SPiD = {};\n    }\n    if (global.SPiD.Talk === null || typeof global.SPiD.Talk !== 'object') {\n        global.SPiD.Talk = {}\n    }\n    if (!isFunction(global.SPiD.Talk.response)) {\n        global.SPiD.Talk.response = (callbackName, data) =\u003e global[callbackName](data);\n    }\n}\n","// Automatically generated in 'npm version' by scripts/genversion.js\n\n'use strict'\nconst version = '5.2.6';\nexport default version;\n","\n/**\n * Registers a component as a property on the provided global object, if not already registered, and dispatches an event to notify listeners.\n * The event is dispatched on `document` and will have the name `$sch${componentClassName}:ready` and a `detail` property with the instance.\n *\n * @param {any} global typically `window`\n * @param {string} componentClassName the name of the component to register, 'identity', 'monetization' or 'payment'\n * @param {any} instance the instance of the component to register\n * @returns {void}\n */\nexport const registerGlobal = (global, componentClassName, instance) =\u003e {\n    const prefixedName = `sch${componentClassName}`;\n    if (!(global)[prefixedName]) {\n        (global)[prefixedName] = instance;\n    }\n    if (typeof global.dispatchEvent === 'function') {\n        global.dispatchEvent(new CustomEvent(`${prefixedName}:ready`, { detail: { instance } }));\n    }\n}\n\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\nimport { assert, isStr, isNonEmptyString, isUrl } from './validate.js';\nimport { urlMapper } from './url.js';\nimport { ENDPOINTS, NAMESPACE } from './config.js';\nimport EventEmitter from 'tiny-emitter';\nimport RESTClient from './RESTClient.js';\nimport Cache from './cache.js';\nimport * as spidTalk from './spidTalk.js';\nimport SDKError from './SDKError.js';\nimport version from './version.js';\nimport { registerGlobal } from './global-registry.js';\n\nconst globalWindow = () =\u003e window;\n\n/**\n * Provides features related to monetization\n */\nexport class Monetization extends EventEmitter {\n    /**\n     * @param {object} options\n     * @param {string} options.clientId - Mandatory client id\n     * @param {string} [options.redirectUri] - Redirect uri\n     * @param {string} options.sessionDomain - Example: \"https://id.site.com\"\n     * @param {string} [options.env=PRE] - Schibsted account environment: `PRE`, `PRO` or `PRO_NO`\n     * @param {object} [options.window]\n     * @throws {SDKError} - If any of options are invalid\n     */\n    constructor({ clientId, redirectUri, env = 'PRE', sessionDomain, window = globalWindow() }) {\n        super();\n        spidTalk.emulate(window);\n        // validate options\n        assert(isNonEmptyString(clientId), 'clientId parameter is required');\n\n        this.cache = new Cache(() =\u003e window \u0026\u0026 window.sessionStorage);\n        this.clientId = clientId;\n        this.env = env;\n        this.redirectUri = redirectUri;\n        this.pendingHasAccessRequests = {};\n        this._setSpidServerUrl(env);\n\n        if (sessionDomain) {\n            assert(isUrl(sessionDomain), 'sessionDomain parameter is not a valid URL');\n            this._setSessionServiceUrl(sessionDomain);\n        }\n        registerGlobal(window, 'Monetization', this);\n    }\n\n    /**\n     * Set SPiD server URL\n     * @private\n     * @param {string} url\n     * @returns {void}\n     */\n    _setSpidServerUrl(url) {\n        assert(isStr(url), `url parameter is invalid: ${url}`);\n        this._spid = new RESTClient({\n            serverUrl: urlMapper(url, ENDPOINTS.SPiD),\n            defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n        });\n    }\n\n    /**\n     * Set session-service domain\n     * @private\n     * @param {string} domain - real URL — (**not** 'PRE' style env key)\n     * @returns {void}\n     */\n    _setSessionServiceUrl(domain) {\n        assert(isStr(domain), `domain parameter is invalid: ${domain}`);\n        const client_sdrn = `sdrn:${NAMESPACE[this.env]}:client:${this.clientId}`;\n        this._sessionService = new RESTClient({\n            serverUrl: domain,\n            log: this.log,\n            defaultParams: { client_sdrn, redirect_uri: this.redirectUri, sdk_version: version  },\n        });\n    }\n\n    /**\n     * Checks if the user has access to a set of products or features.\n     * @param {array} productIds - which products/features to check\n     * @param {number} userId - id of currently logged in user\n     * @throws {SDKError} - If the input is incorrect, or a network call fails in any way\n     * (this will happen if, say, the user is not logged in)\n     * @returns {Object|null} The data object returned from Schibsted account (or `null` if the user\n     * doesn't have access to any of the given products/features)\n     */\n    async hasAccess(productIds, userId) {\n        if (!this._sessionService) {\n            throw new SDKError(`hasAccess can only be called if 'sessionDomain' is configured`);\n        }\n        if (!userId) {\n            throw new SDKError(`'userId' must be specified`);\n        }\n        if (!Array.isArray(productIds)) {\n            throw new SDKError(`'productIds' must be an array`);\n        }\n\n        const sortedIds = [...productIds].sort();\n        const cacheKey = this._accessCacheKey(sortedIds, userId);\n        let data = this.cache.get(cacheKey);\n        if (!data) {\n            if (!this.pendingHasAccessRequests[cacheKey]) {\n                this.pendingHasAccessRequests[cacheKey] = this._sessionService.get(`/hasAccess/${sortedIds.join(',')}`);\n            }\n            const promise = this.pendingHasAccessRequests[cacheKey];\n            try {\n                data = await promise;\n                const expiresSeconds = data.ttl;\n                this.cache.set(cacheKey, data, expiresSeconds * 1000);\n            } finally {\n                // If it rejects, we still want to clear the pending request\n                if (this.pendingHasAccessRequests[cacheKey] === promise) {\n                    delete this.pendingHasAccessRequests[cacheKey];\n                }\n            }\n        }\n\n        if (!data.entitled) {\n            return null;\n        }\n        this.emit('hasAccess', { ids: sortedIds, data });\n        return data;\n    }\n\n    /**\n     * Removes the cached access result.\n     * @param {array} productIds - which products/features to check\n     * @param {number} userId - id of currently logged in user\n     * @returns {void}\n     */\n    clearCachedAccessResult(productIds, userId) {\n        this.cache.delete(this._accessCacheKey(productIds, userId));\n    }\n\n    /**\n     * Compute \"has access\" cache key for the given product ids and user id.\n     * @param {array} productIds - which products/features to check\n     * @param {number} userId - id of currently logged in user\n     * @returns {string}\n     * @private\n     */\n    _accessCacheKey(productIds, userId) {\n        return `prd_${[...productIds].sort()}_${userId}`;\n    }\n\n    /**\n     * Get the url for the end user to review the subscriptions\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url to the subscriptions review page\n     */\n    subscriptionsUrl(redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `subscriptionsUrl(): redirectUri is invalid`);\n        return this._spid.makeUrl('account/subscriptions', { redirect_uri: redirectUri });\n    }\n\n    /**\n     * Get the url for the end user to review the products\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url to the products review page\n     */\n    productsUrl(redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `productsUrl(): redirectUri is invalid`);\n        return this._spid.makeUrl('account/products', { redirect_uri: redirectUri });\n    }\n}\n\nexport default Monetization;\n","/* Copyright 2024 Schibsted Products \u0026 Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\n'use strict';\n\nimport { assert, isNonEmptyString, isUrl, isStr } from './validate.js';\nimport { urlMapper } from './url.js';\nimport { ENDPOINTS } from './config.js';\nimport * as popup from './popup.js';\nimport RESTClient from './RESTClient.js';\nimport * as spidTalk from './spidTalk.js';\nimport { registerGlobal } from './global-registry.js';\n\nconst globalWindow = () =\u003e window;\n\n/**\n * Provides features related to payment\n */\nexport class Payment {\n    /**\n     * @param {object} options\n     * @param {string} options.clientId - Mandatory client id\n     * @param {string} [options.redirectUri] - Redirect uri\n     * @param {string} [options.env=PRE] - Schibsted account environment: `PRE`, `PRO` or `PRO_NO`\n     * @param {string} [options.publisher] - ZUORA publisher\n     * @param {object} [options.window]\n     *\n     * @throws {SDKError} - If any of options are invalid\n     */\n    constructor({ clientId, redirectUri, env = 'PRE', publisher, window = globalWindow() }) {\n        spidTalk.emulate(window);\n        assert(isNonEmptyString(clientId), 'clientId parameter is required');\n\n        this.clientId = clientId;\n        this.redirectUri = redirectUri;\n        this.window = window;\n        this.publisher = publisher;\n        this._setSpidServerUrl(env);\n        this._setBffServerUrl(env);\n        registerGlobal(window, 'Payment', this);\n    }\n\n    /**\n     * Set SPiD server URL\n     * @private\n     * @param {string} url - real URL or 'PRE' style key\n     * @returns {void}\n     */\n    _setSpidServerUrl(url) {\n        assert(isStr(url), `url parameter is invalid: ${url}`);\n        this._spid = new RESTClient({\n            serverUrl: urlMapper(url, ENDPOINTS.SPiD),\n            defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n        });\n    }\n\n    /**\n     * Set BFF server URL - real URL or 'PRE' style key\n     * @private\n     * @param {string} url\n     * @returns {void}\n     */\n    _setBffServerUrl(url) {\n        assert(isStr(url), `url parameter is invalid: ${url}`);\n        this._bff = new RESTClient({\n            serverUrl: urlMapper(url, ENDPOINTS.BFF),\n            defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n        });\n    }\n\n    /**\n     * Close this.popup if it exists and is open\n     * @private\n     * @returns {void}\n     */\n    _closePopup() {\n        if (this.popup) {\n            if (!this.popup.closed) {\n                this.popup.close();\n            }\n            this.popup = null;\n        }\n    }\n\n    /**\n     * Starts the flow for the paylink in a popup or current window\n     * @param {object} options\n     * @param {string} options.paylink - The paylink\n     * @param {boolean} [options.preferPopup=false] - Should we try to open a popup?\n     * @param {string} [options.redirectUri=this.redirectUri]\n     * @returns {Window|null} - Returns a reference to the popup window, or `null` if no popup was\n     * used\n     */\n    payWithPaylink({ paylink, preferPopup, redirectUri = this.redirectUri }) {\n        assert(isUrl(redirectUri), `payWithPaylink(): redirectUri is invalid`);\n        this._closePopup();\n        const url = this.purchasePaylinkUrl(paylink, redirectUri);\n        if (preferPopup) {\n            this.popup =\n                popup.open(this.window, url, 'Schibsted account', { width: 360, height: 570 });\n            if (this.popup) {\n                return this.popup;\n            }\n        }\n        this.window.location.href = url;\n        return null;\n    }\n\n    /**\n     * Get the url for the end user to review the purchase history\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url to the purchase history review page\n     */\n    purchaseHistoryUrl(redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `purchaseHistoryUrl(): redirectUri is invalid`);\n        return this._spid.makeUrl('account/purchasehistory', { redirect_uri: redirectUri });\n    }\n\n    /**\n     * Get the url for the end user to redeem a voucher code\n     * @param {string} voucherCode\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url\n     */\n    redeemUrl(voucherCode, redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `redeemUrl(): redirectUri is invalid`);\n        return this._spid.makeUrl('account/redeem', { voucher_code: voucherCode });\n    }\n\n    /**\n     * @deprecated https://github.com/schibsted/account-sdk-browser/issues/94\n     *\n     * Get the url for the paylink purchase\n     * @todo Check working-ness for BFF + SPiD\n     * @param {string} paylinkId\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url to the API endpoint\n     */\n    purchasePaylinkUrl(paylinkId, redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `purchasePaylinkUrl(): redirectUri is invalid`);\n        assert(isNonEmptyString(paylinkId), `purchasePaylinkUrl(): paylinkId is required`);\n        return this._bff.makeUrl('payment/purchase', {\n            paylink: paylinkId,\n            redirect_uri: redirectUri\n        });\n    }\n\n    /**\n     * Get the url for flow to purchase a product\n     * @param {string} productId\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url to the products review page\n     */\n    purchaseProductFlowUrl(productId, redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `purchaseProductUrl(): redirectUri is invalid`);\n        assert(isNonEmptyString(productId), `purchaseProductFlowUrl(): productId is required`);\n        return this._bff.makeUrl('flow/checkout', {\n            response_type: 'code',\n            flow: 'payment',\n            product_id: productId,\n            redirect_uri: redirectUri\n        });\n    }\n\n    /**\n     * Get the url for flow to purchase a product through a campaign and voucher code\n     * @todo Check working-ness for BFF + SPiD\n     * @param {string} campaignId\n     * @param {string} productId\n     * @param {string} [voucherCode]\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url to the products review page\n     */\n    purchaseCampaignFlowUrl(campaignId, productId, voucherCode, redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `purchaseCampaignFlowUrl(): redirectUri is invalid`);\n        assert(isNonEmptyString(campaignId), `purchaseCampaignFlowUrl(): campaignId is required`);\n        assert(isNonEmptyString(productId), `purchaseCampaignFlowUrl(): productId is required`);\n        return this._bff.makeUrl('flow/checkout', {\n            response_type: 'code',\n            flow: 'payment',\n            campaign_id: campaignId,\n            product_id: productId,\n            voucher_code: voucherCode,\n            redirect_uri: redirectUri\n        });\n    }\n\n    /**\n     * @deprecated\n     * Get the url for flow to purchase a promo code product with ZUORA\n     * @param {string} code - promocode product code\n     * @param {string} [state=''] - An opaque value used by the client to maintain state between\n     * the request and callback. It's also recommended to prevent CSRF\n     * @param {string} [redirectUri=this.redirectUri]\n     * @return {string} - The url to the buy promo code product flow\n     */\n    purchasePromoCodeProductFlowUrl(code, state = '', redirectUri = this.redirectUri) {\n        assert(isUrl(redirectUri), `purchasePromoCodeProductFlowUrl(): redirectUri is invalid`);\n        assert(isNonEmptyString(code), `purchasePromoCodeProductFlowUrl(): code is required`);\n        assert(isNonEmptyString(this.publisher), `purchasePromoCodeProductFlowUrl(): publisher is required in the constructor`);\n        return this._bff.makeUrl('payment/purchase/code', {\n            code,\n            publisher: this.publisher,\n            state,\n            redirect_uri: redirectUri\n        });\n    }\n}\n\nexport default Payment;\n"],"version":3}
