CloudEvents SDK for JavaScript

repository·main·Indexed 18 days ago

https://github.com/cloudevents/sdk-javascript

A JavaScript SDK for implementing the CloudEvents specification, enabling developers to represent, serialize, deserialize, and transmit CloudEvents across various protocols and formats. The SDK supports Spec v1.0 and v0.3 in both Structured and Binary modes, with provided examples for Express, Kafka, MQTT, TypeScript, and WebSockets. It includes utilities for HTTP transport, custom transport integration (e.g., Axios), and an Emitter singleton for event-driven emission.

Tokens
14.8K
Snippets
59
Records
67
Agent score
64%

What's inside cloudevents-sdk-javascript

  1. Run the WebSocket CloudEvents example

    main

    This example demonstrates using CloudEvents over a WebSocket connection between a server and either a Node.js client or a web browser. The workflow involves a client sending a CloudEvent containing a zip code, and a server responding with a CloudEvent containing weather data.

    Prerequisites

    Install the necessary dependencies using npm:

    npm install

    1. Start the Server

    The server listens for WebSocket connections and expects incoming messages to be CloudEvents. It extracts a zip code from the event data, fetches weather information, and responds with a new CloudEvent.

    Configuration: You must provide an Open Weather API key. You can either:

    1. Edit server.js directly to add your key.
    2. Set an environment variable named OPEN_WEATHER_API_KEY.

    To start the server, run:

    node server.js

    2. Start the Client (Node.js)

    The client prompts for a zip code, sends it as a CloudEvent to the server, and prints the resulting weather CloudEvent data to the console.

    To start the client, run:

    node client.js

    3. Use the Browser Client

    To use the web-based interface, open the index.html file in your browser. You can enter a zip code into the form field; the browser will send the CloudEvent via WebSocket and display the weather response or error messages on the screen.

    To stop any process, use CTRL-C in your terminal.

    npm install
    node server.js
    node client.js
  2. Run the MQTT Example application

    main

    To run the MQTT example, you must first install dependencies and compile the project. You also need a running MQTT broker (such as Eclipse Mosquitto) available on port 1883.

    Prerequisites

    • Node.js and npm
    • Docker (to run the broker)

    Steps

    1. Install and compile the project:

      npm install
      npm run compile
    2. Start an MQTT broker using Docker: Run the following command to start an unauthenticated Mosquitto broker:

      docker run -it -d -p 1883:1883 eclipse-mosquitto:2.0 mosquitto -c /mosquitto-no-auth.conf
    3. Start the application:

      npm start
    npm install
    npm run compile
    docker run -it -d -p 1883:1883 eclipse-mosquitto:2.0 mosquitto -c /mosquitto-no-auth.conf
    npm start
  3. Set up Kafka locally with Docker

    main

    To run the Kafka example, you need a Kafka broker and Zookeeper. You can set this up using either individual Docker commands or Docker Compose.

    Option 1: Sequential Docker Commands

    Run Zookeeper first:

    docker run -d \
      --name zookeeper \
      -e ZOOKEEPER_CLIENT_PORT=2181 \
      -e ZOOKEEPER_TICK_TIME=2000 \
      confluentinc/cp-zookeeper:7.3.2

    Then run Kafka, linking it to the Zookeeper container:

    docker run -d \
      --name kafka \
      -p 9092:9092 \
      -e KAFKA_BROKER_ID=1 \
      -e KAFKA_ZOOKEEPER_CONNECT=localhost:2181 \
      -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 \
      -e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \
      -e KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS=0 \
      --link zookeeper:zookeeper \
      confluentinc/cp-kafka:7.3.2

    Option 2: Docker Compose

    If you have the docker-compose file available, navigate to its directory and run:

    docker compose up -d
    docker run -d \
      --name zookeeper \
      -e ZOOKEEPER_CLIENT_PORT=2181 \
      -e ZOOKEEPER_TICK_TIME=2000 \
      confluentinc/cp-zookeeper:7.3.2
    
    docker run -d \
      --name kafka \
      -p 9092:9092 \
      -e KAFKA_BROKER_ID=1 \
      -e KAFKA_ZOOKEEPER_CONNECT=localhost:2181 \
      -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 \
      -e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \
      -e KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS=0 \
      --link zookeeper:zookeeper \
      confluentinc/cp-kafka:7.3.2
  4. Run the Kafka Producer and Consumer examples

    main

    After setting up Kafka, you can run the example CLI application which demonstrates sending user input as a CloudEvent through a Kafka producer and handling/deserializing it with a consumer in a consumer group.

    Prerequisites:

    • NodeJS (>18)
    • A running Kafka broker

    Start the Producer

    Run the following command to start the producer CLI:

    npm run start:producer

    Start the Consumer

    Run the following command to start the consumer, providing a ${groupId} as an argument:

    npm run start:consumer ${groupId}
    # Start the producer
    npm run start:producer
    
    # Start the consumer (replace ${groupId} with your desired group ID)
    npm run start:consumer my-consumer-group
  5. Transition from Emit.send to HTTP.binary or HTTP.structured

    main

    The Emit.send method has been removed. You must now manually handle the transport protocol (e.g., using axios) by first converting your CloudEvent into a transportable message using either HTTP.binary (for binary events) or HTTP.structured (for structured events).

    const axios = require('axios').default;
    const { HTTP } = require("cloudevents");
    
    const ce = new CloudEvent({ type, source, data });
    const message = HTTP.binary(ce); // Or HTTP.structured(ce)
    
    axios({
      method: 'post',
      url: '...',
      data: message.body,
      headers: message.headers,
    });
  6. Transition from Receiver.accept to HTTP.toEvent

    main

    The Receiver class has been removed in version 4.0.0. To convert incoming HTTP requests into CloudEvent objects, use the HTTP.toEvent method. This method accepts an object containing headers and body extracted from your HTTP framework (e.g., Express.js).

    const app = require("express")();
    const { HTTP } = require("cloudevents");
    
    app.post("/", (req, res) => {
      // body and headers come from an incoming HTTP request, e.g. express.js
      const receivedEvent = HTTP.toEvent({ headers: req.headers, body: req.body });
      console.log(receivedEvent);
    });
  7. Implement or use a Binding for transport protocols

    main

    A Binding is the core interface used to bridge CloudEvents with specific transport protocols (like HTTP, Kafka, or MQTT). It defines how to serialize CloudEvents into messages and how to detect and deserialize messages back into CloudEvents.

    When implementing a new protocol, you must provide implementations for:

    • binary: Serializes a CloudEvent using the binary mode (where event attributes are in the message headers).
    • structured: Serializes a CloudEvent using the structured mode (where the event is the message body).
    • toEvent: Converts a Message back into one or more CloudEventV1 objects.
    • isEvent: A predicate to determine if a Message is a valid CloudEvent.
    import { Binding, Message, Headers } from "./message";
    
    // Example of the shape of a Binding implementation
    const myBinding: Binding<MyMessageType> = {
      binary: (event) => { /* ... */ },
      structured: (event) => { /* ... */ },
      toEvent: (message) => { /* ... */ },
      isEvent: (message) => { /* ... */ }
    };
  8. Serialize and Deserialize CloudEvents

    main

    The SDK provides interfaces for converting between CloudEventV1 objects and Message objects:

    • Serializer<M>: A function that takes a CloudEventV1<T> and returns a Message of type M.
    • Deserializer: A function that takes a Message and returns either a single CloudEventV1<T> or an array of events CloudEventV1<T>[] (for batch modes).
    • Detector: A predicate function used to check if a Message contains a valid CloudEvent.
  9. Handle large integers in JSON payloads

    main

    JavaScript's Number type loses precision for very large integers (e.g., Twitter IDs). To prevent this when parsing CloudEvents, set the environment variable CE_USE_BIG_INT to "true". This enables the json-bigint package. Note that this may slow down parsing speed by approximately 7x.

    export CE_USE_BIG_INT=true