Skip to content

Commit

Permalink
documentation(README.md): update with interfaces and types (#131)
Browse files Browse the repository at this point in the history
Adds information about function signatures using TypeScript types and interfaces. Some other minor cleanup.

/kind documentation

Signed-off-by: Lance Ball <[email protected]>
  • Loading branch information
lance authored Nov 3, 2022
1 parent 5ed0cff commit 058fc77
Showing 1 changed file with 69 additions and 19 deletions.
88 changes: 69 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,74 @@
## FaaS Node.js Runtime Framework
# Node.js Function Framework

[![Node.js CI](https://github.com/boson-project/faas-js-runtime/workflows/Node.js%20CI/badge.svg)](https://github.com/boson-project/faas-js-runtime/actions?query=workflow%3A%22Node.js+CI%22+branch%3Amaster)
[![codecov](https://codecov.io/gh/boson-project/faas-js-runtime/branch/main/graph/badge.svg?token=Z72LKANFJI)](https://codecov.io/gh/boson-project/faas-js-runtime)

This module provides a Node.js framework for executing a function that
exists in a user-provided directory path as an `index.js` file. The
directory may also contain an optional `package.json` file which can
be used to declare runtime dependencies for the function.
be used to declare runtime dependencies for the function. You can also
provide a path to an arbitrary JavaScript file instead of a directory
path, allowing you to execute a single file as a function.

The function is loaded and then invoked for incoming HTTP requests
at `localhost:8080`. The incoming request may be a
[Cloud Event](https://github.com/cloudevents/sdk-javascript#readme.) or
just a simple HTTP GET request. In either case, the function will receive
a `Context` object instance that has a `cloudevent` property. For a raw HTTP
request, the incoming request is converted to a Cloud Event.
just a simple HTTP GET/POST request. The invoked user function can be
`async` but that is not required.

The invoked user function can be `async` but that is not required.
## Function Signatures

### CLI
This module supports two different function signatures: HTTP or CloudEvents. In the type definitions below, we use TypeScript to express interfaces and types, but this module is usable from JavaScript as well.

### HTTP Functions

The HTTP function signature is the simplest. It is invoked for every HTTP request that does not contain a CloudEvent.

```typescript
interface HTTPFunction {
(context: Context, body?: IncomingBody): HTTPFunctionReturn;
}
```

Where the `IncomingBody` is either a string, a Buffer, a JavaScript object, or undefined, depending on what was supplied in the HTTP POST message body. The `HTTTPFunctionReturn` type is defined as:

```typescript
type HTTPFunctionReturn = Promise<StructuredReturn> | StructuredReturn | ResponseBody | void;
```

Where the `StructuredReturn` is a JavaScript object with the following properties:

```typescript
interface StructuredReturn {
statusCode?: number;
headers?: Record<string, string>;
body?: ResponseBody;
}
```

If the function returns a `StructuredReturn` object, then the `statusCode` and `headers` properties are used to construct the HTTP response. If the `body` property is present, it is used as the response body. If the function returns `void` or `undefined`, then the response body is empty.

The `ResponseBody` is either a string, a JavaScript object, or a Buffer. JavaScript objects will be serialized as JSON. Buffers will be sent as binary data.

### CloudEvent Functions

CloudEvent functions are used in environments where the incoming HTTP request is a CloudEvent. The function signature is:

```typescript
interface CloudEventFunction {
(context: Context, event: CloudEvent): CloudEventFunctionReturn;
}
```

Where the return type is defined as:

```typescript
type CloudEventFunctionReturn = Promise<CloudEvent> | CloudEvent | HTTPFunctionReturn;
```

The function return type can be anything that a simple HTTP function can return or a CloudEvent. Whatever is returned, it will be sent back to the caller as a response.

## CLI

The easiest way to get started is to use the CLI. You can call it
with the path to any JavaScript file which has a default export that
Expand All @@ -37,16 +88,19 @@ function handle(context) {
module.exports = handle;
```

Additionally, if your JavaScript file exports more than a single function,
an exported `handle` function will be invoked.

You can expose this function as an HTTP endpoint at `localhost:8080`
with the CLI.

```console
npx faas-js-runtime ./index.js
```

### Usage
## Usage as a Module

In my current working directory, I have an `index.js` file like this.
In the current working directory, there is an `index.js` file like this.

```js
const { start } = require('faas-js-runtime');
Expand All @@ -57,10 +111,11 @@ const options = {
logLevel: 'info'
}

// My function directory is in ./function-dir
// The function directory is in ./function-dir
start(require(`${__dirname}/function-dir/`), server => {
// The server is now listening on localhost:8080
// and the function will be invoked for each HTTP
// and the function defined in `function-dir/index.js`
// will be invoked for each HTTP
// request to this endpoint.
console.log('Server listening');

Expand All @@ -74,7 +129,7 @@ like this.

```js
module.exports = async function myFunction(context) {
const ret = 'This is a test function for Node.js FaaS. Success.';
const ret = 'This is a test for Node.js functions. Success.';
return new Promise((resolve, reject) => {
setTimeout(_ => {
context.log.info('sending response to client')
Expand Down Expand Up @@ -104,15 +159,10 @@ $ curl -X POST -d '{"hello": "world"}' \
-H'Ce-id: 1' \
-H'Ce-source: cloud-event-example' \
-H'Ce-type: dev.knative.example' \
-H'Ce-specversion: 0.2' \
-H'Ce-specversion: 1.0' \
http://localhost:8080
```

### Sample

You can see this in action, executing the function at `test/fixtures/async`
by running `node hack/run.js`.

### Tests

Just run `npm test`.
You can see this in action by running `node hack/run.js`.

0 comments on commit 058fc77

Please sign in to comment.