"use strict";
/**
 * @fileoverview Box SDK for Node.js
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const events_1 = require("events");
const qs = __importStar(require("querystring"));
const ccg_session_1 = __importDefault(require("./sessions/ccg-session"));
const api_request_manager_1 = __importDefault(require("./api-request-manager"));
const box_client_1 = __importDefault(require("./box-client"));
const token_manager_1 = __importDefault(require("./token-manager"));
const config_1 = __importDefault(require("./util/config"));
const basic_session_1 = __importDefault(require("./sessions/basic-session"));
const persistent_session_1 = __importDefault(require("./sessions/persistent-session"));
const app_auth_session_1 = __importDefault(require("./sessions/app-auth-session"));
const webhooks_1 = __importDefault(require("./managers/webhooks"));
// ------------------------------------------------------------------------------
// Private
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
// Public
// ------------------------------------------------------------------------------
/**
 * A backend NodeJS SDK to interact with the Box V2 API.
 * This is the single entry point for all SDK consumer interactions. This is the only file that a 3rd party app
 * should require. All other components are private and reached out to via this component.
 * 1. Provides getters to spawn client instances for users to interact with the Box API.
 * 2. Provides manual capability to acquire tokens via token grant endpoints.
 *    However, it is recommended to use clients to do this for you.
 * 3. Emits notification events about relevant request/response events. Useful for logging Box API interactions.
 *    Notification events: request retries, exceeding max retries, permanent failures.
 *
 * @param {UserConfigurationOptions} params User settings used to initialize and customize the SDK
 * @constructor
 */
class BoxSDKNode extends events_1.EventEmitter {
    accessLevels;
    collaborationRoles;
    CURRENT_USER_ID;
    config;
    _eventBus;
    requestManager;
    tokenManager;
    ccgSession;
    /**
     * Expose the BoxClient property enumerations to the SDK as a whole. This allows
     * the consumer to access and use these values from anywhere in their application
     * (like a helper) by requiring the SDK, instead of needing to pass the client.
     */
    static accessLevels = BoxSDKNode.prototype.accessLevels;
    static collaborationRoles = BoxSDKNode.prototype.collaborationRoles;
    static CURRENT_USER_ID = BoxSDKNode.prototype.CURRENT_USER_ID;
    /**
     * Expose Webhooks.validateMessage() to the SDK as a whole. This allows
     * the consumer to call BoxSDK.validateWebhookMessage() by just requiring the SDK,
     * instead of needing to create a client (which is not needed to validate messages).
     */
    static validateWebhookMessage = webhooks_1.default.validateMessage;
    constructor(params) {
        super();
        const eventBus = new events_1.EventEmitter();
        const self = this;
        eventBus.on('response', function () {
            const args /* FIXME */ = [].slice.call(arguments);
            args.unshift('response');
            self.emit.apply(self, args);
        });
        // Setup the configuration with the given params
        this.config = new config_1.default(params);
        this._eventBus = eventBus;
        this._setup();
    }
    /**
     * Setup the SDK instance by instantiating necessary objects with current
     * configuration values.
     *
     * @returns {void}
     * @private
     */
    _setup() {
        // Instantiate the request manager
        this.requestManager = new api_request_manager_1.default(this.config, this._eventBus);
        // Initialize the rest of the SDK with the given configuration
        this.tokenManager = new token_manager_1.default(this.config, this.requestManager);
        this.ccgSession = new ccg_session_1.default(this.config, this.tokenManager);
    }
    /**
     * Gets the BoxSDKNode instance by passing boxAppSettings json downloaded from the developer console.
     *
     * @param {Object} appConfig boxAppSettings object retrieved from Dev Console.
     * @returns {BoxSDKNode} an instance that has been preconfigured with the values from the Dev Console
     */
    static getPreconfiguredInstance(appConfig /* FIXME */) {
        if (typeof appConfig.boxAppSettings !== 'object') {
            throw new TypeError('Configuration does not include boxAppSettings object.');
        }
        const boxAppSettings = appConfig.boxAppSettings;
        const webhooks = appConfig.webhooks;
        if (typeof webhooks === 'object') {
            webhooks_1.default.setSignatureKeys(webhooks.primaryKey, webhooks.secondaryKey);
        }
        const params = {};
        if (typeof boxAppSettings.clientID === 'string') {
            params.clientID = boxAppSettings.clientID;
        }
        if (typeof boxAppSettings.clientSecret === 'string') {
            params.clientSecret = boxAppSettings.clientSecret;
        }
        // Only try to assign app auth settings if they are present
        // Some configurations do not include them (but might include other info, e.g. webhooks)
        if (typeof boxAppSettings.appAuth === 'object' &&
            boxAppSettings.appAuth.publicKeyID) {
            params.appAuth = {
                keyID: boxAppSettings.appAuth.publicKeyID, // Assign publicKeyID to keyID
                privateKey: boxAppSettings.appAuth.privateKey,
            };
            const passphrase = boxAppSettings.appAuth.passphrase;
            if (typeof passphrase === 'string') {
                params.appAuth.passphrase = passphrase;
            }
        }
        if (typeof appConfig.enterpriseID === 'string') {
            params.enterpriseID = appConfig.enterpriseID;
        }
        return new BoxSDKNode(params);
    }
    /**
     * Updates the SDK configuration with new parameters.
     *
     * @param {UserConfigurationOptions} params User settings
     * @returns {void}
     */
    configure(params) {
        this.config = this.config.extend(params);
        this._setup();
    }
    /**
     * Returns a Box Client with a Basic API Session. The client is able to make requests on behalf of a user.
     * A basic session has no access to a user's refresh token. Because of this, once the session's tokens
     * expire the client cannot recover and a new session will need to be generated.
     *
     * @param {string} accessToken A user's Box API access token
     * @returns {BoxClient} Returns a new Box Client paired to a new BasicAPISession
     */
    getBasicClient(accessToken) {
        const apiSession = new basic_session_1.default(accessToken, this.tokenManager);
        return new box_client_1.default(apiSession, this.config, this.requestManager);
    }
    /**
     * Returns a Box Client with a Basic API Session. The client is able to make requests on behalf of a user.
     * A basic session has no access to a user's refresh token. Because of this, once the session's tokens
     * expire the client cannot recover and a new session will need to be generated.
     *
     * @param {string} accessToken A user's Box API access token
     * @returns {BoxClient} Returns a new Box Client paired to a new BasicAPISession
     */
    static getBasicClient(accessToken) {
        return new BoxSDKNode({
            clientID: '',
            clientSecret: '',
        }).getBasicClient(accessToken);
    }
    /**
     * Returns a Box Client with a persistent API session. A persistent API session helps manage the user's tokens,
     * and can refresh them automatically if the access token expires. If a central data-store is given, the session
     * can read & write tokens to it.
     *
     * NOTE: If tokenInfo or tokenStore are formatted incorrectly, this method will throw an error. If you
     * haven't explicitly created either of these objects or are otherwise not completly confident in their validity,
     * you should wrap your call to getPersistentClient in a try-catch to handle any potential errors.
     *
     * @param {TokenInfo} tokenInfo A tokenInfo object to use for authentication
     * @param {TokenStore} [tokenStore] An optional token store for reading/writing tokens to session
     * @returns {BoxClient} Returns a new Box Client paired to a new PersistentAPISession
     */
    getPersistentClient(tokenInfo /* FIXME */, tokenStore) {
        const apiSession = new persistent_session_1.default(tokenInfo, tokenStore, this.config, this.tokenManager);
        return new box_client_1.default(apiSession, this.config, this.requestManager);
    }
    /**
     * Returns a Box Client configured to use Client Credentials Grant for a service account. Requires enterprise ID
     * to be set when configuring SDK instance.
     *
     * @returns {BoxClient} Returns a new Box Client paired to a AnonymousAPISession. All Anonymous API Sessions share the
     * same tokens, which allows them to refresh them efficiently and reduce load on both the application and
     * the API.
     */
    getAnonymousClient() {
        if (!this.config.enterpriseID) {
            throw new Error('Enterprise ID must be passed');
        }
        return this._getCCGClient({
            boxSubjectType: 'enterprise',
            boxSubjectId: this.config.enterpriseID,
        });
    }
    /**
     * Returns a Box Client configured to use Client Credentials Grant for a specified user.
     *
     * @param userId the user ID to use when getting the access token
     * @returns {BoxClient} Returns a new Box Client paired to a AnonymousAPISession. All Anonymous API Sessions share the
     * same tokens, which allows them to refresh them efficiently and reduce load on both the application and
     * the API.
     */
    getCCGClientForUser(userId) {
        return this._getCCGClient({
            boxSubjectType: 'user',
            boxSubjectId: userId,
        });
    }
    _getCCGClient(config) {
        const anonymousTokenManager = new token_manager_1.default({
            ...this.config,
            ...config,
        }, this.requestManager);
        const newAnonymousSession = new ccg_session_1.default(this.config, anonymousTokenManager);
        return new box_client_1.default(newAnonymousSession, this.config, this.requestManager);
    }
    /**
     * Create a new client using App Auth for the given entity. This allows either
     * managing App Users (as the enterprise) or performing operations as the App
     * Users or Managed Users themselves (as a user).
     *
     * @param {string} type The type of entity to operate as, "enterprise" or "user"
     * @param {string} [id] (Optional) The Box ID of the entity to operate as
     * @param {TokenStore} [tokenStore] (Optional) the token store to use for caching tokens
     * @returns {BoxClient} A new client authorized as the app user or enterprise
     */
    getAppAuthClient(type, id, tokenStore) {
        if (type === 'enterprise' && !id) {
            if (this.config.enterpriseID) {
                id = this.config.enterpriseID;
            }
            else {
                throw new Error('Enterprise ID must be passed');
            }
        }
        const appAuthSession = new app_auth_session_1.default(type, id, this.config, this.tokenManager, tokenStore);
        return new box_client_1.default(appAuthSession, this.config, this.requestManager);
    }
    /**
     * Generate the URL for the authorize page to send users to for the first leg of
     * the OAuth2 flow.
     *
     * @param {Object} params The OAuth2 parameters
     * @returns {string} The authorize page URL
     */
    getAuthorizeURL(params) {
        params.client_id = this.config.clientID;
        return `${this.config.authorizeRootURL}/oauth2/authorize?${qs.stringify(params)}`;
    }
    /**
     * Acquires token info using an authorization code
     *
     * @param {string} authorizationCode - authorization code issued by Box
     * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant, null for default behavior
     * @param {Function} [callback] - passed a TokenInfo object if tokens were granted successfully
     * @returns {Promise<TokenInfo>} Promise resolving to the token info
     */
    getTokensAuthorizationCodeGrant(authorizationCode, options, callback) {
        return this.tokenManager
            .getTokensAuthorizationCodeGrant(authorizationCode, options /* FIXME */)
            .asCallback(callback);
    }
    /**
     * Refreshes the access and refresh tokens for a given refresh token.
     *
     * @param {string} refreshToken - A valid OAuth refresh token
     * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant, null for default behavior
     * @param {Function} [callback] - passed a TokenInfo object if tokens were granted successfully
     * @returns {Promise<TokenInfo>} Promise resolving to the token info
     */
    getTokensRefreshGrant(refreshToken, options, callback) {
        if (typeof options === 'function') {
            callback = options;
            options = null;
        }
        return this.tokenManager
            .getTokensRefreshGrant(refreshToken, options /* FIXME */)
            .asCallback(callback);
    }
    /**
     * Gets tokens for enterprise administration of app users
     * @param {string} enterpriseID The ID of the enterprise to generate a token for
     * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant, null for default behavior
     * @param {Function} [callback] Passed the tokens if successful
     * @returns {Promise<TokenInfo>} Promise resolving to the token info
     */
    getEnterpriseAppAuthTokens(enterpriseID, options, callback) {
        if (typeof options === 'function') {
            callback = options;
            options = null;
        }
        if (!enterpriseID) {
            if (this.config.enterpriseID) {
                enterpriseID = this.config.enterpriseID;
            }
            else {
                throw new Error('Enterprise id must be passed');
            }
        }
        return this.tokenManager
            .getTokensJWTGrant('enterprise', enterpriseID, options /* FIXME */)
            .asCallback(callback);
    }
    /**
     * Gets tokens for App Users via a JWT grant
     * @param {string} userID The ID of the App User to generate a token for
     * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant, null for default behavior
     * @param {Function} [callback] Passed the tokens if successful
     * @returns {Promise<TokentInfo>} Promise resolving to the token info
     */
    getAppUserTokens(userID, options, callback) {
        if (typeof options === 'function') {
            callback = options;
            options = null;
        }
        return this.tokenManager
            .getTokensJWTGrant('user', userID, options /* FIXME */)
            .asCallback(callback);
    }
    /**
     * Revokes a token pair associated with a given access or refresh token.
     *
     * @param {string} token - A valid access or refresh token to revoke
     * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant, null for default behavior
     * @param {Function} [callback] - If err, revoke failed. Otherwise, revoke succeeded.
     * @returns {Promise<TokenInfo>} Promise resolving to the token info
     */
    revokeTokens(token, options, callback) {
        if (typeof options === 'function') {
            callback = options;
            options = null;
        }
        return this.tokenManager
            .revokeTokens(token, options /* FIXME */)
            .asCallback(callback);
    }
}
/**
 * Expose the BoxClient property enumerations to the SDK as a whole. This allows
 * the consumer to access and use these values from anywhere in their application
 * (like a helper) by requiring the SDK, instead of needing to pass the client.
 */
BoxSDKNode.prototype.accessLevels = box_client_1.default.prototype.accessLevels;
BoxSDKNode.prototype.collaborationRoles =
    box_client_1.default.prototype.collaborationRoles;
BoxSDKNode.prototype.CURRENT_USER_ID = box_client_1.default.prototype.CURRENT_USER_ID;
/** @module box-node-sdk/lib/box-node-sdk */
exports.default = BoxSDKNode;
//# sourceMappingURL=box-node-sdk.js.map