Source: sdk.js

import Auth from "./managers/auth";
import Referral from "./managers/referral";
import SmartInvites from "./managers/smart-invites";
import SmartWidget from "./managers/widget";
import SmartBanner from "./managers/banner";
import SmartShare from "./managers/share";
import Analytics from "./managers/analytics";
import Http from "./http";
import {Storage} from "./storage";

export default class SDK {
    /**
     * Initialize the SDK.
     * @constructor SDK
     * @param {Object} config
     * @param {string} config.appId - GetSocial App ID
     */
    constructor(config) {
        this._config = config || {};
        this._baseUrl = this._config.baseUrl || SERVICE_URL;
        // Smart Invites service url.
        //
        // Smart Banners and Smart Widget work directly from SI,
        // they are not part of the HTTP API.
        this._siUrl = this._config.siUrl || SI_URL;
        this._http = Http;
        this._accessToken = "";
        this._appId = this._config.appId;

        // Store click ID, if any.
        let cid = SDK.getQueryParam("_gs_cid");
        if (cid !== "") {
            Storage.storeClickID(cid);
        }

        // Endpoints
        this._auth = new Auth(this);
        this._referral = new Referral(this);
        this._smartInvites = new SmartInvites(this);
        this._smartWidget = new SmartWidget(this);
        this._smartBanner = new SmartBanner(this);
        this._smartShare = new SmartShare(this);
        this._analytics = new Analytics(this);
    }

    /**
     * Makes an HTTP request to the given API path with the given options.
     *
     * @ignore
     * @param {string} path - Request URI, e.g <code>/authenticate/user</code>
     * @param {object} options - Request options like method, query params etc.
     * @return {Promise<Http>|undefined} - Promise of an XMLHttpRequest.
     */
    rawRequest(path, options) {
        options = options || {};
        options.method = options.method || "GET";

        let uri;
        try {
            uri = new URL(options.url || options.isSI ? `${this._siUrl}${path}` : `${this._baseUrl}${path}`);
        } catch (e) {
            console.log(e);
            return;
        }

        if (this._accessToken !== "") {
            options.accessToken = this._accessToken;
        }
        if (typeof options.queryParams === "object") {
            /** @var {Object} options.queryParams */
            for (let key in options.queryParams) {
                if (options.queryParams.hasOwnProperty(key)) {
                    uri.searchParams.set(key, options.queryParams[key]);
                }
            }
        }
        if (options.useAppId) {
            uri.searchParams.set("app_id", this._appId);
        }

        options.url = uri.toString();
        return this._http(options);
    }

    /**
     * Wrapper around rawRequest that automatically detects expired access tokens,
     * reauthenticates and repeats the original request.
     *
     * @ignore
     * @param {string} path - Request URI, e.g <code>/authenticate/user</code>
     * @param {object} options - Request options like method, query params etc.
     * @return Promise<Http> - Promise of an XMLHttpRequest.
     */
    authenticatedRequest(path, options) {
        const that = this;
        return new Promise((resolve, reject) => {
            that.rawRequest(path, options).then(function (resp) {
                resolve(resp);
            }).catch(function (resp) {
                if (resp.hasOwnProperty("code") && resp.code === 403) {
                    // Expired access token, reauthenticate.
                    const identity = Storage.getIdentity();
                    that.rawRequest("/authenticate/user", {
                        useAppId: true,
                        method: "POST",
                        queryParams: identity.getParams(),
                    }).then(/** @param {AuthResponse} resp*/ function (resp) {
                        if (resp.hasOwnProperty("access_token")) {
                            Storage.storeAuth(identity.getHash(), resp);
                            // Now that we have reauthenticated,
                            // make the original request again.
                            that.setAccessToken(resp.access_token);
                            return that.rawRequest(path, options);
                        }
                    }).catch(function (error) {
                        reject(error);
                    });
                } else {
                    reject(resp);
                }
            });
        });
    }

    /**
     * Returns the query string parameter with the given name, or an empty string.
     *
     * @ignore
     * @param {string} name - Name of the parameter
     * @return {string}
     */
    static getQueryParam(name) {
        name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
        const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
        const results = regex.exec(window.location.href);
        return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
    }

    /**
     * Sets the SDK access token to the given value.
     *
     * @ignore
     * @param {string} token
     */
    setAccessToken(token) {
        this._accessToken = token;
    }

    /**
     * Authentication endpoints.
     * @memberOf SDK
     * @type Auth
     */
    get auth() {
        return this._auth;
    }

    /**
     * Referral endpoints.
     * @memberOf SDK
     * @type Referral
     */
    get referral() {
        return this._referral;
    }

    /**
     * Deprecated: Use {@link smartInvites} instead.
     * @memberOf SDK
     * @type SmartInvites
     */
    get smartLinks() {
        return this._smartInvites;
    }

    /**
     * Smart Invites.
     * @memberOf SDK
     * @type SmartInvites
     */
    get smartInvites() {
        return this._smartInvites;
    }

    /**
     * Smart Widget.
     * @memberOf SDK
     * @type SmartWidget
     */
    get smartWidget() {
        return this._smartWidget;
    }

    /**
     * Smart Banner.
     * @memberOf SDK
     * @type SmartBanner
     */
    get smartBanner() {
        return this._smartBanner;
    }

    /**
     * Smart Share.
     * @memberOf SDK
     * @type SmartShare
     */
     get smartShare() {
        return this._smartShare;
    }

     /**
     * Analytics.
     * @memberOf SDK
     * @type Analytics
     */
    get analytics() {
        return this._analytics;
    }
};