ui5flowdev
Version:
UI5FlowDev enables you to manage and run your UI5 applications on a local server with reverse-proxy support. It also provides you the option to build your applications and deploy them to SAP NetWeaver ABAP.
1,154 lines (924 loc) • 38.7 kB
JavaScript
const logger = require('../utils/logger.js');
const jsonfile = require('jsonfile');
const path = require('path');
const slash = require('slash');
const uglify = require('uglify-js');
const pd = require('pretty-data').pd;
const maxmin = require('maxmin');
const fs = require('fs-extra');
const requestPromise = require('request-promise');
const request = require('request');
const xmldoc = require('xmldoc');
const isBinaryFile = require("isbinaryfile");
var Utils = {
writeFile: function(file, data, options) {
return new Promise(function(resolve, reject) {
try {
jsonfile.writeFile(file, data, options, function(err) {
if (err) {
logger.error('Error', err);
reject(err);
} else {
resolve();
}
});
} catch (ex) {
logger.error('Exception:', ex);
reject({
status: 'Error',
message: ex.toString()
});
}
});
},
adtSetConnection: function(adtConfig) {
return new Promise(function(resolve, reject) {
try {
var options = adtConfig;
if (!adtConfig.headers['x-csrf-token']) {
adtConfig.headers['x-csrf-token'] = 'Fetch';
}
request(adtConfig, function(error, response, body) {
if (!error && response.statusCode == 200) {
if (response.headers['x-csrf-token']) {
logger.debug('Token fetch successful.');
resolve(response);
}
} else {
if (response.statusCode == 404) {
logger.debug('Warning:', 'Resource not found');
reject('Resource not found');
}
logger.debug('Response with status code:', response.statusCode);
reject(error ? error.toString() : 'Connection creation failed.');
}
});
} catch (ex) {
logger.error('Exception:', ex);
reject({
status: 'Error',
message: ex.toString()
});
}
});
},
createBspApplication: function(adtConfig) {
return new Promise(function(resolve, reject) {
try {
if (!adtConfig) {
reject({
status: 'Error',
message: 'No request configuration provided.'
});
}
var adtCreateQuery = '?type=folder&isBinary=false' +
'&name=' + encodeURIComponent(adtConfig.bspProperties.bspApplication) +
'&description=' + encodeURIComponent(adtConfig.bspProperties.bspAppDescritpion) +
'&devclass=' + encodeURIComponent(adtConfig.bspProperties.bspAppPackage) +
'&corrNr=' + encodeURIComponent(adtConfig.bspProperties.bspTransport);
adtConfig.method = 'POST';
adtConfig.url = adtConfig.host + process.env.FILESTORE_OBJECTS_PATH + '/%20/content' + adtCreateQuery;
request(adtConfig, function(error, response, body) {
if (error) {
logger.error('Error:', error, response.body);
reject(error ? error.toString() : response.body);
}
if (response.statusCode == 200 || response.statusCode == 201) {
logger.debug('Application was created.');
resolve('Application was created.');
/*
Utils.updateApplicationVersionDeployemnt(adtConfig, serverConfig).then(
function(result) {
logger.debug('Application version updated.');
resolve(result);
},
function(error) {
reject('Application version deployment section update failed.');
}
);
*/
} else {
if (response.statusCode == 404) {
logger.error('Error:', 'Application not found');
reject('Application not found');
}
logger.error('Error:', error, response.body);
reject(error ? error.toString() : response.body);
}
});
} catch (ex) {
logger.error('Exception:', ex);
reject({
status: 'Error',
message: ex.toString()
});
}
});
},
bspApplicationIndexCalculation: function(adtConfig, serverConfig) {
return new Promise(function(resolve, reject) {
try {
adtConfig.method = 'POST';
adtConfig.url = adtConfig.host + process.env.FILESTORE_APPINDEX_PATH + '/' + encodeURIComponent(adtConfig.bspProperties.bspApplication);
logger.debug('Calculating application index for %s', adtConfig.bspProperties.bspApplication);
logger.debug('Requesting GET:', adtConfig.url);
request(adtConfig, function(error, response, body) {
if (error) {
logger.error('Error:', error);
reject(error ? error.toString() : error);
}
if (response.statusCode == 200 || response.statusCode == 201) {
logger.debug('Application index calculation for %s successful.', adtConfig.bspProperties.bspApplication);
//resolve('Application index calculation successful.');
Utils.updateApplicationVersionDeployemnt(adtConfig, serverConfig).then(
function(result) {
logger.debug('Application index calculation successful. Deployment finished.');
resolve('Application index calculation successful. Deployment finished.');
},
function(error) {
logger.error('Error:', error);
reject('Application version deployment section update failed.');
}
);
} else {
logger.error('Error:', response.body);
reject(response.body ? response.body : response);
}
});
} catch (ex) {
logger.error('Exception:', ex);
reject(ex.toString());
}
});
},
bspApplicationDeployResources: function(adtConfig, resourcesSync) {
return new Promise(function(resolve, reject) {
try {
if (resourcesSync.length) {
var resourcesSyncItem = resourcesSync.shift();
if (resourcesSyncItem.type === 'folder') {
if (resourcesSyncItem.syncMode === 'update') {
logger.debug('Updating folder %s', resourcesSyncItem.name);
// No action needed in case of fodler update
if (resourcesSync.length) {
Utils.bspApplicationDeployResources(adtConfig, resourcesSync).then(
function(resourcesSync) {
resolve(resourcesSync);
},
function(error) {
reject(error);
}
);
} else {
resolve(resourcesSync);
}
} else {
logger.debug('Deploying folder %s', resourcesSyncItem.name);
Utils.deployFolder(adtConfig, resourcesSyncItem).then(
function(result) {
if (resourcesSync.length) {
Utils.bspApplicationDeployResources(adtConfig, resourcesSync).then(
function(resourcesSync) {
resolve(resourcesSync);
},
function(error) {
reject(error);
}
);
} else {
resolve(result);
}
},
function(error) {
reject(error);
}
);
}
} else {
logger.debug('Deploying file %s', resourcesSyncItem.name);
Utils.deployFile(adtConfig, resourcesSyncItem).then(
function(result) {
if (resourcesSync.length) {
Utils.bspApplicationDeployResources(adtConfig, resourcesSync).then(
function(resourcesSync) {
resolve(resourcesSync);
},
function(error) {
reject(error);
}
);
} else {
resolve(result);
}
},
function(error) {
reject(error);
}
);
}
} else {
reject('No resources to be deployed found.')
}
} catch (ex) {
logger.error('Exception:', ex);
reject(ex.toString());
}
});
},
parseSyncId: function(id, separator = '%2f') {
const lastIndex = id.lastIndexOf(separator);
return {
path: id.substr(0, lastIndex),
filename: id.substr(lastIndex + separator.length),
};
},
deployFolder: function(adtConfig, syncData) {
return new Promise(function(resolve, reject) {
try {
var deployId = Utils.parseSyncId(syncData.id);
switch (syncData.syncMode) {
case 'create':
var adtCreateQuery = '?type=folder&isBinary=false' +
'&name=' + encodeURIComponent(deployId.filename) +
'&devclass=' + encodeURIComponent(adtConfig.bspProperties.bspAppPackage) +
'&corrNr=' + encodeURIComponent(adtConfig.bspProperties.bspTransport);
adtConfig.method = 'POST';
adtConfig.url = adtConfig.host + process.env.FILESTORE_OBJECTS_PATH + '/' + encodeURIComponent(deployId.path) + '/content' + adtCreateQuery;
break;
case 'update':
// No action needed in case of fodler update
break;
case 'delete':
var adtCreateQuery = '?deleteChildren=true&isBinary=false' +
'&corrNr=' + encodeURIComponent(adtConfig.bspProperties.bspTransport);
adtConfig.method = 'DELETE';
adtConfig.url = adtConfig.host + process.env.FILESTORE_OBJECTS_PATH + '/' + encodeURIComponent(syncData.id) + '/content' + adtCreateQuery;
adtConfig.headers['If-Match'] = '*';
break;
}
request(adtConfig, function(error, response, body) {
if (error) {
logger.error('Error:', error);
reject(error ? error.toString() : error);
}
if (response.statusCode == 200 || response.statusCode == 201) {
logger.debug('Resource %s was deployed.', deployId.filename);
resolve('Resource deployed.');
} else {
logger.error('Error:', response.body);
reject(response.body ? response.body : response);
}
});
} catch (ex) {
logger.error('Exception:', ex);
reject(ex.toString());
}
});
},
deployFile: function(adtConfig, syncData) {
return new Promise(function(resolve, reject) {
try {
isBinaryFile(syncData.name, function(error, fileBinary) {
var deployId = Utils.parseSyncId(syncData.id);
switch (syncData.syncMode) {
case 'create':
var adtCreateQuery = '?type=file&charset=UTF-8' +
'&isBinary=' + fileBinary +
'&name=' + encodeURIComponent(deployId.filename) +
'&devclass=' + encodeURIComponent(adtConfig.bspProperties.bspAppPackage) +
'&corrNr=' + encodeURIComponent(adtConfig.bspProperties.bspTransport);
adtConfig.method = 'POST';
adtConfig.url = adtConfig.host + process.env.FILESTORE_OBJECTS_PATH + '/' + encodeURIComponent(deployId.path) + '/content' + adtCreateQuery;
adtConfig.headers['Content-Type'] = 'application/octet-stream';
fs.readFile(syncData.name, function(error, data) {
// Handle empty buffer objects
if (!data) {
data = " ";
}
if (!data.length) {
data = " ";
}
adtConfig.body = data;
Utils.asyncRequest(adtConfig).then(
function(response) {
if (response.statusCode == 200 || response.statusCode == 201) {
logger.debug('Resource %s was deployed.', deployId.filename);
resolve('Resource deployed.');
} else {
logger.error('Error:', response.body);
reject(response.body);
}
},
function(error) {
logger.error('Error:', error);
reject(error ? error.toString() : error);
}
);
});
break;
case 'update':
var adtCreateQuery = '?charset=UTF-8' +
'&isBinary=' + fileBinary +
'&corrNr=' + encodeURIComponent(adtConfig.bspProperties.bspTransport);
adtConfig.method = 'PUT';
adtConfig.url = adtConfig.host + process.env.FILESTORE_OBJECTS_PATH + '/' + encodeURIComponent(syncData.id) + '/content' + adtCreateQuery;
adtConfig.headers['Content-Type'] = 'application/octet-stream';
adtConfig.headers['If-Match'] = '*';
fs.readFile(syncData.name, function(error, data) {
// Handle empty buffer objects
if (!data) {
data = " ";
}
if (!data.length) {
data = " ";
}
adtConfig.body = data;
Utils.asyncRequest(adtConfig).then(
function(response) {
if (response.statusCode == 200 || response.statusCode == 201) {
logger.debug('Resource was deployed.', deployId.filename);
resolve('Resource deployed.');
} else {
logger.error('Error:', response.body);
reject(response.body);
}
},
function(error) {
logger.error('Error:', error);
reject(error ? error.toString() : error);
}
);
});
break;
case 'delete':
var adtCreateQuery = '?corrNr=' + encodeURIComponent(adtConfig.bspProperties.bspTransport);
adtConfig.method = 'DELETE';
adtConfig.url = adtConfig.host + process.env.FILESTORE_OBJECTS_PATH + '/' + encodeURIComponent(syncData.id) + '/content' + adtCreateQuery;
adtConfig.headers['If-Match'] = '*';
logger.debug('Requesting DELETE:', adtConfig.url);
Utils.asyncRequest(adtConfig).then(
function(response) {
if (response.statusCode == 200 || response.statusCode == 201) {
logger.debug('Resource was deployed.', deployId.filename);
resolve('Resource deployed.');
} else {
logger.error('Error:', response.body);
reject(response.body);
}
},
function(error) {
logger.error('Error:', error);
reject(error ? error.toString() : error);
}
);
break;
}
});
} catch (ex) {
logger.error('Exception:', ex);
reject(ex.toString());
}
});
},
updateApplicationVersionDeployemnt: function(adtConfig, serverConfig) {
var appName = adtConfig.appName;
var versionId = adtConfig.versionId;
return new Promise(function(resolve, reject) {
try {
logger.debug('Updating application version:', versionId);
var file = serverConfig.appsData;
jsonfile.readFile(file, function(err, data) {
if (err) {
logger.error('Error', err);
reject(err ? err.toString() : 'File read error.');
}
var editData = {};
if (!data.applications) {
reject('No applications found.');
}
for (var i = 0, iLength = data.applications.length; i < iLength; i++) {
if (data.applications[i].name == appName) {
editData = data.applications[i];
break;
}
}
if (editData.versions) {
var deploymentInfo = {};
for (var j = 0, jLength = editData.versions.length; j < jLength; j++) {
if (editData.versions[j].version_directory == versionId) {
if (!editData.versions[j].deployments) {
editData.versions[j]['deployments'] = [];
}
var deployedAt = new Date().toISOString();
editData.versions[j]['last_deployment_info'] = {
systemDescription: adtConfig.systemDescription,
deployed_at: deployedAt
}
var systemUrl = adtConfig.systemUrl.replace(/\/+$/, '');
var bspAppUrl = adtConfig.bspUrlPattern.replace('{applicationServerUrl}', systemUrl).replace('{bspApplication}', adtConfig.bspProperties.bspApplication);
deploymentInfo = {
bspApplication: adtConfig.bspProperties.bspApplication,
bspAppDescritpion: adtConfig.bspProperties.bspAppDescritpion,
bspAppPackage: adtConfig.bspProperties.bspAppPackage,
bspTransport: adtConfig.bspProperties.bspTransport,
systemDescription: adtConfig.systemDescription,
systemUrl: systemUrl,
bspAppUrl: bspAppUrl,
deployed_at: deployedAt
};
editData.versions[j].deployments.push(deploymentInfo);
break;
}
}
jsonfile.writeFile(file, data, {
spaces: 2,
EOL: '\r\n'
}, function(err) {
if (err) {
logger.error('Error', err);
reject(err ? err.toString() : 'File write error.');
}
resolve(deploymentInfo);
});
} else {
reject('No versions found.');
}
});
} catch (ex) {
logger.error('Exception:', ex);
reject({
status: 'Error',
message: ex.toString()
});
}
});
},
getBspApplicationsList: function(adtConfig) {
return new Promise(function(resolve, reject) {
logger.debug('Collecting BSP applications.');
if (!adtConfig) {
reject({
status: 'Error',
message: 'No request configuration provided.'
});
}
request(adtConfig, function(error, response, body) {
if (error) {
logger.error(error);
reject(error ? error.toString() : error);
}
if (response.statusCode == 200) {
var responseXml = new xmldoc.XmlDocument(response.body);
var bspApsList = [];
responseXml.childrenNamed('atom:entry').map(function(node) {
bspApsList.push({
id: node.valueWithPath('atom:id'),
name: node.valueWithPath('atom:id').replace(new RegExp('%2f', 'g'), '/'),
description: node.valueWithPath('atom:summary')
});
});
resolve(bspApsList);
} else {
if (response.statusCode == 404) {
logger.error('Application not found.', response.body);
reject('Application not found.');
}
if (response.statusCode == 403) {
logger.error('%s Access forbidden.', response.statusCode);
reject('Access forbidden.');
}
if (response.statusCode == 401) {
logger.error('%s Unauthorized access.', response.statusCode);
reject('Unauthorized access.');
}
logger.error('Error:', error);
reject(error);
}
});
});
},
getPackagesList: function(adtConfig) {
return new Promise(function(resolve, reject) {
logger.debug('Collecting packages.');
if (!adtConfig) {
reject({
status: 'Error',
message: 'No request configuration provided.'
});
}
request(adtConfig, function(error, response, body) {
if (error) {
logger.error(error);
reject(error ? error.toString() : error);
}
if (response.statusCode == 200) {
var responseXml = new xmldoc.XmlDocument(response.body);
var packagesList = [];
responseXml.childrenNamed('adtcore:objectReference').map(function(node) {
packagesList.push({
id: node.attr['adtcore:uri'],
description: node.attr['adtcore:name'],
name: node.attr['adtcore:uri'].toUpperCase().replace('/SAP/BC/ADT/VIT/WB/OBJECT_TYPE/DEVCK/OBJECT_NAME/', '').replace('/SAP/BC/ADT/PACKAGES/', '').replace(new RegExp('%2F', 'g'), '/').toUpperCase()
});
});
resolve(packagesList);
} else {
if (response.statusCode == 404) {
logger.error('Application not found.', response.body);
reject('Application not found.');
}
if (response.statusCode == 403) {
logger.error('%s Access forbidden.', response.statusCode);
reject('Access forbidden.');
}
if (response.statusCode == 401) {
logger.error('%s Unauthorized access.', response.statusCode);
reject('Unauthorized access.');
}
logger.error('Error:', error);
reject(error);
}
});
});
},
readSourceDir: function(bspApplication, dirPath, list) {
return new Promise(function(resolve, reject) {
try {
logger.debug('Collect files from %s', dirPath);
var fileList = [];
var bspAppDir = '';
var getAllFiles = function(bspApplication, parentDir, dir, fileList) {
var files = fs.readdirSync(dir);
fileList = fileList || [];
files.forEach(function(file) {
if (fs.statSync(path.join(dir, file)).isDirectory()) {
//bspAppDir = dir.replace(/\\/g, '/').replace(parentDir, '');
bspAppDir = dir.replace(parentDir, '').replace(/\\/g, '/');
bspAppDir = bspAppDir.length ? '/' + bspAppDir : '';
bspAppDir = bspAppDir.replace(new RegExp('/', 'g'), '%2f');
fileList.push({
id: bspApplication + bspAppDir + '%2f' + file,
name: slash(path.join(dir, file)),
type: 'folder'
});
fileList = getAllFiles(bspApplication, parentDir, path.join(dir, file), fileList);
} else {
//bspAppDir = dir.replace(/\\/g, '/').replace(parentDir, '');
bspAppDir = dir.replace(parentDir, '').replace(/\\/g, '/');
bspAppDir = bspAppDir.length ? '/' + bspAppDir : '';
bspAppDir = bspAppDir.replace(new RegExp('/', 'g'), '%2f');
fileList.push({
id: bspApplication + bspAppDir + '%2f' + file,
name: slash(path.join(dir, file)),
type: 'file'
});
}
});
return fileList;
};
getAllFiles(bspApplication, dirPath, dirPath, fileList);
resolve(fileList);
} catch (ex) {
reject(ex);
}
});
},
asyncRequest: function(adtConfig) {
return new Promise(function(resolve, reject) {
request(adtConfig, function(error, response, body) {
if (error) {
reject(error);
}
if (!error && (response.statusCode == 200 || response.statusCode == 201)) {
resolve(response);
} else {
if (response.statusCode == 404) {
resolve(response);
}
reject(response.body);
}
});
});
},
collectResourcesServer: function(adtConfig, items, recursionCheck = {}, recursionId) {
if (!items) {
items = [];
}
return new Promise(function(resolve, reject) {
try {
Utils.asyncRequest(adtConfig).then(
function(response) {
if (response.statusCode == 404) {
resolve(items);
}
if (response.statusCode == 200) {
var responseXml = new xmldoc.XmlDocument(response.body);
var currentFolderItems = [];
responseXml.childrenNamed('atom:entry').map(function(node) {
var id = node.valueWithPath('atom:id');
currentFolderItems.push({
id: id,
type: node.valueWithPath('atom:category@term')
});
items.push({
id: id,
name: id.replace(new RegExp('%2f', 'g'), '/'),
type: node.valueWithPath('atom:category@term')
});
});
var checkFolder = function(item) {
return item.type === 'folder'
}
var subFolders = currentFolderItems.filter(checkFolder);
if (subFolders.length) {
recursionCheck[recursionId] = true;
for (var i = 0, iLength = subFolders.length; i < iLength; i++) {
recursionCheck[subFolders[i].id] = false;
}
for (var i = 0, iLength = subFolders.length; i < iLength; i++) {
var subFolder = subFolders[i];
recursionId = subFolder.id;
adtConfig.url = adtConfig.host + process.env.FILESTORE_OBJECTS_PATH + '/' + encodeURIComponent(subFolder.id) + '/content';
Utils.collectResourcesServer(adtConfig, items, recursionCheck, recursionId).then(
function(items) {
resolve(items);
},
function(error) {
logger.error('Error', error);
reject(error);
}
);
}
} else {
items.sort(function(valueA, valueB) {
return valueA.name.localeCompare(valueB.name);
});
recursionCheck[recursionId] = true;
var isComplete = true;
for (var prop in recursionCheck) {
if (!recursionCheck[prop]) {
isComplete = false;
}
}
if (isComplete) {
resolve(items);
}
}
} else {
logger.error('Error:', error);
reject({
status: 'Error',
message: error.toString()
});
}
},
function(error) {
logger.error('Error', error);
reject(error);
}
);
} catch (ex) {
reject(ex);
}
});
},
getresourcesSync(resourcesServer, resourcesLocal) {
var resourcesSync = resourcesLocal.map(localEntry => {
var serverResourcesExists = !!resourcesServer.find(
serverEntry => serverEntry.type === localEntry.type && serverEntry.id === localEntry.id
);
return Object.assign({}, localEntry, {
syncMode: serverResourcesExists ? 'update' : 'create'
});
});
resourcesServer.forEach(serverEntry => {
var localEntryExists = !!resourcesLocal.find(
localEntry => localEntry.type === serverEntry.type && localEntry.id === serverEntry.id
);
if (!localEntryExists) {
resourcesSync.push(Object.assign({}, serverEntry, {
syncMode: 'delete'
}));
}
});
return Utils.sortResourcesForProcessing(resourcesSync);
},
sortResourcesForProcessing(entries) {
var files = entries.filter(file => file.type === 'file');
var folders = entries.filter(folder => folder.type === 'folder')
.map(folder => Object.assign({}, folder, {
level: folder.name.split('/').length - 1
}));
const createFiles = files.filter(file => file.syncMode === 'create');
const updateFiles = files.filter(file => file.syncMode === 'update');
const deleteFiles = files.filter(file => file.syncMode === 'delete');
const createFolders = folders.filter(folder => folder.syncMode === 'create');
const updateFolders = folders.filter(folder => folder.syncMode === 'update');
const deleteFolders = folders.filter(folder => folder.syncMode === 'delete');
deleteFolders.sort((folderA, folderB) => folderB.level - folderA.level); // highest level first
createFolders.sort((folderA, folderB) => folderA.level - folderB.level); // lowest level first
return [].concat(
deleteFiles,
deleteFolders,
createFolders,
updateFolders, // not processed by ADT
createFiles,
updateFiles
);
},
getSapTransportsList: function(adtConfig, bspProperties) {
return new Promise(function(resolve, reject) {
try {
logger.debug('Collecting transports.');
var sapPackage = adtConfig.bspProperties.bspAppPackage ? adtConfig.bspProperties.bspAppPackage : '';
adtConfig.url = adtConfig.host + process.env.TRANSPORT_PATH; // Transports
adtConfig.method = 'POST';
adtConfig.headers['Content-Type'] = 'application/xml';
adtConfig.body = '<?xml version="1.0" encoding="UTF-8"?>' +
'<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">' +
'<asx:values>' +
'<DATA>' +
'<PGMID/>' +
'<OBJECT/>' +
'<OBJECTNAME/>' +
'<DEVCLASS>' + sapPackage.toUpperCase() + '</DEVCLASS>' +
'<OPERATION>I</OPERATION>' +
'<URI>/sap/bc/adt/filestore/ui5-bsp/objects/' + adtConfig.bspProperties.bspApplication + '/$create</URI>' +
'</DATA>' +
'</asx:values>' +
'</asx:abap>';
request(adtConfig, function(error, response, body) {
if (error) {
logger.error('Error', error);
reject(error);
}
if (!error && (response.statusCode == 200)) {
logger.debug('Transports list collected.');
var responseXml = new xmldoc.XmlDocument(response.body);
var transportsList = {
requests: [],
locks: [],
messages: []
};
var requestList = responseXml.childNamed('asx:values').childNamed('DATA').childNamed('REQUESTS').childrenNamed('CTS_REQUEST');
if (requestList) {
requestList.map(function(node) {
if (node) {
transportsList.requests.push({
id: node.childNamed('REQ_HEADER').valueWithPath('TRKORR'),
description: node.childNamed('REQ_HEADER').valueWithPath('AS4TEXT')
});
}
});
}
var requestLocksList = responseXml.childNamed('asx:values').childNamed('DATA').childNamed('LOCKS').childrenNamed('CTS_OBJECT_LOCK');
if (requestLocksList) {
requestLocksList.map(function(node) {
if (node) {
transportsList.locks.push({
id: node.childNamed('LOCK_HOLDER').childNamed('REQ_HEADER').valueWithPath('TRKORR'),
description: node.childNamed('LOCK_HOLDER').childNamed('REQ_HEADER').valueWithPath('AS4TEXT')
});
}
});
}
var messagesList = responseXml.childNamed('asx:values').childNamed('DATA').childNamed('MESSAGES').childrenNamed('CTS_MESSAGE');
if (messagesList) {
messagesList.map(function(node) {
if (node) {
transportsList.messages.push({
message: node.valueWithPath('TEXT'),
status: node.valueWithPath('SEVERITY') == 'E' ? 'Error' : 'Warning'
});
}
});
}
resolve(transportsList);
} else {
logger.error('Error', response.body);
reject(response.body);
}
});
} catch (ex) {
reject(ex);
}
});
},
buildComponentPreload: function(appName, versionExtId, pathPrefix, srcRepoPath) {
return new Promise(function(resolve, reject) {
// replace last "/" in case is provided
if (pathPrefix.slice(-1) === '/') {
pathPrefix = pathPrefix.replace(/.$/, '');
}
//var sourceRepoDir = process.env.ROOT_DIR_REL + '/' + process.env.APPS_DIR + '/' + appName + srcRepoPath;
var sourceRepoDir = path.join(process.env.APPS_DIR, appName + srcRepoPath);
logger.debug('Build process started for folder %s ', sourceRepoDir);
// Setup
var preloadComponentFileName = 'Component-preload.js';
var componentFileName = 'Component.js';
var options = {
compress: {}
}
options.compress.uglifyjs = options.compress.uglifyjs || {};
options.compress.uglifyjs.fromString = true;
options.compress.uglifyjs.output = options.compress.uglifyjs.output || {};
if (!options.compress.uglifyjs.output.hasOwnProperty("comments")) {
options.compress.uglifyjs.output.comments = copyrightPattern;
}
var copyrightPattern = /copyright|license|\(c\)|released under|\u00a9/i;
var preformattedPattern = /<(?:\w+:)?pre>/;
var processExtensionList = /^.*\.js$|^.*\.xml$|^.*\.json$/;
var fileList = [];
var getAllFiles = function(dir, fileList) {
var files = fs.readdirSync(dir);
fileList = fileList || [];
files.forEach(function(file) {
if (fs.statSync(path.join(dir, file)).isDirectory()) {
fileList = getAllFiles(path.join(dir, file), fileList);
} else {
fileList.push({
fullpath: slash(path.join(dir, file)),
apppath: pathPrefix + '/' + slash(path.join(dir, file).replace(sourceRepoDir, '')),
filename: file
});
}
});
return fileList;
};
getAllFiles(sourceRepoDir, fileList);
if (fileList.length === 0) {
logger.error('No files found in the application root folder.');
reject({
status: 'Error',
message: 'No files found in the application root folder.'
});
}
var preloadComponentFiles = [];
for (var i = 0, len = fileList.length; i < len; i++) {
if (fileList[i].filename === componentFileName) {
preloadComponentFiles.push(fileList[i].apppath);
}
}
if (preloadComponentFiles.length === 0) {
logger.error('Component.js file not found. ');
reject({
status: 'Error',
message: 'Component.js file not found. '
});
}
preloadComponentFiles.forEach(function(file) {
logger.debug('Creating preload module for ' + file);
var preloadDir = path.dirname(file);
var componentPreloadContent = {
version: '2.0',
name: preloadDir + '/Component-preload',
modules: {}
};
for (var i = 0, len = fileList.length; i < len; i++) {
if (processExtensionList.test(fileList[i].filename) && fileList[i].filename !== preloadComponentFileName) {
var fileName = fileList[i].fullpath;
var fileContent = fs.readFileSync(fileName, 'utf8');
var fileExtension = path.extname(fileName);
try {
switch (fileExtension) {
case '.js':
fileContent = uglify.minify(fileContent, options.compress.uglifyjs).code;
break;
case '.json':
fileContent = JSON.stringify(JSON.parse(fileContent));
break;
case '.xml':
if (!preformattedPattern.test(fileContent)) {
fileContent = pd.xmlmin(fileContent, false);
}
break;
}
} catch (ex) {
logger.error('Failed to compress ' + fileName + '.', ex);
// Do not reject here, just use the not-minified content
}
componentPreloadContent.modules[fileList[i].apppath] = fileContent;
}
}
var content = JSON.stringify(componentPreloadContent, null, '\t');
content = 'jQuery.sap.registerPreloadedModules(' + content + ');';
var componentFilePath = path.join(process.env.VERSIONS_DIR, versionExtId, process.env.DIST_VERSION_DIR, preloadComponentFileName);
fs.writeFile(componentFilePath, content, function(err) {
if (err) {
logger.error('Error:', err);
reject({
status: 'Error',
message: err.toString()
});
}
logger.debug('File ' + componentFilePath + ' was saved.');
resolve({
status: 'Success',
message: 'File ' + componentFilePath + ' was saved.'
});
});
});
});
}
}
module.exports = Utils;