golevelup/nestjs

repository·master·Indexed 25 days ago

https://github.com/golevelup/nestjs

A collection of NestJS integrations and utilities for third-party services including RabbitMQ, Google Cloud PubSub, Stripe, Hasura, and GraphQL. It provides specialized packages such as @golevelup/nestjs-common for utility functions and mixins, @golevelup/nestjs-discovery for querying application providers and controllers, and @golevelup/nestjs-rabbitmq for RPC and Pub/Sub message handling.

Tokens
46.2K
Snippets
124
Records
265
Agent score
33%

What's inside golevelup/nestjs

  1. Overview of GoLevelUp NestJS modules

    master
    GoLevelUp provides a collection of specialized modules and utilities designed to extend and enhance NestJS applications. The library includes integrations for messaging (RabbitMQ, Google Cloud Pub/Sub), database/API tools (Hasura, GraphQL Request, Graphile Worker), and third-party services (Stripe, Webhooks), as well as core utilities for discovery and testing.
  2. Handle Hasura Events in NestJS Interceptors, Guards, and Filters

    master

    Hasura event handlers run in a special NestJS context called hasura_event. If you use global Guards, Interceptors, or Filters, they will also apply to Hasura events. To prevent this, check the context type using context.getType() and skip logic if the type is 'hasura_event'.

    @Injectable()
    class ExampleInterceptor implements NestInterceptor {
      intercept(context: ExecutionContext, next: CallHandler<any>) {
        const contextType = context.getType<'http' | 'hasura_event'>();
    
        // Do nothing if this is a Hasura event
        if (contextType === 'hasura_event') {
          return next.handle();
        }
    
        // Execute custom interceptor logic for HTTP request/response
        return next.handle();
      }
    }
  3. Install dependencies and register git hooks

    master
    Before writing code, run pnpm i at the root of the repository. This ensures all packages are installed and all git hooks (such as CommitLint) are correctly registered to validate your changes during the commit process.
    pnpm i
  4. Configure StripeModule

    master

    Import StripeModule into your module (e.g., AppModule). You must provide an apiKey. If you intend to consume webhooks, you must also provide webhookConfig containing your stripeSecrets.

    Snapshot Event Secrets:

    • account: Webhook secret for your account.
    • accountTest: Webhook secret for test mode.
    • connect: Webhook secret for Connected accounts.
    • connectTest: Webhook secret for Connected accounts in test mode.

    Thin Event Secrets (Optional):

    • stripeThinSecrets: Separate secrets for Stripe's v2 thin events (required if using @StripeThinWebhookHandler).
    import { StripeModule } from '@golevelup/nestjs-stripe';
    
    @Module({
      imports: [
        StripeModule.forRoot({
          apiKey: 'sk_***',
          webhookConfig: {
            // Snapshot event secrets
            stripeSecrets: {
              account: 'whsec_***',
              accountTest: 'whsec_***',
              connect: 'whsec_***',
              connectTest: 'whsec_***',
            },
            // Thin event secrets (optional)
            stripeThinSecrets: {
              account: 'whsec_***',
              accountTest: 'whsec_***',
              connect: 'whsec_***',
              connectTest: 'whsec_***',
            },
          },
        }),
      ],
    })
    export class AppModule {}
  5. Configure GraphileWorkerModule

    master

    Import and add GraphileWorkerModule to your NestJS module imports. You can use forRoot for static configuration or forRootAsync for dynamic configuration (e.g., using ConfigService).

    Note: The library is fully ESM. CommonJS (require) is not supported. Your project must support ESM (Node.js 16+ recommended).

    import { Module } from '@nestjs/common';
    import { GraphileWorkerModule } from '@golevelup/nestjs-graphile-worker';
    
    @Module({
      imports: [
        GraphileWorkerModule.forRoot({
          connectionString: process.env.DATABASE_URL,
          // ...other options
        }),
      ],
    })
    export class AppModule {}
  6. Install @golevelup/nestjs-graphql-request

    master

    Install the package using your preferred package manager to enable easy initialization of GraphQLClient for NestJS Dependency Injection.

    npm install ---save @golevelup/nestjs-graphql-request
    # or
    yarn add @golevelup/nestjs-graphql-request
    # or
    pnpm add @golevelup/nestjs-graphql-request
  7. Configure GraphQLRequestModule

    master

    Import and add GraphQLRequestModule to the imports array of your NestJS module. Use the .forRoot() method to provide configuration options, which are based on the graphql-request package (such as endpoint and options for headers).

    import { GraphQLRequestModule } from '@golevelup/nestjs-graphql-request';
    
    @Module({
      imports: [
        GraphQLRequestModule.forRoot({
          // Exposes configuration options based on the graphql-request package
          endpoint: config.get('endpoint'),
          options: {
            headers: {
              'content-type': 'application/json',
              'x-hasura-admin-secret': config.get('secret'),
            },
          },
        }),
      ],
    })
    export class AppModule {}
  8. Prevent RabbitMQ connection during tests

    master

    To avoid attempting to connect to a real RabbitMQ broker during unit or integration tests, pass undefined to RabbitMQModule.forRoot. This causes the connection process to be ignored.

    Common pattern: Use a conditional check on process.env.NODE_ENV to provide the configuration object only when not in a test environment.

    import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
    
    @Module({
      imports: [
        RabbitMQModule.forRoot(
          RabbitMQModule,
          /** Not sending config object makes the connection process to be ignored */
          process.env.NODE_ENV !== 'test'
            ? {
                exchanges: [
                  {
                    name: 'exchange1',
                    type: 'topic',
                  },
                ],
                uri: 'amqp://rabbitmq:rabbitmq@localhost:5672',
                connectionInitOptions: { wait: false },
              }
            : undefined,
        ),
      ],
    })
    export class RabbitExampleModule {}
  9. Configure Simple Raw Body Parsing for Webhooks

    master

    To validate webhooks, you often need access to the unmodified raw request body. Because NestJS enables JSON parsing by default, you must follow these two steps to preserve the raw body on specific routes:

    1. Disable global body parsing

    In your application bootstrap function (usually main.ts), set bodyParser: false when creating the Nest application.

    2. Apply raw body parsing to specific routes

    Use the applyRawBodyOnlyTo utility function within your AppModule (implementing NestModule) to specify which routes should receive the raw body. This utility automatically applies JSON parsing to all other routes while excluding the routes you specify.

    // Step 1: In main.ts
    const app = await NestFactory.create(AppModule, {
      bodyParser: false,
    });
    
    // Step 2: In AppModule
    import { applyRawBodyOnlyTo } from '@golevelup/nestjs-webhooks';
    import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
    
    @Module({})
    class AppModule implements NestModule {
      configure(consumer: MiddlewareConsumer) {
        applyRawBodyOnlyTo(consumer, {
          method: RequestMethod.ALL,
          path: 'webhook',
        });
      }
    }
  10. Mock AmqpConnection for testing

    master

    When testing modules that depend on AmqpConnection, you can mock the connection to satisfy publishers without requiring a real RabbitMQ broker.

    1. Create a mock module that provides a mocked instance of AmqpConnection and exports it.
    2. Use NestJS Test.createTestingModule to override your real RabbitMQ module with the mock module using .overrideModule().useModule().
    // In your test setup...
    
    import { Module } from '@nestjs/common';
    import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
    import { createMock } from '@golevelup/ts-jest';
    import { Test } from '@nestjs/testing';
    import { AppModule } from 'where your root module is located';
    import { RabbitExampleModule } from 'where your rabbitmq module is located';
    
    // Create a valid mock module
    @Module({
      providers: [
        {
          provide: AmqpConnection,
          useValue: createMock<AmqpConnection>(),
        },
      ],
      exports: [AmqpConnection],
    })
    class MockRabbitExampleModule {}
    
    // Then override the real `RabbitMqModule` with the mocked one
    beforeAll(async () => {
      const moduleFixture = await Test.createTestingModule({
        imports: [AppModule],
      })
        .overrideModule(RabbitExampleModule)
        .useModule(MockRabbitExampleModule)
        .compile();
    
      const app = moduleFixture.createNestApplication();
    
      await app.init();
    });
  11. Install @golevelup/nestjs-common

    master

    Install the @golevelup/nestjs-common package using your preferred package manager to access utility functions and low-level reusable modules for the NestJS ecosystem.

    npm install ---save @golevelup/nestjs-common
    # or
    yarn add @golevelup/nestjs-common
    # or
    pnpm add @golevelup/nestjs-common