Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(examples): add typescript http echo actor #1300

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/typescript/actors/http-hello-world/.gitignore
@@ -0,0 +1,8 @@
# JS build output
/dist/

/node_modules/
/keys/

# wash build output
/build/*
1 change: 1 addition & 0 deletions examples/typescript/actors/http-hello-world/.nvmrc
@@ -0,0 +1 @@
v21.5.0
116 changes: 116 additions & 0 deletions examples/typescript/actors/http-hello-world/README.md
@@ -0,0 +1,116 @@
# Typescript HTTP Hello World

This repository contains a hello world HTTP actor component, written in [Typescript][ts].

This component:

- Uses Typescript for it's implementation
- Uses the [`wasi:http`][wasi-http] standard WIT definitions
- Relies on the [`httpserver` capability provider][httpserver-provider] (which exposes the [`wasmcloud:httpserver` interface][httpserver-interface])
- Return `"hello from Typescript"` to all HTTP requests
- Can be declaratively provisioned with [`wadm`][wadm]

[ts]: https://www.typescriptlang.org/
[wasi-http]: https://github.com/WebAssembly/wasi-http
[httpserver-provider]: https://github.com/wasmCloud/wasmCloud/tree/main/crates/providers/http-server
[httpserver-interface]: https://github.com/wasmCloud/interfaces/tree/main/httpserver
[wadm]: https://github.com/wasmCloud/wadm

# Dependencies

This relies on the following installed software:

| Name | Description |
|--------|-------------------------------------------------------------------------------------------------|
| `wash` | [Wasmcloud Shell][wash] controls your [wasmcloud][wasmcloud] host instances and enables building actors |
| `npm` | [Node Package Manager (NPM)][npm] which manages packages for for the NodeJS ecosystem |
| `node` | [NodeJS runtime][nodejs] (see `.nvmrc` for version) |

[wash]: https://github.com/wasmCloud/wasmCloud/tree/main/crates/wash-cli
[node]: https://nodejs.org
[npm]: https://github.com/npm/cli

# Get started

## Install NodeJS dependencies

If you have the basic dependencies installed, you can install NodeJS-level dependcies:

```console
npm install
```

## Start a wasmcloud host

To start a wasmcloud host you can use `wash`:

```console
wash up
```

This command won't return (as it's the running host process), but you can view the output of the host.

## Build the actor component

To build the [actor component][wasmcloud-actor-component], we can use `wash`:

```console
wash build
```

This will build and sign the actor and place a signed [WebAssembly component][wasm-component] at `build/index_s.wasm`.

`build` performs many substeps (see `package.json` for details):

- (`build:tsc`) transpiles Typescript code into Javascript code
- (`build:component`) builds a [WebAssembly component][wasm-component] using the [`jco` toolchain][jco]
- (`build:actor`) sign an actor for this component using `wash`

[wasmcloud-actor-component]: https://wasmcloud.com/docs/concepts/webassembly-components
[wasm-component]: https://component-model.bytecodealliance.org/
[jco]: https://github.com/bytecodealliance/jco

## Update WADM manifest with the built actor path

Before we can start the actor, we need to edit our declarative configuration to reflect the path to the built WebAssembly component in `typescript-http-hello-world.wadm.yaml`:

```yaml
properties:
# TODO: you must replace the path below to match your genreated code in build
image: file:///the/absolute/path/to/build/index_s.wasm
```

Replace the `the/absolute/path/...` above with the path to `build/index_s.wasm`.


## Start the actor along with the HTTP server provider

To start the actor, HTTP server provider and everything we need to run:

```console
npm run wadm:start
```

This command will deploy the application to your running wasmcloud host, using [`wadm`][wadm], a declarative WebAssembly orchestrator.

## Send a request to the running actor

To send a request to the running actor (via the HTTP server provider):

```console
curl localhost:8081
```

> [!INFO]
> Confused as to why it is port 8081?
>
> See `typescript-http-hello-world.wadm.yaml` for more information on the pieces of the architecture;
> actors, providers, and link definitions.

## (Optional) reload on code change

To quickly reload your application after changing the code in `index.ts`:

```console
npm run reload
```
33 changes: 33 additions & 0 deletions examples/typescript/actors/http-hello-world/index.ts
@@ -0,0 +1,33 @@
import {
IncomingRequest,
ResponseOutparam,
OutgoingResponse,
Fields,
} from "wasi:http/types@0.2.0-rc-2023-12-05";

// Implementation of wasi-http incoming-handler
//
// NOTE: To understand the types involved, take a look at wit/deps/http/types.wit
function handle(req: IncomingRequest, resp: ResponseOutparam) {
// Start building an outgoing response
const outgoingResponse = new OutgoingResponse(new Fields());

// Access the outgoing response body
let outgoingBody = outgoingResponse.body();
// Create a stream for the response body
let outputStream = outgoingBody.write();
// // Write hello world to the response stream
outputStream.blockingWriteAndFlush(
new Uint8Array(new TextEncoder().encode("hello from Typescript"))
);

// Set the status code for the response
outgoingResponse.setStatusCode(200);

// Set the created response
ResponseOutparam.set(resp, { tag: "ok", val: outgoingResponse });
}

export const incomingHandler = {
handle,
};
29 changes: 29 additions & 0 deletions examples/typescript/actors/http-hello-world/package.json
@@ -0,0 +1,29 @@
{
"name": "ts-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build:tsc": "tsc",
"build:component": "jco componentize -w wit -o dist/index.wasm dist/index.js",
"build:actor": "wash build --sign-only --config-path wasmcloud.toml",
"build": "npm run build:tsc && npm run build:component && npm run build:actor",
"actor:start": "wash start actor file://$(realpath dist/index_s.wasm) --auction-timeout-ms 10000 --timeout-ms 10000",
"actor:stop": "wash stop actor typescript-http-hello-world",
"wadm:start": "wash app deploy typescript-http-hello-world.wadm.yaml",
"wadm:stop": "wash app delete typescript-http-hello-world v0.0.1",
"start": "npm run build && npm run wadm:start",
"reload": "npm run build && npm run wadm:stop && npm run wadm:start",
"stop": "npm run wadm:stop",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@bytecodealliance/componentize-js": "^0.6.0",
"@bytecodealliance/jco": "^0.14.2",
"@types/node": "^20.10.8",
"typescript": "^5.3.3"
}
}