diff --git a/Platform/Client/httpInterface.js b/Platform/Client/httpInterface.js index 197ffb051..81e4a60af 100644 --- a/Platform/Client/httpInterface.js +++ b/Platform/Client/httpInterface.js @@ -44,202 +44,252 @@ exports.newHttpInterface = function newHttpInterface() { let endpointOrFile = requestPath[1] switch (endpointOrFile) { - case 'Environment': - { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.env), httpResponse) - } + case 'Environment': { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.env), httpResponse) + } break - case 'WEB3': - { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + case 'WEB3': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - async function processRequest(body) { - try { - if (body === undefined) { return } - let params = JSON.parse(body) - - switch (params.method) { - case 'getNetworkClientStatus': { - - let serverResponse = await PL.servers.WEB3_SERVER.getNetworkClientStatus( - params.host, - params.port, - params.interface - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'createWalletAccount': { - - let serverResponse = await PL.servers.WEB3_SERVER.createWalletAccount( - params.entropy - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'getWalletBalances': { - - let serverResponse = await PL.servers.WEB3_SERVER.getWalletBalances( - params.host, - params.port, - params.interface, - params.walletDefinition - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'signData': { - - let serverResponse = await PL.servers.WEB3_SERVER.signData( - params.privateKey, - params.data - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'hashData': { - - let serverResponse = await PL.servers.WEB3_SERVER.hashData( - params.data - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'recoverAddress': { - - let serverResponse = await PL.servers.WEB3_SERVER.recoverAddress( - params.signature - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'mnemonicToPrivateKey': { - - let serverResponse = await PL.servers.WEB3_SERVER.mnemonicToPrivateKey( - params.mnemonic - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - default: { - SA.projects.foundations.utilities.httpResponses.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 - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + async function processRequest(body) { + try { + if (body === undefined) { + return } + let params = JSON.parse(body) + + switch (params.method) { + case 'getNetworkClientStatus': { + + let serverResponse = await PL.servers.WEB3_SERVER.getNetworkClientStatus( + params.host, + params.port, + params.interface + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'createWalletAccount': { + + let serverResponse = await PL.servers.WEB3_SERVER.createWalletAccount( + params.entropy + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'getWalletBalances': { + + let serverResponse = await PL.servers.WEB3_SERVER.getWalletBalances( + params.host, + params.port, + params.interface, + params.walletDefinition + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'signData': { + + let serverResponse = await PL.servers.WEB3_SERVER.signData( + params.privateKey, + params.data + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'hashData': { + + let serverResponse = await PL.servers.WEB3_SERVER.hashData( + params.data + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'recoverAddress': { + + let serverResponse = await PL.servers.WEB3_SERVER.recoverAddress( + params.signature + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'mnemonicToPrivateKey': { + + let serverResponse = await PL.servers.WEB3_SERVER.mnemonicToPrivateKey( + params.mnemonic + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + default: { + SA.projects.foundations.utilities.httpResponses.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 + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) } } + } break - case 'CCXT': - { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + case 'CCXT': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - async function processRequest(body) { - try { - if (body === undefined) { return } - let params = JSON.parse(body) + async function processRequest(body) { + try { + if (body === undefined) { + return + } + let params = JSON.parse(body) - switch (params.method) { - case 'fetchMarkets': { + switch (params.method) { + case 'fetchMarkets': { - const exchangeClass = SA.nodeModules.ccxt[params.exchangeId] + const exchangeClass = SA.nodeModules.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() + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(ccxtMarkets), httpResponse) + return + } + case 'listExchanges': { + let exchanges = [] + for (let i = 0; i < SA.nodeModules.ccxt.exchanges.length; i++) { + let exchangeId = SA.nodeModules.ccxt.exchanges[i] + + const exchangeClass = SA.nodeModules.ccxt[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() + let ccxtExchange + try { + ccxtExchange = new exchangeClass(exchangeConstructorParams) + } catch (err) { + } + if (ccxtExchange === undefined) { + continue } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(ccxtMarkets), httpResponse) - return - } - case 'listExchanges': { - let exchanges = [] - for (let i = 0; i < SA.nodeModules.ccxt.exchanges.length; i++) { - let exchangeId = SA.nodeModules.ccxt.exchanges[i] - - const exchangeClass = SA.nodeModules.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) + 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) } } } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(exchanges), httpResponse) - return } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(exchanges), httpResponse) + return } - - let content = { - err: global.DEFAULT_FAIL_RESPONSE // method not supported - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(content), httpResponse) - - } catch (err) { - console.log('[INFO] httpInterface -> CCXT FetchMarkets -> Could not fetch markets.') - let error = { - result: 'Fail Because', - message: err.message - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) } + + let content = { + err: global.DEFAULT_FAIL_RESPONSE // method not supported + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(content), httpResponse) + + } catch (err) { + console.log('[INFO] httpInterface -> CCXT FetchMarkets -> Could not fetch markets.') + let error = { + result: 'Fail Because', + message: err.message + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) } } + } break - case 'Webhook': - { - switch (requestPath[2]) { // switch by command - case 'Fetch-Messages': { - let exchange = requestPath[3] - let market = requestPath[4] + case 'Webhook': { + switch (requestPath[2]) { // switch by command + case 'Fetch-Messages': { + let exchange = requestPath[3] + let market = requestPath[4] + + /* Some validations */ + if (exchange === undefined) { + console.log('[WARN] httpInterface -> Webhook -> Fetch-Messages -> Message with no Exchange received -> messageReceived = ' + messageReceived) + SA.projects.foundations.utilities.httpResponses.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) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + return + } + + let key = exchange + '-' + market + + let webhookMessages = webhook.get(key) + if (webhookMessages === undefined) { + webhookMessages = [] + } + + console.log('[INFO] httpInterface -> Webhook -> Fetch-Messages -> Exchange-Market = ' + exchange + '-' + market) + console.log('[INFO] httpInterface -> Webhook -> Fetch-Messages -> Messages Fetched by Webhooks Sensor Bot = ' + webhookMessages.length) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(webhookMessages), httpResponse) + webhookMessages = [] + + webhook.set(key, webhookMessages) + break + } + case 'New-Message': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + function processRequest(messageReceived) { + if (messageReceived === undefined) { + return + } + + let timestamp = (new Date()).valueOf() + let source = requestPath[3] + let exchange = requestPath[4] + let market = requestPath[5] /* Some validations */ + if (source === undefined) { + console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no Source received -> messageReceived = ' + messageReceived) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + return + } if (exchange === undefined) { - console.log('[WARN] httpInterface -> Webhook -> Fetch-Messages -> Message with no Exchange received -> messageReceived = ' + messageReceived) + console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no Exchange received -> messageReceived = ' + messageReceived) SA.projects.foundations.utilities.httpResponses.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) + console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no market received -> messageReceived = ' + messageReceived) SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } @@ -251,446 +301,1024 @@ exports.newHttpInterface = function newHttpInterface() { webhookMessages = [] } - console.log('[INFO] httpInterface -> Webhook -> Fetch-Messages -> Exchange-Market = ' + exchange + '-' + market) - console.log('[INFO] httpInterface -> Webhook -> Fetch-Messages -> Messages Fetched by Webhooks Sensor Bot = ' + webhookMessages.length) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(webhookMessages), httpResponse) - webhookMessages = [] - + webhookMessages.push([timestamp, source, messageReceived]) webhook.set(key, webhookMessages) - break - } - case 'New-Message': { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - function processRequest(messageReceived) { - if (messageReceived === undefined) { return } - - let timestamp = (new Date()).valueOf() - let source = requestPath[3] - let exchange = requestPath[4] - let market = requestPath[5] - - /* Some validations */ - if (source === undefined) { - console.log('[WARN] httpInterface -> Webhook -> New-Message -> Message with no Source received -> messageReceived = ' + messageReceived) - SA.projects.foundations.utilities.httpResponses.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) - SA.projects.foundations.utilities.httpResponses.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) - SA.projects.foundations.utilities.httpResponses.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) - - console.log('[INFO] httpInterface -> Webhook -> New-Message -> Exchange-Market = ' + exchange + '-' + market) - console.log('[INFO] httpInterface -> Webhook -> New-Message -> messageReceived = ' + messageReceived) - console.log('[INFO] httpInterface -> Webhook -> New-Message -> Messages waiting to be Fetched by Webhooks Sensor Bot = ' + webhookMessages.length) - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } - break - } - } - } - break - case 'Docs': - { - switch (requestPath[2]) { // switch by command - case 'Save-Node-Schema': { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let docsSchema = JSON.parse(body) - let project = requestPath[3] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Nodes' - - if (checkAllSchmemaDocuments('Node', docsSchema, filePath) === true) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } else { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - break + console.log('[INFO] httpInterface -> Webhook -> New-Message -> Exchange-Market = ' + exchange + '-' + market) + console.log('[INFO] httpInterface -> Webhook -> New-Message -> messageReceived = ' + messageReceived) + console.log('[INFO] httpInterface -> Webhook -> New-Message -> Messages waiting to be Fetched by Webhooks Sensor Bot = ' + webhookMessages.length) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) } - case 'Save-Concept-Schema': { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let docsSchema = JSON.parse(body) - let project = requestPath[3] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Concepts' - - if (checkAllSchmemaDocuments('Concept', docsSchema, filePath) === true) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } else { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - break - } - - case 'Save-Topic-Schema': { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let docsSchema = JSON.parse(body) - let project = requestPath[3] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Topics' - - if (checkAllSchmemaDocuments('Topic', docsSchema, filePath) === true) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } else { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - break - } - - case 'Save-Tutorial-Schema': { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let docsSchema = JSON.parse(body) - let project = requestPath[3] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Tutorials' - - if (checkAllSchmemaDocuments('Tutorial', docsSchema, filePath) === true) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } else { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) - } - - } catch (err) { - console.log('[ERROR] httpInterface -> Docs -> Save-Tutorial-Schema -> Method call produced an error.') - console.log('[ERROR] httpInterface -> Docs -> Save-Tutorial-Schema -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Docs -> Save-Tutorial-Schema -> Params Received = ' + body) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - break - } - - case 'Save-Review-Schema': { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let docsSchema = JSON.parse(body) - let project = requestPath[3] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Reviews' - - if (checkAllSchmemaDocuments('Review', docsSchema, filePath) === true) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } else { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) - } - - } catch (err) { - console.log('[ERROR] httpInterface -> Docs -> Save-Review-Schema -> Method call produced an error.') - console.log('[ERROR] httpInterface -> Docs -> Save-Review-Schema -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Docs -> Save-Review-Schema -> Params Received = ' + body) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - break - } - - case 'Save-Book-Schema': { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let docsSchema = JSON.parse(body) - let project = requestPath[3] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Books' - - if (checkAllSchmemaDocuments('Book', docsSchema, filePath) === true) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } else { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - break - } - } - - function checkAllSchmemaDocuments(category, docsSchema, filePath) { - const fs = SA.nodeModules.fs - let noErrorsDuringSaving = true - - for (let i = 0; i < docsSchema.length; i++) { - let schemaDocument = docsSchema[i] - /* - For some type of schemas we will save the file at an extra - folder derived from the document's type. - */ - let fileName = schemaDocument.type.toLowerCase() - for (let j = 0; j < 10; j++) { - fileName = cleanFileName(fileName) - } - let pageNumber = '00' + schemaDocument.pageNumber - let newFilepath = filePath - switch (category) { - case 'Topic': { - fileName = schemaDocument.topic.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase() - fileName = cleanFileName(fileName) - newFilepath = createPrefixDirectories(filePath, schemaDocument.topic) - break - } - case 'Tutorial': { - fileName = schemaDocument.tutorial.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase() - fileName = cleanFileName(fileName) - newFilepath = createPrefixDirectories(filePath, schemaDocument.tutorial) - break - } - case 'Review': { - fileName = schemaDocument.review.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase() - fileName = cleanFileName(fileName) - newFilepath = createPrefixDirectories(filePath, schemaDocument.review) - break - } - case 'Node': { - newFilepath = createPrefixDirectories(filePath, schemaDocument.type) - break - } - case 'Concept': { - newFilepath = createPrefixDirectories(filePath, schemaDocument.type) - break - } - } - - function createPrefixDirectories(filePath, schemaTextToUse) { - let firstLetter = schemaTextToUse.substring(0, 1) - createNewDir(filePath + '/' + firstLetter) - let extraWord = schemaTextToUse.split(' ')[0] - createNewDir(filePath + '/' + firstLetter + '/' + extraWord) - return filePath + '/' + firstLetter + '/' + extraWord + '/' + cleanFileName(schemaTextToUse) - } - - fileName = fileName + '.json' - - if (schemaDocument.deleted === true) { - try { - fs.unlinkSync(newFilepath + '/' + fileName) - console.log('[SUCCESS] ' + newFilepath + '/' + fileName + ' deleted.') - } catch (err) { - noErrorsDuringSaving = false - console.log('[ERROR] httpInterface -> Docs -> Delete -> ' + newFilepath + '/' + fileName + ' could not be deleted.') - console.log('[ERROR] httpInterface -> Docs -> Delete -> Resolve the issue that is preventing the Client to delete this file. Look at the error message below as a guide. At the UI you will need to delete this page again in order for the Client to retry next time you execute the docs.save command.') - console.log('[ERROR] httpInterface -> Docs -> Delete -> err.stack = ' + err.stack) - } - } else { - if (schemaDocument.updated === true || schemaDocument.created === true) { - try { - let created = schemaDocument.created - let updated = schemaDocument.updated - schemaDocument.updated = undefined - schemaDocument.created = undefined - let fileContent = JSON.stringify(schemaDocument, undefined, 4) - createNewDir(newFilepath) - fs.writeFileSync(newFilepath + '/' + fileName, fileContent) - if (created === true) { - console.log('[SUCCESS] ' + newFilepath + '/' + fileName + ' created.') - } else { - if (updated === true) { - console.log('[SUCCESS] ' + newFilepath + '/' + fileName + ' updated.') - } - } - } catch (err) { - noErrorsDuringSaving = false - console.log('[ERROR] httpInterface -> Docs -> Save -> ' + newFilepath + '/' + fileName + ' could not be created / updated.') - console.log('[ERROR] httpInterface -> Docs -> Save -> err.stack = ' + err.stack) - } - } - } - - function createNewDir(path) { - try { - fs.mkdirSync(path, {recursive: true}) - } catch (err) { - if (err.message.indexOf('file already exists') < 0) { - throw (err) - } - } - } - } - - return noErrorsDuringSaving - } - - function cleanFileName(fileName) { - for (let i = 0; i < 100; i++) { - fileName = fileName - .replace(' ', '-') - .replace('--', '-') - .replace('?', '') - .replace('#', '') - .replace('$', '') - .replace('%', '') - .replace('^', '') - .replace('&', '') - .replace('*', '') - .replace('(', '') - .replace(')', '') - .replace('!', '') - .replace('..', '.') - .replace(',', '') - .replace('\'', '') - } - return fileName - } - } - break - case 'App': - { - // If running the electron app do not try to get git tool. I don't allow it. - if (process.env.SA_MODE === 'gitDisable') { - console.log('[WARN] No contributions on binary distributions. Do manual installation') break } - switch (requestPath[2]) { // switch by command + } + } + break + case 'Docs': { + switch (requestPath[2]) { // switch by command + case 'Save-Node-Schema': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - case 'Contribute': { + async function processRequest(body) { try { - let commitMessage = unescape(requestPath[3]) - const username = unescape(requestPath[4]) - const token = unescape(requestPath[5]) - const currentBranch = unescape(requestPath[6]) - const contributionsBranch = unescape(requestPath[7]) - let error - - /* Unsaving # */ - for (let i = 0; i < 10; i++) { - commitMessage = commitMessage.replace('_SLASH_', '/') - commitMessage = commitMessage.replace('_HASHTAG_', '#') + if (body === undefined) { + return } - contribute() + let docsSchema = JSON.parse(body) + let project = requestPath[3] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Nodes' - async function contribute() { - const { lookpath } = SA.nodeModules.lookpath - const gitpath = await lookpath('git') - if (gitpath === undefined) { - console.log('[ERROR] `git` not installed.') + if (checkAllSchmemaDocuments('Node', docsSchema, filePath) === true) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } else { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + + break + } + + case 'Save-Concept-Schema': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + try { + if (body === undefined) { + return + } + + let docsSchema = JSON.parse(body) + let project = requestPath[3] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Concepts' + + if (checkAllSchmemaDocuments('Concept', docsSchema, filePath) === true) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } else { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + + break + } + + case 'Save-Topic-Schema': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + try { + if (body === undefined) { + return + } + + let docsSchema = JSON.parse(body) + let project = requestPath[3] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Topics' + + if (checkAllSchmemaDocuments('Topic', docsSchema, filePath) === true) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } else { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + + break + } + + case 'Save-Tutorial-Schema': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + try { + if (body === undefined) { + return + } + + let docsSchema = JSON.parse(body) + let project = requestPath[3] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Tutorials' + + if (checkAllSchmemaDocuments('Tutorial', docsSchema, filePath) === true) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } else { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + } + + } catch (err) { + console.log('[ERROR] httpInterface -> Docs -> Save-Tutorial-Schema -> Method call produced an error.') + console.log('[ERROR] httpInterface -> Docs -> Save-Tutorial-Schema -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> Docs -> Save-Tutorial-Schema -> Params Received = ' + body) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + + break + } + + case 'Save-Review-Schema': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + try { + if (body === undefined) { + return + } + + let docsSchema = JSON.parse(body) + let project = requestPath[3] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Reviews' + + if (checkAllSchmemaDocuments('Review', docsSchema, filePath) === true) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } else { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + } + + } catch (err) { + console.log('[ERROR] httpInterface -> Docs -> Save-Review-Schema -> Method call produced an error.') + console.log('[ERROR] httpInterface -> Docs -> Save-Review-Schema -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> Docs -> Save-Review-Schema -> Params Received = ' + body) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + + break + } + + case 'Save-Book-Schema': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + try { + if (body === undefined) { + return + } + + let docsSchema = JSON.parse(body) + let project = requestPath[3] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/Docs-Books' + + if (checkAllSchmemaDocuments('Book', docsSchema, filePath) === true) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } else { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_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 + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + + break + } + } + + function checkAllSchmemaDocuments(category, docsSchema, filePath) { + const fs = SA.nodeModules.fs + let noErrorsDuringSaving = true + + for (let i = 0; i < docsSchema.length; i++) { + let schemaDocument = docsSchema[i] + /* + For some type of schemas we will save the file at an extra + folder derived from the document's type. + */ + let fileName = schemaDocument.type.toLowerCase() + for (let j = 0; j < 10; j++) { + fileName = cleanFileName(fileName) + } + let pageNumber = '00' + schemaDocument.pageNumber + let newFilepath = filePath + switch (category) { + case 'Topic': { + fileName = schemaDocument.topic.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase() + fileName = cleanFileName(fileName) + newFilepath = createPrefixDirectories(filePath, schemaDocument.topic) + break + } + case 'Tutorial': { + fileName = schemaDocument.tutorial.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase() + fileName = cleanFileName(fileName) + newFilepath = createPrefixDirectories(filePath, schemaDocument.tutorial) + break + } + case 'Review': { + fileName = schemaDocument.review.toLowerCase() + '-' + pageNumber.substring(pageNumber.length - 3, pageNumber.length) + '-' + schemaDocument.type.toLowerCase() + fileName = cleanFileName(fileName) + newFilepath = createPrefixDirectories(filePath, schemaDocument.review) + break + } + case 'Node': { + newFilepath = createPrefixDirectories(filePath, schemaDocument.type) + break + } + case 'Concept': { + newFilepath = createPrefixDirectories(filePath, schemaDocument.type) + break + } + } + + function createPrefixDirectories(filePath, schemaTextToUse) { + let firstLetter = schemaTextToUse.substring(0, 1) + createNewDir(filePath + '/' + firstLetter) + let extraWord = schemaTextToUse.split(' ')[0] + createNewDir(filePath + '/' + firstLetter + '/' + extraWord) + return filePath + '/' + firstLetter + '/' + extraWord + '/' + cleanFileName(schemaTextToUse) + } + + fileName = fileName + '.json' + + if (schemaDocument.deleted === true) { + try { + fs.unlinkSync(newFilepath + '/' + fileName) + console.log('[SUCCESS] ' + newFilepath + '/' + fileName + ' deleted.') + } catch (err) { + noErrorsDuringSaving = false + console.log('[ERROR] httpInterface -> Docs -> Delete -> ' + newFilepath + '/' + fileName + ' could not be deleted.') + console.log('[ERROR] httpInterface -> Docs -> Delete -> Resolve the issue that is preventing the Client to delete this file. Look at the error message below as a guide. At the UI you will need to delete this page again in order for the Client to retry next time you execute the docs.save command.') + console.log('[ERROR] httpInterface -> Docs -> Delete -> err.stack = ' + err.stack) + } + } else { + if (schemaDocument.updated === true || schemaDocument.created === true) { + try { + let created = schemaDocument.created + let updated = schemaDocument.updated + schemaDocument.updated = undefined + schemaDocument.created = undefined + let fileContent = JSON.stringify(schemaDocument, undefined, 4) + createNewDir(newFilepath) + fs.writeFileSync(newFilepath + '/' + fileName, fileContent) + if (created === true) { + console.log('[SUCCESS] ' + newFilepath + '/' + fileName + ' created.') } else { - await doGit() - if (error !== undefined) { + if (updated === true) { + console.log('[SUCCESS] ' + newFilepath + '/' + fileName + ' updated.') + } + } + } catch (err) { + noErrorsDuringSaving = false + console.log('[ERROR] httpInterface -> Docs -> Save -> ' + newFilepath + '/' + fileName + ' could not be created / updated.') + console.log('[ERROR] httpInterface -> Docs -> Save -> err.stack = ' + err.stack) + } + } + } - let docs = { - project: 'Foundations', - category: 'Topic', - type: 'App Error - Contribution Not Sent', - anchor: undefined, - placeholder: {} - } + function createNewDir(path) { + try { + fs.mkdirSync(path, {recursive: true}) + } catch (err) { + if (err.message.indexOf('file already exists') < 0) { + throw (err) + } + } + } + } - respondWithDocsObject(docs, error) - return + return noErrorsDuringSaving + } + + function cleanFileName(fileName) { + for (let i = 0; i < 100; i++) { + fileName = fileName + .replace(' ', '-') + .replace('--', '-') + .replace('?', '') + .replace('#', '') + .replace('$', '') + .replace('%', '') + .replace('^', '') + .replace('&', '') + .replace('*', '') + .replace('(', '') + .replace(')', '') + .replace('!', '') + .replace('..', '.') + .replace(',', '') + .replace('\'', '') + } + return fileName + } + } + break + case 'App': { + // If running the electron app do not try to get git tool. I don't allow it. + if (process.env.SA_MODE === 'gitDisable') { + console.log('[WARN] No contributions on binary distributions. Do manual installation') + break + } + switch (requestPath[2]) { // switch by command + + case 'Contribute': { + try { + let commitMessage = unescape(requestPath[3]) + const username = unescape(requestPath[4]) + const token = unescape(requestPath[5]) + const currentBranch = unescape(requestPath[6]) + const contributionsBranch = unescape(requestPath[7]) + let error + + /* Unsaving # */ + for (let i = 0; i < 10; i++) { + commitMessage = commitMessage.replace('_SLASH_', '/') + commitMessage = commitMessage.replace('_HASHTAG_', '#') + } + + contribute() + + async function contribute() { + const {lookpath} = SA.nodeModules.lookpath + const gitpath = await lookpath('git') + if (gitpath === undefined) { + console.log('[ERROR] `git` not installed.') + } else { + await doGit() + if (error !== undefined) { + + let docs = { + project: 'Foundations', + category: 'Topic', + type: 'App Error - Contribution Not Sent', + anchor: undefined, + placeholder: {} } - await doGithub() + respondWithDocsObject(docs, error) + return + } + + await doGithub() + if (error !== undefined) { + + let docs = { + project: 'Foundations', + category: 'Topic', + type: 'App Error - Contribution Not Sent', + anchor: undefined, + placeholder: {} + } + console.log('respond with docs ') + + respondWithDocsObject(docs, error) + return + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } + } + + async function doGit() { + const simpleGit = SA.nodeModules.simpleGit + const options = { + baseDir: process.cwd(), + binary: 'git', + maxConcurrentProcesses: 6, + } + const git = simpleGit(options) + + try { + await git.add('./*') + await git.commit(commitMessage) + await git.push('origin', currentBranch) + } catch (err) { + console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> Method call produced an error.') + console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> commitMessage = ' + commitMessage) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> currentBranch = ' + currentBranch) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> contributionsBranch = ' + contributionsBranch) + console.log('') + console.log('Troubleshooting Tips:') + console.log('') + console.log('1. Make sure that you have set up your Github Username and Token at the APIs -> Github API node at the workspace.') + console.log('2. Make sure you are running the latest version of Git available for your OS.') + console.log('3. Make sure that you have cloned your Superalgos repository fork, and not the main Superalgos repository.') + console.log('4. If your fork is old, you might need to do an app.update and also a node setup at every branch. If you just reforked all is good.') + error = err + } + } + + async function doGithub() { + + const {Octokit} = SA.nodeModules.octokit + + const octokit = new Octokit({ + auth: token, + userAgent: 'Superalgos Beta 12' + }) + + const repo = 'Superalgos' + const owner = 'Superalgos' + const head = username + ':' + contributionsBranch + const base = currentBranch + const title = 'Contribution: ' + commitMessage + + try { + await octokit.pulls.create({ + owner, + repo, + title, + head, + base, + }); + } catch (err) { + if (err.stack.indexOf('A pull request already exists') >= 0) { + return + } else { + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> Method call produced an error.') + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> commitMessage = ' + commitMessage) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> username = ' + username) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> token ends with = ' + '...' + token.substring(token.length - 10)) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> currentBranch = ' + currentBranch) + console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> contributionsBranch = ' + contributionsBranch) + error = err + } + } + } + + } 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 -> commitMessage = ' + commitMessage) + console.log('[ERROR] httpInterface -> App -> Contribute -> username = ' + username) + console.log('[ERROR] httpInterface -> App -> Contribute -> token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] httpInterface -> App -> Contribute -> token ends with = ' + '...' + token.substring(token.length - 10)) + console.log('[ERROR] httpInterface -> App -> Contribute -> currentBranch = ' + currentBranch) + console.log('[ERROR] httpInterface -> App -> Contribute -> contributionsBranch = ' + contributionsBranch) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + break + } + + case 'Update': { + try { + const currentBranch = unescape(requestPath[3]) + update() + + async function update() { + const {lookpath} = SA.nodeModules.lookpath + const gitpath = await lookpath('git'); + if (gitpath === undefined) { + console.log('[ERROR] `git` not installed.') + } else { + let result = await doGit() + + if (result.error === undefined) { + let customResponse = { + result: global.CUSTOM_OK_RESPONSE.result, + message: result.message + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) + } else { + + let docs = { + project: 'Foundations', + category: 'Topic', + type: 'App Error - Update Failed', + anchor: undefined, + placeholder: {} + } + + respondWithDocsObject(docs, result.error) + + } + } + } + + async function doGit() { + const simpleGit = SA.nodeModules.simpleGit + const options = { + baseDir: process.cwd(), + binary: 'git', + maxConcurrentProcesses: 6, + } + const git = simpleGit(options) + + let message + try { + message = await git.pull('https://github.com/Superalgos/Superalgos', currentBranch) + return {message: message} + } catch (err) { + console.log('[ERROR] Error updating ' + currentBranch) + console.log(err.stack) + return {error: err} + } + } + + } catch (err) { + console.log('[ERROR] httpInterface -> App -> Update -> Method call produced an error.') + console.log('[ERROR] httpInterface -> App -> Update -> err.stack = ' + err.stack) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + break + } + + case 'Checkout': { + try { + const currentBranch = unescape(requestPath[3]) + let error + + checkout() + + async function checkout() { + const {lookpath} = SA.nodeModules.lookpath + const gitpath = await lookpath('git'); + if (gitpath === undefined) { + console.log('[ERROR] `git` not installed.') + } else { + await doGit() + + if (error === undefined) { + // Run node setup to prepare instance for branch change + await runNodeSetup() + // Return to UI that Branch is successfully changed + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } else { + let docs = { + project: 'Foundations', + category: 'Topic', + type: 'Switching Branches - Current Branch Not Changed', + anchor: undefined, + placeholder: {} + } + + respondWithDocsObject(docs, error) + } + } + } + + async function doGit() { + const simpleGit = SA.nodeModules.simpleGit + const options = { + baseDir: process.cwd(), + binary: 'git', + maxConcurrentProcesses: 6, + } + const git = simpleGit(options) + try { + await git.checkout(currentBranch) + + // Check to see it main repo has been set as upstream + let remotes = await git.getRemotes(); + let isUpstreamSet + for (let remote in remotes) { + if (remotes[remote].name === 'upstream') { + isUpstreamSet = true + } else { + isUpstreamSet = false + } + } + // If upstream has not been set. Set it now + if (isUpstreamSet === false) { + await git.addRemote('upstream', 'https://github.com/Superalgos/Superalgos'); + } + // Pull branch from main repo + await git.pull('upstream', currentBranch); + // Reset branch to match main repo + let upstreamLocation = `upstream/${currentBranch}` + await git.reset('hard', [upstreamLocation]) + + } catch (err) { + console.log('[ERROR] Error changing current branch to ' + currentBranch) + console.log(err.stack) + error = err + } + } + + async function runNodeSetup() { + console.log("Running Node setup to adjust for new Branch") + const process = SA.nodeModules.process + const childProcess = SA.nodeModules.childProcess + + let dir = process.cwd() + let command = "node setup noShortcuts"; + let stdout = childProcess.execSync(command, + { + cwd: dir + }).toString(); + + console.log("Node Setup has completed with the following result:", stdout) + } + + } catch (err) { + console.log('[ERROR] httpInterface -> App -> Update -> Method call produced an error.') + console.log('[ERROR] httpInterface -> App -> Update -> err.stack = ' + err.stack) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + break + } + + case 'Branch': { + try { + branch() + + async function branch() { + const {lookpath} = SA.nodeModules.lookpath + const gitpath = await lookpath('git'); + if (gitpath === undefined) { + console.log('[ERROR] `git` not installed.') + } else { + let result = await doGit() + + if (result.error === undefined) { + let customResponse = { + result: global.CUSTOM_OK_RESPONSE.result, + message: result + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) + } else { + let docs = { + project: 'Foundations', + category: 'Topic', + type: 'App Error - Could Not Get Current Branch', + anchor: undefined, + placeholder: {} + } + + respondWithDocsObject(docs, error) + } + } + } + + async function doGit() { + const simpleGit = SA.nodeModules.simpleGit + const options = { + baseDir: process.cwd(), + binary: 'git', + maxConcurrentProcesses: 6, + } + const git = simpleGit(options) + try { + return await git.branch() + } catch (err) { + console.log('[ERROR] Error reading current branch.') + console.log(err.stack) + } + } + + } catch (err) { + console.log('[ERROR] httpInterface -> App -> Update -> Method call produced an error.') + console.log('[ERROR] httpInterface -> App -> Update -> err.stack = ' + err.stack) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + break + } + + case 'FixAppSchema': { + /* + We will use this process when we have moved APP SCHEMA files from one project to another, and we need to fix the + actions where this node was referenced, so that it points to the new project where the node has moved to. + */ + let customResponse = { + result: global.CUSTOM_OK_RESPONSE.result, + message: '' + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) + + console.log('Fixing App Schemas...') + + let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS) + let PROJECTS_MAP = new Map() + let directoryCount = 0 + let allAppSchemas = [] + let allAppSchemasFilePaths = [] + let allAppSchemasFileProjects = [] + + for (let i = 0; i < projects.length; i++) { + let project = projects[i] + + + const fs = SA.nodeModules.fs + let folder = 'App-Schema' + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/' + SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(filePath + folder, onFilesReady) + + function onFilesReady(files) { + try { + let SCHEMA_MAP = new Map() + + console.log('files.length... ' + files.length) + + for (let k = 0; k < files.length; k++) { + let name = files[k] + let nameSplitted = name.split(folder) + let fileName = nameSplitted[1] + for (let i = 0; i < 10; i++) { + fileName = fileName.replace('\\', '/') + } + let fileToRead = filePath + folder + fileName + + console.log('Reading file... ' + fileToRead) + + let fileContent = fs.readFileSync(fileToRead) + let schemaDocument + try { + schemaDocument = JSON.parse(fileContent) + SCHEMA_MAP.set(schemaDocument.type, schemaDocument) + allAppSchemas.push(schemaDocument) + allAppSchemasFilePaths.push(fileToRead) + allAppSchemasFileProjects.push(project) + } catch (err) { + console.log('[ERROR] sendSchema -> Error Parsing JSON File: ' + fileToRead + ' .Error = ' + err.stack) + return + } + } + PROJECTS_MAP.set(project, SCHEMA_MAP) + directoryCount++ + + console.log('directoryCount = ' + directoryCount, 'projects.length = ' + projects.length) + //console.log(Array.from(PROJECTS_MAP.get(project).keys())) + if (directoryCount === projects.length) { + fixSchemas() + } + } catch (err) { + console.log(err.stack) + } + } + } + + function fixSchemas() { + try { + console.log('fixSchemas...' + allAppSchemas.length) + let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS) + const fs = SA.nodeModules.fs + let needFixing = 0 + for (let i = 0; i < allAppSchemas.length; i++) { + let schemaDocument = allAppSchemas[i] + let wasUpdated = false + for (let j = 0; j < schemaDocument.menuItems.length; j++) { + let menuItem = schemaDocument.menuItems[j] + if (menuItem.relatedUiObject !== undefined && menuItem.relatedUiObjectProject === undefined) { + needFixing++ + + let hits = 0 + let foundProject + let multiProject = '' + for (let k = 0; k < projects.length; k++) { + let project = projects[k] + + let testDocument = PROJECTS_MAP.get(project).get(menuItem.relatedUiObject) + if (testDocument !== undefined) { + hits++ + foundProject = project + multiProject = multiProject + ' -> ' + project + + let fileProject = allAppSchemasFileProjects[i] + //console.log(fileProject, project) + if (fileProject === project) { + /* If the project of the file is the same as the project found, then we consider this a match*/ + hits = 1 + continue + } + } + } + + if (hits === 0) { + console.log('Problem With No Solution #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject) + console.log('This Node Type was NOT FOUND at any project. ' + menuItem.relatedUiObject) + continue + } + if (hits === 1) { + console.log('Problem With One Solution #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject, ' Found Project:' + foundProject) + + menuItem.relatedUiObjectProject = foundProject + wasUpdated = true + continue + } + console.log('Problem With MULTIPLE Solutions #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject, ' Found at these Projects:' + multiProject) + } + } + + if (wasUpdated === true) { + let fileContent = JSON.stringify(schemaDocument, undefined, 4) + let filePath = allAppSchemasFilePaths[i] + //console.log('Saving File at ' + filePath) + //console.log(fileContent) + //fs.writeFileSync(filePath, fileContent) + } + } + } catch (err) { + console.log(err.stack) + } + } + + break + } + } + + function respondWithDocsObject(docs, error) { + + if (error.message !== undefined) { + docs.placeholder.errorMessage = { + style: 'Error', + text: error.message + } + } + if (error.stack !== undefined) { + docs.placeholder.errorStack = { + style: 'Javascript', + text: error.stack + } + } + if (error.code !== undefined) { + docs.placeholder.errorCode = { + style: 'Json', + text: error.code + } + } + + docs.placeholder.errorDetails = { + style: 'Json', + text: JSON.stringify(error, undefined, 4) + } + + let customResponse = { + result: global.CUSTOM_FAIL_RESPONSE.result, + docs: docs + } + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) + + } + } + break + case 'GOV': { + /* + This is the Governance endpoint at the Http Interface. All methods + related to the Governance System are implemented here and routed + to the backend Servers that can process them. + */ + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + try { + if (body === undefined) { + return + } + + let params = JSON.parse(body) + + switch (params.method) { + case 'getGithubStars': { + + let serverResponse = await PL.servers.GITHUB_SERVER.getGithubStars( + params.repository, + params.username, + params.token + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'getGithubWatchers': { + + let serverResponse = await PL.servers.GITHUB_SERVER.getGithubWatchers( + params.repository, + params.username, + params.token + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'getGithubForks': { + + let serverResponse = await PL.servers.GITHUB_SERVER.getGithubForks( + params.repository, + params.username, + params.token + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'mergePullRequests': { + + let serverResponse = await PL.servers.GITHUB_SERVER.mergePullRequests( + params.commitMessage, + params.username, + params.token + ) + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) + + setInterval( + PL.servers.GITHUB_SERVER.mergePullRequests, + 60000, + params.commitMessage, + params.username, + params.token + ) + + return + } + + case 'UserProfile': { + try { + + let mess = unescape(params.commitMessage) + const username = unescape(params.username) + const token = unescape(params.token) + const currentBranch = unescape(params.currentBranch) + const contributionsBranch = unescape(params.contributionsBranch) + + let error + + await updateUser() + + async function updateUser() { + + await doGithubUser() if (error !== undefined) { let docs = { - project: 'Foundations', + project: 'Governance', category: 'Topic', - type: 'App Error - Contribution Not Sent', + type: 'Gov Error - Contribution Not Sent', anchor: undefined, placeholder: {} } @@ -700,740 +1328,55 @@ exports.newHttpInterface = function newHttpInterface() { return } SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } - } - async function doGit() { - const simpleGit = SA.nodeModules.simpleGit - const options = { - baseDir: process.cwd(), - binary: 'git', - maxConcurrentProcesses: 6, - } - const git = simpleGit(options) + async function doGithubUser() { - try { - await git.add('./*') - await git.commit(commitMessage) - await git.push('origin', currentBranch) - } catch (err) { - console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> Method call produced an error.') - console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> commitMessage = ' + commitMessage) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> currentBranch = ' + currentBranch) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGit -> contributionsBranch = ' + contributionsBranch) - console.log('') - console.log('Troubleshooting Tips:') - console.log('') - console.log('1. Make sure that you have set up your Github Username and Token at the APIs -> Github API node at the workspace.') - console.log('2. Make sure you are running the latest version of Git available for your OS.') - console.log('3. Make sure that you have cloned your Superalgos repository fork, and not the main Superalgos repository.') - console.log('4. If your fork is old, you might need to do an app.update and also a node setup at every branch. If you just reforked all is good.') - error = err - } - } + const {Octokit} = SA.nodeModules.octokit - async function doGithub() { + const octokit = new Octokit({ + auth: token, + userAgent: 'Superalgos Beta 12' + }) - const { Octokit } = SA.nodeModules.octokit + const repo = 'Superalgos' + const owner = 'Superalgos' + const head = username + ':' + contributionsBranch + const base = currentBranch + const title = 'Contribution: ' + mess + const path = 'Projects/Governance/Plugins/User-Profiles/' + username + '.json'; - const octokit = new Octokit({ - auth: token, - userAgent: 'Superalgos Beta 12' - }) + const sha = await getSHA(path); - const repo = 'Superalgos' - const owner = 'Superalgos' - const head = username + ':' + contributionsBranch - const base = currentBranch - const title = 'Contribution: ' + commitMessage - - try { - await octokit.pulls.create({ - owner, - repo, - title, - head, - base, - }); - } catch (err) { - if (err.stack.indexOf('A pull request already exists') >= 0) { + if (sha === undefined) { + console.log('***** Abort GOV.USERPROFILE *****') return - } else { - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> Method call produced an error.') - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> commitMessage = ' + commitMessage) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> username = ' + username) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> token ends with = ' + '...' + token.substring(token.length - 10)) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> currentBranch = ' + currentBranch) - console.log('[ERROR] httpInterface -> App -> Contribute -> doGithub -> contributionsBranch = ' + contributionsBranch) - error = err } - } - } - } 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 -> commitMessage = ' + commitMessage) - console.log('[ERROR] httpInterface -> App -> Contribute -> username = ' + username) - console.log('[ERROR] httpInterface -> App -> Contribute -> token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> App -> Contribute -> token ends with = ' + '...' + token.substring(token.length - 10)) - console.log('[ERROR] httpInterface -> App -> Contribute -> currentBranch = ' + currentBranch) - console.log('[ERROR] httpInterface -> App -> Contribute -> contributionsBranch = ' + contributionsBranch) + let file = await SA.projects.communityPlugins.utilities.plugins.getPluginFileContent( + 'Governance', + 'User-Profiles', + username + '.json' + ) - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - break - } + let buff = new Buffer.from(file, 'utf-8'); + let encodedFile = buff.toString('base64'); - case 'Update': { - try { - const currentBranch = unescape(requestPath[3]) - update() - - async function update() { - const { lookpath } = SA.nodeModules.lookpath - const gitpath = await lookpath('git'); - if (gitpath === undefined) { - console.log('[ERROR] `git` not installed.') - } else { - let result = await doGit() - - if (result.error === undefined) { - let customResponse = { - result: global.CUSTOM_OK_RESPONSE.result, - message: result.message - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) - } else { - - let docs = { - project: 'Foundations', - category: 'Topic', - type: 'App Error - Update Failed', - anchor: undefined, - placeholder: {} - } - - respondWithDocsObject(docs, result.error) - - } - } - } - - async function doGit() { - const simpleGit = SA.nodeModules.simpleGit - const options = { - baseDir: process.cwd(), - binary: 'git', - maxConcurrentProcesses: 6, - } - const git = simpleGit(options) - - let message - try { - message = await git.pull('https://github.com/Superalgos/Superalgos', currentBranch) - return { message: message } - } catch (err) { - console.log('[ERROR] Error updating ' + currentBranch) - console.log(err.stack) - return { error: err } - } - } - - } catch (err) { - console.log('[ERROR] httpInterface -> App -> Update -> Method call produced an error.') - console.log('[ERROR] httpInterface -> App -> Update -> err.stack = ' + err.stack) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - break - } - - case 'Checkout': { - try { - const currentBranch = unescape(requestPath[3]) - let error - - checkout() - - async function checkout() { - const { lookpath } = SA.nodeModules.lookpath - const gitpath = await lookpath('git'); - if (gitpath === undefined) { - console.log('[ERROR] `git` not installed.') - } else { - await doGit() - - if (error === undefined) { - // Run node setup to prepare instance for branch change - await runNodeSetup() - // Return to UI that Branch is successfully changed - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } else { - let docs = { - project: 'Foundations', - category: 'Topic', - type: 'Switching Branches - Current Branch Not Changed', - anchor: undefined, - placeholder: {} - } - - respondWithDocsObject(docs, error) - } - } - } - - async function doGit() { - const simpleGit = SA.nodeModules.simpleGit - const options = { - baseDir: process.cwd(), - binary: 'git', - maxConcurrentProcesses: 6, - } - const git = simpleGit(options) - try { - await git.checkout(currentBranch) - - // Check to see it main repo has been set as upstream - let remotes = await git.getRemotes(); - let isUpstreamSet - for (let remote in remotes) { - if (remotes[remote].name === 'upstream') { - isUpstreamSet = true + try { + await octokit.repos.createOrUpdateFileContents({ + owner: username, + repo: "Superalgos", + path, + message: title, + content: encodedFile, + sha, + branch: base + }); + } catch (err) { + if (err.stack.indexOf('Error User Commit') >= 0) { + return } else { - isUpstreamSet = false - } - } - // If upstream has not been set. Set it now - if (isUpstreamSet === false) { - await git.addRemote('upstream', 'https://github.com/Superalgos/Superalgos'); - } - // Pull branch from main repo - await git.pull('upstream', currentBranch); - // Reset branch to match main repo - let upstreamLocation = `upstream/${currentBranch}` - await git.reset('hard', [upstreamLocation]) - - } catch (err) { - console.log('[ERROR] Error changing current branch to ' + currentBranch) - console.log(err.stack) - error = err - } - } - - async function runNodeSetup() { - console.log("Running Node setup to adjust for new Branch") - const process = SA.nodeModules.process - const childProcess = SA.nodeModules.childProcess - - let dir = process.cwd() - let command = "node setup noShortcuts"; - let stdout = childProcess.execSync(command, - { - cwd: dir - }).toString(); - - console.log("Node Setup has completed with the following result:", stdout) - } - - } catch (err) { - console.log('[ERROR] httpInterface -> App -> Update -> Method call produced an error.') - console.log('[ERROR] httpInterface -> App -> Update -> err.stack = ' + err.stack) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - break - } - - case 'Branch': { - try { - branch() - - async function branch() { - const { lookpath } = SA.nodeModules.lookpath - const gitpath = await lookpath('git'); - if (gitpath === undefined) { - console.log('[ERROR] `git` not installed.') - } else { - let result = await doGit() - - if (result.error === undefined) { - let customResponse = { - result: global.CUSTOM_OK_RESPONSE.result, - message: result - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) - } else { - let docs = { - project: 'Foundations', - category: 'Topic', - type: 'App Error - Could Not Get Current Branch', - anchor: undefined, - placeholder: {} - } - - respondWithDocsObject(docs, error) - } - } - } - - async function doGit() { - const simpleGit = SA.nodeModules.simpleGit - const options = { - baseDir: process.cwd(), - binary: 'git', - maxConcurrentProcesses: 6, - } - const git = simpleGit(options) - try { - return await git.branch() - } catch (err) { - console.log('[ERROR] Error reading current branch.') - console.log(err.stack) - } - } - - } catch (err) { - console.log('[ERROR] httpInterface -> App -> Update -> Method call produced an error.') - console.log('[ERROR] httpInterface -> App -> Update -> err.stack = ' + err.stack) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - break - } - - case 'FixAppSchema': { - /* - We will use this process when we have moved APP SCHEMA files from one project to another, and we need to fix the - actions where this node was referenced, so that it points to the new project where the node has moved to. - */ - let customResponse = { - result: global.CUSTOM_OK_RESPONSE.result, - message: '' - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) - - console.log('Fixing App Schemas...') - - let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS) - let PROJECTS_MAP = new Map() - let directoryCount = 0 - let allAppSchemas = [] - let allAppSchemasFilePaths = [] - let allAppSchemasFileProjects = [] - - for (let i = 0; i < projects.length; i++) { - let project = projects[i] - - - - const fs = SA.nodeModules.fs - let folder = 'App-Schema' - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/' - SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(filePath + folder, onFilesReady) - - function onFilesReady(files) { - try { - let SCHEMA_MAP = new Map() - - console.log('files.length... ' + files.length) - - for (let k = 0; k < files.length; k++) { - let name = files[k] - let nameSplitted = name.split(folder) - let fileName = nameSplitted[1] - for (let i = 0; i < 10; i++) { - fileName = fileName.replace('\\', '/') - } - let fileToRead = filePath + folder + fileName - - console.log('Reading file... ' + fileToRead) - - let fileContent = fs.readFileSync(fileToRead) - let schemaDocument - try { - schemaDocument = JSON.parse(fileContent) - SCHEMA_MAP.set(schemaDocument.type, schemaDocument) - allAppSchemas.push(schemaDocument) - allAppSchemasFilePaths.push(fileToRead) - allAppSchemasFileProjects.push(project) - } catch (err) { - console.log('[ERROR] sendSchema -> Error Parsing JSON File: ' + fileToRead + ' .Error = ' + err.stack) - return - } - } - PROJECTS_MAP.set(project, SCHEMA_MAP) - directoryCount++ - - console.log('directoryCount = ' + directoryCount, 'projects.length = ' + projects.length) - //console.log(Array.from(PROJECTS_MAP.get(project).keys())) - if (directoryCount === projects.length) { - fixSchemas() - } - } catch (err) { - console.log(err.stack) - } - } - } - - function fixSchemas() { - try { - console.log('fixSchemas...' + allAppSchemas.length) - let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS) - const fs = SA.nodeModules.fs - let needFixing = 0 - for (let i = 0; i < allAppSchemas.length; i++) { - let schemaDocument = allAppSchemas[i] - let wasUpdated = false - for (let j = 0; j < schemaDocument.menuItems.length; j++) { - let menuItem = schemaDocument.menuItems[j] - if (menuItem.relatedUiObject !== undefined && menuItem.relatedUiObjectProject === undefined) { - needFixing++ - - let hits = 0 - let foundProject - let multiProject = '' - for (let k = 0; k < projects.length; k++) { - let project = projects[k] - - let testDocument = PROJECTS_MAP.get(project).get(menuItem.relatedUiObject) - if (testDocument !== undefined) { - hits++ - foundProject = project - multiProject = multiProject + ' -> ' + project - - let fileProject = allAppSchemasFileProjects[i] - //console.log(fileProject, project) - if (fileProject === project) { - /* If the project of the file is the same as the project found, then we consider this a match*/ - hits = 1 - continue - } - } - } - - if (hits === 0) { - console.log('Problem With No Solution #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject) - console.log('This Node Type was NOT FOUND at any project. ' + menuItem.relatedUiObject) - continue - } - if (hits === 1) { - console.log('Problem With One Solution #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject, ' Found Project:' + foundProject) - - menuItem.relatedUiObjectProject = foundProject - wasUpdated = true - continue - } - console.log('Problem With MULTIPLE Solutions #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject, ' Found at these Projects:' + multiProject) - } - } - - if (wasUpdated === true) { - let fileContent = JSON.stringify(schemaDocument, undefined, 4) - let filePath = allAppSchemasFilePaths[i] - //console.log('Saving File at ' + filePath) - //console.log(fileContent) - //fs.writeFileSync(filePath, fileContent) - } - } - } catch (err) { - console.log(err.stack) - } - } - - break - } - } - - function respondWithDocsObject(docs, error) { - - if (error.message !== undefined) { - docs.placeholder.errorMessage = { - style: 'Error', - text: error.message - } - } - if (error.stack !== undefined) { - docs.placeholder.errorStack = { - style: 'Javascript', - text: error.stack - } - } - if (error.code !== undefined) { - docs.placeholder.errorCode = { - style: 'Json', - text: error.code - } - } - - docs.placeholder.errorDetails = { - style: 'Json', - text: JSON.stringify(error, undefined, 4) - } - - let customResponse = { - result: global.CUSTOM_FAIL_RESPONSE.result, - docs: docs - } - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse) - - } - } - break - case 'GOV': - { - /* - This is the Governance endpoint at the Http Interface. All methods - related to the Governance System are implemented here and routed - to the backend Servers that can process them. - */ - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let params = JSON.parse(body) - - switch (params.method) { - case 'getGithubStars': { - - let serverResponse = await PL.servers.GITHUB_SERVER.getGithubStars( - params.repository, - params.username, - params.token - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'getGithubWatchers': { - - let serverResponse = await PL.servers.GITHUB_SERVER.getGithubWatchers( - params.repository, - params.username, - params.token - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'getGithubForks': { - - let serverResponse = await PL.servers.GITHUB_SERVER.getGithubForks( - params.repository, - params.username, - params.token - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - return - } - case 'mergePullRequests': { - - let serverResponse = await PL.servers.GITHUB_SERVER.mergePullRequests( - params.commitMessage, - params.username, - params.token - ) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(serverResponse), httpResponse) - - setInterval( - PL.servers.GITHUB_SERVER.mergePullRequests, - 60000, - params.commitMessage, - params.username, - params.token - ) - - return - } - - case 'UserProfile': { - try { - - let mess = unescape(params.commitMessage) - const username = unescape(params.username) - const token = unescape(params.token) - const currentBranch = unescape(params.currentBranch) - const contributionsBranch = unescape(params.contributionsBranch) - - let error - - await updateUser() - - async function updateUser() { - - await doGithubUser() - if (error !== undefined) { - - let docs = { - project: 'Governance', - category: 'Topic', - type: 'Gov Error - Contribution Not Sent', - anchor: undefined, - placeholder: {} - } - console.log('respond with docs ') - - respondWithDocsObject(docs, error) - return - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - - } - - async function doGithubUser() { - - const { Octokit } = SA.nodeModules.octokit - - const octokit = new Octokit({ - auth: token, - userAgent: 'Superalgos Beta 12' - }) - - const repo = 'Superalgos' - const owner = 'Superalgos' - const head = username + ':' + contributionsBranch - const base = currentBranch - const title = 'Contribution: ' + mess - const path = 'Projects/Governance/Plugins/User-Profiles/' + username + '.json' ; - - const sha = await getSHA(path); - - if (sha === undefined){ - console.log('***** Abort GOV.USERPROFILE *****') - return - } - - let file = await SA.projects.communityPlugins.utilities.plugins.getPluginFileContent( - 'Governance', - 'User-Profiles', - username + '.json' - ) - - let buff = new Buffer.from(file, 'utf-8'); - let encodedFile = buff.toString('base64'); - - try { - await octokit.repos.createOrUpdateFileContents({ - owner: username, - repo: "Superalgos", - path, - message: title, - content: encodedFile, - sha, - branch: base - }); - } catch (err) { - if (err.stack.indexOf('Error User Commit') >= 0) { - return - } else { - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> Method call produced an error.') - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> commitMessage = ' + mess) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> username = ' + username) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token ends with = ' + '...' + token.substring(token.length - 10)) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> currentBranch = ' + currentBranch) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> contributionsBranch = ' + contributionsBranch) - error = err - } - } - - try { - await octokit.pulls.create({ - owner, - repo, - title, - head, - base, - }); - } catch (err) { - if (err.stack.indexOf('A pull request already exists') >= 0) { - return - } else { - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> Method call produced an error.') - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> commitMessage = ' + mess) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> username = ' + username) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token ends with = ' + '...' + token.substring(token.length - 10)) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> currentBranch = ' + currentBranch) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> contributionsBranch = ' + contributionsBranch) - error = err - } - - } - - - } - - async function getSHA(path) { - let sha = '' - const { graphql } = SA.nodeModules.graphql - - try{ - - const { repository } = await graphql( - '{ ' + - ' repository(name: "SuperAlgos", owner: "' + username + '") {' + - ' object(expression: "develop:' + path +'") {' + - ' ... on Blob {' + - ' oid' + - ' }' + - ' }' + - ' name' + - ' }' + - '}', - { - headers: { - authorization: 'token ' + token - }, - } - ) - - if (repository.name === undefined){ - console.log('***** Token permission needed : User:READ *****') - sha = undefined - error = '***** Token permission needed : User:READ *****' - return sha - } - - if(repository.object === null ){ - console.log("[User Not Found] -> Creating new user") - return sha - } - sha = repository.object.oid - return sha - - } catch (err) { - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> Method call produced an error.') console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> err.stack = ' + err.stack) console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> commitMessage = ' + mess) @@ -1442,531 +1385,597 @@ exports.newHttpInterface = function newHttpInterface() { console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token ends with = ' + '...' + token.substring(token.length - 10)) console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> currentBranch = ' + currentBranch) console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> contributionsBranch = ' + contributionsBranch) - return sha - + error = err } } - } catch (err) { - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> Method call produced an error.') - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> commitMessage = ' + mess) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> username = ' + username) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> token ends with = ' + '...' + token.substring(token.length - 10)) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> currentBranch = ' + currentBranch) - console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> contributionsBranch = ' + contributionsBranch) + try { + await octokit.pulls.create({ + owner, + repo, + title, + head, + base, + }); + } catch (err) { + if (err.stack.indexOf('A pull request already exists') >= 0) { + return + } else { + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> Method call produced an error.') + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> commitMessage = ' + mess) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> username = ' + username) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token ends with = ' + '...' + token.substring(token.length - 10)) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> currentBranch = ' + currentBranch) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> contributionsBranch = ' + contributionsBranch) + error = err + } - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + + } - break - } - case 'payContributors': { - console.log('----------------------------------------------------------------------------------------------') - console.log('DISTRIBUTION PROCESS STARTED') - console.log('----------------------------------------------------------------------------------------------') + async function getSHA(path) { + let sha = '' + const {graphql} = SA.nodeModules.graphql - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + try { + const {repository} = await graphql( + '{ ' + + ' repository(name: "SuperAlgos", owner: "' + username + '") {' + + ' object(expression: "develop:' + path + '") {' + + ' ... on Blob {' + + ' oid' + + ' }' + + ' }' + + ' name' + + ' }' + + '}', + { + headers: { + authorization: 'token ' + token + }, + } + ) - await PL.servers.WEB3_SERVER.payContributors( - params.contractAddress, - params.contractAbi, - params.paymentsArray, - params.mnemonic - ) + if (repository.name === undefined) { + console.log('***** Token permission needed : User:READ *****') + sha = undefined + error = '***** Token permission needed : User:READ *****' + return sha + } - return - } - default: { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify({ error: 'Method ' + params.method + ' is invalid.' }), httpResponse) + if (repository.object === null) { + console.log("[User Not Found] -> Creating new user") + return sha + } + sha = repository.object.oid + return sha + + } catch (err) { + + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> Method call produced an error.') + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> commitMessage = ' + mess) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> username = ' + username) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> token ends with = ' + '...' + token.substring(token.length - 10)) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> currentBranch = ' + currentBranch) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> doGithub -> contributionsBranch = ' + contributionsBranch) + return sha + + } + } + + } catch (err) { + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> Method call produced an error.') + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> commitMessage = ' + mess) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> username = ' + username) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> token ends with = ' + '...' + token.substring(token.length - 10)) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> currentBranch = ' + currentBranch) + console.log('[ERROR] httpInterface -> Gov -> contributeUserProfile -> contributionsBranch = ' + contributionsBranch) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) } + break } + + case 'payContributors': { + console.log('----------------------------------------------------------------------------------------------') + console.log('DISTRIBUTION PROCESS STARTED') + console.log('----------------------------------------------------------------------------------------------') + + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + + + await PL.servers.WEB3_SERVER.payContributors( + params.contractAddress, + params.contractAbi, + params.paymentsArray, + params.mnemonic + ) + + return + } + default: { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify({error: 'Method ' + params.method + ' is invalid.'}), httpResponse) + } + } + } catch (err) { + console.log('[ERROR] httpInterface -> GOV -> Method call produced an error.') + console.log('[ERROR] httpInterface -> GOV -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> GOV -> Params Received = ' + body) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + try { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) } catch (err) { - console.log('[ERROR] httpInterface -> GOV -> Method call produced an error.') - console.log('[ERROR] httpInterface -> GOV -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> GOV -> Params Received = ' + body) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - try { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } catch (err) { - // we just try to reponnd to the web app, but maybe the response has already been sent. - } + // we just try to reponnd to the web app, but maybe the response has already been sent. } } } + } break - case 'LegacyPlotter.js': - { - SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/LegacyPlotter.js', httpResponse) - } + case 'LegacyPlotter.js': { + SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/LegacyPlotter.js', httpResponse) + } break - case 'PlotterPanel.js': - { - SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/PlotterPanel.js', httpResponse) - } + case 'PlotterPanel.js': { + SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/PlotterPanel.js', httpResponse) + } break case 'Images': // This means the Images folder. - { - let path = global.env.PATH_TO_PLATFORM + '/WebServer/Images/' + requestPath[2] + { + let path = global.env.PATH_TO_PLATFORM + '/WebServer/Images/' + requestPath[2] - if (requestPath[3] !== undefined) { - path = path + '/' + requestPath[3] - } - - if (requestPath[4] !== undefined) { - path = path + '/' + requestPath[4] - } - - if (requestPath[5] !== undefined) { - path = path + '/' + requestPath[5] - } - - path = unescape(path) - - SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + if (requestPath[3] !== undefined) { + path = path + '/' + requestPath[3] } + + if (requestPath[4] !== undefined) { + path = path + '/' + requestPath[4] + } + + if (requestPath[5] !== undefined) { + path = path + '/' + requestPath[5] + } + + path = unescape(path) + + SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + } break case 'Icons': // This means the Icons folder under Projects. - { - let path = global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/Icons' + { + let path = global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/Icons' - if (requestPath[3] !== undefined) { - path = path + '/' + requestPath[3] - } - - if (requestPath[4] !== undefined) { - path = path + '/' + requestPath[4] - } - - if (requestPath[5] !== undefined) { - path = path + '/' + requestPath[5] - } - - path = unescape(path) - - SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + if (requestPath[3] !== undefined) { + path = path + '/' + requestPath[3] } + + if (requestPath[4] !== undefined) { + path = path + '/' + requestPath[4] + } + + if (requestPath[5] !== undefined) { + path = path + '/' + requestPath[5] + } + + path = unescape(path) + + SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + } break case 'GIFs': // This means the GIFs folder under Projects. - { - let path = global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/GIFs' + { + let path = global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/GIFs' - if (requestPath[3] !== undefined) { - path = path + '/' + requestPath[3] - } - - if (requestPath[4] !== undefined) { - path = path + '/' + requestPath[4] - } - - if (requestPath[5] !== undefined) { - path = path + '/' + requestPath[5] - } - - path = unescape(path) - SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + if (requestPath[3] !== undefined) { + path = path + '/' + requestPath[3] } + + if (requestPath[4] !== undefined) { + path = path + '/' + requestPath[4] + } + + if (requestPath[5] !== undefined) { + path = path + '/' + requestPath[5] + } + + path = unescape(path) + SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + } break case 'PNGs': // This means the PNGs folder under Projects. - { - let path = global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/PNGs' + { + let path = global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/PNGs' - if (requestPath[3] !== undefined) { - path = path + '/' + requestPath[3] - } - - if (requestPath[4] !== undefined) { - path = path + '/' + requestPath[4] - } - - if (requestPath[5] !== undefined) { - path = path + '/' + requestPath[5] - } - - path = unescape(path) - SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + if (requestPath[3] !== undefined) { + path = path + '/' + requestPath[3] } + + if (requestPath[4] !== undefined) { + path = path + '/' + requestPath[4] + } + + if (requestPath[5] !== undefined) { + path = path + '/' + requestPath[5] + } + + path = unescape(path) + SA.projects.foundations.utilities.httpResponses.respondWithImage(path, httpResponse) + } break case 'WebServer': // This means the WebServer folder. - { - SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/' + requestPath[2], httpResponse) - } + { + SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/' + requestPath[2], httpResponse) + } break case 'externalScripts': // This means the WebServer folder. - { - SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/externalScripts/' + requestPath[2], httpResponse) + { + // This allows to have sub-folders in externalScripts + let fullPath = '' + for (let i = 2; i < requestPath.length; i++) { + fullPath += requestPath[i] + if (i !== requestPath.length - 1) { + fullPath += '/' + } } + + /** + * Sometimes libs will call fonts/images etc. by themselves thus we should have a filter for file type to respond with the correct content and headers, but from the externalScripts folder + * This code should be improved when needed with specific file types + */ + + let requestedFileExtension = requestPath[requestPath.length - 1].split('.').pop() + switch (requestedFileExtension) { + case 'otf': + case 'ttf': + case 'eot': + case 'woff': + case 'woff2': + SA.projects.foundations.utilities.httpResponses.respondWithFont(global.env.PATH_TO_PLATFORM + '/WebServer/externalScripts/' + fullPath, httpResponse) + break + default: + SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/WebServer/externalScripts/' + fullPath, httpResponse) + } + + } break case 'Plotters': // This means the plotter folder, not to be confused with the Plotters script! - { - let project = requestPath[2] - let dataMine = requestPath[3] - let codeName = requestPath[4] - let moduleName = requestPath[5] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/' + 'Bots-Plotters-Code' + '/' + dataMine + '/plotters/' + codeName + '/' + moduleName - SA.projects.foundations.utilities.httpResponses.respondWithFile(filePath, httpResponse) - } + { + let project = requestPath[2] + let dataMine = requestPath[3] + let codeName = requestPath[4] + let moduleName = requestPath[5] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/' + 'Bots-Plotters-Code' + '/' + dataMine + '/plotters/' + codeName + '/' + moduleName + SA.projects.foundations.utilities.httpResponses.respondWithFile(filePath, httpResponse) + } break - case 'ChartLayers': - { - SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/UI/' + endpointOrFile + '/' + requestPath[2], httpResponse) - } + case 'ChartLayers': { + SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/UI/' + endpointOrFile + '/' + requestPath[2], httpResponse) + } break - case 'Files': - { - SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/UI/Data-Files/' + requestPath[2], httpResponse) - } + case 'Files': { + SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_PLATFORM + '/UI/Data-Files/' + requestPath[2], httpResponse) + } break - case 'Fonts': - { - SA.projects.foundations.utilities.httpResponses.respondWithFont(global.env.PATH_TO_FONTS + '/' + requestPath[2], httpResponse) - } + case 'Fonts': { + SA.projects.foundations.utilities.httpResponses.respondWithFont(global.env.PATH_TO_FONTS + '/' + requestPath[2], httpResponse) + } break - case 'Schema': - { - sendSchema(global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/Schemas/', requestPath[3]) + case 'Schema': { + sendSchema(global.env.PATH_TO_PROJECTS + '/' + requestPath[2] + '/Schemas/', requestPath[3]) - function sendSchema(filePath, schemaType) { - let fs = SA.nodeModules.fs - try { - let folder = '' - switch (schemaType) { - case 'AppSchema': { - folder = 'App-Schema' - break - } - case 'DocsNodeSchema': { - folder = 'Docs-Nodes' - break - } - case 'DocsConceptSchema': { - folder = 'Docs-Concepts' - break - } - case 'DocsTopicSchema': { - folder = 'Docs-Topics' - break - } - case 'DocsTutorialSchema': { - folder = 'Docs-Tutorials' - break - } - case 'DocsReviewSchema': { - folder = 'Docs-Reviews' - break - } - case 'DocsBookSchema': { - folder = 'Docs-Books' - break - } + function sendSchema(filePath, schemaType) { + let fs = SA.nodeModules.fs + try { + let folder = '' + switch (schemaType) { + case 'AppSchema': { + folder = 'App-Schema' + break } - SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(filePath + folder, onFilesReady) - function onFilesReady(files) { - - let schemaArray = [] - for (let k = 0; k < files.length; k++) { - let name = files[k] - let nameSplitted = name.split(folder) - let fileName = nameSplitted[1] - for (let i = 0; i < 10; i++) { - fileName = fileName.replace('\\', '/') - } - let fileToRead = filePath + folder + fileName - - let fileContent = fs.readFileSync(fileToRead) - let schemaDocument - try { - schemaDocument = JSON.parse(fileContent) - } catch (err) { - console.log('[ERROR] sendSchema -> Error Parsing JSON File: ' + fileToRead + ' .Error = ' + err.stack) - SA.projects.foundations.utilities.httpResponses.respondWithContent("[]", httpResponse) - return - } - schemaArray.push(schemaDocument) - } - let schema = JSON.stringify(schemaArray) - SA.projects.foundations.utilities.httpResponses.respondWithContent(schema, httpResponse) + case 'DocsNodeSchema': { + folder = 'Docs-Nodes' + break } - } catch (err) { - if (err.message.indexOf('no such file or directory') < 0) { - console.log('Could not send Schema:', filePath, schemaType) - console.log(err.stack) + case 'DocsConceptSchema': { + folder = 'Docs-Concepts' + break + } + case 'DocsTopicSchema': { + folder = 'Docs-Topics' + break + } + case 'DocsTutorialSchema': { + folder = 'Docs-Tutorials' + break + } + case 'DocsReviewSchema': { + folder = 'Docs-Reviews' + break + } + case 'DocsBookSchema': { + folder = 'Docs-Books' + break } - SA.projects.foundations.utilities.httpResponses.respondWithContent("[]", httpResponse) } + SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(filePath + folder, onFilesReady) + + function onFilesReady(files) { + + let schemaArray = [] + for (let k = 0; k < files.length; k++) { + let name = files[k] + let nameSplitted = name.split(folder) + let fileName = nameSplitted[1] + for (let i = 0; i < 10; i++) { + fileName = fileName.replace('\\', '/') + } + let fileToRead = filePath + folder + fileName + + let fileContent = fs.readFileSync(fileToRead) + let schemaDocument + try { + schemaDocument = JSON.parse(fileContent) + } catch (err) { + console.log('[ERROR] sendSchema -> Error Parsing JSON File: ' + fileToRead + ' .Error = ' + err.stack) + SA.projects.foundations.utilities.httpResponses.respondWithContent("[]", httpResponse) + return + } + schemaArray.push(schemaDocument) + } + let schema = JSON.stringify(schemaArray) + SA.projects.foundations.utilities.httpResponses.respondWithContent(schema, httpResponse) + } + } catch (err) { + if (err.message.indexOf('no such file or directory') < 0) { + console.log('Could not send Schema:', filePath, schemaType) + console.log(err.stack) + } + SA.projects.foundations.utilities.httpResponses.respondWithContent("[]", httpResponse) } } + } break - case 'DirContent': - { - let folderPath = unescape(requestPath[2]) - if (requestPath[3] !== undefined) { - folderPath = folderPath + '/' + requestPath[3] - } + case 'DirContent': { + let folderPath = unescape(requestPath[2]) + if (requestPath[3] !== undefined) { + folderPath = folderPath + '/' + requestPath[3] + } - if (requestPath[4] !== undefined) { - folderPath = folderPath + '/' + requestPath[4] - } + if (requestPath[4] !== undefined) { + folderPath = folderPath + '/' + requestPath[4] + } - if (requestPath[5] !== undefined) { - folderPath = folderPath + '/' + requestPath[5] - } - let folder - if (requestPath[2] === 'Root') { - folder = folderPath.replace('Root', '../Superalgos/') - } else { - folder = global.env.PATH_TO_PROJECTS + '/' + folderPath - } + if (requestPath[5] !== undefined) { + folderPath = folderPath + '/' + requestPath[5] + } + let folder + if (requestPath[2] === 'Root') { + folder = folderPath.replace('Root', '../Superalgos/') + } else { + folder = global.env.PATH_TO_PROJECTS + '/' + folderPath + } + + SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(folder, onFilesReady) + + function onFilesReady(files) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(files), httpResponse) + } + } + break + case 'IconNames': { + let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS) + 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/' SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(folder, onFilesReady) function onFilesReady(files) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(files), httpResponse) - } - } - break - case 'IconNames': - { - let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS) - 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/' - - SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(folder, onFilesReady) - - function onFilesReady(files) { - for (let j = 0; j < files.length; j++) { - let file = files[j] - for (let i = 0; i < 10; i++) { - file = file.replace('/', '\\') - } - icons.push([project, file]) + for (let j = 0; j < files.length; j++) { + let file = files[j] + for (let i = 0; i < 10; i++) { + file = file.replace('/', '\\') } + icons.push([project, file]) + } - projectCounter++ - if (projectCounter === totalProjects) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(icons), httpResponse) - } + projectCounter++ + if (projectCounter === totalProjects) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(icons), httpResponse) } } } + } break - case 'PluginFileNames': - { - processRequest() + case 'PluginFileNames': { + processRequest() - async function processRequest(body) { - try { - let project = unescape(requestPath[2]) - let folder = unescape(requestPath[3]) + async function processRequest(body) { + try { + let project = unescape(requestPath[2]) + let folder = unescape(requestPath[3]) - let response = await SA.projects.communityPlugins.utilities.plugins.getPluginFileNames( - project, - folder - ).catch(err => { - console.log('[ERROR] httpInterface -> PluginFileNames -> err.stack = ' + err.stack) - }) - - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(response), httpResponse) - - } catch (err) { - console.log('[ERROR] httpInterface -> PluginFileNames -> Method call produced an error.') + let response = await SA.projects.communityPlugins.utilities.plugins.getPluginFileNames( + project, + folder + ).catch(err => { console.log('[ERROR] httpInterface -> PluginFileNames -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> PluginFileNames -> Params Received = ' + body) + }) - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(response), httpResponse) + + } catch (err) { + console.log('[ERROR] httpInterface -> PluginFileNames -> Method call produced an error.') + console.log('[ERROR] httpInterface -> PluginFileNames -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> PluginFileNames -> Params Received = ' + body) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) } } + } break - case 'LoadPlugin': - { - processRequest() + case 'LoadPlugin': { + processRequest() - async function processRequest(body) { - try { - let project = unescape(requestPath[2]) - let folder = unescape(requestPath[3]) - let fileName = unescape(requestPath[4]) + async function processRequest(body) { + try { + let project = unescape(requestPath[2]) + let folder = unescape(requestPath[3]) + let fileName = unescape(requestPath[4]) - /*Beta 12 Refactoring Code: Remove this before releasing beta 12.*/ - if (fileName === 'Superalgos-CL.json') { - fileName = 'Superalgos-PL.json' - } + /*Beta 12 Refactoring Code: Remove this before releasing beta 12.*/ + if (fileName === 'Superalgos-CL.json') { + fileName = 'Superalgos-PL.json' + } - await SA.projects.communityPlugins.utilities.plugins.getPluginFileContent( - project, - folder, - fileName - ) - .then(response => { + await SA.projects.communityPlugins.utilities.plugins.getPluginFileContent( + project, + folder, + fileName + ) + .then(response => { SA.projects.foundations.utilities.httpResponses.respondWithContent(response, httpResponse) } - ) - .catch(err => { - let error = { - result: 'Fail Because', - message: err - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - return - }) - - } catch (err) { - console.log('[ERROR] httpInterface -> LoadPlugin -> Method call produced an error.') - console.log('[ERROR] httpInterface -> LoadPlugin -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> LoadPlugin -> Params Received = ' + body) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - } - break - case 'SavePlugin': - { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - - async function processRequest(body) { - try { - if (body === undefined) { return } - - let plugin = JSON.parse(body) - let project = requestPath[2] - let folder = requestPath[3] - let fileName = requestPath[4] - let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/' + folder - let fileContent = JSON.stringify(plugin, undefined, 4) - const fs = SA.nodeModules.fs - fs.writeFileSync(filePath + '/' + fileName + '.json', fileContent) - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } catch (err) { - console.log('[ERROR] httpInterface -> SavePlugin -> Method call produced an error.') - console.log('[ERROR] httpInterface -> SavePlugin -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> SavePlugin -> Params Received = ' + body) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - } - break - case 'Workspace.js': - { - let fs = SA.nodeModules.fs - - try { - let filePath = global.env.PATH_TO_DEFAULT_WORKSPACE + '/Getting-Started-Tutorials.json' - fs.readFile(filePath, onFileRead) - } catch (e) { - console.log('[ERROR] Error reading the Workspace.', e) - } - - function onFileRead(err, workspace) { - if (err) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(undefined, httpResponse) - } else { - let responseContent = 'function getWorkspace(){ return ' + workspace + '}' - SA.projects.foundations.utilities.httpResponses.respondWithContent(responseContent, httpResponse) - } - } - } - break - case 'ListWorkspaces': - { - let allWorkspaces = [] - let projects = SA.projects.foundations.utilities.filesAndDirectories.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 = SA.nodeModules.fs - fs.readdir(dirPath, onDirRead) - - function onDirRead(err, fileList) { - let updatedFileList = [] - - if (err) { - /* - If we have a problem reading this folder we will assume that it is - because this project does not need this folder and that's it. - */ - //console.log('[WARN] Error reading a directory content. filePath = ' + dirPath) - } else { - 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() - } + ) + .catch(err => { + let error = { + result: 'Fail Because', + message: err } - } catch (err) { - console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) - console.log('[ERROR] err.stack = ' + err.stack) - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) return - } - } - } + }) - function readMyWorkspaces() { - let dirPath = global.env.PATH_TO_MY_WORKSPACES + } catch (err) { + console.log('[ERROR] httpInterface -> LoadPlugin -> Method call produced an error.') + console.log('[ERROR] httpInterface -> LoadPlugin -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> LoadPlugin -> Params Received = ' + body) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + } + break + case 'SavePlugin': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + try { + if (body === undefined) { + return + } + + let plugin = JSON.parse(body) + let project = requestPath[2] + let folder = requestPath[3] + let fileName = requestPath[4] + let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Plugins/' + folder + let fileContent = JSON.stringify(plugin, undefined, 4) + const fs = SA.nodeModules.fs + fs.writeFileSync(filePath + '/' + fileName + '.json', fileContent) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } catch (err) { + console.log('[ERROR] httpInterface -> SavePlugin -> Method call produced an error.') + console.log('[ERROR] httpInterface -> SavePlugin -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> SavePlugin -> Params Received = ' + body) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } + } + } + break + case 'Workspace.js': { + let fs = SA.nodeModules.fs + + try { + let filePath = global.env.PATH_TO_DEFAULT_WORKSPACE + '/Getting-Started-Tutorials.json' + fs.readFile(filePath, onFileRead) + } catch (e) { + console.log('[ERROR] Error reading the Workspace.', e) + } + + function onFileRead(err, workspace) { + if (err) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(undefined, httpResponse) + } else { + let responseContent = 'function getWorkspace(){ return ' + workspace + '}' + SA.projects.foundations.utilities.httpResponses.respondWithContent(responseContent, httpResponse) + } + } + } + break + case 'ListWorkspaces': { + let allWorkspaces = [] + let projects = SA.projects.foundations.utilities.filesAndDirectories.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 = SA.nodeModules.fs fs.readdir(dirPath, onDirRead) function onDirRead(err, fileList) { + let updatedFileList = [] + if (err) { - // This happens the first time you run the software. - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(allWorkspaces), httpResponse) - return + /* + If we have a problem reading this folder we will assume that it is + because this project does not need this folder and that's it. + */ + //console.log('[WARN] Error reading a directory content. filePath = ' + dirPath) } else { - let updatedFileList = [] for (let i = 0; i < fileList.length; i++) { - let name = fileList[i] - updatedFileList.push(['', name]) + let name = 'Plugin \u2192 ' + fileList[i] + updatedFileList.push([project, name]) } - allWorkspaces = allWorkspaces.concat(updatedFileList) - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(allWorkspaces), httpResponse) - return + } + allWorkspaces = allWorkspaces.concat(updatedFileList) + projectsCount++ + if (projectsCount === projects.length) { + readMyWorkspaces() } } } catch (err) { @@ -1977,172 +1986,197 @@ exports.newHttpInterface = function newHttpInterface() { } } } - break - case 'LoadMyWorkspace': - { - let fileName = unescape(requestPath[2]) - let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json' - SA.projects.foundations.utilities.httpResponses.respondWithFile(filePath, httpResponse) - } - break - case 'SaveWorkspace': - { - SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) - async function processRequest(body) { + function readMyWorkspaces() { + let dirPath = global.env.PATH_TO_MY_WORKSPACES + try { + let fs = SA.nodeModules.fs + fs.readdir(dirPath, onDirRead) - if (body === undefined) { return } - - let fileContent = body - let fileName = unescape(requestPath[2]) - let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json' - - try { - let fs = SA.nodeModules.fs - let dir = global.env.PATH_TO_MY_WORKSPACES; - - /* Create Dir if it does not exist */ - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir, {recursive: true}); - } - - fs.writeFile(filePath, fileContent, onFileWritten) - - function onFileWritten(err) { - if (err) { - console.log('[ERROR] SaveWorkspace -> onFileWritten -> Error writing 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 - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } else { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + function onDirRead(err, fileList) { + if (err) { + // This happens the first time you run the software. + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(allWorkspaces), httpResponse) + return + } else { + let updatedFileList = [] + for (let i = 0; i < fileList.length; i++) { + let name = fileList[i] + updatedFileList.push(['', name]) } - } - - } catch (err) { - console.log('[ERROR] SaveWorkspace -> Error writing the Workspace file. fileName = ' + fileName) - console.log('[ERROR] SaveWorkspace -> err.stack = ' + err.stack) - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) - } - } - } - break - case 'ProjectsSchema': - { - let path = global.env.PATH_TO_PROJECTS + '/' + 'ProjectsSchema.json' - SA.projects.foundations.utilities.httpResponses.respondWithFile(path, httpResponse) - } - break - case 'ListSpaceFiles': - { - let fs = SA.nodeModules.fs - let allFiles = [] - let projects = SA.projects.foundations.utilities.filesAndDirectories.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 = SA.projects.foundations.utilities.filesAndDirectories.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 = SA.projects.foundations.utilities.filesAndDirectories.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) { - SA.projects.foundations.utilities.httpResponses.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) { - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(allFiles), httpResponse) - } - } - } - } catch (err) { - console.log('[ERROR] Error reading a directory content. filePath = ' + path) - console.log('[ERROR] err.stack = ' + err.stack) - SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + allWorkspaces = allWorkspaces.concat(updatedFileList) + SA.projects.foundations.utilities.httpResponses.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) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + return } } + } break - case 'ListFunctionLibraries': - { - SA.projects.foundations.utilities.httpResponses.respondWithProjectFolderFileList(httpResponse, 'Function-Libraries', 'UI') - } + case 'LoadMyWorkspace': { + let fileName = unescape(requestPath[2]) + let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json' + SA.projects.foundations.utilities.httpResponses.respondWithFile(filePath, httpResponse) + } break - case 'ListUtilitiesFiles': - { - SA.projects.foundations.utilities.httpResponses.respondWithProjectFolderFileList(httpResponse, 'Utilities', 'UI') - } - break - case 'ListGlobalFiles': - { - SA.projects.foundations.utilities.httpResponses.respondWithProjectFolderFileList(httpResponse, 'Globals', 'UI') - } - break - case 'Projects': - { - let path = '' - for (let i = 2; i < 10; i++) { - if (requestPath[i] !== undefined) { - let parameter = unescape(requestPath[i]) - path = path + '/' + parameter + case 'SaveWorkspace': { + SA.projects.foundations.utilities.httpRequests.getRequestBody(httpRequest, httpResponse, processRequest) + + async function processRequest(body) { + + if (body === undefined) { + return + } + + let fileContent = body + let fileName = unescape(requestPath[2]) + let filePath = global.env.PATH_TO_MY_WORKSPACES + '/' + fileName + '.json' + + try { + let fs = SA.nodeModules.fs + let dir = global.env.PATH_TO_MY_WORKSPACES; + + /* Create Dir if it does not exist */ + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, {recursive: true}); } + fs.writeFile(filePath, fileContent, onFileWritten) + + function onFileWritten(err) { + if (err) { + console.log('[ERROR] SaveWorkspace -> onFileWritten -> Error writing 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 + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) + } else { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) + } + } + + } catch (err) { + console.log('[ERROR] SaveWorkspace -> Error writing the Workspace file. fileName = ' + fileName) + console.log('[ERROR] SaveWorkspace -> err.stack = ' + err.stack) + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse) } - let filePath = global.env.PATH_TO_PROJECTS + path - SA.projects.foundations.utilities.httpResponses.respondWithFile(filePath, httpResponse) } + } break - case 'Storage': - { - let pathToFile = httpRequest.url.substring(9) - /* Unsavping # */ - for (let i = 0; i < 10; i++) { - pathToFile = pathToFile.replace('_HASHTAG_', '#') + case 'ProjectsSchema': { + let path = global.env.PATH_TO_PROJECTS + '/' + 'ProjectsSchema.json' + SA.projects.foundations.utilities.httpResponses.respondWithFile(path, httpResponse) + } + break + case 'ListSpaceFiles': { + let fs = SA.nodeModules.fs + let allFiles = [] + let projects = SA.projects.foundations.utilities.filesAndDirectories.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 = SA.projects.foundations.utilities.filesAndDirectories.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 = SA.projects.foundations.utilities.filesAndDirectories.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) { + SA.projects.foundations.utilities.httpResponses.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) { + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(allFiles), httpResponse) + } + } + } + } catch (err) { + console.log('[ERROR] Error reading a directory content. filePath = ' + path) + console.log('[ERROR] err.stack = ' + err.stack) + SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) + return + } } - SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_DATA_STORAGE + '/' + pathToFile, httpResponse) } + } break - default: - { - SA.projects.foundations.utilities.httpResponses.respondWithWebFile(httpResponse, endpointOrFile, global.env.PATH_TO_PLATFORM) + case 'ListFunctionLibraries': { + SA.projects.foundations.utilities.httpResponses.respondWithProjectFolderFileList(httpResponse, 'Function-Libraries', 'UI') + } + break + case 'ListUtilitiesFiles': { + SA.projects.foundations.utilities.httpResponses.respondWithProjectFolderFileList(httpResponse, 'Utilities', 'UI') + } + break + case 'ListGlobalFiles': { + SA.projects.foundations.utilities.httpResponses.respondWithProjectFolderFileList(httpResponse, 'Globals', 'UI') + } + break + case 'Projects': { + let path = '' + for (let i = 2; i < 10; i++) { + if (requestPath[i] !== undefined) { + let parameter = unescape(requestPath[i]) + path = path + '/' + parameter + } + } + let filePath = global.env.PATH_TO_PROJECTS + path + SA.projects.foundations.utilities.httpResponses.respondWithFile(filePath, httpResponse) + } + break + case 'Storage': { + let pathToFile = httpRequest.url.substring(9) + /* Unsavping # */ + for (let i = 0; i < 10; i++) { + pathToFile = pathToFile.replace('_HASHTAG_', '#') + } + SA.projects.foundations.utilities.httpResponses.respondWithFile(global.env.PATH_TO_DATA_STORAGE + '/' + pathToFile, httpResponse) + } + break + default: { + SA.projects.foundations.utilities.httpResponses.respondWithWebFile(httpResponse, endpointOrFile, global.env.PATH_TO_PLATFORM) + } } } catch (err) { if (err.stack !== undefined) { diff --git a/Platform/UI/Globals.js b/Platform/UI/Globals.js index 1f34fc0a0..84b558b77 100644 --- a/Platform/UI/Globals.js +++ b/Platform/UI/Globals.js @@ -261,6 +261,11 @@ let CURRENT_PANORAMA_POSITION = 0 let CAN_SPACES_DRAW = false // This global variable regulates when spaces can or can not draw their contents. +const codeEditorType = { + CODE: "code", + CONFIG: "config" +} + function toRadians(angle) { return angle * (Math.PI / 180); } diff --git a/Platform/WebServer/css/code-editor.css b/Platform/WebServer/css/code-editor.css new file mode 100644 index 000000000..c030c8170 --- /dev/null +++ b/Platform/WebServer/css/code-editor.css @@ -0,0 +1,15 @@ +.code-editor-page { + font: 400 17px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + color: #365558; + line-height: 150%; + margin: 20 25 20 30px; +} + +.editor{ + height: 70vh; + overflow: hidden; +} + +#code-path { + margin-bottom: 15px; +} \ No newline at end of file diff --git a/Platform/WebServer/externalScripts/min-maps/vs/base/worker/workerMain.js.map b/Platform/WebServer/externalScripts/min-maps/vs/base/worker/workerMain.js.map new file mode 100644 index 000000000..5504b7895 --- /dev/null +++ b/Platform/WebServer/externalScripts/min-maps/vs/base/worker/workerMain.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["out-editor/vs/base/worker/fake","out-editor/vs/base/worker/vs/loader.js","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/diff/diffChange.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/errors.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/functional.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/iterator.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/keyCodes.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/lifecycle.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/linkedList.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/platform.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/process.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/path.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/stopwatch.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/event.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/cancellation.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/strings.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/hash.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/diff/diff.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/types.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/uint.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/uri.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/common/worker/simpleWorker.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/core/characterClassifier.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/core/position.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/core/range.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/core/selection.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/core/token.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/diff/diffComputer.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/model/wordHelper.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/modes/linkComputer.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/standalone/standaloneEnums.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/standalone/standaloneBase.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/viewModel/prefixSumComputer.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/model/mirrorTextModel.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/editor/common/services/editorSimpleWorker.ts","out-editor/vs/base/worker/file:/Users/alex/src/vscode2/out-editor-src/vs/base/worker/workerMain.ts"],"sourcesContent":["}).call(this);","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n/*---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n * Please make sure to make edits in the .ts file at https://github.com/microsoft/vscode-loader/\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *--------------------------------------------------------------------------------------------*/\nvar _amdLoaderGlobal = this;\nvar _commonjsGlobal = typeof global === 'object' ? global : {};\nvar AMDLoader;\n(function (AMDLoader) {\n AMDLoader.global = _amdLoaderGlobal;\n var Environment = /** @class */ (function () {\n function Environment() {\n this._detected = false;\n this._isWindows = false;\n this._isNode = false;\n this._isElectronRenderer = false;\n this._isWebWorker = false;\n this._isElectronNodeIntegrationWebWorker = false;\n }\n Object.defineProperty(Environment.prototype, \"isWindows\", {\n get: function () {\n this._detect();\n return this._isWindows;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(Environment.prototype, \"isNode\", {\n get: function () {\n this._detect();\n return this._isNode;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(Environment.prototype, \"isElectronRenderer\", {\n get: function () {\n this._detect();\n return this._isElectronRenderer;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(Environment.prototype, \"isWebWorker\", {\n get: function () {\n this._detect();\n return this._isWebWorker;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(Environment.prototype, \"isElectronNodeIntegrationWebWorker\", {\n get: function () {\n this._detect();\n return this._isElectronNodeIntegrationWebWorker;\n },\n enumerable: false,\n configurable: true\n });\n Environment.prototype._detect = function () {\n if (this._detected) {\n return;\n }\n this._detected = true;\n this._isWindows = Environment._isWindows();\n this._isNode = (typeof module !== 'undefined' && !!module.exports);\n this._isElectronRenderer = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions.electron !== 'undefined' && process.type === 'renderer');\n this._isWebWorker = (typeof AMDLoader.global.importScripts === 'function');\n this._isElectronNodeIntegrationWebWorker = this._isWebWorker && (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions.electron !== 'undefined' && process.type === 'worker');\n };\n Environment._isWindows = function () {\n if (typeof navigator !== 'undefined') {\n if (navigator.userAgent && navigator.userAgent.indexOf('Windows') >= 0) {\n return true;\n }\n }\n if (typeof process !== 'undefined') {\n return (process.platform === 'win32');\n }\n return false;\n };\n return Environment;\n }());\n AMDLoader.Environment = Environment;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n var LoaderEvent = /** @class */ (function () {\n function LoaderEvent(type, detail, timestamp) {\n this.type = type;\n this.detail = detail;\n this.timestamp = timestamp;\n }\n return LoaderEvent;\n }());\n AMDLoader.LoaderEvent = LoaderEvent;\n var LoaderEventRecorder = /** @class */ (function () {\n function LoaderEventRecorder(loaderAvailableTimestamp) {\n this._events = [new LoaderEvent(1 /* LoaderAvailable */, '', loaderAvailableTimestamp)];\n }\n LoaderEventRecorder.prototype.record = function (type, detail) {\n this._events.push(new LoaderEvent(type, detail, AMDLoader.Utilities.getHighPerformanceTimestamp()));\n };\n LoaderEventRecorder.prototype.getEvents = function () {\n return this._events;\n };\n return LoaderEventRecorder;\n }());\n AMDLoader.LoaderEventRecorder = LoaderEventRecorder;\n var NullLoaderEventRecorder = /** @class */ (function () {\n function NullLoaderEventRecorder() {\n }\n NullLoaderEventRecorder.prototype.record = function (type, detail) {\n // Nothing to do\n };\n NullLoaderEventRecorder.prototype.getEvents = function () {\n return [];\n };\n NullLoaderEventRecorder.INSTANCE = new NullLoaderEventRecorder();\n return NullLoaderEventRecorder;\n }());\n AMDLoader.NullLoaderEventRecorder = NullLoaderEventRecorder;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n var Utilities = /** @class */ (function () {\n function Utilities() {\n }\n /**\n * This method does not take care of / vs \\\n */\n Utilities.fileUriToFilePath = function (isWindows, uri) {\n uri = decodeURI(uri).replace(/%23/g, '#');\n if (isWindows) {\n if (/^file:\\/\\/\\//.test(uri)) {\n // This is a URI without a hostname => return only the path segment\n return uri.substr(8);\n }\n if (/^file:\\/\\//.test(uri)) {\n return uri.substr(5);\n }\n }\n else {\n if (/^file:\\/\\//.test(uri)) {\n return uri.substr(7);\n }\n }\n // Not sure...\n return uri;\n };\n Utilities.startsWith = function (haystack, needle) {\n return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;\n };\n Utilities.endsWith = function (haystack, needle) {\n return haystack.length >= needle.length && haystack.substr(haystack.length - needle.length) === needle;\n };\n // only check for \"?\" before \"#\" to ensure that there is a real Query-String\n Utilities.containsQueryString = function (url) {\n return /^[^\\#]*\\?/gi.test(url);\n };\n /**\n * Does `url` start with http:// or https:// or file:// or / ?\n */\n Utilities.isAbsolutePath = function (url) {\n return /^((http:\\/\\/)|(https:\\/\\/)|(file:\\/\\/)|(\\/))/.test(url);\n };\n Utilities.forEachProperty = function (obj, callback) {\n if (obj) {\n var key = void 0;\n for (key in obj) {\n if (obj.hasOwnProperty(key)) {\n callback(key, obj[key]);\n }\n }\n }\n };\n Utilities.isEmpty = function (obj) {\n var isEmpty = true;\n Utilities.forEachProperty(obj, function () {\n isEmpty = false;\n });\n return isEmpty;\n };\n Utilities.recursiveClone = function (obj) {\n if (!obj || typeof obj !== 'object' || obj instanceof RegExp) {\n return obj;\n }\n if (!Array.isArray(obj) && Object.getPrototypeOf(obj) !== Object.prototype) {\n // only clone \"simple\" objects\n return obj;\n }\n var result = Array.isArray(obj) ? [] : {};\n Utilities.forEachProperty(obj, function (key, value) {\n if (value && typeof value === 'object') {\n result[key] = Utilities.recursiveClone(value);\n }\n else {\n result[key] = value;\n }\n });\n return result;\n };\n Utilities.generateAnonymousModule = function () {\n return '===anonymous' + (Utilities.NEXT_ANONYMOUS_ID++) + '===';\n };\n Utilities.isAnonymousModule = function (id) {\n return Utilities.startsWith(id, '===anonymous');\n };\n Utilities.getHighPerformanceTimestamp = function () {\n if (!this.PERFORMANCE_NOW_PROBED) {\n this.PERFORMANCE_NOW_PROBED = true;\n this.HAS_PERFORMANCE_NOW = (AMDLoader.global.performance && typeof AMDLoader.global.performance.now === 'function');\n }\n return (this.HAS_PERFORMANCE_NOW ? AMDLoader.global.performance.now() : Date.now());\n };\n Utilities.NEXT_ANONYMOUS_ID = 1;\n Utilities.PERFORMANCE_NOW_PROBED = false;\n Utilities.HAS_PERFORMANCE_NOW = false;\n return Utilities;\n }());\n AMDLoader.Utilities = Utilities;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n function ensureError(err) {\n if (err instanceof Error) {\n return err;\n }\n var result = new Error(err.message || String(err) || 'Unknown Error');\n if (err.stack) {\n result.stack = err.stack;\n }\n return result;\n }\n AMDLoader.ensureError = ensureError;\n ;\n var ConfigurationOptionsUtil = /** @class */ (function () {\n function ConfigurationOptionsUtil() {\n }\n /**\n * Ensure configuration options make sense\n */\n ConfigurationOptionsUtil.validateConfigurationOptions = function (options) {\n function defaultOnError(err) {\n if (err.phase === 'loading') {\n console.error('Loading \"' + err.moduleId + '\" failed');\n console.error(err);\n console.error('Here are the modules that depend on it:');\n console.error(err.neededBy);\n return;\n }\n if (err.phase === 'factory') {\n console.error('The factory method of \"' + err.moduleId + '\" has thrown an exception');\n console.error(err);\n return;\n }\n }\n options = options || {};\n if (typeof options.baseUrl !== 'string') {\n options.baseUrl = '';\n }\n if (typeof options.isBuild !== 'boolean') {\n options.isBuild = false;\n }\n if (typeof options.paths !== 'object') {\n options.paths = {};\n }\n if (typeof options.config !== 'object') {\n options.config = {};\n }\n if (typeof options.catchError === 'undefined') {\n options.catchError = false;\n }\n if (typeof options.recordStats === 'undefined') {\n options.recordStats = false;\n }\n if (typeof options.urlArgs !== 'string') {\n options.urlArgs = '';\n }\n if (typeof options.onError !== 'function') {\n options.onError = defaultOnError;\n }\n if (!Array.isArray(options.ignoreDuplicateModules)) {\n options.ignoreDuplicateModules = [];\n }\n if (options.baseUrl.length > 0) {\n if (!AMDLoader.Utilities.endsWith(options.baseUrl, '/')) {\n options.baseUrl += '/';\n }\n }\n if (typeof options.cspNonce !== 'string') {\n options.cspNonce = '';\n }\n if (typeof options.preferScriptTags === 'undefined') {\n options.preferScriptTags = false;\n }\n if (!Array.isArray(options.nodeModules)) {\n options.nodeModules = [];\n }\n if (options.nodeCachedData && typeof options.nodeCachedData === 'object') {\n if (typeof options.nodeCachedData.seed !== 'string') {\n options.nodeCachedData.seed = 'seed';\n }\n if (typeof options.nodeCachedData.writeDelay !== 'number' || options.nodeCachedData.writeDelay < 0) {\n options.nodeCachedData.writeDelay = 1000 * 7;\n }\n if (!options.nodeCachedData.path || typeof options.nodeCachedData.path !== 'string') {\n var err = ensureError(new Error('INVALID cached data configuration, \\'path\\' MUST be set'));\n err.phase = 'configuration';\n options.onError(err);\n options.nodeCachedData = undefined;\n }\n }\n return options;\n };\n ConfigurationOptionsUtil.mergeConfigurationOptions = function (overwrite, base) {\n if (overwrite === void 0) { overwrite = null; }\n if (base === void 0) { base = null; }\n var result = AMDLoader.Utilities.recursiveClone(base || {});\n // Merge known properties and overwrite the unknown ones\n AMDLoader.Utilities.forEachProperty(overwrite, function (key, value) {\n if (key === 'ignoreDuplicateModules' && typeof result.ignoreDuplicateModules !== 'undefined') {\n result.ignoreDuplicateModules = result.ignoreDuplicateModules.concat(value);\n }\n else if (key === 'paths' && typeof result.paths !== 'undefined') {\n AMDLoader.Utilities.forEachProperty(value, function (key2, value2) { return result.paths[key2] = value2; });\n }\n else if (key === 'config' && typeof result.config !== 'undefined') {\n AMDLoader.Utilities.forEachProperty(value, function (key2, value2) { return result.config[key2] = value2; });\n }\n else {\n result[key] = AMDLoader.Utilities.recursiveClone(value);\n }\n });\n return ConfigurationOptionsUtil.validateConfigurationOptions(result);\n };\n return ConfigurationOptionsUtil;\n }());\n AMDLoader.ConfigurationOptionsUtil = ConfigurationOptionsUtil;\n var Configuration = /** @class */ (function () {\n function Configuration(env, options) {\n this._env = env;\n this.options = ConfigurationOptionsUtil.mergeConfigurationOptions(options);\n this._createIgnoreDuplicateModulesMap();\n this._createNodeModulesMap();\n this._createSortedPathsRules();\n if (this.options.baseUrl === '') {\n if (this.options.nodeRequire && this.options.nodeRequire.main && this.options.nodeRequire.main.filename && this._env.isNode) {\n var nodeMain = this.options.nodeRequire.main.filename;\n var dirnameIndex = Math.max(nodeMain.lastIndexOf('/'), nodeMain.lastIndexOf('\\\\'));\n this.options.baseUrl = nodeMain.substring(0, dirnameIndex + 1);\n }\n if (this.options.nodeMain && this._env.isNode) {\n var nodeMain = this.options.nodeMain;\n var dirnameIndex = Math.max(nodeMain.lastIndexOf('/'), nodeMain.lastIndexOf('\\\\'));\n this.options.baseUrl = nodeMain.substring(0, dirnameIndex + 1);\n }\n }\n }\n Configuration.prototype._createIgnoreDuplicateModulesMap = function () {\n // Build a map out of the ignoreDuplicateModules array\n this.ignoreDuplicateModulesMap = {};\n for (var i = 0; i < this.options.ignoreDuplicateModules.length; i++) {\n this.ignoreDuplicateModulesMap[this.options.ignoreDuplicateModules[i]] = true;\n }\n };\n Configuration.prototype._createNodeModulesMap = function () {\n // Build a map out of nodeModules array\n this.nodeModulesMap = Object.create(null);\n for (var _i = 0, _a = this.options.nodeModules; _i < _a.length; _i++) {\n var nodeModule = _a[_i];\n this.nodeModulesMap[nodeModule] = true;\n }\n };\n Configuration.prototype._createSortedPathsRules = function () {\n var _this = this;\n // Create an array our of the paths rules, sorted descending by length to\n // result in a more specific -> less specific order\n this.sortedPathsRules = [];\n AMDLoader.Utilities.forEachProperty(this.options.paths, function (from, to) {\n if (!Array.isArray(to)) {\n _this.sortedPathsRules.push({\n from: from,\n to: [to]\n });\n }\n else {\n _this.sortedPathsRules.push({\n from: from,\n to: to\n });\n }\n });\n this.sortedPathsRules.sort(function (a, b) {\n return b.from.length - a.from.length;\n });\n };\n /**\n * Clone current configuration and overwrite options selectively.\n * @param options The selective options to overwrite with.\n * @result A new configuration\n */\n Configuration.prototype.cloneAndMerge = function (options) {\n return new Configuration(this._env, ConfigurationOptionsUtil.mergeConfigurationOptions(options, this.options));\n };\n /**\n * Get current options bag. Useful for passing it forward to plugins.\n */\n Configuration.prototype.getOptionsLiteral = function () {\n return this.options;\n };\n Configuration.prototype._applyPaths = function (moduleId) {\n var pathRule;\n for (var i = 0, len = this.sortedPathsRules.length; i < len; i++) {\n pathRule = this.sortedPathsRules[i];\n if (AMDLoader.Utilities.startsWith(moduleId, pathRule.from)) {\n var result = [];\n for (var j = 0, lenJ = pathRule.to.length; j < lenJ; j++) {\n result.push(pathRule.to[j] + moduleId.substr(pathRule.from.length));\n }\n return result;\n }\n }\n return [moduleId];\n };\n Configuration.prototype._addUrlArgsToUrl = function (url) {\n if (AMDLoader.Utilities.containsQueryString(url)) {\n return url + '&' + this.options.urlArgs;\n }\n else {\n return url + '?' + this.options.urlArgs;\n }\n };\n Configuration.prototype._addUrlArgsIfNecessaryToUrl = function (url) {\n if (this.options.urlArgs) {\n return this._addUrlArgsToUrl(url);\n }\n return url;\n };\n Configuration.prototype._addUrlArgsIfNecessaryToUrls = function (urls) {\n if (this.options.urlArgs) {\n for (var i = 0, len = urls.length; i < len; i++) {\n urls[i] = this._addUrlArgsToUrl(urls[i]);\n }\n }\n return urls;\n };\n /**\n * Transform a module id to a location. Appends .js to module ids\n */\n Configuration.prototype.moduleIdToPaths = function (moduleId) {\n if (this._env.isNode) {\n var isNodeModule = ((this.nodeModulesMap[moduleId] === true)\n || (this.options.amdModulesPattern instanceof RegExp && !this.options.amdModulesPattern.test(moduleId)));\n if (isNodeModule) {\n // This is a node module...\n if (this.isBuild()) {\n // ...and we are at build time, drop it\n return ['empty:'];\n }\n else {\n // ...and at runtime we create a `shortcut`-path\n return ['node|' + moduleId];\n }\n }\n }\n var result = moduleId;\n var results;\n if (!AMDLoader.Utilities.endsWith(result, '.js') && !AMDLoader.Utilities.isAbsolutePath(result)) {\n results = this._applyPaths(result);\n for (var i = 0, len = results.length; i < len; i++) {\n if (this.isBuild() && results[i] === 'empty:') {\n continue;\n }\n if (!AMDLoader.Utilities.isAbsolutePath(results[i])) {\n results[i] = this.options.baseUrl + results[i];\n }\n if (!AMDLoader.Utilities.endsWith(results[i], '.js') && !AMDLoader.Utilities.containsQueryString(results[i])) {\n results[i] = results[i] + '.js';\n }\n }\n }\n else {\n if (!AMDLoader.Utilities.endsWith(result, '.js') && !AMDLoader.Utilities.containsQueryString(result)) {\n result = result + '.js';\n }\n results = [result];\n }\n return this._addUrlArgsIfNecessaryToUrls(results);\n };\n /**\n * Transform a module id or url to a location.\n */\n Configuration.prototype.requireToUrl = function (url) {\n var result = url;\n if (!AMDLoader.Utilities.isAbsolutePath(result)) {\n result = this._applyPaths(result)[0];\n if (!AMDLoader.Utilities.isAbsolutePath(result)) {\n result = this.options.baseUrl + result;\n }\n }\n return this._addUrlArgsIfNecessaryToUrl(result);\n };\n /**\n * Flag to indicate if current execution is as part of a build.\n */\n Configuration.prototype.isBuild = function () {\n return this.options.isBuild;\n };\n /**\n * Test if module `moduleId` is expected to be defined multiple times\n */\n Configuration.prototype.isDuplicateMessageIgnoredFor = function (moduleId) {\n return this.ignoreDuplicateModulesMap.hasOwnProperty(moduleId);\n };\n /**\n * Get the configuration settings for the provided module id\n */\n Configuration.prototype.getConfigForModule = function (moduleId) {\n if (this.options.config) {\n return this.options.config[moduleId];\n }\n };\n /**\n * Should errors be caught when executing module factories?\n */\n Configuration.prototype.shouldCatchError = function () {\n return this.options.catchError;\n };\n /**\n * Should statistics be recorded?\n */\n Configuration.prototype.shouldRecordStats = function () {\n return this.options.recordStats;\n };\n /**\n * Forward an error to the error handler.\n */\n Configuration.prototype.onError = function (err) {\n this.options.onError(err);\n };\n return Configuration;\n }());\n AMDLoader.Configuration = Configuration;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n /**\n * Load `scriptSrc` only once (avoid multiple @@ -21,6 +22,10 @@ + + + -
-

-

-

-

The UI is loading...

+ style="overflow:hidden; background: url(Images/superalgos-platform.jpg); background-size: cover;" + onresize="onResize()"> +
+

+

+

+

The UI is loading...

+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
- -
-
-
 
+
+
+ +
+
+
 
- -
-
-
- - - - - - - -
- - - - - - - -
-
-
+ +
+
+
+ + + + + + + +
+ + + + + + + +
+
+
-