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

@bluealba/conduit-plugins-sdk

v1.2.0-feature-rms-366-add-new-advanced--273

Published

SDK for building Resource Management Interactions plugins

Readme

@bluealba/conduit-plugins-sdk

SDK for building Conduit plugins.

Installation

You can use the SDK in two ways: globally or locally within your plugin project.

Global Installation (Recommended for CLI usage)

Install the SDK globally to use the conduit command from anywhere:

# Using npm
npm install -g @bluealba/conduit-plugins-sdk

# Using pnpm
pnpm install -g @bluealba/conduit-plugins-sdk

# Using yarn
yarn global add @bluealba/conduit-plugins-sdk

After global installation, the conduit command is available system-wide:

conduit help
conduit create plugin my-plugin --type=source
cd my-plugin && conduit build

To uninstall globally:

# Using npm
npm uninstall -g @bluealba/conduit-plugins-sdk

# Using pnpm
pnpm uninstall -g @bluealba/conduit-plugins-sdk

# Using yarn
yarn global remove @bluealba/conduit-plugins-sdk

Local Installation (Per-project)

Install the SDK as a dependency in your plugin project:

# Using npm
npm install @bluealba/conduit-plugins-sdk

# Using pnpm
pnpm add @bluealba/conduit-plugins-sdk

# Using yarn
yarn add @bluealba/conduit-plugins-sdk

The SDK has a peer dependency on zod, so make sure it is installed in your project:

pnpm add zod

With local installation, use package manager executors to run commands:

# Using npm
npx conduit build

# Using pnpm
pnpm conduit build

# Using yarn
yarn conduit build

Usage

This SDK provides type definitions and utilities for creating plugins for the Conduit system.

Plugin Types

The SDK includes interfaces for four plugin types:

  • SourcePlugin - Fetches data from external sources and normalizes it into NormalizedInteraction objects
  • EnrichPlugin - Processes and modifies normalized interactions
  • RejectionPlugin - Determines whether an interaction should be rejected and provides a reason
  • PricePlugin - Calculates pricing for interactions

Source Plugin Example

import type {
  SourcePlugin,
  NormalizedInteraction,
  RawDataItem,
  SyncContext,
} from "@bluealba/conduit-plugins-sdk";
import { z } from "zod";

const ConfigSchema = z.object({
  apiKey: z.string(),
});

type Config = z.infer<typeof ConfigSchema>;

export class MySourcePlugin implements SourcePlugin<unknown, Config> {
  readonly metadata = {
    type: "source" as const,
    name: "my-source-plugin",
    version: "1.0.0",
    displayName: "My Source Plugin",
    description: "Fetches interactions from my system",
    sdkVersion: "1.0.0",
  };

  readonly configSchema = ConfigSchema;
  readonly secretFields = ["apiKey"];

  async sync(
    context: SyncContext<Config>,
  ): Promise<{ rawData: RawDataItem; normalizedInteraction: NormalizedInteraction }[]> {
    const { config, logger, lastSyncDate } = context;
    logger.info({ lastSyncDate }, "Starting sync");
    // Fetch and normalize data using config.apiKey
    return [];
  }
}

Enrich Plugin Example

import type {
  EnrichPlugin,
  RawInteraction,
  NormalizedInteraction,
} from "@bluealba/conduit-plugins-sdk";
import { z } from "zod";

const ConfigSchema = z.object({});
type Config = z.infer<typeof ConfigSchema>;

export class MyEnrichPlugin implements EnrichPlugin<Config> {
  readonly metadata = {
    type: "enrich" as const,
    name: "my-enrich-plugin",
    version: "1.0.0",
    displayName: "My Enrich Plugin",
    description: "Enriches normalized interactions",
    sdkVersion: "1.0.0",
  };

  readonly configSchema = ConfigSchema;
  readonly secretFields: string[] = [];

  process(
    _raw: RawInteraction,
    normalized: NormalizedInteraction,
    _config?: Config,
  ): NormalizedInteraction {
    // Modify and return the normalized interaction
    return normalized;
  }
}

Rejection Plugin Example

import type {
  RejectionPlugin,
  RawInteraction,
  NormalizedInteraction,
  RejectionResult,
  DeepReadonly,
} from "@bluealba/conduit-plugins-sdk";
import { z } from "zod";

const ConfigSchema = z.object({});
type Config = z.infer<typeof ConfigSchema>;

export class MyRejectionPlugin implements RejectionPlugin<Config> {
  readonly metadata = {
    type: "rejection" as const,
    name: "my-rejection-plugin",
    version: "1.0.0",
    displayName: "My Rejection Plugin",
    description: "Rejects interactions matching custom criteria",
    sdkVersion: "1.0.0",
  };

  readonly configSchema = ConfigSchema;
  readonly secretFields: string[] = [];

  reject(
    _raw: DeepReadonly<RawInteraction>,
    normalized: DeepReadonly<NormalizedInteraction>,
    _config?: Config,
  ): RejectionResult | undefined {
    if (normalized.buysideAttendees.length === 0) {
      return { rejected: true, reason: "No buyside attendees" };
    }
    return { rejected: false, reason: null };
  }
}

Price Plugin Example

import type {
  PricePlugin,
  RawInteraction,
  NormalizedInteraction,
  PricingResult,
  DeepReadonly,
} from "@bluealba/conduit-plugins-sdk";
import { z } from "zod";

const ConfigSchema = z.object({
  pricePerAttendee: z.number().nonnegative(),
});

type Config = z.infer<typeof ConfigSchema>;

export class MyPricePlugin implements PricePlugin<Config> {
  readonly metadata = {
    type: "price" as const,
    name: "my-price-plugin",
    version: "1.0.0",
    displayName: "My Price Plugin",
    description: "Calculates pricing based on attendee count",
    sdkVersion: "1.0.0",
  };

  readonly configSchema = ConfigSchema;
  readonly secretFields: string[] = [];

  calculatePricing(
    _raw: DeepReadonly<RawInteraction>,
    normalized: DeepReadonly<NormalizedInteraction>,
    config?: Config,
  ): PricingResult {
    const pricePerAttendee = config?.pricePerAttendee ?? 50;
    const value = normalized.buysideAttendees.length * pricePerAttendee;
    return {
      strategy: "per-attendee",
      matchedRule: `${normalized.buysideAttendees.length}-attendees`,
      value,
    };
  }
}

CLI Commands

The SDK provides command-line tools for scaffolding, building, and publishing plugins.

Available Commands

Check available commands

conduit help

Create a new plugin

conduit create plugin <name> --type=<type>

If --type is omitted, an interactive prompt lets you select the plugin type.

Plugin types: source, enrich, rejection, price

Build a plugin

conduit build

Publish a plugin to the server

conduit publish

Uploads dist/bundle.js to the Conduit server. Set the CONDUIT_URL environment variable to point to a non-default server (default: http://localhost:3000).

Usage with Different Package Managers

Using npm

# Check available commands
npx conduit help

# Create a new plugin
npx conduit create plugin my-plugin --type=source

# Build the plugin
npx conduit build

# Publish the plugin
npx conduit publish

# Or via package.json scripts
npm run build

Using pnpm

# Check available commands
pnpm conduit help

# Create a new plugin (pnpm automatically finds binaries)
pnpm conduit create plugin my-plugin --type=source

# Build the plugin
pnpm conduit build

# Publish the plugin
pnpm conduit publish

# Or via package.json scripts
pnpm build

Using yarn

# Check available commands
yarn conduit help

# Create a new plugin
yarn conduit create plugin my-plugin --type=source

# Build the plugin
yarn conduit build

# Publish the plugin
yarn conduit publish

# Or via package.json scripts
yarn build

Example Workflow

# 1. Create a new source plugin
pnpm conduit create plugin salesforce-source --type=source

# 2. Navigate into the plugin directory
cd salesforce-source

# 3. Install dependencies
pnpm install

# 4. Implement the plugin logic in src/plugin.ts

# 5. Build the plugin
pnpm conduit build

# 6. Publish to the Conduit server
pnpm conduit publish

Adding to package.json scripts

For convenience, add this script to your plugin's package.json:

{
  "scripts": {
    "build": "conduit build"
  }
}

Environment Variables

| Variable | Description | Default | |---------------|------------------------------------------|--------------------------| | CONDUIT_URL | Conduit server base URL for publish | http://localhost:3000 |

Development

# Install dependencies
pnpm install

# Build the SDK
pnpm build

# Watch mode for development
pnpm dev

# Run tests
pnpm test