@nestbolt/likeable
Configuration
LikeableModule.forRoot()/forRootAsync() options and the full LikeableService API.
forRoot
LikeableModule.forRoot() registers LikeableService and the LikeEntity repository globally:
import { LikeableModule } from "@nestbolt/likeable";
@Module({
imports: [LikeableModule.forRoot()],
})
export class AppModule {}The options object is currently reserved for future use -- calling forRoot() with no arguments is the standard form. Per-entity behavior is configured via the @Likeable() decorator, not via global options.
forRootAsync
Use forRootAsync() when you need module setup to depend on other providers (e.g., ConfigService):
import { ConfigModule, ConfigService } from "@nestjs/config";
import { LikeableModule } from "@nestbolt/likeable";
@Module({
imports: [
ConfigModule.forRoot(),
LikeableModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (_config: ConfigService) => ({}),
}),
],
})
export class AppModule {}forRootAsync Options
| Option | Type | Description |
|---|---|---|
imports | any[] | Modules to import for dependency injection |
inject | any[] | Providers to inject into the factory function |
useFactory | (...args) => LikeableModuleOptions | Factory function that returns the options |
LikeableService API
LikeableService is available via dependency injection after module registration:
@Injectable()
export class MyService {
constructor(private readonly likeable: LikeableService) {}
}All methods take the entity constructor as the first argument so the service can resolve the polymorphic type stored in the likes table.
like(entity, entityId, userId)
Records that userId likes (entity, entityId). Idempotent -- a duplicate like for the same (user, entity) pair is silently swallowed:
await likeable.like(Post, post.id, userId);
await likeable.like(Post, post.id, userId); // no-op, no exceptionEmits like.liked on the first successful insert. Duplicates do not emit.
unlike(entity, entityId, userId)
Removes the like for (userId, entity, entityId):
await likeable.unlike(Post, post.id, userId);Emits like.unliked only when a row was actually deleted -- calling unlike() on something that wasn't liked is a no-op and does not emit.
toggle(entity, entityId, userId)
Flips the like state and returns the new state (true if now liked, false if now unliked):
const liked = await likeable.toggle(Post, post.id, userId);
console.log(liked); // true on first call, false on second, etc.isLikedBy(entity, entityId, userId)
Returns true if userId has liked (entity, entityId):
const liked = await likeable.isLikedBy(Post, post.id, userId);getLikesCount(entity, entityId)
Returns the total number of likes for an entity:
const count = await likeable.getLikesCount(Post, post.id);getLikers(entity, entityId)
Returns the list of user IDs that have liked the entity, ordered by most recent first:
const userIds = await likeable.getLikers(Post, post.id);getUserLikes(entity, userId)
Returns the list of entity IDs of the given type that the user has liked, ordered by most recent first:
const postIds = await likeable.getUserLikes(Post, userId);getUserLikesCount(entity, userId)
Returns the number of entities of the given type that the user has liked:
const count = await likeable.getUserLikesCount(Post, userId);isLikeable(entity)
Returns true if the entity class is decorated with @Likeable():
likeable.isLikeable(Post); // true
likeable.isLikeable(SomeOtherEntity); // falsegetOptions()
Returns the resolved LikeableModuleOptions passed to forRoot() / forRootAsync():
const options = likeable.getOptions();Static: LikeableService.getInstance()
Returns the active LikeableService instance, or null if the module hasn't been initialized. This is what the mixin uses internally to bridge entity instances to the service:
const service = LikeableService.getInstance();You normally don't need to call this directly -- prefer dependency injection or the mixin methods.