UNPKG

forge-apis

Version:

⚠️ Deprecated: This package is no longer maintained. Use 'https://github.com/autodesk-platform-services/aps-sdk-node' instead.

519 lines (475 loc) 17.7 kB
/** * Forge SDK * The Forge Platform contains an expanding collection of web service components that can be used with Autodesk cloud-based products or your own technologies. Take advantage of Autodesk’s expertise in design and engineering. * * Contact: forge.help@autodesk.com * * NOTE: This class is auto generated by the swagger code generator program. * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*jshint esversion: 9 */ module.exports = (function () { 'use strict'; const axios = require('axios'); /** * @module ApiClient */ /** * Manages low level client-server communications, parameter marshalling, etc. There should not be any need for an * application to use this class directly - the *Api and model classes provide the public API for the service. The * contents of this file should be regarded as internal but are documented for completeness. * @alias module:ApiClient * @class */ const exports = function (basepath) { /** * The base URL against which to resolve every API call's (relative) path. * @type {String} * @default https://developer.api.autodesk.com */ this.basePath = (basepath || 'https://developer.api.autodesk.com').replace(/\/+$/, ''); /** * The default HTTP headers to be included for all API calls. * @type {Array.<String>} * @default {} */ this.defaultHeaders = {}; /** * The default HTTP timeout for all API calls. * @type {Number} * @default 60000 */ this.timeout = 60000; }; exports.prototype.switchServerPath = function (basepath) { if (basepath !== undefined) this.basePath = basepath.replace(/\/+$/, ''); }; /** * Returns a string representation for an actual parameter. * @param param The actual parameter. * @returns {String} The string representation of <code>param</code>. */ exports.prototype.paramToString = function (param) { if (param === undefined || param === null) { return (''); } if (param instanceof Date) { return (param.toJSON()); } return (param.toString()); }; /** * Builds full URL by appending the given path to the base URL and replacing path parameter place-holders with parameter values. * NOTE: query parameters are not handled here. * @param {String} path The path to append to the base URL. * @param {Object} pathParams The parameter values to append. * @returns {String} The encoded path with parameter values substituted. */ exports.prototype.buildUrl = function (path, pathParams) { const _this = this; if (!path.match(/^\//)) path = '/' + path; let url = (this.basePath + path).replace(/\{([\w-]+)}/g, function (fullMatch, key) { let value = fullMatch; if (pathParams.hasOwnProperty(key)) value = _this.paramToString(pathParams[key]); return (encodeURIComponent(value)); }); return (url); }; /** * Checks whether the given content type represents JSON.<br> * JSON content type examples:<br> * <ul> * <li>application/json</li> * <li>application/json; charset=UTF8</li> * <li>APPLICATION/JSON</li> * </ul> * @param {String} contentType The MIME content type to check. * @returns {Boolean} <code>true</code> if <code>contentType</code> represents JSON, otherwise <code>false</code>. */ exports.prototype.isJsonMime = function (contentType) { return (Boolean(contentType !== undefined && contentType !== null && contentType.match(/^application\/(vnd.api\+)?json(;.*)?$/i))); }; /** * Chooses a content type from the given array, with JSON preferred; i.e. return JSON if included, otherwise return the first. * @param {Array.<String>} contentTypes * @returns {String} The chosen content type, preferring JSON. */ exports.prototype.jsonPreferredMime = function (contentTypes) { for (let i = 0; i < contentTypes.length; i++) { if (this.isJsonMime(contentTypes[i])) return contentTypes[i]; } return (contentTypes[0]); }; /** * Checks whether the given parameter value represents file-like content. * @param param The parameter to check. * @returns {Boolean} <code>true</code> if <code>param</code> represents a file. */ exports.prototype.isFileParam = function (param) { const type = typeof param; if ((type === 'number') || (type === 'boolean') || (type === 'string') || (type === 'undefined')) { return false; } return (param instanceof require('fs').ReadStream) || (typeof Buffer === 'function' && param instanceof Buffer); }; /** * Normalizes parameter values: * <ul> * <li>remove nils</li> * <li>keep files and arrays</li> * <li>format to string with `paramToString` for other cases</li> * </ul> * @param {Object.<String, Object>} params The parameters as object properties. * @returns {Object.<String, Object>} normalized parameters. */ exports.prototype.normalizeParams = function (params) { const newParams = {}; for (const key in params) { if (params.hasOwnProperty(key) && params[key] !== undefined && params[key] !== null) { const value = params[key]; if (this.isFileParam(value) || Array.isArray(value)) { newParams[key] = value; } else { newParams[key] = this.paramToString(value); } } } return (newParams); }; /** * Enumeration of collection format separator strategies. * @enum {String} * @readonly */ exports.CollectionFormatEnum = { /** * Comma-separated values. Value: <code>csv</code> * @const */ CSV: ',', /** * Space-separated values. Value: <code>ssv</code> * @const */ SSV: ' ', /** * Tab-separated values. Value: <code>tsv</code> * @const */ TSV: '\t', /** * Pipe(|)-separated values. Value: <code>pipes</code> * @const */ PIPES: '|', /** * Native array. Value: <code>multi</code> * @const */ MULTI: 'multi' }; /** * Builds a string representation of an array-type actual parameter, according to the given collection format. * @param {Array} param An array parameter. * @param {module:ApiClient.CollectionFormatEnum} collectionFormat The array element separator strategy. * @returns {String|Array} A string representation of the supplied collection, using the specified delimiter. Returns * <code>param</code> as is if <code>collectionFormat</code> is <code>multi</code>. */ exports.prototype.buildCollectionParam = function buildCollectionParam(param, collectionFormat) { if (param === undefined || param === null) { return null; } switch (collectionFormat) { case 'csv': return param.map(this.paramToString).join(','); case 'ssv': return param.map(this.paramToString).join(' '); case 'tsv': return param.map(this.paramToString).join('\t'); case 'pipes': return param.map(this.paramToString).join('|'); case 'multi': // return the array directly return param.map(this.paramToString); default: throw new Error('Unknown collection format: ' + collectionFormat); } }; /** * Applies authentication header to the request. * @param {Object} requestParams - The requestParams object created by a <code>axios()</code> call. * @param {Object} headers - The headers that passed to this method * @param {Object} oauth2client - OAuth2 client that has a credentials object * @param {Object} credentials - The credentials object */ exports.prototype.applyAuthToRequest = function (requestParams, headers, oauth2client, credentials) { const _this = this; function setAuthHeader(credentials) { if (credentials && credentials.access_token) headers['Authorization'] = 'Bearer ' + credentials.access_token; // jshint ignore:line } return new Promise(function (resolve, reject) { // if the request doesn't require authentication, just resolve the promise if (!credentials || (credentials && !credentials.access_token)) return (resolve()); // let's see if the token is already expired? // be careful access tokens are validated once teh query was received by the server, not when emitted // for this reason, we need to aknowledge the time to upload payload/file/etc... (300 == 5min) if (oauth2client && oauth2client.autoRefresh && credentials.expires_at - 300000 <= Date.now()) { // set the correct promiseObj, for 2 or 3 legged token let isCredentialsTypeTwoLegged = credentials.refresh_token === undefined; const getCredentialsPromise = isCredentialsTypeTwoLegged ? oauth2client.authenticate() // 2-legged: create a new credentials object : oauth2client.refreshToken(credentials); // 3-legged: use refresh getCredentialsPromise.then(function (newCredentials) { _this.debug('credentials were refreshed, new credentials:', newCredentials); // For a 2-legged token just update the credentials object if (isCredentialsTypeTwoLegged) { oauth2client.setCredentials(newCredentials); } setAuthHeader(newCredentials); resolve(); }, function (err) { reject(err); }); } else { setAuthHeader(credentials); _this.debug('set current credentials to header', credentials); resolve(); } }); }; /** * Enable working in debug mode * To activate, simple set ForgeSdk.setDebug(true); */ exports.prototype.debug = function debug() { if (this.isDebugMode) { const args = Array.prototype.slice.call(arguments); console.log(...args); } }; exports.prototype.warn = function warn() { if (this.isDebugMode) { const args = Array.prototype.slice.call(arguments); console.warn(args); } }; exports.prototype.error = function error() { if (this.isDebugMode) { const args = Array.prototype.slice.call(arguments); console.error(['\x1b[31mError:', ...args, '\x1b[0m']); } }; /** * Is this obj a readable stream */ exports.isReadableStream = function (obj) { return (obj && typeof obj.pipe === 'function' && typeof obj._read === 'function' && typeof obj._readableState === 'object'); }; /** * Is this obj a writable stream */ exports.isWritableStream = function (obj) { return (obj && typeof obj.pipe === 'function' && typeof obj._write === 'function' && typeof obj._writableState === 'object'); }; /** * Invokes the REST service using the supplied settings and parameters. * @param {String} path The base URL to invoke. * @param {String} httpMethod The HTTP method to use. * @param {Object.<String, String>} pathParams A map of path parameters and their values. * @param {Object.<String, Object>} queryParams A map of query parameters and their values. * @param {Object.<String, Object>} headerParams A map of header parameters and their values. * @param {Object.<String, Object>} formParams A map of form parameters and their values. * @param {Object} bodyParam The value to pass as the request body. * @param {Array.<String>} contentTypes An array of request MIME types. * @param {Array.<String>} accepts An array of acceptable response MIME types. * @param {(String|Array|Object|Function)} returnType The required type to return; can be a string for simple types or the * constructor for a complex type. * @param {Object} oauth2client oauth2client for the call * @param {Object} credentials credentials for the call * @param {String} responseType The type of the response data * @returns {Object} A Promise object. */ exports.prototype.callApi = function callApi(path, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, returnType, oauth2client, credentials, responseType ) { const _this = this; const requestParams = {}; requestParams.uri = this.buildUrl(path, pathParams); requestParams.method = httpMethod; const headers = {}; requestParams.qs = this.normalizeParams(queryParams); requestParams.timeout = this.timeout; requestParams.responseType = responseType; const contentType = this.jsonPreferredMime(contentTypes); if (contentType) headers['Content-Type'] = contentType; if (contentType === 'application/x-www-form-urlencoded') { requestParams.form = this.normalizeParams(formParams); } else if (contentType === 'multipart/form-data') { requestParams.formData = this.normalizeParams(formParams); } else if (bodyParam) { requestParams.body = bodyParam; if (this.isJsonMime(contentType)) requestParams.json = true; } if (accepts.length > 0) { headers['Accept'] = accepts.join(','); // jshint ignore:line for (let i = 0; i < accepts.length; i++) { if (accepts[i] === 'application/octet-stream') requestParams.encoding = null; } } if (headerParams['Accept-Encoding'] === 'gzip, deflate') requestParams.encoding = null; headerParams['User-Agent'] = 'forge-apis/0.9.12 (nodejs)'; _this.debug('request params were', requestParams); return new Promise(function (resolve, reject) { _this.applyAuthToRequest(requestParams, headers, oauth2client, credentials).then(function () { // headerParams optional overrides requestParams.headers = Object.assign(headers, headerParams); requestParams.headers = Object.assign(requestParams.headers, _this.defaultHeaders); requestParams.agentOptions = { secureProtocol: 'TLSv1_2_method' // 'TLSv1.2' }; requestParams.headers && Object.keys(requestParams.headers).map((key) => { if (requestParams.headers[key] === undefined) delete requestParams.headers[key]; }); // jshint ignore:line axios({ method: requestParams.method, url: requestParams.uri, headers: requestParams.headers, params: requestParams.qs || {}, maxContentLength: Infinity, maxBodyLength: Infinity, data: requestParams.body, responseType: requestParams.responseType }) .then((response) => { if (response.statusCode >= 400) { _this.debug('error response', { statusCode: response.status || response.statusCode, statusMessage: response.statusText || response.statusMessage, headers: response.headers, }); reject({ statusCode: response.status || response.statusCode, statusMessage: response.statusText || response.statusMessage, headers: response.headers, statusBody: response.data, }); } else { resolve({ statusCode: response.status || response.statusCode, headers: response.headers, body: response.data, }); } }) .catch((err) => { err.statusCode = err.status; reject(err); }); }, function (err) { throw new Error(err.toString()); }); }); }; /** * Parses an ISO-8601 string representation of a date value. * @param {String} str The date value as a string. * @returns {Date} The parsed date object. */ exports.parseDate = function (str) { return (new Date(str.replace(/T/i, ' '))); }; /** * Converts a value to the specified type. * @param {(String|Object)} data The data to convert, as a string or object. * @param {(String|Array.<String>|Object.<String, Object>|Function)} type The type to return. Pass a string for simple types * or the constructor function for a complex type. Pass an array containing the type name to return an array of that type. To * return an object, pass an object with one property whose name is the key type and whose value is the corresponding value type: * all properties on <code>data<code> will be converted to this type. * @returns {Object} An instance of the specified type. */ exports.convertToType = function (data, type) { switch (type) { case 'Boolean': return (Boolean(data)); case 'Integer': return (parseInt(data, 10)); case 'Number': return (parseFloat(data)); case 'String': return (String(data)); case 'Date': return (this.parseDate(String(data))); default: if (type === Object) { // generic object, return directly return (data); } else if (typeof type === 'function') { // for model type like: User return (type.constructFromObject(data)); } else if (Array.isArray(type)) { // for array type like: ['String'] const itemType = type[0]; return (data.map(function (item) { return (exports.convertToType(item, itemType)); })); } else if (typeof type === 'object') { // for plain object type like: {'String': 'Integer'} let keyType, valueType; for (const k in type) { if (type.hasOwnProperty(k)) { keyType = k; valueType = type[k]; break; } } const result = {}; for (const j in data) { if (data.hasOwnProperty(j)) { const key = exports.convertToType(j, keyType); result[key] = exports.convertToType(data[j], valueType); } } return (result); } else { // for unknown type, return the data directly return (data); } } }; exports.version = '0.9.12'; exports.userAgentHeaders = { 'User-Agent': `forge-apis/${exports.version} nodejs api wrappers library`, }; /** * The default API client implementation. * @type {module:ApiClient} */ exports.instance = new exports(); return (exports); }());