Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ const Tutorials = [
link: `/tutorials/agenda`
},
{
text: "Pulse",
text: "Pulse (deprecated)",
link: `/tutorials/pulse`
},
{
Expand Down
3 changes: 0 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,6 @@ frameworks:
- title: Vike
href: /tutorials/vike.html
src: /vike.svg
- title: Pulse
href: /tutorials/pulse.html
src: /pulse.png
- title: Vault
href: /plugins/premium/config-source/vault.html
src: /vault.png
Expand Down
4 changes: 4 additions & 0 deletions docs/tutorials/agenda.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ Migrate to @tsed/agenda v8.30.0:
- `AgendaModule` → `Agenda` from `agenda`
```

::: tip Migrating from `@tsed/pulse`?
`@tsed/pulse` is deprecated. See the [Pulse migration guide](/tutorials/pulse#migrate-to-tsed-agenda) for step-by-step rewrites from `@tsed/pulse` to `@tsed/agenda`.
:::

## Configure your server

Import `@tsed/agenda` in your Server:
Expand Down
212 changes: 178 additions & 34 deletions docs/tutorials/pulse.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,65 @@
---
description: "Use Pulse cron with Express/Koa, TypeScript and Ts.ED."
description: "@tsed/pulse is deprecated. Migrate from Pulse to @tsed/agenda with Agenda v6 in your Express/Koa TypeScript Ts.ED application."
head:
- - meta
- name: description
content: Use Pulse cron with Express/Koa, TypeScript and Ts.ED. Pulse is a maintained for of Agenda, a light-weight job scheduling library for Node.js
content: "@tsed/pulse is deprecated. Migrate from Pulse to @tsed/agenda with Agenda v6 in your Express/Koa TypeScript Ts.ED application. Pulse is a fork of Agenda, a light-weight job scheduling library for Node.js"
- - meta
- name: keywords
content: ts.ed express typescript agenda node.js javascript decorators pulse pulse-cron pulsecron job-scheduling cron background-jobs
content: ts.ed express typescript agenda node.js javascript decorators pulse pulse-cron pulsecron job-scheduling cron background-jobs deprecated migration
---

# Pulse

<Banner src="/pulse.png" href="https://github.com/pulsecron/pulse" height="200" />

::: warning
::: danger Deprecated
`@tsed/pulse` is deprecated and will be removed in a future major release. This package won't receive any future updates.
**Do not start new projects on `@tsed/pulse`.**

For new projects, use `@tsed/agenda` with Agenda v6.
Existing consumers should migrate to `@tsed/agenda` + `agenda` + `@agendajs/mongo-backend`.
For new projects, use [`@tsed/agenda`](/tutorials/agenda) with Agenda v6.
Existing `@tsed/pulse` users should plan a migration to `@tsed/agenda` + `agenda` + `@agendajs/mongo-backend`
by following the [migration guide](#migrate-to-tsed-agenda) below.

The legacy Pulse examples below are kept only to help existing consumers migrate old code.
The legacy Pulse examples at the end of this page are kept only to help existing consumers maintain or migrate old code.
:::

## Feature

`@pulsecron/pulse` is maintained fork of the Agenda.

Currently, `@tsed/pulse` allows you to decorate classes with `@Pulse` and
corresponding methods to have them picked up by the @pulsecron/pulse library to be
`@pulsecron/pulse` is a fork of Agenda. `@tsed/pulse` allowed you to decorate classes with `@Pulse` and
corresponding methods to have them picked up by the `@pulsecron/pulse` library to be
scheduled automatically (`@Every`) or programmatically (`@Define`) via the PulseService.

For more information about Pulse look at the documentation [here](https://github.com/pulsecron/pulse);
The same features are available in `@tsed/agenda` on top of Agenda v6, which is the recommended and maintained
scheduling integration for Ts.ED. See the [Agenda documentation](/tutorials/agenda).

## Installation

To begin, install the Pulse module for Ts.ED:
Do not install `@tsed/pulse` for new projects. Install the recommended Agenda v6 stack instead:

::: code-group

```sh [npm]
npm install --save @tsed/agenda agenda @agendajs/mongo-backend
```

```sh [yarn]
yarn add @tsed/agenda agenda @agendajs/mongo-backend
```

```sh [pnpm]
pnpm add @tsed/agenda agenda @agendajs/mongo-backend
```

```sh [bun]
bun add @tsed/agenda agenda @agendajs/mongo-backend
```

:::

Then follow the [Agenda documentation](/tutorials/agenda) to configure your server.

:::: details Legacy installation (existing projects that cannot migrate yet)

::: code-group

Expand All @@ -56,12 +81,50 @@ bun add @tsed/pulse @pulsecron/pulse

:::

## Migrate to Agenda
::::

## Migrate to `@tsed/agenda`

The target stack is `@tsed/agenda` + `agenda` (v6) + `@agendajs/mongo-backend`.

### 1. Replace dependencies

| Remove | Add |
| ------------------ | ------------------------- |
| `@tsed/pulse` | `@tsed/agenda` |
| `@pulsecron/pulse` | `agenda` |
| | `@agendajs/mongo-backend` |

Migrate from `@tsed/pulse` to `@tsed/agenda` on top of Agenda v6.
::: code-group

```sh [npm]
npm uninstall @tsed/pulse @pulsecron/pulse
npm install --save @tsed/agenda agenda @agendajs/mongo-backend
```

```sh [yarn]
yarn remove @tsed/pulse @pulsecron/pulse
yarn add @tsed/agenda agenda @agendajs/mongo-backend
```

```sh [pnpm]
pnpm remove @tsed/pulse @pulsecron/pulse
pnpm add @tsed/agenda agenda @agendajs/mongo-backend
```

```sh [bun]
bun remove @tsed/pulse @pulsecron/pulse
bun add @tsed/agenda agenda @agendajs/mongo-backend
```

:::

### 2. Update the server configuration

The `pulse` configuration key becomes `agenda`, and the legacy `db` options move into a `MongoBackend` instance.

```diff
import {Configuration} from "@tsed/di";
import {Configuration} from "@tsed/di";
-import "@tsed/pulse";
+import "@tsed/agenda";
+import {MongoBackend} from "@agendajs/mongo-backend";
Expand All @@ -81,28 +144,110 @@ import {Configuration} from "@tsed/di";
export class Server {}
```

The Ts.ED specific flags (`enabled`, `disableJobProcessing`, `drainJobsBeforeClose`) keep the same names and
behavior in `@tsed/agenda`.

### 3. Update decorators, injection and lifecycle hooks

`@tsed/agenda` exposes the same `@Every` and `@Define` decorators. The class decorator is `@JobsController`
and the scheduler instance is the `Agenda` class from `agenda` (there is no `AgendaModule`).

```diff
-import {Pulse, Every, Define, PulseModule} from "@tsed/pulse";
-import {Job} from "@pulsecron/pulse";
+import {JobsController, Every, Define} from "@tsed/agenda";
+import {Agenda, Job} from "agenda";

-@Pulse({namespace: "email"})
+@JobsController({namespace: "email"})
export class EmailJobService {
@Inject()
- pulse: PulseModule;
+ agenda: Agenda;

@Every("60 minutes", {name: "maintenanceJob"})
async sendAdminStatistics(job: Job) {}

@Define({name: "sendWelcomeEmail"})
async sendWelcomeEmail(job: Job) {}

- async $beforePulseStart() {}
- async $afterPulseStart() {}
+ async $beforeAgendaStart() {}
+ async $afterAgendaStart() {}
}
```

Scheduling APIs keep the same shape (`now()`, `schedule()`, `every()`, `create()`), so call sites only need the
injected instance to be renamed:

```diff
@Service()
export class UsersService {
@Inject()
- private pulse: PulseModule;
+ private agenda: Agenda;

async create(user: User) {
- await this.pulse.now("email.sendWelcomeEmail", {user});
- await this.pulse.schedule("in 2 hours", "email.sendFollowUpEmail", {user});
+ await this.agenda.now("email.sendWelcomeEmail", {user});
+ await this.agenda.schedule("in 2 hours", "email.sendFollowUpEmail", {user});
}
}
```

### AI migration note

Apply these deterministic rewrites:
Apply these deterministic rewrites when migrating a codebase with a coding agent:

```text
Migrate from @tsed/pulse to @tsed/agenda:
Migrate from @tsed/pulse to @tsed/agenda (Agenda v6):

Dependencies
- remove `@tsed/pulse` → add `@tsed/agenda`
- remove `@pulsecron/pulse` → add `agenda` + `@agendajs/mongo-backend`

Imports
- `import "@tsed/pulse"` → `import "@tsed/agenda"`
- add `import {MongoBackend} from "@agendajs/mongo-backend"`
- `@Pulse(...)` → `@JobsController(...)`
- `PulseModule` → `Agenda` from `agenda`
- `pulse` config key → `agenda`
- `pulse.db.address` → `agenda.backend: new MongoBackend({address: ...})`
- `import {Pulse, JobsController, Every, Define, PulseModule, PulseService} from "@tsed/pulse"` → `import {JobsController, Every, Define} from "@tsed/agenda"`
- `import {Job} from "@pulsecron/pulse"` → `import {Job} from "agenda"`
- add `import {Agenda} from "agenda"` where `PulseModule` / `PulseService` was injected
- add `import {MongoBackend} from "@agendajs/mongo-backend"` in the server configuration file

Configuration (@Configuration / TsED.Configuration)
- `pulse: {...}` config key → `agenda: {...}`
- `pulse.db.address` → `agenda.backend: new MongoBackend({address})`
- `pulse.db.collection` / `pulse.db.options` → `agenda.backend: new MongoBackend({collection, options})`
- `pulse.mongo` / `pulse.repository` → `agenda.backend`
- `pulse.ensureIndex` / `pulse.sort` → move into `new MongoBackend(...)`
- `@pulsecron/pulse` dependency → `agenda` + `@agendajs/mongo-backend`
- `pulse.mongo` → `agenda.backend: new MongoBackend({mongo})`
- `pulse.ensureIndex` / `pulse.sort` → move inside `new MongoBackend({ensureIndex, sort})`, sort directions use `"asc"` / `"desc"`
- `pulse.enabled`, `pulse.disableJobProcessing`, `pulse.drainJobsBeforeClose` → keep the same names under `agenda`
- `PulseSettings` type → `AgendaSettings`

For more details about @tsed/agenda, see [Agenda for Ts.ED](https://tsed.dev/ai/tutorials/agenda.md).
Decorators and injection
- `@Pulse(...)` → `@JobsController(...)`
- `@JobsController(...)` (from `@tsed/pulse`) → `@JobsController(...)` (from `@tsed/agenda`)
- `@Every(...)` / `@Define(...)` → unchanged (import them from `@tsed/agenda`)
- `PulseModule` / `PulseService` injected type → `Agenda` (from `agenda`)
- `pulse.now(...)`, `pulse.schedule(...)`, `pulse.every(...)`, `pulse.create(...)`, `pulse.define(...)` → same methods on the injected `Agenda`
- `pulse.jobs(...)` → `agenda.queryJobs(...)`

Lifecycle hooks
- `$beforePulseStart()` → `$beforeAgendaStart()`
- `$afterPulseStart()` → `$afterAgendaStart()`
```

## Configure your server
For more details about `@tsed/agenda`, see [Agenda for Ts.ED](/tutorials/agenda)
(LLM-friendly version: [tsed.dev/tutorials/agenda.md](https://tsed.dev/tutorials/agenda.md)).

## Legacy usage (existing projects only)

::: warning
The following sections document the deprecated `@tsed/pulse` API. They are kept for reference only.
Do not use them for new code.
:::

### Configure your server

Import `@tsed/pulse` in your Server:

Expand All @@ -115,7 +260,7 @@ const mongoConnectionString = "mongodb://127.0.0.1/pulse";
@Configuration({
pulse: {
enabled: true, // Enable Pulse jobs for this instance.
// drainJobsBeforeStop: true, // Wait for jobs to finish before stopping the pulse process.
// drainJobsBeforeClose: true, // Wait for jobs to finish before stopping the pulse process.
// disableJobProcessing: true, // Prevents jobs from being processed.
// pass any options that you would normally pass to new Pulse(), e.g.
db: {
Expand All @@ -126,7 +271,7 @@ const mongoConnectionString = "mongodb://127.0.0.1/pulse";
export class Server {}
```

## Create a new Service
### Create a new Service

Decorate the class with `@Pulse`. The `namespace` option is optional and will
prefix the job name with `namespace.`
Expand Down Expand Up @@ -167,7 +312,7 @@ export class EmailJobService {
}
```

## Define a job processor manually
### Define a job processor manually

PulseModule exposes methods to manually define a job processor. It can be useful to define a job processor when you need to fetch data beforehand and dynamically build job name / options.

Expand Down Expand Up @@ -213,14 +358,13 @@ export class EmailJobService {
}
```

## Inject Pulse
### Inject Pulse

Inject the PulseService instance to interact with it directly, e.g. to schedule
a job manually.

```typescript
import {Service} from "@tsed/di";
import {AfterRoutesInit} from "@tsed/platform-params";
import {Service, Inject} from "@tsed/di";
import {PulseModule} from "@tsed/pulse";

@Service()
Expand Down
29 changes: 29 additions & 0 deletions openspec/changes/complete-pulse-deprecation-docs/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Context

`@tsed/pulse` is superseded by `@tsed/agenda` on Agenda v6. The first deprecation pass only covered part of the docs, so users still receive install commands for Pulse and coding agents lack a complete rewrite table. `AgendaModule` no longer exists in `@tsed/agenda` (consumers inject `Agenda` from `agenda`), so the migration examples suggested in the issue must be adapted to the current API.

## Goals / Non-Goals

**Goals:**

- Make both Pulse docs entry points self-sufficient deprecation + migration guides.
- Give IDEs and npm a deprecation signal without changing runtime behavior.
- Stop promoting Pulse from discovery surfaces (home page, sidebar label).

**Non-Goals:**

- Removing the `@tsed/pulse` package or its tests.
- Running `npm deprecate` (a publish-time operation handled by maintainers).
- Changing `@tsed/agenda` behavior.

## Decisions

- Keep legacy Pulse examples, but move them under a clearly labelled "Legacy usage (existing projects only)" section after the migration guide, so the reading order is deprecation → replacement → migration → legacy reference.
- Document migration targets against the actual `@tsed/agenda` API: `@JobsController`, `Agenda` from `agenda`, `$beforeAgendaStart` / `$afterAgendaStart`, `queryJobs()`. Do not mention `AgendaModule`, which was removed.
- Use `@deprecated` TSDoc on every exported symbol rather than a runtime warning, to avoid noisy logs for existing consumers.
- Keep the tutorial page reachable from the sidebar (labelled deprecated) so existing users can find the migration guide, but remove the home page card that promotes new adoption.

## Risks / Trade-offs

- [Docs drift between README and tutorial] → Both files share the same migration content, adapted only for GitHub alerts vs VitePress containers.
- [Broken anchors] → GitHub slug `#migrate-to-tsedagenda` and VitePress slug `#migrate-to-tsed-agenda` are used respectively.
25 changes: 25 additions & 0 deletions openspec/changes/complete-pulse-deprecation-docs/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Why

Issue [#3376](https://github.com/tsedio/tsed/issues/3376) asks to deprecate `@tsed/pulse` and redirect users to `@tsed/agenda` + Agenda v6. The archived `migrate-tsed-agenda-to-v6` change added a first banner and a config diff, but both Pulse docs entry points still promote `npm install @tsed/pulse @pulsecron/pulse`, the package README lacks the AI-oriented rewrite section, the tutorial lacks the decorator/injection/lifecycle-hook diffs, the README banner is malformed, and the package itself carries no deprecation signal for IDEs or npm.

## What Changes

- Turn `packages/third-parties/pulse/readme.md` and `docs/tutorials/pulse.md` into complete deprecation + migration guides: deprecation banner, Agenda v6 install commands (npm/yarn/pnpm/bun), dependency table, config diff, decorator/injection/lifecycle-hook diffs, and an AI-oriented deterministic rewrite list. Legacy Pulse usage is moved under an explicit "Legacy usage" section.
- Mark the `@tsed/pulse` public API (`JobsController`, `Pulse`, `Every`, `Define`, `PulseSettings`, `PulseService`, `PulseModule`, the `pulse` configuration key) with `@deprecated` TSDoc pointing to `@tsed/agenda`, and prefix the package description with `[DEPRECATED]`.
- Stop promoting Pulse: remove the Pulse card from the docs home page and label the sidebar entry "Pulse (deprecated)".
- Cross-link the Agenda docs (tutorial and README) to the Pulse migration guide.

## Capabilities

### New Capabilities

<!-- none -->

### Modified Capabilities

- `pulse-deprecation-guidance`: require Agenda v6 install guidance, package-level deprecation signals, and that Pulse is no longer promoted from the docs home page.

## Impact

- Affected files: `packages/third-parties/pulse/{readme.md,package.json,src/**}`, `docs/tutorials/pulse.md`, `docs/tutorials/agenda.md`, `packages/third-parties/agenda/readme.md`, `docs/index.md`, `docs/.vitepress/config.mts`.
- No runtime behavior change: only TSDoc comments and package metadata change in `@tsed/pulse`.
Loading
Loading