"use strict";
/**
 * @fileoverview Box API Client
 * @deprecated This BoxClient class and the entire manual/legacy sdk package is deprecated and will be removed in the future version.
 * It is recommended to use BoxClient from sdk-gen package instead.
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const bluebird_1 = require("bluebird");
// ------------------------------------------------------------------------------
// API Resource Managers
// ------------------------------------------------------------------------------
const ai_generated_1 = __importDefault(require("./managers/ai.generated"));
const collaboration_allowlist_1 = __importDefault(require("./managers/collaboration-allowlist"));
const collaborations_1 = __importDefault(require("./managers/collaborations"));
const collections_1 = __importDefault(require("./managers/collections"));
const comments_1 = __importDefault(require("./managers/comments"));
const device_pins_1 = __importDefault(require("./managers/device-pins"));
const enterprise_1 = __importDefault(require("./managers/enterprise"));
const events_1 = __importDefault(require("./managers/events"));
const files_1 = __importDefault(require("./managers/files"));
const folders_1 = __importDefault(require("./managers/folders"));
const groups_1 = __importDefault(require("./managers/groups"));
const legal_hold_policies_1 = __importDefault(require("./managers/legal-hold-policies"));
const metadata_1 = __importDefault(require("./managers/metadata"));
const recent_items_1 = __importDefault(require("./managers/recent-items"));
const retention_policies_1 = __importDefault(require("./managers/retention-policies"));
const search_1 = __importDefault(require("./managers/search"));
const shared_items_1 = __importDefault(require("./managers/shared-items"));
const sign_requests_generated_1 = __importDefault(require("./managers/sign-requests.generated"));
const sign_templates_generated_1 = __importDefault(require("./managers/sign-templates.generated"));
const storage_policies_1 = __importDefault(require("./managers/storage-policies"));
const tasks_1 = __importDefault(require("./managers/tasks"));
const terms_of_service_1 = __importDefault(require("./managers/terms-of-service"));
const trash_1 = __importDefault(require("./managers/trash"));
const users_1 = __importDefault(require("./managers/users"));
const web_links_1 = __importDefault(require("./managers/web-links"));
const webhooks_1 = __importDefault(require("./managers/webhooks"));
const file_requests_manager_1 = __importDefault(require("./managers/file-requests-manager"));
const shield_information_barriers_generated_1 = __importDefault(require("./managers/shield-information-barriers.generated"));
const shield_information_barrier_segments_generated_1 = __importDefault(require("./managers/shield-information-barrier-segments.generated"));
const shield_information_barrier_segment_members_generated_1 = __importDefault(require("./managers/shield-information-barrier-segment-members.generated"));
const shield_information_barrier_segment_restrictions_generated_1 = __importDefault(require("./managers/shield-information-barrier-segment-restrictions.generated"));
const shield_information_barrier_reports_generated_1 = __importDefault(require("./managers/shield-information-barrier-reports.generated"));
const integration_mappings_1 = __importDefault(require("./managers/integration-mappings"));
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const util_1 = __importDefault(require("util"));
const errors_1 = __importDefault(require("./util/errors"));
const httpStatusCodes = require('http-status');
const net_1 = require("net");
const merge_options_1 = __importDefault(require("merge-options"));
const paging_iterator_1 = __importDefault(require("./util/paging-iterator"));
const pkg = require('../package.json');
// ------------------------------------------------------------------------------
// SDK-Gen Imports (for getAuthentication, getNetworkSession, getSdkGenClient)
// ------------------------------------------------------------------------------
const developerTokenAuth_1 = require("./sdk-gen/box/developerTokenAuth");
const oauth_1 = require("./sdk-gen/box/oauth");
const jwtAuth_1 = require("./sdk-gen/box/jwtAuth");
const ccgAuth_1 = require("./sdk-gen/box/ccgAuth");
const tokenStorage_1 = require("./sdk-gen/box/tokenStorage");
const token_storage_adapter_1 = require("./util/token-storage-adapter");
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 ccg_session_1 = __importDefault(require("./sessions/ccg-session"));
const network_1 = require("./sdk-gen/networking/network");
const baseUrls_1 = require("./sdk-gen/networking/baseUrls");
const retries_1 = require("./sdk-gen/networking/retries");
const boxNetworkClient_1 = require("./sdk-gen/networking/boxNetworkClient");
const logging_1 = require("./sdk-gen/internal/logging");
const utils_1 = require("./sdk-gen/internal/utils");
const client_1 = require("./sdk-gen/client");
// ------------------------------------------------------------------------------
// Private
// ------------------------------------------------------------------------------
// The Authorization header label
var HEADER_AUTHORIZATION = 'Authorization', 
// Prefix our token with this string in the Authorization header
HEADER_AUTHORIZATION_PREFIX = 'Bearer ', 
// The 'BoxApi' header label
HEADER_BOXAPI = 'BoxApi', 
// The XFF header label - Used to give the API better information for uploads, rate-limiting, etc.
HEADER_XFF = 'X-Forwarded-For', 
// As-User header
HEADER_AS_USER = 'As-User', 
// Range of SUCCESS http status codes
HTTP_STATUS_CODE_SUCCESS_BLOCK_RANGE = [200, 299];
/**
 * Build the 'Authorization' Header for the API
 *
 * @param {string} accessToken An OAuth Access Token
 * @returns {string} A properly formatted 'Authorization' header
 * @private
 */
function buildAuthorizationHeader(accessToken) {
    return HEADER_AUTHORIZATION_PREFIX + accessToken;
}
/**
 * Returns true iff the response is a 401 UNAUTHORIZED that is caused by an expired access token.
 * @param {APIRequest~ResponseObject} response - The response returned by an APIRequestManager request
 * @returns {boolean} - true iff the response is a 401 UNAUTHORIZED caused by an expired access token
 * @private
 */
function isUnauthorizedDueToExpiredAccessToken(response /* FIXME */) {
    // There are three cases to consider:
    // 1) The response body is a Buffer. This indicates that the request was malformed (i.e. malformed url) so return false.
    // 2) The status code is UNAUTHORIZED and the response body is an empty object or null. This indicates that the access tokens are expired, so return true.
    // 3) The status code is UNAUTHORIZED and the response body is a non-empty object. This indicates that the 401 was returned for some reason other
    //    than expired tokens, so return false.
    if (Buffer.isBuffer(response.body)) {
        return false;
    }
    var isResponseStatusCodeUnauthorized = response.statusCode === httpStatusCodes.UNAUTHORIZED, isResponseBodyEmpty = !response.body || Object.getOwnPropertyNames(response.body).length === 0;
    return isResponseStatusCodeUnauthorized && isResponseBodyEmpty;
}
/**
 * Returns a full URL. If the url argument begins with http:// or https://, then url is simply returned.
 * Otherwise, the defaultBasePath is prepended to url and returned.
 *
 * @param {string} defaultBasePath The default root URL that will be prepended if `url` is a partial url
 * @param {string} url A full or partial URL that will be used to construct the final URL
 * @returns {string} The final URL
 * @private
 */
function getFullURL(defaultBasePath, url) {
    if (/^https?:\/\//.test(url)) {
        return url;
    }
    return defaultBasePath + url;
}
/**
 * Construct the X-Box-UA header to send analytics identifiers
 * @param {Object} [client] Analytics client information
 * @returns {string} The header value
 */
function constructBoxUAHeader(client /* FIXME */) {
    var analyticsIdentifiers = {
        agent: `box-node-sdk/${pkg.version}`,
        env: `Node/${process.version.replace('v', '')}`,
    };
    if (client) {
        analyticsIdentifiers.client = `${client.name}/${client.version}`;
    }
    return Object.keys(analyticsIdentifiers)
        .map((k) => `${k}=${analyticsIdentifiers[k]}`)
        .join('; ');
}
/**
 * @deprecated This BoxClient class and the entire manual/legacy SDK package is deprecated and will be removed in the future version.
 * It is recommended to use BoxClient from sdk-gen package instead.
 */
class BoxClient {
    /**
     * The BoxClient can make API calls on behalf of a valid API Session. It is responsible
     * for formatting the requests and handling the response. Its goal is to deliver
     * sensible results to the user.
     *
     * @param {APISession} apiSession An initialized API Session, used to get/revoke tokens and handle
     * unauthorized responses from the API.
     * @param {Config} config The SDK configuration options
     * @param {APIRequestManager} requestManager The API Request Manager
     * @constructor
     */
    constructor(apiSession, config /* FIXME */, requestManager) {
        // Runtime deprecation warning
        process.emitWarning('DEPRECATION WARNING: This BoxClient class and the entire manual/legacy SDK package is deprecated and will be removed in the future version. ' +
            'Please use the new BoxClient from "box-node-sdk/sdk-gen/client" instead. ');
        // the API Session used by the client for authentication
        this._session = apiSession;
        // Attach a request manager instance for making requests
        this._requestManager = requestManager;
        // An object of custom headers to apply to every request. Modified via BoxClient.setCustomHeader().
        this._customHeaders = {};
        // Attach the configured properties
        this._baseURL = util_1.default.format('%s/%s', config.apiRootURL, config.apiVersion);
        this._uploadBaseURL = util_1.default.format('%s/%s', config.uploadAPIRootURL, config.apiVersion);
        this._uploadRequestTimeoutMS = config.uploadRequestTimeoutMS;
        this._useIterators = config.iterators;
        this._analyticsClient = config.analyticsClient;
        // Attach API Resource Managers
        this.ai = new ai_generated_1.default(this);
        this.users = new users_1.default(this);
        this.files = new files_1.default(this);
        this.fileRequests = new file_requests_manager_1.default(this);
        this.folders = new folders_1.default(this);
        this.comments = new comments_1.default(this);
        this.collaborations = new collaborations_1.default(this);
        this.groups = new groups_1.default(this);
        this.sharedItems = new shared_items_1.default(this);
        this.metadata = new metadata_1.default(this);
        this.collections = new collections_1.default(this);
        this.events = new events_1.default(this);
        this.search = new search_1.default(this);
        this.tasks = new tasks_1.default(this);
        this.trash = new trash_1.default(this);
        this.enterprise = new enterprise_1.default(this);
        this.legalHoldPolicies = new legal_hold_policies_1.default(this);
        this.weblinks = new web_links_1.default(this);
        this.retentionPolicies = new retention_policies_1.default(this);
        this.devicePins = new device_pins_1.default(this);
        this.webhooks = new webhooks_1.default(this);
        this.recentItems = new recent_items_1.default(this);
        this.collaborationAllowlist = new collaboration_allowlist_1.default(this);
        this.termsOfService = new terms_of_service_1.default(this);
        this.storagePolicies = new storage_policies_1.default(this);
        this.signRequests = new sign_requests_generated_1.default(this);
        this.signTemplates = new sign_templates_generated_1.default(this);
        this.shieldInformationBarriers = new shield_information_barriers_generated_1.default(this);
        this.shieldInformationBarrierSegments =
            new shield_information_barrier_segments_generated_1.default(this);
        this.shieldInformationBarrierSegmentMembers =
            new shield_information_barrier_segment_members_generated_1.default(this);
        this.shieldInformationBarrierSegmentRestrictions =
            new shield_information_barrier_segment_restrictions_generated_1.default(this);
        this.shieldInformationBarrierReports = new shield_information_barrier_reports_generated_1.default(this);
        this.integrationMappings = new integration_mappings_1.default(this);
    }
    /**
     * Returns an object containing the given headers as well as other headers (like the authorization header and
     * custom headers) that should be included in a request.
     * @param {?Object} callerHeaders - headers that the caller wishes to include in the request. This method will not
     * override these headers with its own. Thus, if all the headers that this method was planning to add are already
     * specified here, this method will return an object with exactly the same headers.
     * @param {string} accessToken - the access token that will be used to make the request
     * @returns {Object} - a new object with the headers needed for the request
     * @private
     */
    _createHeadersForRequest(callerHeaders, accessToken) {
        var headers = {};
        // 'Authorization' - contains your valid access token for authorization
        headers[HEADER_AUTHORIZATION] = buildAuthorizationHeader(accessToken);
        // We copy our own custom headers (XFF, BoxApi, etc.) before copying over the caller-specified headers so that
        // the caller-specified headers will take precedence.
        Object.assign(headers, this._customHeaders, callerHeaders);
        // Add analytics headers last so they cannot be overwritten
        Object.assign(headers, {
            'X-Box-UA': constructBoxUAHeader(this._analyticsClient),
        });
        return headers;
    }
    /**
     * Makes an API request to the Box API on behalf of the client. Before executing
     * the request, it first ensures the user has usable tokens. Will be called again
     * if the request returns a temporary error. Will propogate error if request returns
     * a permanent error, or if usable tokens are not available.
     *
     * @param {Object} params - Request lib params to configure the request
     * @param {Function} [callback] - passed response data
     * @returns {Promise} Promise resolving to the response
     * @private
     */
    _makeRequest(params /* FIXME */, callback) {
        var promise = this._session
            .getAccessToken(this._tokenOptions)
            .then((accessToken) => {
            params.headers = this._createHeadersForRequest(params.headers, accessToken);
            if (params.streaming) {
                // streaming is specific to the SDK, so delete it from params before continuing
                delete params.streaming;
                var responseStream = this._requestManager.makeStreamingRequest(params);
                // Listen to 'response' event, so we can cleanup the token store in case when the request is unauthorized
                // due to expired access token
                responseStream.on('response', (response /* FIXME */) => {
                    if (isUnauthorizedDueToExpiredAccessToken(response)) {
                        var expiredTokensError = errors_1.default.buildAuthError(response);
                        // Give the session a chance to handle the error (ex: a persistent session will clear the token store)
                        if (this._session.handleExpiredTokensError) {
                            this._session.handleExpiredTokensError(expiredTokensError);
                        }
                    }
                });
                return responseStream;
            }
            // Make the request to Box, and perform standard response handling
            return this._requestManager.makeRequest(params);
        });
        return promise
            .then((response /* FIXME */) => {
            if (!response.statusCode) {
                // Response is not yet complete, and is just a stream that will return the response later
                // Just return the stream, since it doesn't need further response handling
                return response;
            }
            if (isUnauthorizedDueToExpiredAccessToken(response)) {
                var expiredTokensError = errors_1.default.buildAuthError(response);
                // Give the session a chance to handle the error (ex: a persistent session will clear the token store)
                if (this._session.handleExpiredTokensError) {
                    return this._session.handleExpiredTokensError(expiredTokensError);
                }
                throw expiredTokensError;
            }
            return response;
        })
            .asCallback(callback);
    }
    /**
     * Set a custom header. A custom header is applied to every request for the life of the client. To
     * remove a header, set it's value to null.
     *
     * @param {string} header The name of the custom header to set.
     * @param {*} value The value of the custom header. Set to null to remove the given header.
     * @returns {void}
     */
    setCustomHeader(header, value) {
        if (value) {
            this._customHeaders[header] = value;
        }
        else {
            delete this._customHeaders[header];
        }
    }
    /**
     * Sets the list of requesting IP addresses for the X-Forwarded-For header. Used to give the API
     * better information for uploads, rate-limiting, etc.
     *
     * @param {string[]} ips - Array of IP Addresses
     * @returns {void}
     */
    setIPs(ips) {
        var validIPs = ips.filter((ipString) => (0, net_1.isIP)(ipString)).join(', ');
        this.setCustomHeader(HEADER_XFF, validIPs);
        this._tokenOptions = { ip: validIPs };
    }
    /**
     * Sets the shared item context on the API Session. Overwrites any current context.
     *
     * @param {string} url The shared link url
     * @param {?string} password The shared link password, null if no password exists.
     * @returns {void}
     */
    setSharedContext(url, password) {
        var sharedContextAuthHeader = this.buildSharedItemAuthHeader(url, password);
        this.setCustomHeader(HEADER_BOXAPI, sharedContextAuthHeader);
    }
    /**
     * Removes any current shared item context from API Session.
     *
     * @returns {void}
     */
    revokeSharedContext() {
        this.setCustomHeader(HEADER_BOXAPI, null);
    }
    /**
     * Set up the As-User context, which is used by enterprise admins to
     * impersonate their managed users and perform actions on their behalf.
     *
     * @param {string} userID - The ID of the user to impersonate
     * @returns {void}
     */
    asUser(userID) {
        this.setCustomHeader(HEADER_AS_USER, userID);
    }
    /**
     * Revoke the As-User context and return to making calls on behalf of the user
     * who owns the client's access token.
     *
     * @returns {void}
     */
    asSelf() {
        this.setCustomHeader(HEADER_AS_USER, null);
    }
    /**
     * Revokes the client's access tokens. The client will no longer be tied to a user
     * and will be unable to make calls to the API, rendering it effectively useless.
     *
     * @param {Function} [callback] Called after revoking, with an error if one existed
     * @returns {Promise} A promise resolving when the client's access token is revoked
     */
    revokeTokens(callback) {
        return this._session.revokeTokens(this._tokenOptions).asCallback(callback);
    }
    /**
     * Exchange the client access token for one with lower scope
     * @param {string|string[]} scopes The scope(s) requested for the new token
     * @param {string} [resource] The absolute URL of an API resource to scope the new token to
     * @param {Object} [options] - Optional parameters
     * @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens with Token Auth client
     * @param {SharedLinkParams} [options.sharedLink] - Optional shared link parameters for creating tokens using shared links
     * @param {Function} [callback] Called with the new token
     * @returns {Promise<TokenInfo>} A promise resolving to the exchanged token info
     */
    exchangeToken(scopes, resource, options, callback) {
        // Shuffle optional parameters
        if (typeof options === 'function') {
            callback = options;
            options = {};
        }
        var opts = Object.assign({ tokenRequestOptions: this._tokenOptions || null }, options);
        return this._session
            .exchangeToken(scopes, resource, opts)
            .asCallback(callback);
    }
    /**
     * Makes GET request to Box API V2 endpoint
     *
     * @param {string} path - path to a certain API endpoint (ex: /file)
     * @param {?Object} params - object containing parameters for the request, such as query strings and headers
     * @param {Function} [callback] - passed final API response or err if request failed
     * @returns {void}
     */
    get(path, params, callback) {
        var newParams = (0, merge_options_1.default)({}, params || {});
        newParams.method = 'GET';
        newParams.url = getFullURL(this._baseURL, path);
        return this._makeRequest(newParams, callback);
    }
    /**
     * Makes POST request to Box API V2 endpoint
     *
     * @param {string} path - path to a certain API endpoint (ex: /file)
     * @param {?Object} params - object containing parameters for the request, such as query strings and headers
     * @param {Function} [callback] - passed final API response or err if request failed
     * @returns {void}
     */
    post(path, params, callback) {
        var newParams = (0, merge_options_1.default)({}, params || {});
        newParams.method = 'POST';
        newParams.url = getFullURL(this._baseURL, path);
        return this._makeRequest(newParams, callback);
    }
    /**
     * Makes PUT request to Box API V2 endpoint
     *
     * @param {string} path - path to a certain API endpoint (ex: /file)
     * @param {?Object} params - object containing parameters for the request, such as query strings and headers
     * @param {Function} callback - passed final API response or err if request failed
     * @returns {void}
     */
    put(path, params, callback) {
        var newParams = (0, merge_options_1.default)({}, params || {});
        newParams.method = 'PUT';
        newParams.url = getFullURL(this._baseURL, path);
        return this._makeRequest(newParams, callback);
    }
    /**
     * Makes DELETE request to Box API V2 endpoint
     *
     * @param {string} path - path to a certain API endpoint (ex: /file)
     * @param {?Object} params - object containing parameters for the request, such as query strings and headers
     * @param {Function} callback - passed final API response or err if request failed
     * @returns {void}
     */
    del(path, params, callback) {
        var newParams = (0, merge_options_1.default)({}, params || {});
        newParams.method = 'DELETE';
        newParams.url = getFullURL(this._baseURL, path);
        return this._makeRequest(newParams, callback);
    }
    /**
     * Makes an OPTIONS call to a Box API V2 endpoint
     *
     * @param {string} path - Path to an API endpoint (e.g. /files/content)
     * @param {?Object} params - An optional object containing request parameters
     * @param {Function} callback - Called with API call results, or err if call failed
     * @returns {void}
     */
    options(path, params, callback) {
        var newParams = (0, merge_options_1.default)({}, params || {});
        newParams.method = 'OPTIONS';
        newParams.url = getFullURL(this._baseURL, path);
        return this._makeRequest(newParams, callback);
    }
    /**
     * Makes a POST call to a Box API V2 upload endpoint
     * @param {string} path - path to an upload API endpoint
     * @param {?Object} params - an optional object containing request parameters
     * @param {?Object} formData - multipart form data to include in the upload request {@see https://github.com/mikeal/request#multipartform-data-multipart-form-uploads}
     * @param {Function} callback - called with API call results, or an error if the call failed
     * @returns {void}
     */
    upload(path, params, formData, callback) {
        var defaults = {
            method: 'POST',
        };
        var newParams = (0, merge_options_1.default)(defaults, params || {});
        newParams.url = getFullURL(this._uploadBaseURL, path);
        newParams.formData = formData;
        newParams.timeout = this._uploadRequestTimeoutMS;
        return this._makeRequest(newParams, callback);
    }
    /**
     * Build the 'BoxApi' Header used for authenticating access to a shared item
     *
     * @param {string} url The shared link url
     * @param {string} [password] The shared link password
     * @returns {string} A properly formatted 'BoxApi' header
     */
    buildSharedItemAuthHeader(url, password) {
        var encodedURL = encodeURIComponent(url), encodedPassword = encodeURIComponent(password !== null && password !== void 0 ? password : '');
        if (password) {
            return util_1.default.format('shared_link=%s&shared_link_password=%s', encodedURL, encodedPassword);
        }
        return util_1.default.format('shared_link=%s', encodedURL);
    }
    /**
     * Return a callback that properly handles a successful response code by passing the response
     * body to the original callback. Any request error or unsuccessful response codes are propagated
     * back to the callback as errors. This is the standard behavior of most endpoints.
     *
     * @param {Function} callback The original callback given by the consumer
     * @returns {?Function} A new callback that processes the response before passing it to the callback.
     */
    defaultResponseHandler(callback) {
        var self = this;
        if (!callback) {
            return null;
        }
        return function (err, response /* FIXME */) {
            // Error with Request
            if (err) {
                callback(err);
                return;
            }
            // Successful Response
            if (response.statusCode >= HTTP_STATUS_CODE_SUCCESS_BLOCK_RANGE[0] &&
                response.statusCode <= HTTP_STATUS_CODE_SUCCESS_BLOCK_RANGE[1]) {
                if (self._useIterators && paging_iterator_1.default.isIterable(response)) {
                    callback(null, new paging_iterator_1.default(response, self));
                    return;
                }
                callback(null, response.body);
                return;
            }
            // Unexpected Response
            callback(errors_1.default.buildUnexpectedResponseError(response));
        };
    }
    /**
     * Wrap a client method with the default handler for both callback and promise styles
     * @param {Function} method The client method (e.g. client.get)
     * @returns {Function}  The wrapped method
     */
    wrapWithDefaultHandler(method) {
        var self = this;
        return function wrappedClientMethod( /* arguments */) {
            // Check if the last argument is a callback
            var lastArg = arguments[arguments.length - 1], callback;
            if (typeof lastArg === 'function') {
                callback = self.defaultResponseHandler(lastArg);
                arguments[arguments.length - 1] = callback;
            }
            var ret = method.apply(self, arguments);
            if (ret instanceof bluebird_1.Promise) {
                ret = ret.then((response) => {
                    if (response.statusCode >= HTTP_STATUS_CODE_SUCCESS_BLOCK_RANGE[0] &&
                        response.statusCode <= HTTP_STATUS_CODE_SUCCESS_BLOCK_RANGE[1]) {
                        if (self._useIterators && paging_iterator_1.default.isIterable(response)) {
                            return new paging_iterator_1.default(response, self);
                        }
                        return response.body;
                    }
                    throw errors_1.default.buildUnexpectedResponseError(response);
                });
            }
            if (callback) {
                // If the callback will handle any errors, don't worry about the promise
                ret.suppressUnhandledRejections();
            }
            return ret;
        };
    }
    /**
     * Add a SDK plugin. Warning: This will modify the box-client interface and can override existing properties.
     * @param {string} name Plugin name. Will be accessible via client.<plugin-name>
     * @param {Function} plugin The SDK plugin to add
     * @param {Object} [options] Plugin-specific options
     * @returns {void}
     * @throws Will throw an error if plugin name matches an existing method on box-client
     */
    plug(name, plugin, options) {
        options = options || {};
        if (name in this && typeof this[name] === 'function') {
            throw new Error('You cannot define a plugin that overrides an existing method on the client');
        }
        // Create plugin and export plugin onto client.
        this[name] = plugin(this, options);
    }
    /**
     * Get an sdk-gen Authentication object configured with the current client's authentication settings.
     * This allows reusing authentication configuration between the legacy SDK and sdk-gen SDK.
     *
     * @param {Object} [options] Optional configuration
     * @param {TokenStorage} [options.tokenStorage] Optional custom token storage (sdk-gen format)
     * @returns {Authentication} A configured sdk-gen Authentication object
     * @throws {Error} If the authentication type cannot be determined or is not supported
     */
    getAuthentication(options) {
        var _a, _b, _c, _d, _e, _f;
        let tokenStorage = options === null || options === void 0 ? void 0 : options.tokenStorage;
        if (this._session instanceof basic_session_1.default) {
            if (!tokenStorage) {
                tokenStorage = new tokenStorage_1.InMemoryTokenStorage({
                    token: { accessToken: this._session._accessToken },
                });
            }
            return new developerTokenAuth_1.BoxDeveloperTokenAuth({
                token: this._session._accessToken,
                config: {
                    clientId: ((_b = (_a = this._session._tokenManager) === null || _a === void 0 ? void 0 : _a._config) === null || _b === void 0 ? void 0 : _b.clientID) || '',
                    clientSecret: ((_d = (_c = this._session._tokenManager) === null || _c === void 0 ? void 0 : _c._config) === null || _d === void 0 ? void 0 : _d.clientSecret) || '',
                },
            });
        }
        if (this._session instanceof persistent_session_1.default) {
            const session = this._session;
            if (!tokenStorage) {
                if (session._tokenStore) {
                    tokenStorage = (0, token_storage_adapter_1.wrapLegacyTokenStore)(session._tokenStore);
                }
                else {
                    const currentToken = (0, token_storage_adapter_1.convertLegacyTokenInfoToAccessToken)(session._tokenInfo);
                    tokenStorage = new tokenStorage_1.InMemoryTokenStorage({
                        token: currentToken,
                    });
                }
            }
            const config = new oauth_1.OAuthConfig({
                clientId: session._config.clientID,
                clientSecret: session._config.clientSecret,
                tokenStorage: tokenStorage,
            });
            return new oauth_1.BoxOAuth({ config });
        }
        if (this._session instanceof app_auth_session_1.default) {
            const session = this._session;
            const appAuthConfig = session._config.appAuth;
            if (!appAuthConfig) {
                throw new Error('AppAuth configuration not found. Cannot create Authentication object.');
            }
            if (!tokenStorage) {
                if (session._tokenStore) {
                    tokenStorage = (0, token_storage_adapter_1.wrapLegacyTokenStore)(session._tokenStore);
                }
                else {
                    const existingToken = session._tokenInfo
                        ? (0, token_storage_adapter_1.convertLegacyTokenInfoToAccessToken)(session._tokenInfo)
                        : undefined;
                    tokenStorage = new tokenStorage_1.InMemoryTokenStorage({
                        token: existingToken,
                    });
                }
            }
            const jwtConfig = new jwtAuth_1.JwtConfig({
                clientId: session._config.clientID,
                clientSecret: session._config.clientSecret,
                jwtKeyId: appAuthConfig.keyID,
                privateKey: appAuthConfig.privateKey,
                privateKeyPassphrase: appAuthConfig.passphrase,
                enterpriseId: session._type === 'enterprise' ? session._id : undefined,
                userId: session._type === 'user' ? session._id : undefined,
                tokenStorage: tokenStorage,
            });
            return new jwtAuth_1.BoxJwtAuth({ config: jwtConfig });
        }
        if (this._session instanceof ccg_session_1.default) {
            const session = this._session;
            if (!tokenStorage) {
                const existingToken = session._tokenInfo
                    ? (0, token_storage_adapter_1.convertLegacyTokenInfoToAccessToken)(session._tokenInfo)
                    : undefined;
                tokenStorage = new tokenStorage_1.InMemoryTokenStorage({
                    token: existingToken,
                });
            }
            const config = session._config;
            const ccgConfig = new ccgAuth_1.CcgConfig({
                clientId: config.clientID,
                clientSecret: config.clientSecret,
                enterpriseId: config.boxSubjectType === 'enterprise'
                    ? config.boxSubjectId
                    : undefined,
                userId: config.boxSubjectType === 'user' ? config.boxSubjectId : undefined,
                tokenStorage: tokenStorage,
            });
            return new ccgAuth_1.BoxCcgAuth({ config: ccgConfig });
        }
        // Unknown session type
        throw new Error(`Unknown session type. Cannot create Authentication object from ${((_f = (_e = this._session) === null || _e === void 0 ? void 0 : _e.constructor) === null || _f === void 0 ? void 0 : _f.name) || 'unknown session'}.`);
    }
    /**
     * Get an sdk-gen NetworkSession configured with the current SDK's network settings.
     * This allows reusing network configuration between the legacy SDK and sdk-gen SDK.
     * @param {Object} [options] Optional configuration for SDK-Gen-only properties
     * @param {NetworkClient} [options.networkClient] Custom network client
     * @param {RetryStrategy} [options.retryStrategy] Custom retry strategy
     * @param {DataSanitizer} [options.dataSanitizer] Custom data sanitizer
     * @param {Interceptor[]} [options.interceptors] Request interceptors
     * @param {Object} [options.additionalHeaders] Additional headers
     * @returns {NetworkSession} Configured NetworkSession for sdk-gen
     */
    getNetworkSession(options) {
        var _a, _b, _c;
        const session = this._session;
        const config = session._config || {};
        // Build BaseUrls from legacy config
        // Legacy authorizeRootURL is 'https://account.box.com/api'
        // SDK-Gen oauth2Url should be 'https://account.box.com/api/oauth2'
        let oauth2Url = 'https://account.box.com/api/oauth2';
        if (config.authorizeRootURL) {
            oauth2Url = config.authorizeRootURL.endsWith('/oauth2')
                ? config.authorizeRootURL
                : `${config.authorizeRootURL}/oauth2`;
        }
        const baseUrls = new baseUrls_1.BaseUrls({
            baseUrl: config.apiRootURL || 'https://api.box.com',
            uploadUrl: config.uploadAPIRootURL || 'https://upload.box.com/api',
            oauth2Url: oauth2Url,
        });
        let proxyConfig;
        if ((_a = config.proxy) === null || _a === void 0 ? void 0 : _a.url) {
            proxyConfig = {
                url: config.proxy.url,
                username: config.proxy.username || undefined,
                password: config.proxy.password || undefined,
            };
        }
        const legacyHeaders = ((_b = config.request) === null || _b === void 0 ? void 0 : _b.headers) || {};
        const additionalHeaders = Object.assign(Object.assign({}, legacyHeaders), ((options === null || options === void 0 ? void 0 : options.additionalHeaders) || {}));
        const retryStrategy = (options === null || options === void 0 ? void 0 : options.retryStrategy) ||
            new retries_1.BoxRetryStrategy({
                maxAttempts: config.numMaxRetries || 5,
                retryBaseInterval: (config.retryIntervalMS || 2000) / 1000,
            });
        const agentOptions = ((_c = config.request) === null || _c === void 0 ? void 0 : _c.agentOptions) || { keepAlive: true };
        return new network_1.NetworkSession({
            additionalHeaders: additionalHeaders,
            baseUrls: baseUrls,
            interceptors: (options === null || options === void 0 ? void 0 : options.interceptors) || [],
            agent: (0, utils_1.createAgent)(agentOptions, proxyConfig),
            agentOptions: agentOptions,
            proxyConfig: proxyConfig,
            networkClient: (options === null || options === void 0 ? void 0 : options.networkClient) || new boxNetworkClient_1.BoxNetworkClient({}),
            retryStrategy: retryStrategy,
            dataSanitizer: (options === null || options === void 0 ? void 0 : options.dataSanitizer) || new logging_1.DataSanitizer({}),
        });
    }
    /**
     * Get a fully configured sdk-gen BoxClient that shares authentication and
     * network settings with this legacy client.
     *
     * @param {Object} [options] Optional configuration
     * @param {Object} [options.authOptions] Options to pass to getAuthentication()
     * @param {TokenStorage} [options.authOptions.tokenStorage] Custom token storage
     * @param {Object} [options.networkOptions] Options to pass to getNetworkSession()
     * @param {NetworkClient} [options.networkOptions.networkClient] Custom network client
     * @param {RetryStrategy} [options.networkOptions.retryStrategy] Custom retry strategy
     * @param {DataSanitizer} [options.networkOptions.dataSanitizer] Custom data sanitizer
     * @param {Interceptor[]} [options.networkOptions.interceptors] Request interceptors
     * @param {Object} [options.networkOptions.additionalHeaders] Additional headers
     * @returns {BoxClient} A fully configured sdk-gen BoxClient
     */
    getSdkGenClient(options) {
        // Get authentication using getAuthentication() method
        const auth = this.getAuthentication(options === null || options === void 0 ? void 0 : options.authOptions);
        // Get network session using getNetworkSession() method
        const networkSession = this.getNetworkSession(options === null || options === void 0 ? void 0 : options.networkOptions);
        // Create and return the fully configured sdk-gen BoxClient
        return new client_1.BoxClient({
            auth: auth,
            networkSession: networkSession,
        });
    }
}
// ------------------------------------------------------------------------------
// Public
// ------------------------------------------------------------------------------
/**
 * Enum of valid collaboration roles
 *
 * @readonly
 * @enum {CollaborationRole}
 */
BoxClient.prototype.collaborationRoles = {
    EDITOR: 'editor',
    VIEWER: 'viewer',
    PREVIEWER: 'previewer',
    UPLOADER: 'uploader',
    PREVIEWER_UPLOADER: 'previewer uploader',
    VIEWER_UPLOADER: 'viewer uploader',
    CO_OWNER: 'co-owner',
    OWNER: 'owner',
};
/**
 * Enum of Box item types
 *
 * @readonly
 * @enum {ItemType}
 */
BoxClient.prototype.itemTypes = {
    FILE: 'file',
    FOLDER: 'folder',
};
/**
 * Enum of valid values for setting different access levels. To be used when
 * creating and editting shared links, upload emails, etc.
 *
 * @readonly
 * @type {AccessLevel}
 */
BoxClient.prototype.accessLevels = {
    OPEN: { access: 'open' },
    COLLABORATORS: { access: 'collaborators' },
    COMPANY: { access: 'company' },
    DEFAULT: {},
    DISABLED: null,
};
/** @const {string} */
BoxClient.prototype.CURRENT_USER_ID = users_1.default.prototype.CURRENT_USER_ID;
// ------------------------------------------------------------------------------
// Public
// ------------------------------------------------------------------------------
/**
 * @deprecated This module is deprecated. Please use box-node-sdk/sdk-gen/client instead.
 * @module box-node-sdk/lib/box-client
 * @see {@Link BoxClient}
 */
exports.default = BoxClient;
//# sourceMappingURL=box-client.js.map