← Files WixARCHIVED FILE

skills/wix-headless-templates/blog/project/src/wix/blog/post-likes.ts

2.23 KB · Oct 8, 2026 · 12:02 UTC

↓ Download file

See the change to this file →

// Post likes (Wix Blog Like service) over the SDK — the `likes` module of @wix/blog. Every call
// here runs as the CALLING identity: a member, or the anonymous visitor the token stands for. The
// like read is personal ("did I like it?") and the writes are the viewer's, so all three are
// CLIENT-ONLY — the post store runs them only in a browser, never during SSR (where the identity
// is the app and the read answers PermissionDenied). The rules (FQDN, query, body) live in
// ./posts-core, shared with the REST twin in templates/blog/rest/post-likes.ts.
// docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/likes/create-like.md
// docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/likes/query-likes.md
// docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/likes/delete-like-by-fqdn-and-entity-id.md
import { likes as likesModule } from "@wix/blog";
import { wixModule } from "../sdk";
import { fetchPostMetrics } from "./posts";
import { BLOG_POST_FQDN } from "./posts-core";
import type { LikeState } from "./types";

const likes = wixModule(likesModule);

/** Like the post as the current viewer. Throws on failure — the store rolls its optimistic flip back. */
export async function likePost(postId: string): Promise<void> {
  await likes.createLike({ like: { entityId: postId, fqdn: BLOG_POST_FQDN } });
}

/** Remove the current viewer's like. */
export async function unlikePost(postId: string): Promise<void> {
  await likes.deleteLikeByFqdnAndEntityId({ fqdn: BLOG_POST_FQDN, entityId: postId });
}

/**
 * Whether THIS viewer liked the post, plus the post's fresh counters — two independent reads
 * (allSettled): a failed metrics read still delivers the liked flag and vice versa. The like
 * read is `limit(1)`: the only question is whether this viewer's row exists.
 */
export async function fetchLikeState(postId: string): Promise<LikeState> {
  const [likeRes, metrics] = await Promise.allSettled([
    likes.queryLikes().eq("fqdn", BLOG_POST_FQDN).eq("entityId", postId).limit(1).find(),
    fetchPostMetrics(postId),
  ]);
  return {
    liked: likeRes.status === "fulfilled" && (likeRes.value.items ?? []).length > 0,
    metrics: metrics.status === "fulfilled" ? metrics.value : null,
  };
}

SHA-256: 64d1474fdd4bd798a6a4c4f55380c9244db9532f4e3fea2a196f2cf1a802b284