3.4.49 • Published 4 months ago

@orwoods/networking v3.4.49

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

@orwoods/networking

npm version Node.js Version License TypeScript

📋 Overview

A lightweight npm library designed for rapid and seamless setup of gRPC clients/servers and Kafka consumers/producers in Node.js. It includes a single command for generating build files from .proto files with full TypeScript support to simplify development.

Demo project: https://github.com/orwoods/networking-example

🚀 Features

  • 🌐 Easy gRPC Setup: Effortlessly set up both gRPC clients and servers.
  • 🌐 Easy Kafka Setup: Effortlessly set up both Kafka clients and servers.
  • ⚙️ Proto Compilation: One-command generation of TypeScript classes from .proto files.
  • 🛠 TypeScript Support: Full TypeScript support for type-safe development.
  • 📦 Zero Configuration: Minimal configuration needed to get started.

📦 Installation

In the command below, if necessary, specify the correct path to the proto files

npm install @orwoods/networking

jq '.scripts["build-proto"] = "./node_modules/.bin/build-proto-cli src/proto"' package.json > tmp.json && mv tmp.json package.json

🛠️ Compilation of Protobuf files

1. Place the *.proto files in the src/proto folder

...or whatever folder you specified in the build-proto command

2. Run command to compile to JS and TS

npm run build-proto

or just

./node_modules/.bin/build-proto-cli src/proto

💻 Kafka usage Example

Here's a quick example to get you started:

1. Setting up a Kafka Producer

Create a file named src/producer.ts:

import { KafkaProducer, KafkaConfig } from '@orwoods/networking';

export class Producer extends KafkaProducer {
  public async getConfig(): Promise<KafkaConfig> {
    return {
      brokers: ['127.0.0.1:9092'],
    };
  }
}

2. Setting up a Kafka Consumer

Create a file named src/consumer.ts:

import { KafkaConfig, KafkaConsumer, ConsumerConfig } from '@orwoods/networking';
import { Notification } from '../proto/generated/notification_pb';

export class Consumer extends KafkaConsumer {
  public async getConfig(): Promise<KafkaConfig> {
    return {
      clientId: 'example-consumer-app',
      brokers: ['127.0.0.1:9092'],
    };
  }

  public async getConsumerConfig(): Promise<ConsumerConfig> {
    return {
      groupId: 'example-group-id',
    };
  }

  public async onMessage(topic: string, data: Buffer): Promise<void> {
    const notification = Notification.deserializeBinary(data);

    console.warn('New message', {
      topic,
      subject: notification.getSubject(),
      body: notification.getBody(),
      url: notification.getUrl(),
    });
  }
}

3. Running

Create a file named src/test_kafka.ts:

import { Consumer } from './kafka/listener';
import { Producer } from './kafka/producer';
import { Notification } from './proto/generated/notification_pb';

(async () => {
  const consumer = new Consumer();
  const producer = new Producer();

  await consumer.subscribe(['example']);

  const object = new Notification();
  object.setSubject('Hello');
  object.setBody('World');
  object.setUrl('http://127.0.0.1');

  await producer.send({
    topic: 'example',
    acks: 1,
    messages: [{ object }],
  });
})();

💻 gRPC usage Example

Here's a quick example to get you started:

1. Setting up a gRPC Server

Create a file named src/server.ts:

import { GrpcServer } from '@orwoods/networking';
import { IOrdersServer, IOrdersService, OrdersService } from '../proto/generated/ordersService_grpc_pb';
import { GetOrderResponse } from '../proto/generated/ordersService_pb';

export class Server extends GrpcServer <IOrdersServer, IOrdersService> {
  public constructor () {
    super(OrdersService, {
      getOrder: (call, callback) => {
        console.warn(new Date(), 'Request from the client:', {
          id: call.request.getId(),
        });

        const order = new GetOrderResponse();
        order.setStatus('finished');

        callback(null, order);
      },
    });
  }

  public async getProps () {
    return Promise.resolve({
      host: '127.0.0.1',
      port: 55306,
      tls: false,
    });
  }
}

2. Setting up a gRPC Client

Create a file named src/client.ts:

import { promisify } from 'util';
import { GrpcClient } from '@orwoods/networking';
import { OrdersClient } from './grpc/generated/ordersService_grpc_pb';
import { GetOrderResponse, GetOrderRequest } from './grpc/generated/ordersService_pb';

export class Client extends GrpcClient <OrdersClient> {
  private getOrderFn!: (_args: GetOrderRequest) => Promise<GetOrderResponse>;

  constructor () {
    super(OrdersClient);
  }

  protected onInit () {
    this.getOrderFn = promisify(this.client.getOrder.bind(this.client));
  }

  public async getOrder (request: GetOrderRequest): Promise<GetOrderResponse | null> {
    return this.makeRequest(async () => this.getOrderFn(request), () => null);
  }

  public async getProps () {
    return {
      host: '127.0.0.1',
      port: 55306,
      tls: false,
      requestTimeoutMs: 60000,
      connectionTimeoutMs: 10000,
      reconnectionDelayMs: 1000,
      maxReconnectionAttempts: 50,
      grpcStatusesForReconnect: [
        grpc.status.UNAVAILABLE,
        grpc.status.DEADLINE_EXCEEDED,
        grpc.status.INTERNAL,
        grpc.status.RESOURCE_EXHAUSTED,
        grpc.status.UNKNOWN,
        grpc.status.DATA_LOSS,
      ],
    };
  }
}

3. Running the Server

Create a file named src/test_server.ts:

import { Server } from './server';

(async () => {
  const server = new Server();
  await server.start();
})();

To start the server, run:

ts-node src/test_server.ts

4. Running the Client

Create a file named src/test_client.ts:

import { Client } from './client';
import { GetOrderRequest } from './grpc/generated/ordersService_pb';

(async () => {
  const client = new Client();
  await client.connect();

  setInterval(async () => {
    const request = new GetOrderRequest();
    request.setId('example-id');

    try {
      const order = await client.getOrder(request);

      console.log(new Date(), 'Response from the server:', {
        id: request.getId(),
        status: order.getStatus(),
      });
    } catch (error) {
      console.error(error);
    }
  }, 1000);
})();

To start the client, run:

ts-node src/test_client.ts

5. Expected Output

When you run both the server and the client, you should see the following output in your terminal:

2024-11-15T17:56:33.808Z Request from the client: { id: 'example-id' }
...
2024-11-15T17:56:33.809Z Response from the server: { id: 'example-id', status: 'finished' }

⚖️ License

This project is licensed under the MIT License - see the LICENSE file for details.

3.4.49

4 months ago

3.4.48

4 months ago

3.4.47

4 months ago

3.4.46

4 months ago

3.4.45

4 months ago

3.4.44

4 months ago

3.4.43

4 months ago

3.4.40

8 months ago

3.4.39

8 months ago

3.4.38

8 months ago

3.4.37

8 months ago

3.4.36

8 months ago

3.4.35

8 months ago

3.4.34

8 months ago

3.4.33

8 months ago

3.4.32

10 months ago

3.4.31

11 months ago

3.4.30

11 months ago

3.4.29

11 months ago

3.4.28

11 months ago

3.4.27

11 months ago

3.4.26

11 months ago

3.4.25

11 months ago

3.4.24

11 months ago

3.4.23

11 months ago

3.4.22

11 months ago

3.4.21

11 months ago

3.4.20

11 months ago

3.4.19

11 months ago

3.4.18

11 months ago

3.4.17

11 months ago

3.4.15

11 months ago

3.4.14

11 months ago

3.4.13

11 months ago

3.4.12

11 months ago

3.4.11

11 months ago

3.4.10

11 months ago

3.4.9

11 months ago

3.4.8

11 months ago

3.4.7

11 months ago

3.4.6

11 months ago

3.4.5

11 months ago

3.4.4

11 months ago

3.4.3

11 months ago

3.4.1

11 months ago

3.4.0

11 months ago

3.3.49

11 months ago

3.3.46

11 months ago

3.3.45

11 months ago

3.3.44

11 months ago

3.3.43

11 months ago

3.3.42

11 months ago

3.3.41

11 months ago

3.3.40

11 months ago

3.3.39

11 months ago

3.3.24

11 months ago

3.3.23

11 months ago

3.3.22

11 months ago

3.3.21

11 months ago

3.3.20

11 months ago

3.3.19

11 months ago