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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tacxou/nestjs_module_ldap

v1.0.1

Published

LDAP module for NestJS Framework

Readme

Overview

@tacxou/nestjs_module_ldap registers one or more LDAP connections inside a NestJS application. It wraps ldapts clients in a LdapManager, exposes them through Nest dependency injection, and optionally performs an initial bind when the module boots.

Installation

Install the library together with its peer dependencies:

npm install @tacxou/nestjs_module_ldap ldapts
# or
yarn add @tacxou/nestjs_module_ldap ldapts

Supported NestJS versions: ^6, ^7, ^8, ^9, ^10, and ^11.

Quick start

Register the module in your root AppModule with synchronous configuration:

import { Module } from '@nestjs/common'
import { LdapModule } from '@tacxou/nestjs_module_ldap'

@Module({
  imports: [
    LdapModule.forRoot({
      config: {
        clients: [
          {
            name: 'default',
            default: true,
            options: { url: 'ldap://ldap.example.com:389' },
            bind: {
              dn: 'cn=service,dc=example,dc=com',
              password: process.env.LDAP_PASSWORD,
            },
          },
        ],
      },
    }),
  ],
})
export class AppModule {}

Inject the manager anywhere in your application:

import { Injectable } from '@nestjs/common'
import { InjectLdap, LdapManager } from '@tacxou/nestjs_module_ldap'

@Injectable()
export class UsersService {
  constructor(@InjectLdap() private readonly ldap: LdapManager) {}

  async findUser(dn: string) {
    const client = this.ldap.defaultClient
    const { searchEntries } = await client.search(dn, {
      scope: 'base',
      filter: '(objectClass=*)',
    })
    return searchEntries[0]
  }
}

Configuration

LdapModuleOptions

| Field | Type | Description | | --- | --- | --- | | config.clients | LdapClientOptions[] | List of named LDAP connections to create at startup. |

LdapClientOptions

| Field | Type | Required | Description | | --- | --- | --- | --- | | name | string | yes | Connection identifier used with @InjectLdap(name). | | options | ClientOptions | yes | ldapts client options (url, TLS settings, timeouts, …). | | default | boolean | no | Marks the default client returned by ldap.defaultClient. When only one client is configured, it becomes the default automatically. | | bind | { dn, password?, controls? } | no | Optional bind performed during module initialization. |

ClientOptions, DN, Control, and other ldapts symbols are re-exported from the package entry point.

Registration modes

Synchronous — LdapModule.forRoot(options, connection?)

Use when configuration is known at compile time or can be read synchronously from process.env.

LdapModule.forRoot({
  config: {
    clients: [
      {
        name: 'primary',
        options: { url: 'ldap://localhost:389' },
      },
    ],
  },
})

Asynchronous — LdapModule.forRootAsync(options, connection?)

Use with @nestjs/config, a secrets manager, or any async provider.

import { ConfigModule, ConfigService } from '@nestjs/config'
import { LdapModule } from '@tacxou/nestjs_module_ldap'
import type { ClientOptions } from 'ldapts'

@Module({
  imports: [
    ConfigModule.forRoot(),
    LdapModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        config: {
          clients: [
            {
              name: 'default',
              options: config.get<ClientOptions>('ldap.options'),
              bind: {
                dn: config.get<string>('ldap.bindDn'),
                password: config.get<string>('ldap.bindPassword'),
              },
            },
          ],
        },
      }),
    }),
  ],
})
export class AppModule {}

useClass and useExisting

You can also delegate option building to a dedicated factory class:

import { Injectable } from '@nestjs/common'
import type { LdapModuleOptions, LdapModuleOptionsFactory } from '@tacxou/nestjs_module_ldap'

@Injectable()
export class LdapConfigService implements LdapModuleOptionsFactory {
  createLdapModuleOptions(): LdapModuleOptions {
    return {
      config: {
        clients: [{ name: 'default', options: { url: 'ldap://localhost:389' } }],
      },
    }
  }
}

// AppModule
LdapModule.forRootAsync({
  imports: [LdapConfigModule],
  useExisting: LdapConfigService,
})

Multiple connections

Register additional connections by passing a connection name as the second argument to forRoot / forRootAsync, then inject them with @InjectLdap(name):

@Module({
  imports: [
    LdapModule.forRoot(primaryOptions),
    LdapModule.forRoot(secondaryOptions, 'reporting'),
  ],
})
export class AppModule {}

@Injectable()
export class ReportingService {
  constructor(@InjectLdap('reporting') private readonly ldap: LdapManager) {}
}

Each registration is global: once imported, the connection is available application-wide.

LdapManager API

| Member | Description | | --- | --- | | defaultClient | The ldapts Client marked as default (or the only configured client). | | clients | Map of all registered clients keyed by connection name. | | initialized | true after the optional startup bind phase completes. | | getClient(name) | Returns a client by name; throws if the connection does not exist. | | initialize() | Binds every client that declares bind credentials. Called automatically by the module. |

Public exports

The package entry point exposes:

  • LdapModule
  • LdapManager
  • InjectLdap()
  • Configuration interfaces (LdapModuleOptions, LdapClientOptions, …)
  • DI token helpers (getLdapConnectionToken, getLdapOptionsToken)
  • Selected ldapts types and classes (Client, ClientOptions, DN, …)

Example: per-request user bind

The repository includes an illustrative middleware in examples/ldap.middleware.ts that decrypts a password and binds the default LDAP client for the current request. Adapt it to your authentication flow and secret management practices.

Development

yarn install
yarn test          # unit tests
yarn test:coverage # tests with coverage report
yarn build         # compile TypeScript to dist/
yarn lint          # ESLint on src/

License

MIT — see LICENSE.