NestboltNestbolt

@nestbolt/sluggable

Events

Listen to slug generation and regeneration events via @nestjs/event-emitter.

@nestbolt/sluggable emits events when slugs are generated or regenerated. Events are dispatched via @nestjs/event-emitter when it's installed.

Setup

Install and register the event emitter module:

npm install @nestjs/event-emitter
import { EventEmitterModule } from "@nestjs/event-emitter";

@Module({
  imports: [
    EventEmitterModule.forRoot(),
    SluggableModule.forRoot(),
    // ...
  ],
})
export class AppModule {}

If @nestjs/event-emitter is not installed, the package works normally but no events are emitted.

Events

sluggable.slug-generated

Emitted after a slug is generated on entity insert.

import { OnEvent } from "@nestjs/event-emitter";
import { SLUGGABLE_EVENTS, type SlugGeneratedEvent } from "@nestbolt/sluggable";

@Injectable()
export class SlugListener {
  @OnEvent(SLUGGABLE_EVENTS.SLUG_GENERATED)
  handleSlugGenerated(event: SlugGeneratedEvent) {
    console.log(`Slug "${event.slug}" generated for entity`);
    console.log("Source fields:", event.sourceFields);
    console.log("Source text:", event.sourceText);
  }
}

Payload: SlugGeneratedEvent

FieldTypeDescription
entityanyThe entity instance that received the slug
slugstringThe generated slug
sourceFieldsstring[]Field names used to generate the slug
sourceTextstringThe concatenated source text before slugification

sluggable.slug-regenerated

Emitted after a slug is regenerated on entity update. Only fires when the new slug differs from the old one.

import { OnEvent } from "@nestjs/event-emitter";
import { SLUGGABLE_EVENTS, type SlugRegeneratedEvent } from "@nestbolt/sluggable";

@Injectable()
export class SlugListener {
  @OnEvent(SLUGGABLE_EVENTS.SLUG_REGENERATED)
  handleSlugRegenerated(event: SlugRegeneratedEvent) {
    console.log(`Slug changed: "${event.oldSlug}" → "${event.newSlug}"`);
    // Create a redirect from the old slug to the new one
  }
}

Payload: SlugRegeneratedEvent

FieldTypeDescription
entityanyThe entity instance with the updated slug
oldSlugstringThe previous slug value
newSlugstringThe newly generated slug
sourceFieldsstring[]Field names used to generate the slug

Event Constants

Use the SLUGGABLE_EVENTS constant for type-safe event names:

import { SLUGGABLE_EVENTS } from "@nestbolt/sluggable";

SLUGGABLE_EVENTS.SLUG_GENERATED;    // "sluggable.slug-generated"
SLUGGABLE_EVENTS.SLUG_REGENERATED;  // "sluggable.slug-regenerated"

Practical Example: Slug Redirect Tracking

A common use case is tracking old slugs to create redirects when slugs change:

@Injectable()
export class SlugRedirectListener {
  constructor(
    @InjectRepository(SlugRedirect)
    private readonly redirectRepo: Repository<SlugRedirect>,
  ) {}

  @OnEvent(SLUGGABLE_EVENTS.SLUG_REGENERATED)
  async handleSlugRegenerated(event: SlugRegeneratedEvent) {
    await this.redirectRepo.save(
      this.redirectRepo.create({
        oldSlug: event.oldSlug,
        newSlug: event.newSlug,
        entityType: event.entity.constructor.name,
        entityId: event.entity.id,
      }),
    );
  }
}