UNPKG

@twec/node-suite

Version:

Generic functionality for connecting to NetSuite Web Services from Node

186 lines (163 loc) 5.82 kB
const path = require('path'); const fs = require('fs'); const util = require('util'); const debug = require('debug')('node-suite'); const soap = require('./soap'); const foldersUtils = require('./folders'); const readFile = util.promisify(fs.readFile); // const DEFAULT_SUITETALK_VERSION = 'v17_2'; // https://webservices.netsuite.com/wsdl/v2017_2_0/netsuite.wsdl const DEFAULT_VERSION = 'v2017_2'; class NetSuite { constructor(config, errorHandler) { const defaultConfig = { concurrency: 5, version: DEFAULT_VERSION, domain: '', passport: { account: '' }, oauth: { consumer: { key: '', secret: '' }, token: { key: '', secret: '' }, }, }; this.config = { ...defaultConfig, ...config }; this.handleError = errorHandler || ((error) => { throw error; }); } // ----- Error Handling handleResponseError(status) { const error = new Error('Unsuccessful response from NetSuite'); const detail = status.statusDetail; if (detail) { error.message = detail.message; error.code = detail.code; } this.handleError(error); } // ----- Helper methods static async readFileContent(filePath) { const file = await readFile(filePath); return file.toString('base64'); } // ---- Methods for getting NetSuite-specific Body Formats for SOAP Requests getUrnFileCabinet() { return `urn:filecabinet_${this.config.version}.documents.webservices.netsuite.com`; } static getRecordBody({ type, internalId, externalId }) { return { name: 'platformMsgs:recordRef', attributes: { 'xsi:type': 'platformCore:RecordRef', type, internalId, externalId, }, }; } static getUploadExternalId(filename, folderInternalId) { const now = (new Date()).getTime(); return `${filename}_${folderInternalId}_${now}`; } getUploadBody({ filename, fileContent, folderInternalId }) { // Based on https://gitlab.com/twec/digital/netsuite-upload-utils/blob/master/src/file-cabinet-client.ts#L295 return { name: 'platformMsgs:recordRef', attributes: { 'xmlns:q1': this.getUrnFileCabinet(), 'xsi:type': 'q1:File', internalId: '', externalId: NetSuite.getUploadExternalId(filename, folderInternalId), }, children: [ { name: 'q1:name', value: filename }, { name: 'q1:content', value: fileContent }, { name: 'q1:folder', attributes: { internalId: folderInternalId, type: 'folder', }, }, ], }; } getSearchFolderBody() { // Originally based on https://gitlab.com/twec/digital/netsuite-upload-utils/blob/master/src/file-cabinet-client.ts#L354 return { name: 'platformMsgs:search', attributes: { xmlns: this.getUrnFileCabinet(), 'xsi:type': 'FolderSearch', // FolderSearch - http://www.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2018_1/schema/search/foldersearch.html?mode=package }, }; } // ---- Make Requests async makeSoapRequest(operation, body) { debug('Making soap request - ', operation, 'using body:', body); try { return await soap({ config: this.config, operation, body }); } catch (err) { this.handleError(err); return err; } } checkStatusSuccess(status) { if (status && status['@isSuccess'] && status['@isSuccess'] !== 'true') { this.handleResponseError(status); } } async get({ type, internalId, externalId }) { const body = NetSuite.getRecordBody({ type, internalId, externalId }); const response = await this.makeSoapRequest('get', body); const { status, record } = (response || {}); this.checkStatusSuccess(status); return record; } async searchFolder(folderPath) { // Originally based on https://gitlab.com/twec/digital/netsuite-upload-utils/blob/master/src/file-cabinet-client.ts#L340 const folderPathArray = folderPath.split(path.sep); debug(folderPath, folderPathArray); const body = this.getSearchFolderBody(); debug('Searching for folder', folderPathArray); try { const response = await this.makeSoapRequest('search', body); const { status, recordList } = (response || {}); this.checkStatusSuccess(status); debug('response status:', status); const folderRecords = (recordList || {}).record || []; // debug(folderRecords); const folder = foldersUtils.findFolderRecord(folderPathArray, folderRecords); if (!folder) { this.handleError(new Error('Folder not found')); } return folder; } catch (err) { this.handleError(err); return err; } } async fetchFolderInternalId(targetFilePath) { const folderPath = path.dirname(targetFilePath); const folderRecord = await this.searchFolder(folderPath); debug(folderRecord); const folderInternalId = folderRecord['@internalId']; return folderInternalId; } async upload(localFilePath, targetFilePath) { // Upload a local file to netsuite debug('Upload', localFilePath, 'to', targetFilePath); const fileContent = await NetSuite.readFileContent(localFilePath); return this.uploadFileContent(fileContent, targetFilePath); } async uploadFileContent(fileContent, targetFilePath) { const folderInternalId = await this.fetchFolderInternalId(targetFilePath); const filename = path.basename(targetFilePath); const body = this.getUploadBody({ filename, folderInternalId, fileContent, }); const response = await this.makeSoapRequest('upsert', body); debug('Upload response:', response); const { status, baseRef } = (response || {}); this.checkStatusSuccess(status); return baseRef; } } module.exports = NetSuite;