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

nest-temporal-host

v0.0.82

Published

NestJS module for hosting Temporal workers with decorator-driven workflows and activities

Downloads

201

Readme

nest-temporal-host

A NestJS module for hosting Temporal workers with a decorator-driven API. Define workflows and activities using familiar NestJS patterns — no manual handler wiring, full dependency injection in activities, and multi-worker support out of the box.

Installation

npm install nest-temporal-host

Setup

Register TemporalHostModule in your root AppModule. It manages the full worker lifecycle — connecting to Temporal, registering activities and workflows, and shutting down cleanly on process exit.

Synchronous

import { TemporalHostModule } from "nest-temporal-host";

@Module({
  imports: [
    TemporalHostModule.forRoot({
      connection: { address: "localhost:7233" },
      namespace: "default",
      workers: [
        {
          taskQueue: "orders",
          workflowsPath: require.resolve("./workflows/order.workflow"),
          activities: [OrderActivity],
        },
      ],
    }),
  ],
})
export class AppModule {}

Asynchronous (with ConfigService)

import { TemporalHostModule } from "nest-temporal-host";

@Module({
  imports: [
    TemporalHostModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        connection: { address: config.get("TEMPORAL_URL") },
        namespace: config.get("TEMPORAL_NAMESPACE"),
        workers: [
          {
            taskQueue: config.get("TASK_QUEUE"),
            workflowsPath: require.resolve("./workflows/order.workflow"),
            activities: [OrderActivity],
          },
        ],
      }),
    }),
  ],
})
export class AppModule {}

Multiple workers

A single app can run multiple workers on different task queues concurrently:

TemporalHostModule.forRoot({
  connection: { address: "localhost:7233" },
  workers: [
    {
      taskQueue: "payments",
      workflowsPath: require.resolve("./workflows/payment.workflow"),
      activities: [PaymentActivity],
    },
    {
      taskQueue: "notifications",
      workflowsPath: require.resolve("./workflows/notification.workflow"),
      activities: [NotificationActivity],
    },
  ],
});

Module options

| Option | Type | Default | Description | | -------------------- | ---------------------------- | ---------------- | ------------------------------------------------ | | connection.address | string | localhost:7233 | Temporal server gRPC address | | connection.tls | TLSConfig | — | TLS config for Temporal Cloud or secured servers | | namespace | string | default | Temporal namespace | | workers | TemporalWorkerDefinition[] | — | One or more worker definitions |

Worker definition options

| Option | Type | Required | Description | | --------------- | -------- | -------- | --------------------------------------------------------- | | taskQueue | string | Yes | Task queue name this worker listens on | | workflowsPath | string | Yes | Absolute path to the file exporting your workflow classes | | activities | Type[] | No | @Activity() classes to register with this worker |


Defining Activities

Decorate a class with @Activity(). All public methods are registered as activity implementations. The class participates in NestJS DI — inject any provider as normal.

import { Activity } from "nest-temporal-host";

@Activity()
export class OrderActivity {
  constructor(private readonly orderService: OrderService) {}

  async processOrder(orderId: string): Promise<string> {
    return this.orderService.process(orderId);
  }

  async sendConfirmation(orderId: string): Promise<void> {
    await this.orderService.notify(orderId);
  }
}

Activities run in the Node.js context — full NestJS DI is available.


Defining Workflows

Extend TemporalWorkflow and decorate the class with @Workflow(). Use method decorators to declare the entry point and handlers — no manual setHandler calls needed.

import {
  Workflow,
  Execute,
  Signal,
  Query,
  Update,
  UpdateValidator,
  TemporalWorkflow,
  proxyActivities,
} from "nest-temporal-host";
import type { OrderActivity } from "../activities/order.activity";

const { processOrder, sendConfirmation } = proxyActivities<
  typeof OrderActivity
>({
  startToCloseTimeout: "5 minutes",
});

@Workflow()
export class OrderWorkflow extends TemporalWorkflow {
  private status = "pending";

  @Execute()
  async run(orderId: string): Promise<string> {
    await this.waitUntil(() => this.status !== "pending", "1 day");

    if (this.status === "approved") {
      await processOrder(orderId);
      await sendConfirmation(orderId);
    }

    return this.status;
  }

  @Signal("approve")
  onApprove(by: string): void {
    this.status = `approved by ${by}`;
  }

  @Signal("cancel")
  onCancel(reason: string): void {
    this.status = `cancelled: ${reason}`;
  }

  @Query("status")
  getStatus(): string {
    return this.status;
  }

  @Update("expedite")
  onExpedite(priority: number): string {
    this.status = `expedited at priority ${priority}`;
    return this.status;
  }

  @UpdateValidator("expedite")
  validateExpedite(priority: number): void {
    if (priority < 1 || priority > 5) {
      throw new Error("Priority must be between 1 and 5");
    }
  }
}

Workflows run inside Temporal's sandboxed V8 context. NestJS DI is not available here. Use @Activity() classes for any DI-aware logic.


Decorator Reference

@Activity()

Marks a class as a Temporal activity provider. Implies @Injectable().

@Workflow()

Marks a class as a Temporal workflow. Must extend TemporalWorkflow.

@Execute()

The workflow entry point. Every @Workflow() class must have exactly one @Execute() method. This is the method Temporal invokes when the workflow is started.

@Signal(name: string)

Registers a method as a signal handler. Signals are fire-and-forget — they do not return a value to the caller.

@Query(name: string)

Registers a method as a query handler. Queries are synchronous reads — they must not modify workflow state and return a value immediately.

@Update(name: string)

Registers a method as an update handler. Updates block until the workflow acknowledges the request and can return a value to the caller.

@UpdateValidator(name: string)

Registers a method as a validator for an update. Runs before the @Update handler. Throw an error here to reject the update before any state is mutated.


TemporalWorkflow base class

| Member | Description | | ------------------------- | --------------------------------------------------------------------------------------------------------- | | waitUntil(fn, timeout?) | Waits until the predicate returns true or the optional timeout expires. Wraps Temporal's condition(). |


Signal vs Query vs Update

| | Signal | Query | Update | | ---------------- | ----------------- | ----------------- | ------------------------ | | Direction | Caller → Workflow | Caller ← Workflow | Caller ↔ Workflow | | Return value | None | Yes | Yes | | Blocks caller | No | No | Yes (until acknowledged) | | Can mutate state | Yes | No | Yes | | Can be validated | No | — | Yes (@UpdateValidator) |