import { logger } from "@plane/logger"; import { TPage } from "@plane/types"; // services import { AppError } from "@/lib/errors"; import { APIService } from "../api.service"; export type TPageDescriptionPayload = { description_binary: string; description_html: string; description: object; }; export abstract class PageCoreService extends APIService { protected abstract basePath: string; constructor() { super(); } async fetchDetails(pageId: string): Promise { return this.get(`${this.basePath}/pages/${pageId}/`, { headers: this.getHeader(), }) .then((response) => response?.data) .catch((error) => { const appError = new AppError(error, { context: { operation: "fetchDetails", pageId }, }); logger.error("Failed to fetch page details", appError); throw appError; }); } async fetchDescriptionBinary(pageId: string): Promise { return this.get(`${this.basePath}/pages/${pageId}/description/`, { headers: { ...this.getHeader(), "Content-Type": "application/octet-stream", }, responseType: "arraybuffer", }) .then((response) => response?.data) .catch((error) => { const appError = new AppError(error, { context: { operation: "fetchDescriptionBinary", pageId }, }); logger.error("Failed to fetch page description binary", appError); throw appError; }); } /** * Updates the title of a page */ async updatePageProperties( pageId: string, params: { data: Partial; abortSignal?: AbortSignal } ): Promise { const { data, abortSignal } = params; // Early abort check if (abortSignal?.aborted) { throw new AppError(new DOMException("Aborted", "AbortError")); } // Create an abort listener that will reject the pending promise let abortListener: (() => void) | undefined; const abortPromise = new Promise((_, reject) => { if (abortSignal) { abortListener = () => { reject(new AppError(new DOMException("Aborted", "AbortError"))); }; abortSignal.addEventListener("abort", abortListener); } }); try { return await Promise.race([ this.patch(`${this.basePath}/pages/${pageId}/`, data, { headers: this.getHeader(), signal: abortSignal, }) .then((response) => response?.data) .catch((error) => { const appError = new AppError(error, { context: { operation: "updatePageProperties", pageId }, }); if (appError.code === "ABORT_ERROR") { throw appError; } logger.error("Failed to update page properties", appError); throw appError; }), abortPromise, ]); } finally { // Clean up abort listener if (abortSignal && abortListener) { abortSignal.removeEventListener("abort", abortListener); } } } async updateDescriptionBinary(pageId: string, data: TPageDescriptionPayload): Promise { return this.patch(`${this.basePath}/pages/${pageId}/description/`, data, { headers: this.getHeader(), }) .then((response) => response?.data) .catch((error) => { const appError = new AppError(error, { context: { operation: "updateDescriptionBinary", pageId }, }); logger.error("Failed to update page description binary", appError); throw appError; }); } }