Mali: Minimalistic gRPC Framework

0.47.1 · active · verified Sun Apr 19

Mali is a minimalistic, middleware-based gRPC microservice framework for Node.js, designed to simplify the creation of gRPC servers. It operates similarly to popular HTTP frameworks like Koa or Express, leveraging a context object (`ctx`) for request and response handling within a cascading middleware pattern. The current stable version is `0.47.1`. The project maintains a regular, albeit not rapid, release cadence, primarily focusing on dependency updates, performance improvements, and bug fixes, as seen in recent versions like `v0.47.0` and `v0.46.0`. Its key differentiator lies in its commitment to minimalism and a familiar middleware API for gRPC, abstracting away some of the complexities of the underlying `@grpc/grpc-js` and `@grpc/proto-loader` libraries, which are required as peer dependencies. It also ships with TypeScript types.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates setting up a basic Mali gRPC server, defining a simple 'Greeter' service with a 'SayHello' method, and then creating a client to interact with it. It includes the necessary proto definition and server startup/shutdown.

const Mali = require('mali');
const path = require('path');
const fs = require('fs');

// A minimalistic gRPC service definition
const PROTO_CONTENT = `
  syntax = "proto3";

  package helloworld;

  service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
  }

  message HelloRequest {
    string name = 1;
  }

  message HelloReply {
    string message = 1;
  }
`;

// Write the proto content to a temporary file for Mali to load
const PROTO_PATH = path.resolve(__dirname, 'helloworld.proto');
fs.writeFileSync(PROTO_PATH, PROTO_CONTENT);

function sayHello (ctx) {
  ctx.res = { message: `Hello ${ctx.req.name || 'World'}` };
  console.log(`Handled SayHello for ${ctx.req.name || 'World'}`);
}

async function main () {
  const app = new Mali(PROTO_PATH);
  app.use({ sayHello });
  const port = '0.0.0.0:50051';
  app.start(port);
  console.log(`gRPC server running on ${port}`);

  // Basic client to test the server (optional, for demonstration)
  const grpc = require('@grpc/grpc-js');
  const protoLoader = require('@grpc/proto-loader');
  const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true });
  const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
  const client = new hello_proto.Greeter(port, grpc.credentials.createInsecure());

  client.sayHello({ name: 'Mali User' }, (err, response) => {
    if (err) {
      console.error('Client error:', err);
    } else {
      console.log('Client received:', response.message);
    }
    // Clean up temporary proto file and stop the server for a real test
    fs.unlinkSync(PROTO_PATH);
    app.shutdown();
  });
}

main().catch(console.error);

view raw JSON →