@nestbolt/likeable
Decorator
@Likeable() decorator options for per-entity polymorphic type configuration.
The @Likeable() decorator marks a TypeORM entity as likeable. It stores a small piece of metadata that LikeableService reads to decide what value to write to the likeable_type column of the likes table.
Basic Usage
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
import { Likeable } from "@nestbolt/likeable";
@Likeable()
@Entity("posts")
export class Post {
@PrimaryGeneratedColumn("uuid")
id!: string;
@Column()
title!: string;
}With no options, the entity's class name ("Post") is used as the polymorphic type.
Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
type | string | Class name (ctor.name) | Polymorphic type stored in the likes.likeable_type column |
Custom Polymorphic Type
Set type when you need the value stored in likes.likeable_type to differ from the class name. This is important if:
- You rename the entity class but want existing rows to keep working
- You bundle/minify your code and class names get mangled
- Two entities in different modules share the same class name
@Likeable({ type: "BlogPost" })
@Entity("posts")
export class Post {
@PrimaryGeneratedColumn("uuid")
id!: string;
}All like operations on Post will read and write rows where likeable_type = "BlogPost".
Multiple Entity Types
Each likeable entity gets its own polymorphic type, all stored in the same likes table:
@Likeable() // type = "Post"
@Entity("posts")
export class Post { /* ... */ }
@Likeable() // type = "Comment"
@Entity("comments")
export class Comment { /* ... */ }
@Likeable({ type: "Product" })
@Entity("products")
export class ProductEntity { /* ... */ }Likes are scoped per type -- liking a Post with id abc and a Comment with id abc creates two distinct rows.
How the Type is Resolved
LikeableService resolves the polymorphic type once per call:
- If
@Likeable({ type: "..." })was provided, that string is used. - Otherwise, the entity class's
nameproperty is used (Post.name === "Post").
If the entity is missing the @Likeable() decorator entirely, the service still works -- it falls back to the class name. But explicitly decorating is recommended so the intent is clear and so LikeableService.isLikeable() returns true.
Composing with Other Decorators
@Likeable() is a pure metadata decorator with no runtime side effects, so it composes cleanly with any TypeORM or other Nestbolt decorators:
import { HasMedia } from "@nestbolt/medialibrary";
import { Sluggable } from "@nestbolt/sluggable";
import { Likeable } from "@nestbolt/likeable";
@Sluggable({ from: "name" })
@Likeable({ type: "Product" })
@HasMedia({ modelType: "Product" })
@Entity("products")
export class ProductEntity {
/* ... */
}Order between Nestbolt decorators does not matter.