├── .devcontainer ├── Dockerfile └── devcontainer.json ├── docs └── img │ ├── codespaces.png │ ├── vscode_run.png │ ├── vscode_build.png │ ├── vscode_code.png │ ├── vscode_debug.png │ ├── vscode_port.png │ ├── vscode_create.png │ ├── vscode_terminal.png │ └── vscode_terminal2.png ├── node ├── test.js └── app.js ├── src └── lib.rs ├── .vscode ├── tasks.json ├── settings.json └── launch.json ├── Cargo.toml ├── .gitignore ├── .github └── workflows │ ├── core.yml │ └── ext.yml ├── README.md └── README-Codespaces.md /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM wasmedge/appdev_x86_64:0.8.2 2 | -------------------------------------------------------------------------------- /docs/img/codespaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/codespaces.png -------------------------------------------------------------------------------- /docs/img/vscode_run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_run.png -------------------------------------------------------------------------------- /node/test.js: -------------------------------------------------------------------------------- 1 | const { say } = require('../pkg/wasmedge_nodejs_starter_lib.js'); 2 | console.log( say("Node.js") ); 3 | -------------------------------------------------------------------------------- /docs/img/vscode_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_build.png -------------------------------------------------------------------------------- /docs/img/vscode_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_code.png -------------------------------------------------------------------------------- /docs/img/vscode_debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_debug.png -------------------------------------------------------------------------------- /docs/img/vscode_port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_port.png -------------------------------------------------------------------------------- /docs/img/vscode_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_create.png -------------------------------------------------------------------------------- /docs/img/vscode_terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_terminal.png -------------------------------------------------------------------------------- /docs/img/vscode_terminal2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/wasmedge-nodejs-starter/HEAD/docs/img/vscode_terminal2.png -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen] 4 | pub fn say(s: &str) -> String { 5 | println!("The Rust function say() received {}", s); 6 | let r = String::from("hello "); 7 | return r + s; 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [{ 4 | "label": "ssvmup build", 5 | "type": "shell", 6 | "command": "ssvmup build", 7 | "args": [], 8 | "problemMatcher": [] 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.workingDirectories": [ 3 | { 4 | "directory": "./node", 5 | "changeProcessCWD": true 6 | } 7 | ], 8 | "search.exclude": { 9 | "**/target": true 10 | }, 11 | "lldb.verboseLogging": true 12 | } 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasmedge_nodejs_starter" 3 | version = "0.1.0" 4 | authors = ["ubuntu"] 5 | edition = "2018" 6 | 7 | [package.metadata.ssvmup.profile.release] 8 | wasm-opt = ['-O4'] 9 | 10 | [lib] 11 | name = "wasmedge_nodejs_starter_lib" 12 | path = "src/lib.rs" 13 | crate-type =["cdylib"] 14 | 15 | [dependencies] 16 | wasm-bindgen = "=0.2.61" 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | target 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | # nodejs 13 | node_modules 14 | build 15 | npm-debug.log 16 | package-lock.json 17 | 18 | # ssvm 19 | pkg 20 | 21 | # local computer 22 | .env 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceFolder}/node/app.js", 12 | "cwd": "${workspaceFolder}/node", 13 | "preLaunchTask": "ssvmup build" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /node/app.js: -------------------------------------------------------------------------------- 1 | const { say } = require('../pkg/wasmedge_nodejs_starter_lib.js'); 2 | 3 | const http = require('http'); 4 | const url = require('url'); 5 | const hostname = '0.0.0.0'; 6 | const port = 3000; 7 | 8 | const server = http.createServer((req, res) => { 9 | const queryObject = url.parse(req.url,true).query; 10 | if (!queryObject['name']) { 11 | res.end(`Please use command curl http://${hostname}:${port}/?name=MyName \n`); 12 | } else { 13 | res.end(say(queryObject['name']) + '\n'); 14 | } 15 | }); 16 | 17 | server.listen(port, hostname, () => { 18 | console.log(`Server running at http://${hostname}:${port}/`); 19 | }); 20 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Second State Rust Node.js", 3 | "dockerFile": "Dockerfile", 4 | 5 | // Set *default* container specific settings.json values on container create. 6 | "settings": { 7 | "terminal.integrated.profiles.linux": { 8 | "bash login": { 9 | "path": "/bin/bash", 10 | "args": ["-l"] 11 | } 12 | }, 13 | "terminal.integrated.defaultProfile.linux": "bash login", 14 | "lldb.executable": "/usr/bin/lldb" 15 | }, 16 | 17 | // Add the IDs of extensions you want installed when the container is created. 18 | "extensions": [ 19 | "rust-lang.rust", 20 | "bungcip.better-toml", 21 | "vadimcn.vscode-lldb", 22 | "dbaeumer.vscode-eslint" 23 | ], 24 | 25 | "forwardPorts": [3000] 26 | 27 | // Use 'postCreateCommand' to run commands after the container is created. 28 | // "postCreateCommand": "bash -l" 29 | 30 | // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. 31 | // "remoteUser": "node" 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/core.yml: -------------------------------------------------------------------------------- 1 | name: wasmedge-core 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-20.04 13 | 14 | strategy: 15 | matrix: 16 | node-version: [10.x, 12.x, 14.x] 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v1 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | 26 | - name: Install apt-get packages 27 | run: | 28 | sudo ACCEPT_EULA=Y apt-get update 29 | sudo ACCEPT_EULA=Y apt-get upgrade 30 | sudo apt-get install wget git curl software-properties-common 31 | 32 | - name: Install Rust target 33 | run: | 34 | rustup target add wasm32-wasi 35 | 36 | - name: Install npm packages 37 | run: | 38 | npm install -g rustwasmc 39 | npm install wasmedge-core 40 | 41 | - name: Build 42 | run: | 43 | rustup override set 1.50.0 44 | rustwasmc build 45 | 46 | - name: Test 47 | run: | 48 | source $HOME/.profile 49 | node node/test.js 50 | rustwasmc clean 51 | 52 | - name: Upload artifact 53 | uses: actions/upload-artifact@v1 54 | with: 55 | name: ubuntu-18.04-nodejs-${{ matrix.node-version }} 56 | path: node 57 | -------------------------------------------------------------------------------- /.github/workflows/ext.yml: -------------------------------------------------------------------------------- 1 | name: wasmedge-extensions 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-20.04 13 | 14 | strategy: 15 | matrix: 16 | node-version: [10.x, 12.x, 14.x] 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v1 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | 26 | - name: Install apt-get packages 27 | run: | 28 | sudo ACCEPT_EULA=Y apt-get update 29 | sudo ACCEPT_EULA=Y apt-get upgrade 30 | sudo apt-get install wget git curl software-properties-common 31 | 32 | - name: Install Rust target 33 | run: | 34 | rustup target add wasm32-wasi 35 | 36 | - name: Install npm packages 37 | run: | 38 | npm install -g rustwasmc 39 | npm install wasmedge-extensions 40 | 41 | - name: Build 42 | run: | 43 | rustup override set 1.50.0 44 | rustwasmc build --enable-ext 45 | 46 | - name: Test 47 | run: | 48 | source $HOME/.profile 49 | node node/test.js 50 | rustwasmc clean 51 | 52 | - name: Upload artifact 53 | uses: actions/upload-artifact@v1 54 | with: 55 | name: ubuntu-18.04-nodejs-${{ matrix.node-version }} 56 | path: node 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Info 2 | 3 | This project is no longer updated. If you are interested in using javascript, please refer to [the wasmedge-quickjs repo](https://github.com/second-state/wasmedge-quickjs) 4 | 5 | # Getting started 6 | 7 | ![Build and test](https://github.com/second-state/wasmedge-nodejs-starter/workflows/Build%20and%20test/badge.svg) 8 | 9 | [Fork this project](https://github.com/second-state/wasmedge-nodejs-starter/fork) to create your own Rust functions as a web service. 10 | 11 | ## How it works 12 | 13 | * The Rust function source code is in the `src/lib.rs` file. 14 | * Use the [rustwasmc tool](https://www.secondstate.io/articles/rustwasmc/) to compile the Rust function into a WebAssembly module in the `pkg` directory. 15 | * Optional: Use the `node node/app.js` command to test the function locally in Node.js. 16 | * Upload the `pkg/*.wasm` file to the [Second State FaaS service](https://www.secondstate.io/articles/getting-started-with-function-as-a-service-in-rust/), OR to a [Node.js server](https://www.secondstate.io/articles/getting-started-with-rust-function/), to turn it into a web service. 17 | 18 | ## Setup 19 | 20 | It is easy to use our `appdev` Docker image to run the dev environment. You can choose from `x86_64` or `aarch64` versions of the image. Alternatively, you could also use Github Codespaces to run the following example. 21 | 22 | ``` 23 | $ docker pull wasmedge/appdev_x86_64 24 | $ docker run -p 3000:3000 --rm -it -v $(pwd):/app wasmedge/appdev_x86_64 25 | (docker) # 26 | ``` 27 | 28 | ## Build 29 | 30 | Use the `rustwasmc` command to build the Rust function into a WebAssembly bytecode file. 31 | 32 | ``` 33 | (docker) # cd /app 34 | (docker) # rustwasmc build 35 | ``` 36 | 37 | ## Test and debug 38 | 39 | From the first terminal window, start the Node.js application. 40 | 41 | ``` 42 | (docker) # node node/app.js 43 | ``` 44 | 45 | From a second terminal window, you can test the local server. 46 | 47 | ``` 48 | $ curl http://localhost:3000/?name=WasmEdge 49 | hello WasmEdge 50 | ``` 51 | 52 | ### Optional: Upload to the FaaS and test 53 | 54 | Upload the wasm file in the pkg folder to the FaaS. Double check the .wasm file name before you upload. 55 | 56 | ``` 57 | (docker) # curl --location --request POST 'https://rpc.ssvm.secondstate.io:8081/api/executables' \ 58 | --header 'Content-Type: application/octet-stream' \ 59 | --header 'SSVM-Description: say hello' \ 60 | --data-binary '@pkg/hello_lib_bg.wasm' 61 | ``` 62 | 63 | The FaaS returns 64 | 65 | ``` 66 | {"wasm_id":161,"wasm_sha256":"0xfb413547a8aba56d0349603a7989e269f3846245e51804932b3e02bc0be4b665","usage_key":"00000000-0000-0000-0000-000000000000","admin_key":"00xxxxxx-xxxx-xxxx-xxxx-4adc960fd2b8"} 67 | ``` 68 | 69 | Make a function call via the web. 70 | 71 | ``` 72 | (docker) # curl --location --request POST 'https://rpc.ssvm.secondstate.io:8081/api/run/161/say' \ 73 | --header 'Content-Type: text/plain' \ 74 | --data-raw 'Second State FaaS' 75 | hello Second State FaaS 76 | ``` 77 | 78 | You can easily incorporate this web service into your HTML web pages. [See how](https://www.secondstate.io/articles/getting-started-with-function-as-a-service-in-rust/#web-ui) 79 | 80 | ## More exercises 81 | 82 | Now, you can copy and paste code from [this project](https://github.com/second-state/wasm-learning/tree/master/nodejs/functions). 83 | 84 | * `src/lib.rs` --> Replace with [code here](https://github.com/second-state/wasm-learning/blob/master/nodejs/functions/src/lib.rs) 85 | * `Cargo.toml` --> Replace with [code here](https://github.com/second-state/wasm-learning/blob/master/nodejs/functions/Cargo.toml) 86 | * `node/app.js` --> Replace with [code here](https://github.com/second-state/wasm-learning/blob/master/nodejs/functions/node/app.js) 87 | 88 | * FaaS deployment: https://github.com/second-state/wasm-learning/tree/master/faas 89 | * Node.js deployment: https://github.com/second-state/wasm-learning/tree/master/nodejs 90 | 91 | ## Read more: 92 | 93 | * [Tutorials for FaaS](https://www.secondstate.io/faas/) 94 | * [Getting started with FaaS in Rust](https://www.secondstate.io/articles/getting-started-with-function-as-a-service-in-rust/) 95 | * [Use Binary Data as Function Input and Output](https://www.secondstate.io/articles/use-binary-data-as-function-input-and-output/) 96 | * [Mixing Text and Binary Data in Call Arguments](https://www.secondstate.io/articles/mixing-text-and-binary-data-in-call-arguments/) 97 | * [Internet of Functions: webhooks](https://www.secondstate.io/articles/internet-of-functions-webhooks/) 98 | * [AI as A Service on WebAssembly](https://www.secondstate.io/articles/ai-as-a-servide-on-webaasembly/) 99 | * [Tutorials for Node.js micro-services](https://www.secondstate.io/ssvm/) 100 | * [The Case for WebAssembly on the Server-side](https://www.secondstate.io/articles/why-webassembly-server/) 101 | * [Getting started on Rust and WebAssembly for server-side apps](https://www.secondstate.io/articles/getting-started-with-rust-function/) 102 | * [Passing function arguments in JSON](https://www.secondstate.io/articles/rust-functions-in-nodejs/) 103 | * [Use Tensorflow and AI models from WebAssembly](https://www.secondstate.io/articles/face-detection-ai-as-a-service/) 104 | 105 | ## Resources 106 | 107 | * [The WasmEdge Runtime](https://github.com/WasmEdge/WasmEdge) is a high performance WebAssembly virtual machine designed for edge computing (including Edge Cloud) applications. 108 | * [The rustwasmc](https://github.com/second-state/rustwasmc) is a [toolchain](https://www.secondstate.io/articles/rustwasmc/) for compiling Rust programs into WebAssembly, and then make them accessible from JavaScripts via the WasmEdge Runtime. 109 | * [The Second State FaaS](https://github.com/second-state/wasm-joey) is an open source FaaS engine based on WebAssembly and Node.js. 110 | 111 | Brought to you by the Open source dev team at [Second State](https://www.secondstate.io/). Follow us on [Twitter](https://twitter.com/secondstateinc), [Facebook](https://www.facebook.com/SecondState.io/), [LinkedIn](https://www.linkedin.com/company/second-state/), [YouTube](https://www.youtube.com/channel/UCePMT5duHcIbJlwJRSOPDMQ), or [Medium](https://medium.com/wasm) 112 | -------------------------------------------------------------------------------- /README-Codespaces.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | ![Build and test](https://github.com/second-state/ssvm-nodejs-starter/workflows/Build%20and%20test/badge.svg) 4 | 5 | [Fork this project](https://github.com/second-state/wasmedge-nodejs-starter/fork) to create your own Rust functions as a web service. 6 | 7 | ## How it works 8 | 9 | * The Rust function source code is in the `src/lib.rs` file. 10 | * Use the [rustwasmc tool](https://www.secondstate.io/articles/rustwasmc/) to compile the Rust function into a WebAssembly module in the `pkg` directory. 11 | * Optional: Use the `node node/app.js` command to test the function locally in Node.js. 12 | * Upload the `pkg/*.wasm` file to the [Second State FaaS service](https://www.secondstate.io/articles/getting-started-with-function-as-a-service-in-rust/), OR to a [Node.js server](https://www.secondstate.io/articles/getting-started-with-rust-function/), to turn it into a web service. 13 | 14 | This is the Github Codespaces edition. Check out the [Docker edition here](README.md). 15 | 16 | ## Github Codespaces 17 | 18 | ![GitHub Codespaces](docs/img/codespaces.png) 19 | 20 | Click on the Code -> Open with Codespaces menu, and wait for the Codespaces IDE screen to build and come up. This could take a few minutes as it installs all the dependencies Rust and WebAssembly requires. 21 | 22 | Open the `src/lib.rs` and `Cargo.toml` files to learn about the Rust function. 23 | 24 | Open the Terminal window via the `Terminal -> New Terminal` menu, and run the command and wait until it completes building. 25 | 26 | ``` 27 | $ rustwasmc build 28 | ``` 29 | 30 | ### Option 1: Upload to the FaaS and test 31 | 32 | Run the following command in the terminal window. Upload the wasm file in the pkg folder to the FaaS. Double check the .wasm file name before you upload. 33 | 34 | ``` 35 | $ curl --location --request POST 'https://rpc.ssvm.secondstate.io:8081/api/executables' \ 36 | --header 'Content-Type: application/octet-stream' \ 37 | --header 'SSVM-Description: say hello' \ 38 | --data-binary '@pkg/hello_lib_bg.wasm' 39 | ``` 40 | 41 | The FaaS returns 42 | 43 | ``` 44 | {"wasm_id":161,"wasm_sha256":"0xfb413547a8aba56d0349603a7989e269f3846245e51804932b3e02bc0be4b665","usage_key":"00000000-0000-0000-0000-000000000000","admin_key":"00xxxxxx-xxxx-xxxx-xxxx-4adc960fd2b8"} 45 | ``` 46 | 47 | Make a function call via the web. 48 | 49 | ``` 50 | (docker) # curl --location --request POST 'https://rpc.ssvm.secondstate.io:8081/api/run/161/say' \ 51 | --header 'Content-Type: text/plain' \ 52 | --data-raw 'Second State FaaS' 53 | hello Second State FaaS 54 | ``` 55 | 56 | You can easily incorporate this web service into your HTML web pages. [See how](https://www.secondstate.io/articles/getting-started-with-function-as-a-service-in-rust/#web-ui) 57 | 58 | 59 | ### Option 2: Local test and debug 60 | 61 | From the terminal window, start the Node.js application. 62 | 63 | ``` 64 | (docker) # node node/app.js 65 | ``` 66 | 67 | Create a second terminal window, you can test the local server. 68 | 69 | ``` 70 | $ curl http://localhost:3000/?name=WasmEdge 71 | hello WasmEdge 72 | ``` 73 | 74 | ## More exercises 75 | 76 | Now, you can copy and paste code from [this project](https://github.com/second-state/wasm-learning/tree/master/nodejs/functions). 77 | 78 | * `src/lib.rs` --> Replace with [code here](https://github.com/second-state/wasm-learning/blob/master/nodejs/functions/src/lib.rs) 79 | * `Cargo.toml` --> Replace with [code here](https://github.com/second-state/wasm-learning/blob/master/nodejs/functions/Cargo.toml) 80 | * `node/app.js` --> Replace with [code here](https://github.com/second-state/wasm-learning/blob/master/nodejs/functions/node/app.js) 81 | 82 | Build, deploy, test. You can find many more examples to play with here: 83 | 84 | * FaaS deployment: https://github.com/second-state/wasm-learning/tree/master/faas 85 | * Node.js deployment: https://github.com/second-state/wasm-learning/tree/master/nodejs 86 | 87 | ## Read more: 88 | 89 | * [Tutorials for FaaS](https://www.secondstate.io/faas/) 90 | * [Getting started with FaaS in Rust](https://www.secondstate.io/articles/getting-started-with-function-as-a-service-in-rust/) 91 | * [Use Binary Data as Function Input and Output](https://www.secondstate.io/articles/use-binary-data-as-function-input-and-output/) 92 | * [Mixing Text and Binary Data in Call Arguments](https://www.secondstate.io/articles/mixing-text-and-binary-data-in-call-arguments/) 93 | * [Internet of Functions: webhooks](https://www.secondstate.io/articles/internet-of-functions-webhooks/) 94 | * [AI as A Service on WebAssembly](https://www.secondstate.io/articles/ai-as-a-servide-on-webaasembly/) 95 | * [Tutorials for Node.js micro-services](https://www.secondstate.io/ssvm/) 96 | * [The Case for WebAssembly on the Server-side](https://www.secondstate.io/articles/why-webassembly-server/) 97 | * [Getting started on Rust and WebAssembly for server-side apps](https://www.secondstate.io/articles/getting-started-with-rust-function/) 98 | * [Passing function arguments in JSON](https://www.secondstate.io/articles/rust-functions-in-nodejs/) 99 | * [Access operating system resources from WebAssembly (WASI)](https://www.secondstate.io/articles/wasi-access-system-resources/) 100 | * [Use Tensorflow and AI models from WebAssembly](https://www.secondstate.io/articles/face-detection-ai-as-a-service/) 101 | 102 | ## Resources 103 | 104 | * [The WasmEdge Runtime](https://github.com/WasmEdge/WasmEdge) is a high performance WebAssembly virtual machine. 105 | * [The rustwasmc](https://github.com/second-state/rustwasmc) is a [toolchain](https://www.secondstate.io/articles/ssvmup/) for compiling Rust programs into WebAssembly, and then make them accessible from JavaScripts via the WasmEdge Runtime. 106 | * [The Second State FaaS](https://github.com/second-state/wasm-joey) is an open source FaaS engine based on WebAssembly and Node.js. 107 | 108 | Brought to you by the Open source dev team at [Second State](https://www.secondstate.io/). Follow us on [Twitter](https://twitter.com/secondstateinc), [Facebook](https://www.facebook.com/SecondState.io/), [LinkedIn](https://www.linkedin.com/company/second-state/), [YouTube](https://www.youtube.com/channel/UCePMT5duHcIbJlwJRSOPDMQ), or [Medium](https://medium.com/wasm) 109 | 110 | --------------------------------------------------------------------------------