npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@moveaxlab/nestjs-grpc-client

v10.1.0

Published

![NPM](https://img.shields.io/npm/l/%40moveaxlab%2Fgraphql-client) [![npm](https://img.shields.io/npm/v/@moveaxlab/nestjs-grpc-client)](https://www.npmjs.com/package/@moveaxlab/nestjs-grpc-client) ![Static Badge](https://img.shields.io/badge/node_version-

Downloads

296

Readme

NestJS gRPC Client

NPM npm Static Badge

This library defines gRPC dataloaders you can inject dynamically in GraphQL resolvers in order to optimize calls via batching and caching.

More about the dataloader pattern at https://github.com/graphql/dataloader

Installation

yarn add @moveaxlab/nestjs-grpc-client

Usage

Dataloaders

gRPC dataloaders are based on gRPC clients defined as follows:

// package.client.ts
import { GrpcClientForService } from '@moveax/nestjs-grpc-client';
import { grpcPkg } from 'somewhere'; // import also your autogenerated gRPC package

export type PackageClient = GrpcClientForService<
    grpcPkg.PackageServiceDefinition
>;
// OR
export type PackageClientWithStreamingMethods = GrpcClientForService<
    grpcPkg.PackageServiceDefinition,
    'myClientStreamingMethod' | 'myBidirectionalStreamingMethod'
>;

Implement your gRPC dataloader:

// package.dataloader.ts
import { Metadata } from '@grpc/grpc-js';
import { GrpcDataLoaderProvider, DataLoaderForClient, Request, createDataLoaderDecorator } from '@moveax/nestjs-grpc-client';
import { Injectable, Logger } from '@nestjs/common';
import { PackageClient } from 'package.client';
import { grpcPkg } from 'somewhere'; // import also your autogenerated gRPC package

@Injectable()
export class PackageDataLoaderProvider extends GrpcDataLoaderProvider<PackageClient> {
    client: PackageClient;
    logger = new Logger(PackageDataLoaderProvider.name);

    createMetadata(_: Request): Metadata {
        const metadata = new Metadata();
        // you can use the Express' request token to authenticate also the gRPC call 
        metadata.set('authorization', req.get('authorization'));
        return metadata;
    }

   get cacheConfig() {
      return {
         someMethod: {
            cacheKeyFn: (request: grpcPkg.ISomeMethodRequest) => {
               return `pkgService.someMethod:${input.param1}-${input.param2}`;
            },
            ttl: 60,
         },
      };
   }
}

export const PackageService = createDataLoaderDecorator(PackageDataLoaderProvider.prototype);

export type PackageDataloader = DataLoaderForClient<PackageClient>;
  1. The cacheConfig getter returns an object containing cache configuration for the various methods. If a method needs to be cached, the cacheConfig must contain an entry for that method that takes in input the method request and returns a string, which will be used as the cache key. A TTL can be specified, that will be used if global caching is enabled (see below).
  2. The PackageService is an object containing a parameter decorator for each method of the gRPC client. You can use the decorator in your resolvers to obtain an instance of the dataloader (see below).
  3. The PackageDataloader is a type containing the types of each method dataloader. You can use the type in your resolvers to add type safety to your loaders.

Add the GrpcDataLoaderInterceptor to your app in order to load dataloaders relevant for the request at runtime:

import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { GrpcDataLoaderInterceptor } from '@moveax/nestjs-grpc-client';

@Module({
  provides: [
    {
      provide: APP_INTERCEPTOR,
      useClass: GrpcDataLoaderInterceptor,
    }
  ],
  /* ... */
})
export class AppModule {}

Now you can use the dataloader in your resolvers:

// imports omitted for lack of will

@Resolver()
class Whatever {
    @Query()
    async getWhatever(
        @PackageService.someMethod() loader: PackageDataloader['someMethod']
    ) {
        const response = await loader.load(/* gRPC request */);
        // do whatever you want with the response now
    }
}

Batching requests

To batch several requests to a given service when doing API composition, specify the mergeConfig inside your dataloader provider.

The mergeConfig provides two properties for each endpoint:

  • mergeInput, that takes an array of requests and combines them to a single request
  • splitOutput, that takes the original array of requests and a single response, and splits it into an array of responses

Global caching

To use global caching, pass true to the loader decorator:

// imports omitted for lack of will

@Resolver()
class Whatever {
    @Query()
    async getWhatever(
        @PackageService.someMethod(true) loader: PackageDataloader['someMethod']
    ) {
        const response = await loader.load(/* gRPC request */);
        // do whatever you want with the response now
    }
}

The ttl must be set to something greater than 0 inside the cacheConfig for the dataloader, for global caching to work. The TTL is expressed in seconds.

All requests to that specific dataloader will be cached for ttl seconds, in a cache shared between all calls. Use global caching with care: the global cache will skip all authorization logic that may live inside your backend services.