diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 652791349..f1553be19 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,9 +2,14 @@ name: Publish Docker image on: push: - branches: [master, develop] - release: - types: [published, created, edited] + branches: + - master + - develop + release: + types: + - published + - created + - edited jobs: publish: diff --git a/.github/workflows/release_build.yml b/.github/workflows/release_build.yml index fbb2ef9e0..646f96612 100644 --- a/.github/workflows/release_build.yml +++ b/.github/workflows/release_build.yml @@ -1,38 +1,16 @@ name: Build/release Binaries + on: - pull_request: - branches: [master] - #release: - # types: [published, created] + release: + types: + - published workflow_dispatch: jobs: - create-release: - runs-on: ubuntu-latest - steps: - - name: Download a file - run: curl "https://raw.githubusercontent.com/${{ github.repository }}/master/package.json" -o package.json - - - name: get-version - id: version - uses: nyaa8/package-version@v1 - with: - path: './package.json' - - - name: Create release - id: create_release - uses: viperproject/create-nightly-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ env.PACKAGE_VERSION }} - release_name: Superalgos-v${{ env.PACKAGE_VERSION }} - build-release: runs-on: ${{ matrix.os }} - needs: create-release strategy: matrix: os: [windows-latest, macos-latest] @@ -40,19 +18,15 @@ jobs: steps: - name: Check out Git repository uses: actions/checkout@v2 - with: - ref: develop - name: Install Node.js, NPM and Yarn uses: actions/setup-node@v1 with: node-version: 14 - - - name: get-version - id: version - uses: nyaa8/package-version@v1 - with: - path: './package.json' + + - name: Get version + id: vars + run: echo "::set-output name=tag::$(node -p "require('./package.json').version")" - name: Build/release Electron app uses: samuelmeuli/action-electron-builder@v1 @@ -60,10 +34,6 @@ jobs: # GitHub token, automatically provided to the action # (No need to define this secret in the repo settings) github_token: ${{ secrets.github_token }} - args: "-c.extraMetadata.version=${{ env.PACKAGE_VERSION }} -c build/electron-builder.json -p always" - - # If the commit is tagged with a version (e.g. "v1.0.0"), - # release the app after building - # release: ${{ startsWith(github.ref, 'refs/tags/v') }} + args: "-c.extraMetadata.version=${{ steps.vars.outputs.tag }} -c build/electron-builder.json -p always" release: true diff --git a/.github/workflows/release_build_dev.yml b/.github/workflows/release_build_dev.yml index a0784fb09..d34a09fa7 100644 --- a/.github/workflows/release_build_dev.yml +++ b/.github/workflows/release_build_dev.yml @@ -17,11 +17,9 @@ jobs: id: date run: echo "::set-output name=date::$(date +'%Y%m%d')" - - name: get-version - id: version - uses: nyaa8/package-version@v1 - with: - path: './package.json' + - name: Get version + id: vars + run: echo "::set-output name=tag::$(node -p "require('./package.json').version")" - name: Create nightly release id: create_release @@ -29,8 +27,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: ${{ env.PACKAGE_VERSION }}.${{ steps.date.outputs.date }} - release_name: Superalgos ${{ env.PACKAGE_VERSION }} Snapshot ${{ steps.date.outputs.date }} + tag_name: ${{ steps.vars.outputs.tag }}.${{ steps.date.outputs.date }} + release_name: Superalgos-Beta-v${{ steps.vars.outputs.tag }} Snapshot ${{ steps.date.outputs.date }} keep_num: 5 keep_tags: false @@ -39,7 +37,7 @@ jobs: needs: create-release strategy: matrix: - os: [windows-latest, macos-latest] + os: [windows-latest, macos-latest, ubuntu-latest] steps: - name: Get current date @@ -56,11 +54,9 @@ jobs: with: node-version: 14 - - name: get-version - id: version - uses: nyaa8/package-version@v1 - with: - path: './package.json' + - name: Get version + id: vars + run: echo "::set-output name=tag::$(node -p "require('./package.json').version")" - name: Build/release Electron app uses: samuelmeuli/action-electron-builder@v1 @@ -68,7 +64,7 @@ jobs: # GitHub token, automatically provided to the action # (No need to define this secret in the repo settings) github_token: ${{ secrets.github_token }} - args: "-c.extraMetadata.main=electron-wrapper.js -c.extraMetadata.version=${{ env.PACKAGE_VERSION }}.${{ steps.date.outputs.date }} -c build/electron-builder.json -p onTagOrDraft" + args: "-c.extraMetadata.version=${{ steps.vars.outputs.tag }}.${{ steps.date.outputs.date }} -c build/electron-builder.json -p onTagOrDraft" # If the commit is tagged with a version (e.g. "v1.0.0"), # release the app after building diff --git a/.vscode/Network-Node-1.code-workspace b/.vscode/Network-Node-1.code-workspace new file mode 100644 index 000000000..97e2d4c8f --- /dev/null +++ b/.vscode/Network-Node-1.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "C:\\Superalgos" + } + ], + "settings": { + "search.maintainFileSearchCache": true + } +} \ No newline at end of file diff --git a/.vscode/Network-Node-2.code-workspace b/.vscode/Network-Node-2.code-workspace new file mode 100644 index 000000000..97e2d4c8f --- /dev/null +++ b/.vscode/Network-Node-2.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "C:\\Superalgos" + } + ], + "settings": { + "search.maintainFileSearchCache": true + } +} \ No newline at end of file diff --git a/.vscode/Network-Node-3.code-workspace b/.vscode/Network-Node-3.code-workspace new file mode 100644 index 000000000..97e2d4c8f --- /dev/null +++ b/.vscode/Network-Node-3.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "C:\\Superalgos" + } + ], + "settings": { + "search.maintainFileSearchCache": true + } +} \ No newline at end of file diff --git a/Desktop/DesktopApp.js b/Desktop/DesktopApp.js index 02e44aa7a..5da36f492 100644 --- a/Desktop/DesktopApp.js +++ b/Desktop/DesktopApp.js @@ -1,126 +1,69 @@ exports.newDesktopApp = function newDesktopApp() { let thisObject = { + userProfiles: undefined, + p2pNetworkClient: undefined, + p2pNetwork: undefined, + p2pNetworkPeers: undefined, + webSocketsClient: undefined, + webSocketsInterface: undefined, + socialGraph: undefined, run: run } + DK.desktopApp = thisObject + return thisObject async function run() { - /* - Here we will store our running objects: - */ - DK.running = {} - /* - This is the Personal Social Graph for the user running this App. - */ - DK.running.socialGraph = DK.projects.socialTrading.modules.socialGraph.newSocialTradingModulesSocialGraph() - await DK.running.socialGraph.initialize() - /* - This is the Web Sockets client that interacts with the Superalgos Network. - */ - DK.running.webSocketsClient = SA.projects.network.modules.webSocketsAppClient.newNetworkModulesWebSocketsAppClient() - await DK.running.webSocketsClient.initialize() - console.log('Desktop Client Connected to Network Node via Web Sockets ................... Connected to port ' + global.env.NETWORK_WEB_SOCKETS_INTERFACE_PORT) - /* These are the Network Interfaces by which the Web App interacts with this Desktop Client.*/ + setupNetwork() + setupServices() - DK.running.webSocketsInterface = DK.projects.socialTrading.modules.webSocketsInterface.newDesktopModulesWebSocketsInterface() - DK.running.webSocketsInterface.initialize() - console.log('Desktop Client Web Sockets Interface ....................................... Listening at port ' + global.env.DESKTOP_WEB_SOCKETS_INTERFACE_PORT) - - - DK.running.httpInterface = DK.projects.socialTrading.modules.httpInterface.newDesktopModulesHttpInterface() - DK.running.httpInterface.initialize() - console.log('Desktop Client Http Interface .............................................. Listening at port ' + global.env.DESKTOP_HTTP_INTERFACE_PORT) - - return - - let queryMessage - let query - /* - Test Query User Profiles. - */ - queryMessage = { - queryType: SA.projects.socialTrading.globals.queryTypes.USER_PROFILES, - emitterUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId, - initialIndex: 'Last', - amountRequested: 10, - direction: 'Past' + async function setupNetwork() { + /* + We set up ourselves as a Network Client. + */ + thisObject.p2pNetworkClient = SA.projects.network.modules.p2pNetworkClient.newNetworkModulesP2PNetworkClient() + await thisObject.p2pNetworkClient.initialize() + /* + We will read all user profiles plugins and get from there our network identity. + */ + thisObject.userProfiles = SA.projects.network.modules.userProfiles.newNetworkModulesUserProfiles() + await thisObject.userProfiles.initialize(global.env.DESKTOP_APP_SIGNING_ACCOUNT, thisObject.p2pNetworkClient) + /* + We set up the P2P Network. + */ + thisObject.p2pNetwork = SA.projects.network.modules.p2pNetwork.newNetworkModulesP2PNetwork() + await thisObject.p2pNetwork.initialize('Network Client') + /* + Set up the connections to network nodes. + */ + thisObject.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkPeers() + await thisObject.p2pNetworkPeers.initialize( + 'Network Client', + thisObject.p2pNetworkClient, + thisObject.p2pNetwork, + global.env.DESKTOP_APP_MAX_OUTGOING_PEERS + ) } - query = { - requestType: 'Query', - queryMessage: JSON.stringify(queryMessage) - } + async function setupServices() { + /* + This is the Personal Social Graph for the user running this App. + */ + thisObject.socialGraph = DK.projects.socialTrading.modules.socialGraph.newSocialTradingModulesSocialGraph() + await thisObject.socialGraph.initialize() + /* + These are the Network Interfaces by which the Web App interacts with this Desktop Client. + */ + thisObject.webSocketsInterface = DK.projects.socialTrading.modules.webSocketsInterface.newDesktopModulesWebSocketsInterface() + thisObject.webSocketsInterface.initialize() + console.log('Desktop Client Web Sockets Interface ....................................... Listening at port ' + global.env.DESKTOP_WEB_SOCKETS_INTERFACE_PORT) - await DK.webSocketsClient.sendMessage( - JSON.stringify(query) - ) - .then(showProfiles) - .catch(onError) - - async function showProfiles(profiles) { - console.log(profiles) - - for (let i = 0; i < profiles.length; i++) { - let profile = profiles[i] - - /* - Test Following Profiles. - */ - let eventMessage = { - eventId: SA.projects.foundations.utilities.miscellaneousFunctions.genereteUniqueId(), - eventType: SA.projects.socialTrading.globals.eventTypes.FOLLOW_USER_PROFILE, - emitterUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId, - targetUserProfileId: profile.userProfileId - } - - let event = { - requestType: 'Event', - eventMessage: JSON.stringify(eventMessage) - } - - await DK.webSocketsClient.sendMessage( - JSON.stringify(event) - ) - .then(followAdded) - .catch(onError) - - function followAdded() { - console.log("User Profile " + profile.userProfileHandle + " followed.") - } - } - } - /* - Test Query User Profile Stats. - */ - queryMessage = { - queryType: SA.projects.socialTrading.globals.queryTypes.USER_PROFILE_STATS, - emitterUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId, - targetUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId - } - - query = { - requestType: 'Query', - queryMessage: JSON.stringify(queryMessage) - } - - await DK.webSocketsClient.sendMessage( - JSON.stringify(query) - ) - .then(showProfilesStats) - .catch(onError) - - function showProfilesStats(profile) { - console.log(profile) - } - - /* - Error Handling - */ - function onError(errorMessage) { - console.log('[ERROR] Query not executed. ' + errorMessage) + thisObject.httpInterface = DK.projects.socialTrading.modules.httpInterface.newDesktopModulesHttpInterface() + thisObject.httpInterface.initialize() + console.log('Desktop Client Http Interface .............................................. Listening at port ' + global.env.DESKTOP_HTTP_INTERFACE_PORT) } } } diff --git a/Desktop/UI/Globals.js b/Desktop/UI/Globals.js index 2bce6ff39..4599bca36 100644 --- a/Desktop/UI/Globals.js +++ b/Desktop/UI/Globals.js @@ -1,4 +1,4 @@ - +/* Root object*/ /* Root objects*/ let UI = { projects: {}, @@ -13,3 +13,4 @@ We will use this to load functions originally intended for Nodejs */ let exports = {} + diff --git a/Docker/README.md b/Docker/README.md index 151d21f8e..80d729df7 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -16,9 +16,9 @@ ## Introduction -This walkthrough is broken up into to parts: a quick-start guide to running [Superalgos](https://github.com/Superalgos/Superalgos) with Docker and a deeper, more theoretical dive into containers with the hopes of explaining some of the design decisions. +This walk through is broken up into to parts: a quick-start guide to running [Superalgos](https://github.com/Superalgos/Superalgos) with Docker and a deeper, more theoretical dive into containers with the hopes of explaining some of the design decisions. -[Superalgos](https://github.com/Superalgos/Superalgos), at its core, is a web application which also means it can be deployed inside a container like many other web applications. One of the leading platforms for operating containers is Docker. Docker can run on many different operatng systems and compute platforms. The containers provide an easy, fast, repeatable, and secure way to deploy and distribute applications. While it doesn't take much experience to run containers or Docker, there are some basics that any user should learn in order to use the technology effectively. +[Superalgos](https://github.com/Superalgos/Superalgos), at its core, is a web application which also means it can be deployed inside a container like many other web applications. One of the leading platforms for operating containers is Docker. Docker can run on many different operating systems and compute platforms. The containers provide an easy, fast, repeatable, and secure way to deploy and distribute applications. While it doesn't take much experience to run containers or Docker, there are some basics that any user should learn in order to use the technology effectively. Before getting started, be aware that Docker is not the originally intended method of running the [Superalgos](https://github.com/Superalgos/Superalgos) application and as such there are some drawbacks to doing so. Namely, you won't be able contribute back to the project or configure your Governance profile. We'll discuss this more later. Therefore, you should only consider using the Docker container for production deployments. @@ -55,7 +55,7 @@ Docker should automatically start after installation. If you don't see the whale ### Linux and BSD -On Linux and BSD systems, Docker can be installed using the prefered package manager. [Step by step instructions for many different distributions](https://docs.docker.com/engine/install/debian/) of Linux can be found in the official Docker Docs. Since [Superalgos](https://github.com/Superalgos/Superalgos) runs well on Raspberry Pi 4 single-board computers, I'm going to illustrate the commands necessary to run [Superalgos](https://github.com/Superalgos/Superalgos) on the Raspbian Linux distribution. +On Linux and BSD systems, Docker can be installed using the preferred package manager. [Step by step instructions for many different distributions](https://docs.docker.com/engine/install/debian/) of Linux can be found in the official Docker Docs. Since [Superalgos](https://github.com/Superalgos/Superalgos) runs well on Raspberry Pi 4 single-board computers, I'm going to illustrate the commands necessary to run [Superalgos](https://github.com/Superalgos/Superalgos) on the Raspbian Linux distribution. ```shell # install the requirements @@ -70,7 +70,7 @@ sudo apt-get install \ # add the gpg keys to verify the packages curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg -# confgure the official repository +# configure the official repository echo \ "deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null @@ -84,7 +84,7 @@ Docker should automatically start when it is done installing. You can check its ## Running Superalgos -Now that we have Docker installed and running, we can run the container. The option `--rm` will remove the isntance of the container when it is exited. +Now that we have Docker installed and running, we can run the container. The option `--rm` will remove the instance of the container when it is exited. ```shell docker run --rm ghcr.io/superalgos/superalgos:latest @@ -147,7 +147,7 @@ Continue reading the [Docker Command Line documentation](https://docs.docker.com ### Using Docker-Compose -Docker-compose is a wrapper for the Docker API which makes it a little easier to maintain a declaritive configuration for an application instead of using the direct command line commands. There is a sample docker-compose configuration included in the [Superalgos](https://github.com/Superalgos/Superalgos) which you can as the basis for your own configuration. +Docker-compose is a wrapper for the Docker API which makes it a little easier to maintain a declarative configuration for an application instead of using the direct command line commands. There is a sample docker-compose configuration included in the [Superalgos](https://github.com/Superalgos/Superalgos) which you can as the basis for your own configuration. Let's download the sample and edit it. If you don't use `vim`, change that command for your preferred editor. @@ -236,10 +236,10 @@ Docker has many advantages which can aid in every step from development through Docker maintains a list of [Dockerfile best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) in their main documentation. These tips dictate many of the decisions around the Superalgos Dockerfile. Some of the tips that are used by [Superalgos](https://github.com/Superalgos/Superalgos) are listed below. - Use `.dockerignore` to prevent unwanted data from entering the container. This keeps the container small but also enhances security to prevent secrets from leaking into a container by accident. -- Don't install unneccesary packages. In lieu of multi-stage builds, build caches and build dependencies are removed before finalizing the container. Only packages that are necessary for the execution of the application are installed. This is why `git` is not present. +- Don't install unnecessary packages. In lieu of multi-stage builds, build caches and build dependencies are removed before finalizing the container. Only packages that are necessary for the execution of the application are installed. This is why `git` is not present. - Minimize the number of layers. Many `RUN` commands are combined into one using `&&` in order to reduce the number of layers. - Sort multiline arguments. This mostly enhances readability and maintainability. -- Leverage build cache. When testing locally, several of the tips above help levarage the build cache and speed up build times. +- Leverage build cache. When testing locally, several of the tips above help leverage the build cache and speed up build times. ### Twelve Factor App diff --git a/Environment.js b/Environment.js index 47627f378..04b9a78a4 100644 --- a/Environment.js +++ b/Environment.js @@ -11,9 +11,9 @@ exports.newEnvironment = function () { DEMO_MODE: false, BASE_PATH: basePath, WEB_SERVER_URL: 'localhost', - PLATFORM_WEB_SOCKETS_INTERFACE_PORT: 18041, + PLATFORM_WEB_SOCKETS_INTERFACE_PORT: 16042, + DESKTOP_WEB_SOCKETS_INTERFACE_PORT: 17042, NETWORK_WEB_SOCKETS_INTERFACE_PORT: 18042, - DESKTOP_WEB_SOCKETS_INTERFACE_PORT: 18043, DESKTOP_WEB_SOCKETS_INTERFACE_HOST: 'localhost', PLATFORM_HTTP_INTERFACE_PORT: 34248, DESKTOP_HTTP_INTERFACE_PORT: 34249, @@ -28,10 +28,14 @@ exports.newEnvironment = function () { PATH_TO_MY_WORKSPACES: path.join(basePath, './Platform/My-Workspaces'), PATH_TO_FONTS: path.join(basePath, './Platform/WebServer/Fonts'), DESKTOP_APP_SIGNING_ACCOUNT: 'Social-Trading-Desktop-App-1', + DESKTOP_APP_MAX_OUTGOING_PEERS: 2, MOBILE_APP_SIGNING_ACCOUNT: 'Social-Trading-Mobile-App-1', SERVER_APP_SIGNING_ACCOUNT: 'Social-Trading-Server-App-1', PLATFORM_APP_SIGNING_ACCOUNT: 'Algo-Traders-Platform-1', P2P_NETWORK_NODE_SIGNING_ACCOUNT: 'P2P-Network-Node-1', + P2P_NETWORK_NODE_MAX_INCOMING_CLIENTS: 20, + P2P_NETWORK_NODE_MAX_INCOMING_PEERS: 2, + P2P_NETWORK_NODE_MAX_OUTGOING_PEERS: 2 } if (process.env.DATA_PATH) { diff --git a/Network/NetwokNode.js b/Network/NetwokNode.js index 22a04fbdb..8edc1c6f4 100644 --- a/Network/NetwokNode.js +++ b/Network/NetwokNode.js @@ -1,28 +1,70 @@ exports.newNetworkNode = function newNetworkNode() { let thisObject = { + userProfiles: undefined, + p2pNetwork: undefined, + p2pNetworkPeers: undefined, + p2pNetworkNode: undefined, + webSocketsInterface: undefined, socialGraphService: undefined, storage: undefined, run: run } + NT.networkNode = thisObject + return thisObject async function run() { - /* - Other Network Nodes and Client Apps will communicate with this Network Node via it's Websocket Interface. - */ - NT.webSocketsInterface = NT.projects.network.modules.webSocketsInterface.newNetworkModulesWebSocketsInterface() - NT.webSocketsInterface.initialize() - /* - The Social Graph Service is the first and for now, the only service this Network Node provides. - */ - thisObject.socialGraphService = NT.projects.socialTrading.modules.socialGraph.newNetworkModulesSocialGraph() - await thisObject.socialGraphService.initialize() - /* - The Sotrage deals with persisting the Social Graph. - */ - thisObject.storage = NT.projects.socialTrading.modules.storage.newSocialTradingModulesStorage() - thisObject.storage.initialize() + + await setupNetwork() + await setupServices() + + async function setupNetwork() { + /* + We set up ourselves as a Network Node. + */ + thisObject.p2pNetworkNode = SA.projects.network.modules.p2pNetworkNode.newNetworkModulesP2PNetworkNode() + await thisObject.p2pNetworkNode.initialize() + /* + We will read all user profiles plugins and get from there our network identity. + */ + thisObject.userProfiles = SA.projects.network.modules.userProfiles.newNetworkModulesUserProfiles() + await thisObject.userProfiles.initialize(global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT, thisObject.p2pNetworkNode) + /* + Let's discover who is at the p2p network. + */ + thisObject.p2pNetwork = SA.projects.network.modules.p2pNetwork.newNetworkModulesP2PNetwork() + await thisObject.p2pNetwork.initialize('Network Peer') + /* + Set up the connections to network nodes. + */ + thisObject.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkPeers() + await thisObject.p2pNetworkPeers.initialize( + 'Network Peer', + thisObject.p2pNetworkNode, + thisObject.p2pNetwork, + global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS + ) + } + + async function setupServices() { + /* + The Social Graph Service is the first and for now, the only service this Network Node provides. + */ + thisObject.socialGraphService = NT.projects.socialTrading.modules.socialGraph.newNetworkModulesSocialGraph() + await thisObject.socialGraphService.initialize() + /* + The Sotrage deals with persisting the Social Graph. + */ + thisObject.storage = NT.projects.socialTrading.modules.storage.newSocialTradingModulesStorage() + thisObject.storage.initialize() + /* + Other Network Nodes and Client Apps will communicate with this Network Node via it's Websocket Interface. + */ + thisObject.webSocketsInterface = NT.projects.network.modules.webSocketsInterface.newNetworkModulesWebSocketsInterface() + thisObject.webSocketsInterface.initialize() + console.log('Network Node Web Sockets Interface ....................................... Listening at port ' + JSON.parse(NT.networkNode.p2pNetworkNode.node.config).webSocketsPort) + } } } diff --git a/NetworkRoot.js b/NetworkRoot.js index daa007839..a09e3cd62 100644 --- a/NetworkRoot.js +++ b/NetworkRoot.js @@ -10,7 +10,7 @@ exports.newNetworkRoot = function newNetworkRoot() { return thisObject - async function run() { + async function run(debugSettings) { /* The NT object is accessible everywhere at the Superalgos Network. It provides access to all modules built for this Network. @@ -25,6 +25,10 @@ exports.newNetworkRoot = function newNetworkRoot() { let ENVIRONMENT = require('./Environment.js'); let ENVIRONMENT_MODULE = ENVIRONMENT.newEnvironment() global.env = ENVIRONMENT_MODULE + + if (debugSettings !== undefined && debugSettings.P2P_NETWORK_NODE_SIGNING_ACCOUNT !== undefined) { + global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT = debugSettings.P2P_NETWORK_NODE_SIGNING_ACCOUNT + } /* First thing is to load the project schema file. */ diff --git a/Platform/Client/taskManagerServer.js b/Platform/Client/taskManagerServer.js index c645e497b..c96063c6e 100644 --- a/Platform/Client/taskManagerServer.js +++ b/Platform/Client/taskManagerServer.js @@ -65,7 +65,7 @@ let path = global.env.BASE_PATH + '/TaskServerRoot.js' - /* Workarround to avoid having the same debug port at the forked process which makes it crash. */ + /* Workaround to avoid having the same debug port at the forked process which makes it crash. */ for (let i = 0; i < process.execArgv.length; i++) { let argument = process.execArgv[i] if (argument.indexOf('--inspect') > -1) { @@ -94,7 +94,7 @@ console.log(`[ERROR] Client -> Task Manager Server -> runTask -> Task Server exited with error ${err}`) tasksMap.delete(task.id) }) - /* If the Tast Server stops, we remove it from our task map */ + /* If the Task Server stops, we remove it from our task map */ task.childProcess.on('close', (code, signal) => { //console.log('[INFO] Client -> Task Manager Server -> runTask -> Task Terminated. -> Task Name = ' + task.name) //console.log('[INFO] Client -> Task Manager Server -> runTask -> Task Terminated. -> Task Id = ' + task.id) @@ -190,7 +190,7 @@ function finalize() { - /* Before disconnecting we will forze all eventListeners to stop listening. */ + /* Before disconnecting we will force all eventListeners to stop listening. */ const eventListenersArray = [...eventListeners.values()] for (let i = 0; i < eventListenersArray.length; i++) { let handler = eventListenersArray[i] diff --git a/Platform/Client/webSocketsInterface.js b/Platform/Client/webSocketsInterface.js index 6159d840b..9b51c398c 100644 --- a/Platform/Client/webSocketsInterface.js +++ b/Platform/Client/webSocketsInterface.js @@ -41,7 +41,7 @@ try { if (global.env.DEMO_MODE === true) { /* - In DEMO MODE we will accept Task / Sessioins Running or Stopping if you are requesting this from localhost only. + In DEMO MODE we will accept Task / Sessions Running or Stopping if you are requesting this from localhost only. */ if (socket._socket.remoteAddress !== "::1") { if ( diff --git a/Platform/PlatformApp.js b/Platform/PlatformApp.js index dffa50d13..d156752dd 100644 --- a/Platform/PlatformApp.js +++ b/Platform/PlatformApp.js @@ -20,7 +20,7 @@ exports.newPlatformApp = function newPlatformApp() { }) process.on('unhandledRejection', (reason, p) => { - // Signal user that a necissary node module is missing + // Signal user that a necessary node module is missing if (reason.code == 'MODULE_NOT_FOUND') { console.log("[ERROR] Dependency library not found. Please try running the 'node setup' command and then restart the Superalgos Platform Client.") console.log('[ERROR] Platform App -> reason = ' + JSON.stringify(reason)) diff --git a/Platform/UI/Canvas.js b/Platform/UI/Canvas.js index 210194f73..7a2d09b74 100644 --- a/Platform/UI/Canvas.js +++ b/Platform/UI/Canvas.js @@ -515,6 +515,11 @@ function newCanvas() { return } } + if (nodeOnFocus.payload.uiObject.listSelector !== undefined) { + if (nodeOnFocus.payload.uiObject.listSelector.visible === true) { + return + } + } if (nodeOnFocus.payload.uiObject.conditionEditor !== undefined) { if (nodeOnFocus.payload.uiObject.conditionEditor.visible === true) { return diff --git a/Platform/UI/ProductStorage.js b/Platform/UI/ProductStorage.js index ad44db9bf..fad952099 100644 --- a/Platform/UI/ProductStorage.js +++ b/Platform/UI/ProductStorage.js @@ -8,7 +8,7 @@ function newProductStorage(name) { /* This object will initialize children objects that will end up loading the data of each set defined at each product of the bot received at initialization. - Once all the underlaying objects are fully initialized it will callback. + Once all the underlying objects are fully initialized it will callback. At the same time it will raise an event for each underlaying file being loaded, so that the UI can reflect the progress to the end user. diff --git a/Platform/UI/Utilities.js b/Platform/UI/Utilities.js index b8be0cd45..54affe934 100644 --- a/Platform/UI/Utilities.js +++ b/Platform/UI/Utilities.js @@ -15,7 +15,7 @@ function getSchemaDocument(node, project) { even those can fail. For that reason, we will temporally see if we can find the schema document at any of the available projects. - TODO: We need to explictly declare the project of a relatedUIObject in order to avoid potential name collision + TODO: We need to explicitly declare the project of a relatedUIObject in order to avoid potential name collision between nodes belonging to more than one project. */ diff --git a/Platform/WebServer/Images/Languages/AR.png b/Platform/WebServer/Images/Languages/AR.png new file mode 100644 index 000000000..be757caa6 Binary files /dev/null and b/Platform/WebServer/Images/Languages/AR.png differ diff --git a/Projects/Foundations/Icons/Languages/ZA.png b/Platform/WebServer/Images/Languages/ZA.png similarity index 100% rename from Projects/Foundations/Icons/Languages/ZA.png rename to Platform/WebServer/Images/Languages/ZA.png diff --git a/Platform/WebServer/externalScripts/flexsearch.bundle.js b/Platform/WebServer/externalScripts/flexsearch.bundle.js new file mode 100644 index 000000000..dd0c08309 --- /dev/null +++ b/Platform/WebServer/externalScripts/flexsearch.bundle.js @@ -0,0 +1,33 @@ +/**! + * FlexSearch.js v0.7.2 (Bundle) + * Copyright 2018-2021 Nextapps GmbH + * Author: Thomas Wilkerling + * Licence: Apache-2.0 + * https://github.com/nextapps-de/flexsearch + */ +(function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;var t;function u(a){return"undefined"!==typeof a?a:!0}function aa(a){const b=Array(a);for(let c=0;c=this.B&&(w||!n[l])){var f=L(q,d,r),g="";switch(this.G){case "full":if(3f;h--)if(h-f>=this.B){var k=L(q,d,r,e,f);g=l.substring(f,h);M(this,n,g,k,a,c)}break}case "reverse":if(2=this.B&&M(this,n, +g,L(q,d,r,e,h),a,c);g=""}case "forward":if(1=this.B&&M(this,n,g,f,a,c);break}default:if(this.C&&(f=Math.min(f/this.C(b,l,r)|0,q-1)),M(this,n,l,f,a,c),w&&1=this.B&&!e[l]){e[l]=1;const p=this.l&&l>f;M(this,m,p?f:l,L(g+(d/2>g?0:1),d,r,h-1,k-1),a,c,p?l:f)}}}}this.m||(this.register[a]=1)}}return this}; +function L(a,b,c,d,e){return c&&1=this.B&&!c[q])if(this.s||f||this.map[q])k[w++]=q,c[q]=1;else return d;a=k;e=a.length}if(!e)return d;b||(b=100);h=this.depth&&1=d)))break;if(n){if(f)return ta(k,d,0);b[b.length]=k;return}}return!c&&k}function ta(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} +function ua(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}t.contain=function(a){return!!this.register[a]};t.update=function(a,b){return this.remove(a).add(a,b)}; +t.remove=function(a,b){const c=this.register[a];if(c){if(this.m)for(let d=0,e;db||c)e=e.slice(c,c+b);d&&(e=za.call(this,e));return{tag:a,result:e}}}function za(a){const b=Array(a.length);for(let c=0,d;c +