Files
Superalgos/Client/httpInterface.js
T

1382 lines
62 KiB
JavaScript

exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER) {
let thisObject = {
initialize: initialize,
finalize: finalize,
run: run
}
const open = require('open')
let port = global.env.HTTP_INTERFACE_PORT
let http = require('http')
let isHttpServerStarted = false
let webhook = new Map()
return thisObject
function finalize() {
}
function initialize() {
}
function run() {
startHtttpServer()
}
function startHtttpServer() {
try {
if (isHttpServerStarted === false) {
gWebServer = http.createServer(onBrowserRequest).listen(port)
isHttpServerStarted = true
/* Starting the browser now is optional */
if (process.argv.includes("noBrowser")) {
//Running Client only with no UI.
} else {
open('http://localhost:' + port)
}
}
} catch (err) {
console.log('[ERROR] httpInterface -> startHtttpServer -> Error = ' + err.stack)
}
}
function onBrowserRequest(httpRequest, httpResponse) {
function getBody(callback) { // Gets the de body from a POST httpRequest to the web server
try {
let body = ''
httpRequest.on('data', function (data) {
body += data
// Too much POST data
//if (body.length > 1e6) {
// httpRequest.connection.destroy()
//}
})
httpRequest.on('end', function () {
callback(body)
})
httpRequest.on('error', function (err) {
console.log('[INFO] httpInterface -> onBrowserRequest -> getBody -> err = ' + err.stack)
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
})
} catch (err) {
console.log('[INFO] httpInterface -> onBrowserRequest -> getBody -> err = ' + err.stack)
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
}
}
let requestParameters = httpRequest.url.split('/')
requestParameters = httpRequest.url.split('?') // Remove version information
requestParameters = requestParameters[0].split('/')
switch (requestParameters[1]) {
case 'WEB3':
{
getBody(processRequest)
async function processRequest(body) {
try {
let params = JSON.parse(body)
switch (params.method) {
case 'getNetworkClientStatus': {
let serverResponse = await WEB3_SERVER.getNetworkClientStatus(
params.host,
params.port,
params.interface
)
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'createWalletAccount': {
let serverResponse = await WEB3_SERVER.createWalletAccount(
params.entropy
)
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'getWalletBalances': {
let serverResponse = await WEB3_SERVER.getWalletBalances(
params.host,
params.port,
params.interface,
params.walletDefinition
)
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
default: {
respondWithContent(JSON.stringify({ error: 'Method ' + params.method + ' is invalid.' }), httpResponse)
}
}
} catch (err) {
console.log('[ERROR] httpInterface -> WEB3s -> Method call produced an error.')
console.log('[ERROR] httpInterface -> WEB3s -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> WEB3s -> Params Received = ' + body)
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
}
}
break
}
case 'CCXT':
{
getBody(processRequest)
async function processRequest(body) {
try {
let params = JSON.parse(body)
const ccxt = require('ccxt')
switch (params.method) {
case 'fetchMarkets': {
const exchangeClass = ccxt[params.exchangeId]
const exchangeConstructorParams = {
'timeout': 30000,
'enableRateLimit': true,
verbose: false
}
let ccxtExchange = new exchangeClass(exchangeConstructorParams)
let ccxtMarkets = []
if (ccxtExchange.has.fetchMarkets === true) {
ccxtMarkets = await ccxtExchange.fetchMarkets()
}
respondWithContent(JSON.stringify(ccxtMarkets), httpResponse)
return
}
case 'listExchanges': {
let exchanges = []
for (let i = 0; i < ccxt.exchanges.length; i++) {
let exchangeId = ccxt.exchanges[i]
const exchangeClass = ccxt[exchangeId]
const exchangeConstructorParams = {
'timeout': 30000,
'enableRateLimit': true,
verbose: false
}
let ccxtExchange
try { ccxtExchange = new exchangeClass(exchangeConstructorParams) }
catch (err) { }
if (ccxtExchange === undefined) { continue }
if (ccxtExchange.has.fetchOHLCV === params.has.fetchOHLCV) {
if (ccxtExchange.has.fetchMarkets === params.has.fetchMarkets) {
if (ccxtExchange.timeframes['1m'] !== undefined) {
let exchange = {
name: ccxtExchange.name,
id: ccxtExchange.id
}
exchanges.push(exchange)
}
}
}
}
respondWithContent(JSON.stringify(exchanges), httpResponse)
return
}
}
let content = {
err: global.DEFAULT_FAIL_RESPONSE // method not supported
}
} catch (err) {
console.log('[INFO] httpInterface -> CCXT FetchMarkets -> Could not fetch markets.')
let error = {
result: 'Fail Because',
message: err.message
}
respondWithContent(JSON.stringify(error), httpResponse)
}
}
break
}
break
case 'Webhook':
{
switch (requestParameters[2]) { // switch by command
case 'Fetch-Messages': {
let exchange = requestParameters[3]
let market = requestParameters[4]
/* Some validations */
if (exchange === undefined) {
console.log('[WARN] httpInterface -> Webhook -> Fetch-Messages -> Message with no Exchange received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
if (market === undefined) {
console.log('[WARN] httpInterface -> Webhook -> Fetch-Messages -> Message with no market received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
let key = exchange + '-' + market
let webhookMessages = webhook.get(key)
if (webhookMessages === undefined) {
webhookMessages = []
}
respondWithContent(JSON.stringify(webhookMessages), httpResponse)
webhookMessages = []
webhook.set(key, webhookMessages)
break
}
case 'New-Message': {
getBody(processRequest)
function processRequest(messageReceived) {
let timestamp = (new Date()).valueOf()
let source = requestParameters[3]
let exchange = requestParameters[4]
let market = requestParameters[5]
/* Some validations */
if (source === undefined) {
console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no Source received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
if (exchange === undefined) {
console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no Exchange received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
if (market === undefined) {
console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no market received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
let key = exchange + '-' + market
let webhookMessages = webhook.get(key)
if (webhookMessages === undefined) {
webhookMessages = []
}
webhookMessages.push([timestamp, source, messageReceived])
webhook.set(key, webhookMessages)
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
}
break
}
}
break
}
break
case 'Docs':
{
switch (requestParameters[2]) { // switch by command
case 'Save-Node-Schema': {
getBody(processRequest)
async function processRequest(body) {
try {
let docsSchema = JSON.parse(body)
let project = requestParameters[3]
let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Nodes'
const fs = require('fs')
fs.rmdir(filePath, { recursive: true }, onDirDeleted)
function onDirDeleted(err) {
if (err && err.code === 'EBUSY') {
throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.')
}
try {
fs.mkdirSync(filePath)
} catch (err) {
if (err.code !== 'EEXIST') {
throw (err)
}
}
for (let i = 0; i < docsSchema.length; i++) {
let schemaDocument = docsSchema[i]
let fileContent = JSON.stringify(schemaDocument, undefined, 4)
let fileName = schemaDocument.type.toLowerCase()
for (let j = 0; j < 10; j++) {
fileName = fileName.replace(' ', '-')
}
fileName = fileName + '.json'
fs.writeFileSync(filePath + '/' + fileName, fileContent)
}
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
}
} catch (err) {
console.log('[ERROR] httpInterface -> Docs -> Save-Node-Schema -> Method call produced an error.')
console.log('[ERROR] httpInterface -> Docs -> Save-Node-Schema -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> Docs -> Save-Node-Schema -> Params Received = ' + body)
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
}
}
break
}
case 'Save-Concept-Schema': {
getBody(processRequest)
async function processRequest(body) {
try {
let docsSchema = JSON.parse(body)
let project = requestParameters[3]
let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Concepts'
const fs = require('fs')
fs.rmdir(filePath, { recursive: true }, onDirDeleted)
function onDirDeleted(err) {
if (err && err.code === 'EBUSY') {
throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.')
}
try {
fs.mkdirSync(filePath)
} catch (err) {
if (err.code !== 'EEXIST') {
throw (err)
}
}
for (let i = 0; i < docsSchema.length; i++) {
let schemaDocument = docsSchema[i]
let fileContent = JSON.stringify(schemaDocument, undefined, 4)
let fileName = schemaDocument.type.toLowerCase()
for (let j = 0; j < 10; j++) {
fileName = fileName.replace(' ', '-')
}
fileName = fileName + '.json'
fs.writeFileSync(filePath + '/' + fileName, fileContent)
}
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
}
} catch (err) {
console.log('[ERROR] httpInterface -> Docs -> Save-Concept-Schema -> Method call produced an error.')
console.log('[ERROR] httpInterface -> Docs -> Save-Concept-Schema -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> Docs -> Save-Concept-Schema -> Params Received = ' + body)
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
}
}
break
}
case 'Save-Topic-Schema': {
getBody(processRequest)
async function processRequest(body) {
try {
let docsSchema = JSON.parse(body)
let project = requestParameters[3]
let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Topics'
const fs = require('fs')
fs.rmdir(filePath, { recursive: true }, onDirDeleted)
function onDirDeleted(err) {
if (err && err.code === 'EBUSY') {
throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.')
}
try {
fs.mkdirSync(filePath)
} catch (err) {
if (err.code !== 'EEXIST') {
throw (err)
}
}
for (let i = 0; i < docsSchema.length; i++) {
let schemaDocument = docsSchema[i]
let fileContent = JSON.stringify(schemaDocument, undefined, 4)
let pageNumber = '00' + schemaDocument.pageNumber
let fileName = schemaDocument.topic.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase()
for (let j = 0; j < 10; j++) {
fileName = fileName.replace(' ', '-')
}
fileName = fileName + '.json'
fs.writeFileSync(filePath + '/' + fileName, fileContent)
}
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
}
} catch (err) {
console.log('[ERROR] httpInterface -> Docs -> Save-Topic-Schema -> Method call produced an error.')
console.log('[ERROR] httpInterface -> Docs -> Save-Topic-Schema -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> Docs -> Save-Topic-Schema -> Params Received = ' + body)
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
}
}
break
}
case 'Save-Book-Schema': {
getBody(processRequest)
async function processRequest(body) {
try {
let docsSchema = JSON.parse(body)
let project = requestParameters[3]
let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Books'
const fs = require('fs')
fs.rmdir(filePath, { recursive: true }, onDirDeleted)
function onDirDeleted(err) {
if (err && err.code === 'EBUSY') {
throw ('Can not delete the folder ' + filePath + ' because a file in it is open by some other program.')
}
try {
fs.mkdirSync(filePath)
} catch (err) {
if (err.code !== 'EEXIST') {
throw (err)
}
}
for (let i = 0; i < docsSchema.length; i++) {
let schemaDocument = docsSchema[i]
let fileContent = JSON.stringify(schemaDocument, undefined, 4)
let fileName = schemaDocument.type.toLowerCase()
for (let j = 0; j < 10; j++) {
fileName = fileName.replace(' ', '-')
}
fileName = fileName + '.json'
fs.writeFileSync(filePath + '/' + fileName, fileContent)
}
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
}
} catch (err) {
console.log('[ERROR] httpInterface -> Docs -> Save-Book-Schema -> Method call produced an error.')
console.log('[ERROR] httpInterface -> Docs -> Save-Book-Schema -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> Docs -> Save-Book-Schema -> Params Received = ' + body)
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
}
}
break
}
}
break
}
break
case 'App': {
switch (requestParameters[2]) { // switch by command
case 'Contribute': {
try {
const simpleGit = require('simple-git');
const options = {
baseDir: process.cwd(),
binary: 'git',
maxConcurrentProcesses: 6,
}
const git = simpleGit(options)
const commitMessage = unescape(requestParameters[3])
git
.add('./*')
.commit(commitMessage)
.push('origin', 'in-app-documentation')
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
} catch (err) {
console.log('[ERROR] httpInterface -> App -> Contribute -> Method call produced an error.')
console.log('[ERROR] httpInterface -> App -> Contribute -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> App -> Contribute -> Params Received = ' + requestParameters[3])
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
}
break
}
}
break
}
case 'LegacyPlotter.js':
{
respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/LegacyPlotter.js', httpResponse)
}
break
case 'PlotterPanel.js':
{
respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/PlotterPanel.js', httpResponse)
}
break
case 'Images': // This means the Images folder.
{
let path = global.env.PATH_TO_CLIENT + 'WebServer/Images/' + requestParameters[2]
if (requestParameters[3] !== undefined) {
path = path + '/' + requestParameters[3]
}
if (requestParameters[4] !== undefined) {
path = path + '/' + requestParameters[4]
}
if (requestParameters[5] !== undefined) {
path = path + '/' + requestParameters[5]
}
path = unescape(path)
respondWithImage(path, httpResponse)
}
break
case 'Icons': // This means the Icons folder under Projects.
{
let path = global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/Icons'
if (requestParameters[3] !== undefined) {
path = path + '/' + requestParameters[3]
}
if (requestParameters[4] !== undefined) {
path = path + '/' + requestParameters[4]
}
if (requestParameters[5] !== undefined) {
path = path + '/' + requestParameters[5]
}
path = unescape(path)
respondWithImage(path, httpResponse)
}
break
case 'GIFs': // This means the GIFs folder under Projects.
{
let path = global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/GIFs'
if (requestParameters[3] !== undefined) {
path = path + '/' + requestParameters[3]
}
if (requestParameters[4] !== undefined) {
path = path + '/' + requestParameters[4]
}
if (requestParameters[5] !== undefined) {
path = path + '/' + requestParameters[5]
}
path = unescape(path)
respondWithImage(path, httpResponse)
}
break
case 'PNGs': // This means the PNGs folder under Projects.
{
let path = global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/PNGs'
if (requestParameters[3] !== undefined) {
path = path + '/' + requestParameters[3]
}
if (requestParameters[4] !== undefined) {
path = path + '/' + requestParameters[4]
}
if (requestParameters[5] !== undefined) {
path = path + '/' + requestParameters[5]
}
path = unescape(path)
respondWithImage(path, httpResponse)
}
break
case 'favicon.ico': // This means the Scripts folder.
{
respondWithImage(global.env.PATH_TO_CLIENT + 'WebServer/Images/' + 'favicon.ico', httpResponse)
}
break
case 'WebServer': // This means the WebServer folder.
{
respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/' + requestParameters[2], httpResponse)
}
break
case 'externalScripts': // This means the WebServer folder.
{
respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/externalScripts/' + requestParameters[2], httpResponse)
}
break
case 'Plotters': // This means the plotter folder, not to be confused with the Plotters script!
{
let project = requestParameters[2]
let dataMine = requestParameters[3]
let codeName = requestParameters[4]
let moduleName = requestParameters[5]
let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/' + 'Bots-Plotters-Code' + '/' + dataMine + '/plotters/' + codeName + '/' + moduleName
respondWithFile(filePath, httpResponse)
}
break
case 'ChartLayers':
{
respondWithFile(global.env.PATH_TO_UI + '/' + requestParameters[1] + '/' + requestParameters[2], httpResponse)
}
break
case 'Files':
{
respondWithFile(global.env.PATH_TO_DATA_FILES + '/' + requestParameters[2], httpResponse)
}
break
case 'Fonts':
{
respondWithFont(global.env.PATH_TO_FONTS + '/' + requestParameters[2], httpResponse)
}
break
case 'ProjectNames':
{
let projects = getDirectories(global.env.PATH_TO_PROJECTS)
respondWithContent(JSON.stringify(projects), httpResponse)
}
break
case 'Schema':
{
sendSchema(global.env.PATH_TO_PROJECTS + '/' + requestParameters[2] + '/Schemas/', requestParameters[3])
}
break
case 'IconNames':
{
let projects = getDirectories(global.env.PATH_TO_PROJECTS)
const fs = require('fs')
let icons = []
let totalProjects = projects.length
let projectCounter = 0
for (let i = 0; i < projects.length; i++) {
let project = projects[i]
const folder = global.env.PATH_TO_PROJECTS + '/' + project + '/Icons/'
fs.readdir(folder, (err, files) => {
for (let j = 0; j < files.length; j++) {
let file = files[j]
icons.push([project, file])
}
projectCounter++
if (projectCounter === totalProjects) {
respondWithContent(JSON.stringify(icons), httpResponse)
}
})
}
}
break
case 'PluginFileNames':
{
let project = unescape(requestParameters[2])
let pluginType = unescape(requestParameters[3])
const fs = require('fs')
let folder = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/' + pluginType
fs.readdir(folder, (err, files) => {
respondWithContent(JSON.stringify(files), httpResponse)
})
}
break
case 'LoadPlugin':
{
let project = unescape(requestParameters[2])
let pluginType = unescape(requestParameters[3])
let fileName = unescape(requestParameters[4])
let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/' + pluginType + '/' + fileName
respondWithFile(filePath, httpResponse)
}
break
case 'Workspace.js':
{
let fs = require('fs')
try {
let filePath = global.env.PATH_TO_DEFAULT_WORKSPACE + '/Getting-Started.json'
fs.readFile(filePath, onFileRead)
} catch (e) {
console.log('[ERROR] Error reading the Workspace.', e)
}
function onFileRead(err, workspace) {
if (err) {
respondWithContent(undefined, httpResponse)
} else {
let responseContent = 'function getWorkspace(){ return ' + workspace + '}'
respondWithContent(responseContent, httpResponse)
}
}
}
break
case 'ListWorkspaces':
{
let allWorkspaces = []
let projects = getDirectories(global.env.PATH_TO_PROJECTS)
let projectsCount = 0
for (let i = 0; i < projects.length; i++) {
let project = projects[i]
readPluginWorkspaces()
function readPluginWorkspaces() {
let dirPath = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/Workspaces'
try {
let fs = require('fs')
fs.readdir(dirPath, onDirRead)
function onDirRead(err, fileList) {
if (err) {
console.log('[WARN] Error reading a directory content. filePath = ' + dirPath)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
} else {
let updatedFileList = []
for (let i = 0; i < fileList.length; i++) {
let name = 'Plugin \u2192 ' + fileList[i]
updatedFileList.push([project, name])
}
allWorkspaces = allWorkspaces.concat(updatedFileList)
projectsCount++
if (projectsCount === projects.length) {
readMyWorkspaces()
}
return
}
}
} catch (err) {
console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath)
console.log('[ERROR] err.stack = ' + err.stack)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
}
}
function readMyWorkspaces() {
let dirPath = global.env.PATH_TO_MY_WORKSPACES
try {
let fs = require('fs')
fs.readdir(dirPath, onDirRead)
function onDirRead(err, fileList) {
if (err) {
// This happens the first time you run the software.
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
} else {
let updatedFileList = []
for (let i = 0; i < fileList.length; i++) {
let name = fileList[i]
updatedFileList.push(['', name])
}
allWorkspaces = allWorkspaces.concat(updatedFileList)
respondWithContent(JSON.stringify(allWorkspaces), httpResponse)
return
}
}
} catch (err) {
console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath)
console.log('[ERROR] err.stack = ' + err.stack)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
}
}
break
case 'LoadMyWorkspace':
{
let fileName = unescape(requestParameters[2])
let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json'
respondWithFile(filePath, httpResponse)
}
break
case 'SaveWorkspace':
{
getBody(processRequest)
async function processRequest(body) {
let fileContent = body
let fileName = unescape(requestParameters[2])
let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json'
try {
let fs = require('fs')
let dir = global.env.PATH_TO_MY_WORKSPACES;
/* Create Dir if it does not exist */
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
fs.writeFile(filePath, fileContent, onFileWritten)
function onFileWritten(err) {
if (err) {
console.log('[ERROR] SaveWorkspace -> onFileWritten -> Error writting the Workspace file. fileName = ' + fileName)
console.log('[ERROR] SaveWorkspace -> onFileWritten -> err.stack = ' + err.stack)
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
} else {
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
}
}
} catch (err) {
console.log('[ERROR] SaveWorkspace -> Error writting the Workspace file. fileName = ' + fileName)
console.log('[ERROR] SaveWorkspace -> err.stack = ' + err.stack)
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
respondWithContent(JSON.stringify(error), httpResponse)
}
}
}
break
case 'ListFunctionLibraries':
{
returnProjectFolderFileList('Function-Libraries')
}
break
case 'ProjectsSchema':
{
let path = global.env.PATH_TO_PROJECTS + '/' + 'ProjectsSchema.json'
respondWithFile(path, httpResponse)
}
break
case 'ListSpaceFiles':
{
let fs = require('fs')
let allFiles = []
let projects = getDirectories(global.env.PATH_TO_PROJECTS)
let dirCount = 0
let totalDirs = 0
for (let i = 0; i < projects.length; i++) {
let project = projects[i]
let dirPath = project + '/UI/Spaces'
let spaces = getDirectories(global.env.PATH_TO_PROJECTS + '/' + dirPath)
for (let j = 0; j < spaces.length; j++) {
let space = spaces[j]
readDirectory(dirPath + '/' + space)
}
function readDirectory(path) {
try {
totalDirs++
fs.readdir(global.env.PATH_TO_PROJECTS + '/' + path, onDirRead)
let otherDirs = getDirectories(global.env.PATH_TO_PROJECTS + '/' + path)
for (let m = 0; m < otherDirs.length; m++) {
let otherDir = otherDirs[m]
readDirectory(path + '/' + otherDir)
}
function onDirRead(err, fileList) {
if (err) {
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
} else {
let updatedFileList = []
for (let k = 0; k < fileList.length; k++) {
let name = fileList[k]
if (name.indexOf('.js') < 0) { continue }
updatedFileList.push(path + '/' + name)
}
allFiles = allFiles.concat(updatedFileList)
dirCount++
if (dirCount === totalDirs) {
respondWithContent(JSON.stringify(allFiles), httpResponse)
}
}
}
} catch (err) {
console.log('[ERROR] Error reading a directory content. filePath = ' + path)
console.log('[ERROR] err.stack = ' + err.stack)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
}
}
}
break
case 'ListUtilitiesFiles':
{
returnProjectFolderFileList('Utilities')
}
break
case 'ListGlobalFiles':
{
returnProjectFolderFileList('Globals')
}
break
case 'Projects':
{
let path = ''
for (let i = 2; i < 10; i++) {
if (requestParameters[i] !== undefined) {
let parameter = unescape(requestParameters[i])
path = path + '/' + parameter
}
}
let filePath = global.env.PATH_TO_PROJECTS + path
respondWithFile(filePath, httpResponse)
}
break
case 'Storage':
{
respondWithFile(global.env.PATH_TO_DATA_STORAGE + '/' + httpRequest.url.substring(9), httpResponse)
}
break
case 'main.css':
{
sendStyleSheet('main.css')
}
break
case 'tutorial.css':
{
sendStyleSheet('tutorial.css')
}
break
case 'docs.css':
{
sendStyleSheet('docs.css')
}
break
case 'context-menu.css':
{
sendStyleSheet('context-menu.css')
}
break
case 'credits.css':
{
sendStyleSheet('credits.css')
}
break
case 'docs.css':
{
sendStyleSheet('docs.css')
}
break
case 'font-awasome.css':
{
sendStyleSheet('font-awasome.css')
}
break
case 'prism.css':
{
sendStyleSheet('prism.css')
}
break
case 'ExecuteTerminalCommand':
{
let command = unescape(requestParameters[2])
executeTerminalCommand(command)
}
break
default:
{
homePage()
}
}
function returnProjectFolderFileList(projectFolderName) {
{
let allLibraries = []
let projects = getDirectories(global.env.PATH_TO_PROJECTS)
let projectsCount = 0
for (let i = 0; i < projects.length; i++) {
let project = projects[i]
let dirPath = global.env.PATH_TO_PROJECTS + '/' + project + '/' + 'UI' + '/' + projectFolderName
try {
let fs = require('fs')
fs.readdir(dirPath, onDirRead)
function onDirRead(err, fileList) {
if (err) {
console.log('[WARN] Error reading a directory content. filePath = ' + dirPath)
return
} else {
let updatedFileList = []
for (let i = 0; i < fileList.length; i++) {
let name = fileList[i]
updatedFileList.push([project, name])
}
allLibraries = allLibraries.concat(updatedFileList)
projectsCount++
if (projectsCount === projects.length) {
respondWithContent(JSON.stringify(allLibraries), httpResponse)
}
return
}
}
} catch (err) {
console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath)
console.log('[ERROR] err.stack = ' + err.stack)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse)
return
}
}
}
}
function executeTerminalCommand(command) {
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function lsWithGrep() {
try {
const { stdout, stderr } = await exec(command);
console.log('stdout:', stdout);
console.log('stderr:', stderr);
} catch (err) {
console.error(err.stack);
};
};
lsWithGrep();
}
function sendSchema(filePath, schemaType) {
let fs = require('fs')
if (schemaType === 'AppSchema') {
let fileName = 'AppSchema.json'
try {
filePath = filePath + fileName
fs.readFile(filePath, onFileRead)
} catch (e) {
console.log('[ERROR] Error reading the ' + fileName, e)
}
function onFileRead(err, schema) {
if (err) {
respondWithContent(undefined, httpResponse)
} else {
respondWithContent(schema, httpResponse)
}
}
} else {
try {
let folder = ''
switch (schemaType) {
case 'DocsNodeSchema': {
folder = 'Docs-Nodes'
break
}
case 'DocsConceptSchema': {
folder = 'Docs-Concepts'
break
}
case 'DocsTopicSchema': {
folder = 'Docs-Topics'
break
}
case 'DocsBookSchema': {
folder = 'Docs-Books'
break
}
}
let schemaArray = []
let fileList = fs.readdirSync(filePath + '/' + folder)
for (let k = 0; k < fileList.length; k++) {
let name = fileList[k]
let fileContent = fs.readFileSync(filePath + '/' + folder + '/' + name)
let schemaDocument = JSON.parse(fileContent)
schemaArray.push(schemaDocument)
}
let schema = JSON.stringify(schemaArray)
respondWithContent(schema, httpResponse)
} catch (err) {
console.log('Could not send Schema:', filePath, schemaType)
console.log(err.stack)
respondWithContent("[]", httpResponse)
}
}
}
function sendStyleSheet(fileName) {
let fs = require('fs')
try {
let filePath = global.env.PATH_TO_CLIENT + 'WebServer/css/' + fileName
fs.readFile(filePath, onFileRead)
function onFileRead(err, file) {
try {
let fileContent = file.toString()
fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT)
fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT)
fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT)
respondWithContent(fileContent, httpResponse, 'text/css')
} catch (err) {
console.log('[ERROR] httpInterface -> mainCSS -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
}
}
} catch (err) {
console.log(err)
}
}
function homePage() {
if (requestParameters[1] === '') {
let fs = require('fs')
try {
let fileName = global.env.PATH_TO_CLIENT + 'WebServer/index.html'
fs.readFile(fileName, onFileRead)
function onFileRead(err, file) {
try {
let fileContent = file.toString()
fileContent = fileContent.replace('HTTP_INTERFACE_PORT', global.env.HTTP_INTERFACE_PORT)
respondWithContent(fileContent, httpResponse)
} catch (err) {
console.log('[ERROR] httpInterface -> homePage -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
}
}
} catch (err) {
console.log(err)
}
} else {
respondWithFile(global.env.PATH_TO_UI + '/' + requestParameters[1], httpResponse)
}
}
}
function respondWithFile(fileName, httpResponse) {
let fs = require('fs')
if (fileName.indexOf('undefined') > 0) {
console.log('[WRN] httpInterface -> respondWithFile -> Received httpRequest for undefined file. ')
respondWithContent(undefined, httpResponse)
} else {
try {
fs.readFile(fileName, onFileRead)
function onFileRead(err, file) {
if (!err) {
respondWithContent(file.toString(), httpResponse)
} else {
//console.log('File requested not found: ' + fileName)
respondWithContent(undefined, httpResponse)
}
}
} catch (err) {
returnEmptyArray()
}
}
}
function respondWithContent(content, httpResponse, contentType) {
try {
httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1.
httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0.
httpResponse.setHeader('Expires', '0') // Proxies.
httpResponse.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains.
if (content !== undefined) {
if (contentType !== undefined) {
httpResponse.writeHead(200, { 'Content-Type': contentType })
} else {
httpResponse.writeHead(200, { 'Content-Type': 'text/html' })
}
httpResponse.write(content)
} else {
httpResponse.writeHead(404, { 'Content-Type': 'text/html' })
httpResponse.write('The specified key does not exist.')
}
httpResponse.end('\n')
} catch (err) {
returnEmptyArray(httpResponse)
}
}
function respondWithImage(fileName, httpResponse) {
let fs = require('fs')
try {
fs.readFile(fileName, onFileRead)
function onFileRead(err, file) {
if (err) {
console.log('[ERROR] httpInterface -> respondWithImage -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
return
}
try {
httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1.
httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0.
httpResponse.setHeader('Expires', '0') // Proxies.
httpResponse.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains.
httpResponse.writeHead(200, { 'Content-Type': 'image/png' })
httpResponse.end(file, 'binary')
} catch (err) {
console.log('[ERROR] httpInterface -> respondWithImage -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
}
}
} catch (err) {
console.log('[ERROR] httpInterface -> respondWithImage -> err = ' + err.stack)
}
}
function respondWithFont(fileName, httpResponse) {
let fs = require('fs')
try {
fs.readFile(fileName, onFileRead)
function onFileRead(err, file) {
try {
if (err) {
console.log('[ERROR] httpInterface -> respondWithBinary -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
return
}
httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1.
httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0.
httpResponse.setHeader('Expires', '0') // Proxies.
httpResponse.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains.
if (fileName.indexOf('2') < 0) {
httpResponse.writeHead(200, { 'Content-Type': 'font/woff' })
} else {
httpResponse.writeHead(200, { 'Content-Type': 'font/woff2' })
}
httpResponse.end(file, 'binary')
} catch (err) {
console.log('[ERROR] httpInterface -> respondWithBinary -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
}
}
} catch (err) {
console.log('[ERROR] httpInterface -> respondWithBinary -> err = ' + err.stack)
}
}
function returnEmptyArray(httpResponse) {
try {
httpResponse.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1.
httpResponse.setHeader('Pragma', 'no-cache') // HTTP 1.0.
httpResponse.setHeader('Expires', '0') // Proxies.
httpResponse.writeHead(200, { 'Content-Type': 'text/html' })
httpResponse.write('[]')
httpResponse.end('\n')
} catch (err) {
console.log('[ERROR] httpInterface -> returnEmptyArray -> err.stack ' + err.stack)
}
}
function getDirectories(path) {
const fs = require('fs')
return fs.readdirSync(path).filter(function (file) {
return fs.statSync(path + '/' + file).isDirectory();
});
}
}