@nestbolt/sluggable
Decorator
@Sluggable() decorator options for per-entity slug configuration.
The @Sluggable() decorator is applied to your TypeORM entity class to enable automatic slug generation. It stores configuration metadata that the SluggableSubscriber reads on insert and update.
Basic Usage
import { Sluggable } from "@nestbolt/sluggable";
@Sluggable({ from: "title" })
@Entity("posts")
export class Post {
@PrimaryGeneratedColumn("uuid")
id!: string;
@Column()
title!: string;
@Column({ default: "" })
slug!: string;
}Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
from | string | string[] | (required) | Source field(s) to generate the slug from |
slugField | string | "slug" | Entity column to store the generated slug |
separator | string | Module default ("-") | Word separator for this entity |
maxLength | number | Module default (255) | Maximum slug length for this entity |
onUpdate | "keep" | "regenerate" | Module default ("keep") | Update behavior for this entity |
unique | boolean | true | Enable unique slug collision handling |
Source Fields
Single Field
@Sluggable({ from: "title" })
// { title: "Hello World" } → "hello-world"Multiple Fields
Pass an array to concatenate multiple fields:
@Sluggable({ from: ["firstName", "lastName"] })
// { firstName: "John", lastName: "Doe" } → "john-doe"Fields are joined with a space before slugifying. Empty or falsy fields are filtered out:
@Sluggable({ from: ["firstName", "middleName", "lastName"] })
// { firstName: "John", middleName: "", lastName: "Doe" } → "john-doe"Custom Slug Field
By default, the slug is stored in the slug column. Use slugField to change it:
@Sluggable({ from: "title", slugField: "permalink" })
@Entity("articles")
export class Article {
@PrimaryGeneratedColumn("uuid")
id!: string;
@Column()
title!: string;
@Column({ default: "" })
permalink!: string;
}Per-Entity Separator and Max Length
Override the global separator and max length for specific entities:
@Sluggable({ from: "name", separator: "_", maxLength: 30 })
@Entity("categories")
export class Category {
@PrimaryGeneratedColumn("uuid")
id!: string;
@Column()
name!: string;
@Column({ default: "" })
slug!: string;
}
// { name: "Electronics & Gadgets" } → "electronics_gadgets"Disabling Unique Slugs
By default, slug uniqueness is enforced with collision detection. Set unique: false to disable it:
@Sluggable({ from: "title", unique: false })
@Entity("tags")
export class Tag {
@PrimaryGeneratedColumn("uuid")
id!: string;
@Column()
title!: string;
@Column({ default: "" })
slug!: string;
}
// Two tags with title "JavaScript" both get slug "javascript" -- no suffixSee Unique Slugs for more details.
Update Behavior
Control what happens when the entity is updated:
@Sluggable({ from: "title", onUpdate: "regenerate" })
@Entity("pages")
export class Page {
// ...
}"keep"-- slug is preserved on update (unless it's empty)"regenerate"-- slug is regenerated when source fields change
See Update Behavior for full details.
Skip Conditions
The subscriber skips slug generation in these cases:
- Slug already set -- if the slug field has a truthy value on insert, the subscriber leaves it as-is. This lets you set custom slugs manually.
- Source fields empty -- if all source fields are empty or falsy, no slug is generated.
- No decorator -- entities without
@Sluggable()are ignored by the subscriber.