docs: update README and examples with new API (#138)

This commit modifies the README to show new API usage for the
`HTTPReceiver` and `CloudEvent` classes, and updates the examples
to use this as well.

Overall structure and content has been modified to look more like
the sdk-go README.

Fixes: https://github.com/cloudevents/sdk-javascript/issues/128

Signed-off-by: Lance Ball <lball@redhat.com>
This commit is contained in:
Lance Ball 2020-05-11 09:41:05 -04:00 committed by GitHub
parent 5a6cde5695
commit b866edddd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 353 deletions

305
README.md
View File

@ -3,7 +3,6 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/bd66e7c52002481993cd6d610534b0f7)](https://www.codacy.com/app/fabiojose/sdk-javascript?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cloudevents/sdk-javascript&amp;utm_campaign=Badge_Grade)
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/bd66e7c52002481993cd6d610534b0f7)](https://www.codacy.com/app/fabiojose/sdk-javascript?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cloudevents/sdk-javascript&amp;utm_campaign=Badge_Coverage)
[![Build Status](https://travis-ci.org/cloudevents/sdk-javascript.svg?branch=master)](https://travis-ci.org/cloudevents/sdk-javascript)
[![downloads](https://img.shields.io/npm/dy/cloudevents-sdk.svg)](https://www.npmjs.com/package/cloudevents-sdk)
[![npm version](https://img.shields.io/npm/v/cloudevents-sdk.svg)](https://www.npmjs.com/package/cloudevents-sdk)
[![vulnerabilities](https://snyk.io/test/github/cloudevents/sdk-javascript/badge.svg)](https://snyk.io/test/github/cloudevents/sdk-javascript)
[![licence](https://img.shields.io/github/license/cloudevents/sdk-javascript)](http://www.apache.org/licenses/LICENSE-2.0)
@ -11,273 +10,91 @@
The CloudEvents SDK for JavaScript.
## Status
This module will help you to:
This SDK is still considered a work in progress.
* Represent CloudEvents in memory
* Use [Event Formats](https://github.com/cloudevents/spec/blob/v1.0/spec.md#event-format) to serialize/deserialize CloudEvents
* Use [Protocol Bindings](https://github.com/cloudevents/spec/blob/v1.0/spec.md#protocol-binding) to send/receive CloudEvents
This SDK current supports the following versions of CloudEvents:
_Note:_ Supported
[CloudEvents specification](https://github.com/cloudevents/spec): 0.3, 1.0
- v1.0
### A Note on Versioning
**Checkout the [changelog](CHANGELOG.md) to see what's going on!**
The CloudEvents protocol version is distinct from this module's version number.
For example, this module may be versioned as v2.0.0 but support the v0.3 and v1.0
versions of the CloudEvent specification.
## Installation
## Usage
This CloudEvents SDK requires nodejs 6.11+
**See the full working example: [here](./examples/express-ex).**
### Nodejs
### Installation
```sh
npm install cloudevents-sdk
```
## Specification Support
The CloudEvents SDK requires a current LTS version of Node.js. At the moment
those are Node.js 10.x and Node.js 12.x. To install in your Node.js project:
These are the supported specifications by this version.
| **Specifications** | v0.3 | **v1.0** |
|---------------------------------------|------|----------|
| CloudEvents | yes | yes |
| HTTP Transport Binding - Structured | yes | yes |
| HTTP Transport Binding - Binary | yes | yes |
| JSON Event Format | yes | yes |
### What we can do
| **What** | v0.3 | **v1.0** |
|-------------------------------------|------|----------|
| Create events | yes | yes |
| Emit Structured events over HTTP | yes | yes |
| Emit Binary events over HTTP | yes | yes |
| JSON Event Format | yes | yes |
| Receive Structured events over HTTP | yes | yes |
| Receive Binary events over HTTP | yes | yes |
## How to use
### Usage
```js
const v1 = require("cloudevents-sdk/v1");
/*
* Creating an event
*/
let myevent = v1.event()
.type("com.github.pull.create")
.source("urn:event:from:myapi/resource/123");
```console
npm install --save cloudevents-sdk
```
#### Formatting
```js
const v1 = require("cloudevents-sdk/v1");
/*
* Creating an event
*/
let myevent = v1.event()
.type("com.github.pull.create")
.source("urn:event:from:myapi/resource/123");
/*
* Format the payload and return it
*/
let formatted = myevent.format();
```
#### Emitting
```js
const v1 = require("cloudevents-sdk/v1");
/*
* Creating an event
*/
let myevent = v1.event()
.type("com.github.pull.create")
.source("urn:event:from:myapi/resource/123");
// The binding configuration using POST
let config = {
method: "POST",
url : "https://myserver.com"
};
// The binding instance
let binding = new v1.StructuredHTTPEmitter(config);
// Emit the event using Promise
binding.emit(myevent)
.then(response => {
// Treat the response
console.log(response.data);
}).catch(err => {
// Deal with errors
console.error(err);
});
```
### Receiving and Emitting Events
#### Receiving Events
You can choose any framework for port binding. But, use the
StructuredHTTPReceiver or BinaryHTTPReceiver to process the HTTP Payload and
HTTP Headers, extracting the CloudEvents.
:smiley: **Checkout the full working example: [here](./examples/express-ex).**
You can choose almost any popular web framework for port binding. Use an
`HTTPReceiver` to process the incoming HTTP request. The receiver accepts
binary and structured events in either the 1.0 or 0.3 protocol formats.
```js
// some parts were removed //
const {
CloudEvent,
HTTPReceiever
} = require("cloudevents-sdk");
const v1 = require("cloudevents-sdk/v1");
// Create a receiver to accept events over HTTP
const receiver = new HTTPReceiver();
const receiver = new v1.StructuredHTTPReceiver();
// body and headers come from an incoming HTTP request, e.g. express.js
const receivedEvent = receiver.accept(req.body, req.headers);
console.log(receivedEvent.format());
```
// some parts were removed //
#### Emitting Events
app.post("/", (req, res) => {
try {
let myevent = receiver.parse(req.body, req.headers);
Currently, to emit events, you'll need to decide whether the event is in
binary or structured format, and determine what version of the CloudEvents
specification you want to send the event as.
// TODO use the event
```js
const { CloudEvent } = require("cloudevents-sdk");
const { StructuredHTTPEmitter } = require("cloudevents-sdk/v1");
res.status(201).send("Event Accepted");
const myevent = new CloudEvent()
.type("com.github.pull.create")
.source("urn:event:from:myapi/resource/123");
} catch(err) {
// TODO deal with errors
console.error(err);
res.status(415)
.header("Content-Type", "application/json")
.send(JSON.stringify(err));
}
const emitter = new StructuredHTTPEmitter({
method: "POST",
url : "https://myserver.com"
});
// Emit the event
emitter.emit(myevent)
```
## Unit Testing
## Supported specification features
The unit test checks the result of formatted payload and the constraints.
```bash
npm test
```
## The API
### `CloudEvent` class
```js
/*
* Format the payload and return an Object.
*/
Object CloudEvent.format()
/*
* Format the payload as String.
*/
String CloudEvent.toString()
```
### `Formatter` classes
Every formatter class must implement these methods to work properly.
```js
/*
* Format the CloudEvent payload argument and return an Object.
*/
Object Formatter.format(Object)
/*
* Format the CloudEvent payload as String.
*/
String Formatter.toString(Object)
```
### `Parser` classes
Every Parser class must implement these methods to work properly.
```js
/*
* The default constructor with Parser as decorator
*/
Parser(Parser)
/*
* Try to parse the payload to some event format
*/
Object Parser.parse(payload)
```
### `Spec` classes
Every Spec class must implement these methods to work properly.
```js
/*
* The constructor must receives the CloudEvent type.
*/
Spec(CloudEvent)
/*
* Checks the spec constraints, throwing an error if do not pass.
* @throws Error when it is an invalid event
*/
Spec.check()
/*
* Checks if the argument pass through the spec constraints
* @throws Error when it is an invalid event
*/
Spec.check(Object)
```
### `Binding` classes
Every Binding class must implement these methods to work properly.
#### Emitter Binding
Following we have the signature for the binding to emit CloudEvents.
```js
/*
* The constructor must receives the map of configurations.
*/
Binding(config)
/*
* Emits the event using an instance of CloudEvent.
*/
Binding.emit(cloudEvent)
```
#### Receiver Binding
Following we have the signature for the binding to receive CloudEvents.
```js
/*
* The constructor must receives the map of configurations.
*/
Receiver(config)
/*
* Checks if some Object and a Map of headers
* follows the binding definition, throwing an error if did not follow
*/
Receiver.check(Object, Map)
/*
* Checks and parse as CloudEvent
*/
CloudEvent Receiver.parse(Object, Map)
```
## Versioning
- `x.M.p`: where `x` relates to spec version, `M` relates to minor and `p` relates
to fixes. See [semver](https://semver.org/)
| | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/tree/v1.0) |
| ----------------------------- | --- | --- |
| CloudEvents Core | :heavy_check_mark: | :heavy_check_mark: |
| AMQP Protocol Binding | :x: | :x: |
| AVRO Event Format | :x: | :x: |
| HTTP Protocol Binding | :heavy_check_mark: | :heavy_check_mark: |
| JSON Event Format | :heavy_check_mark: | :heavy_check_mark: |
| Kafka Protocol Binding | :x: | :x: |
| NATS Protocol Binding | :x: | :x: |
| STAN Protocol Binding | :x: | :x: |
## Community
@ -291,3 +108,9 @@ to fixes. See [semver](https://semver.org/)
[CNCF's Slack workspace](https://slack.cncf.io/).
- Email: https://lists.cncf.io/g/cncf-cloudevents-sdk
- Contact for additional information: Fabio José (`@fabiojose` on slack).
## Contributing
We love contributions from the community! Please check the
[Contributor's Guide](https://github.com/cloudevents/sdk-javascript/blob/master/CONTRIBUTING.md)
for information on how to get involved.

View File

@ -17,7 +17,7 @@ __A Structured One__
curl -X POST \
-d'@../payload/v1/structured-event-0.json' \
-H'Content-Type:application/cloudevents+json' \
http://localhost:3000/v1
http://localhost:3000/
```
__A Structured One with Extension__
@ -28,7 +28,7 @@ __A Structured One with Extension__
curl -X POST \
-d'@../payload/v1/structured-event-1.json' \
-H'Content-Type:application/cloudevents+json' \
http://localhost:3000/v1
http://localhost:3000/
```
__A Structured One with Base64 Event Data__
@ -39,7 +39,7 @@ __A Structured One with Base64 Event Data__
curl -X POST \
-d'@../payload/v1/structured-event-2.json' \
-H'Content-Type:application/cloudevents+json' \
http://localhost:3000/v1
http://localhost:3000/
```
__A Binary One__
@ -53,7 +53,7 @@ curl -X POST \
-H'ce-source:https://github.com/cloudevents/spec/pull/123' \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-11-06T11:17:00Z' \
http://localhost:3000/v1/binary
http://localhost:3000/
```
__A Binary One with Extension__
@ -68,7 +68,7 @@ curl -X POST \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-11-06T11:17:00Z' \
-H'ce-my-extension:extension value' \
http://localhost:3000/v1/binary
http://localhost:3000/
```
__A Binary One with Base 64 Encoding__
@ -82,12 +82,9 @@ curl -X POST \
-H'ce-source:https://github.com/cloudevents/spec/pull/123' \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-11-06T11:17:00Z' \
http://localhost:3000/v1/binary
http://localhost:3000/
```
__A Batch One__
TODO
## Spec v0.3
@ -99,7 +96,7 @@ __A Structured One__
curl -X POST \
-d'@../payload/v03/structured-event-0.json' \
-H'Content-Type:application/cloudevents+json' \
http://localhost:3000/v03
http://localhost:3000/
```
__A Structured One with Extension__
@ -110,7 +107,7 @@ __A Structured One with Extension__
curl -X POST \
-d'@../payload/v03/structured-event-1.json' \
-H'Content-Type:application/cloudevents+json' \
http://localhost:3000/v03
http://localhost:3000/
```
__A Binary One__
@ -124,7 +121,7 @@ curl -X POST \
-H'ce-source:https://github.com/cloudevents/spec/pull/123' \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-06-21T17:31:00Z' \
http://localhost:3000/v03
http://localhost:3000/
```
__A Binary One with Extension__
@ -139,7 +136,7 @@ curl -X POST \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-06-21T17:31:00Z' \
-H'ce-my-extension:extension value' \
http://localhost:3000/v03
http://localhost:3000/
```
__A Binary One with Base 64 Encoding__
@ -154,10 +151,6 @@ curl -X POST \
-H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \
-H'ce-time:2019-06-21T17:31:00Z' \
-H'ce-datacontentencoding:base64' \
http://localhost:3000/v03
http://localhost:3000/
```
__A Batch One__
TODO

View File

@ -1,14 +1,10 @@
/* eslint-disable no-console */
const express = require("express");
const { HTTPReceiver } = require("../../");
const app = express();
const v03 = require("cloudevents-sdk/v03");
const unmarshaller03 = new v03.HTTPUnmarshaller();
const v1 = require("cloudevents-sdk/v1");
const structured1 = new v1.StructuredHTTPReceiver();
const binary1 = new v1.BinaryHTTPReceiver();
const receiver = new HTTPReceiver();
app.use((req, res, next) => {
let data = "";
@ -24,18 +20,15 @@ app.use((req, res, next) => {
});
});
app.post("/v1", function(req, res) {
app.post("/", function(req, res) {
console.log(req.headers);
console.log(req.body);
try {
const myevent = structured1.parse(req.body, req.headers);
// pretty print
console.log("Accepted event:");
console.log(JSON.stringify(myevent.format(), null, 2));
res.status(201)
.json(myevent.format());
const event = receiver.accept(req.headers, req.body);
const asJSON = event.format();
console.log(`Accepted event: ${JSON.stringify(event.format(), null, 2)}`);
res.status(201).json(asJSON);
} catch (err) {
console.error(err);
res.status(415)
@ -44,47 +37,6 @@ app.post("/v1", function(req, res) {
}
});
app.post("/v1/binary", function(req, res) {
console.log(req.headers);
console.log(req.body);
try {
const myevent = binary1.parse(req.body, req.headers);
// pretty print
console.log("Accepted event:");
console.log(JSON.stringify(myevent.format(), null, 2));
res.status(201)
.json(myevent.format());
} catch (err) {
console.error(err);
res.status(415)
.header("Content-Type", "application/json")
.send(JSON.stringify(err));
}
});
app.post("/v03", function(req, res) {
console.log(req.headers);
console.log(req.body);
unmarshaller03.unmarshall(req.body, req.headers)
.then((cloudevent) => {
// pretty print
console.log("Accepted event:");
console.log(JSON.stringify(cloudevent.format(), null, 2));
res.status(201)
.json(cloudevent.format());
})
.catch((err) => {
console.error(err);
res.status(415)
.header("Content-Type", "application/json")
.send(JSON.stringify(err));
});
});
app.listen(3000, function() {
console.log("Example app listening on port 3000!");
});

View File

@ -1,14 +1,9 @@
import CloudEvent, {
event,
StructuredHTTPEmitter,
BinaryHTTPEmitter,
StructuredHTTPReceiver,
BinaryHTTPReceiver
} from 'cloudevents-sdk/v1';
import { CloudEvent, HTTPREceiver } from '../../';
export function doSomeStuff() {
const receiver = new HTTPREceiver();
const myevent: CloudEvent = event()
const myevent: CloudEvent = new CloudEvent()
.source('/source')
.type('type')
.dataContentType('text/plain')
@ -20,39 +15,13 @@ export function doSomeStuff() {
console.log(myevent.toString());
console.log(myevent.getExtensions());
const config = {
method: "POST",
url : "https://enu90y24i64jp.x.pipedream.net/"
};
// ------ emitter structured
const structured = new StructuredHTTPEmitter(config);
structured.emit(myevent).then(res => {
// success
console.log("Structured Mode: Success!")
})
.catch(err => {
// error
console.error(err);
});
// ------ emitter binary
const binary = new BinaryHTTPEmitter(config);
binary.emit(myevent).then(res => {
console.log("Binary Mode: Success!");
})
.catch(err => {
console.error(err);
});
// ------ receiver structured
const payload = myevent.toString();
const headers = {
"Content-Type":"application/cloudevents+json"
};
const receiverStructured = new StructuredHTTPReceiver();
console.log(receiverStructured.parse(payload, headers).toString());
console.log(receiver.accept(headers, payload).toString());
// ------ receiver binary
const extension1 = "mycuston-ext1";
@ -70,10 +39,9 @@ export function doSomeStuff() {
"ce-extension1" : extension1
};
const receiverBinary = new BinaryHTTPReceiver();
console.log(receiverBinary.parse(data, attributes).toString());
console.log(receiver.accept(attributes, data).toString());
return true;
return true;
}
doSomeStuff();