Skip to main content
Glama
bookstack-client.ts13 kB
import axios, { AxiosInstance, AxiosResponse } from "axios"; import FormData from "form-data"; import { BookStackConfig, ApiResponse, PaginationParams, User, Role, Book, Chapter, Page, Shelf, Attachment, ImageGallery, SearchResult, ContentPermissions, AuditLogEntry, RecycleBinItem, CreateBookRequest, CreateChapterRequest, CreatePageRequest, CreateShelfRequest, CreateUserRequest, CreateRoleRequest, CreateAttachmentRequest, CreateImageRequest, } from "../types/index.js"; export class BookStackClient { private api: AxiosInstance; constructor(config: BookStackConfig) { this.api = axios.create({ baseURL: `${config.baseUrl}/api`, headers: { Authorization: `Token ${config.tokenId}:${config.token}`, "Content-Type": "application/json", Accept: "application/json", }, }); } // Helper method for GET requests with pagination private async get<T>( endpoint: string, params?: PaginationParams ): Promise<ApiResponse<T[]>> { const response: AxiosResponse<ApiResponse<T[]>> = await this.api.get( endpoint, { params } ); return response.data; } // Helper method for POST requests private async post<T>(endpoint: string, data?: any): Promise<T> { const response: AxiosResponse<T> = await this.api.post(endpoint, data); return response.data; } // Helper method for PUT requests private async put<T>(endpoint: string, data?: any): Promise<T> { const response: AxiosResponse<T> = await this.api.put(endpoint, data); return response.data; } // Helper method for DELETE requests private async delete(endpoint: string): Promise<void> { await this.api.delete(endpoint); } // Helper method for multipart form data private async postMultipart<T>( endpoint: string, formData: FormData ): Promise<T> { const response: AxiosResponse<T> = await this.api.post(endpoint, formData, { headers: { ...formData.getHeaders(), }, }); return response.data; } // ========== BOOKS ========== async getBooks(params?: PaginationParams): Promise<ApiResponse<Book[]>> { return this.get<Book>("/books", params); } async getBook(id: number): Promise<Book> { const response: AxiosResponse<Book> = await this.api.get(`/books/${id}`); return response.data; } async createBook(data: CreateBookRequest): Promise<Book> { return this.post<Book>("/books", data); } async updateBook( id: number, data: Partial<CreateBookRequest> ): Promise<Book> { return this.put<Book>(`/books/${id}`, data); } async deleteBook(id: number): Promise<void> { return this.delete(`/books/${id}`); } async exportBookHtml(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/books/${id}/export/html` ); return response.data; } async exportBookPdf(id: number): Promise<Buffer> { const response: AxiosResponse<Buffer> = await this.api.get( `/books/${id}/export/pdf`, { responseType: "arraybuffer", } ); return response.data; } async exportBookPlainText(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/books/${id}/export/plaintext` ); return response.data; } async exportBookMarkdown(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/books/${id}/export/markdown` ); return response.data; } // ========== CHAPTERS ========== async getChapters( params?: PaginationParams ): Promise<ApiResponse<Chapter[]>> { return this.get<Chapter>("/chapters", params); } async getChapter(id: number): Promise<Chapter> { const response: AxiosResponse<Chapter> = await this.api.get( `/chapters/${id}` ); return response.data; } async createChapter(data: CreateChapterRequest): Promise<Chapter> { return this.post<Chapter>("/chapters", data); } async updateChapter( id: number, data: Partial<CreateChapterRequest> ): Promise<Chapter> { return this.put<Chapter>(`/chapters/${id}`, data); } async deleteChapter(id: number): Promise<void> { return this.delete(`/chapters/${id}`); } async exportChapterHtml(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/chapters/${id}/export/html` ); return response.data; } async exportChapterPdf(id: number): Promise<Buffer> { const response: AxiosResponse<Buffer> = await this.api.get( `/chapters/${id}/export/pdf`, { responseType: "arraybuffer", } ); return response.data; } async exportChapterPlainText(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/chapters/${id}/export/plaintext` ); return response.data; } async exportChapterMarkdown(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/chapters/${id}/export/markdown` ); return response.data; } // ========== PAGES ========== async getPages(params?: PaginationParams): Promise<ApiResponse<Page[]>> { return this.get<Page>("/pages", params); } async getPage(id: number): Promise<Page> { const response: AxiosResponse<Page> = await this.api.get(`/pages/${id}`); return response.data; } async createPage(data: CreatePageRequest): Promise<Page> { return this.post<Page>("/pages", data); } async updatePage( id: number, data: Partial<CreatePageRequest> ): Promise<Page> { return this.put<Page>(`/pages/${id}`, data); } async deletePage(id: number): Promise<void> { return this.delete(`/pages/${id}`); } async exportPageHtml(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/pages/${id}/export/html` ); return response.data; } async exportPagePdf(id: number): Promise<Buffer> { const response: AxiosResponse<Buffer> = await this.api.get( `/pages/${id}/export/pdf`, { responseType: "arraybuffer", } ); return response.data; } async exportPagePlainText(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/pages/${id}/export/plaintext` ); return response.data; } async exportPageMarkdown(id: number): Promise<string> { const response: AxiosResponse<string> = await this.api.get( `/pages/${id}/export/markdown` ); return response.data; } // ========== SHELVES ========== async getShelves(params?: PaginationParams): Promise<ApiResponse<Shelf[]>> { return this.get<Shelf>("/shelves", params); } async getShelf(id: number): Promise<Shelf> { const response: AxiosResponse<Shelf> = await this.api.get(`/shelves/${id}`); return response.data; } async createShelf(data: CreateShelfRequest): Promise<Shelf> { return this.post<Shelf>("/shelves", data); } async updateShelf( id: number, data: Partial<CreateShelfRequest> ): Promise<Shelf> { return this.put<Shelf>(`/shelves/${id}`, data); } async deleteShelf(id: number): Promise<void> { return this.delete(`/shelves/${id}`); } // ========== USERS ========== async getUsers(params?: PaginationParams): Promise<ApiResponse<User[]>> { return this.get<User>("/users", params); } async getUser(id: number): Promise<User> { const response: AxiosResponse<User> = await this.api.get(`/users/${id}`); return response.data; } async createUser(data: CreateUserRequest): Promise<User> { return this.post<User>("/users", data); } async updateUser( id: number, data: Partial<CreateUserRequest> ): Promise<User> { return this.put<User>(`/users/${id}`, data); } async deleteUser(id: number, migrateOwnershipId?: number): Promise<void> { const data = migrateOwnershipId ? { migrate_ownership_id: migrateOwnershipId } : undefined; await this.api.delete(`/users/${id}`, { data }); } // ========== ROLES ========== async getRoles(params?: PaginationParams): Promise<ApiResponse<Role[]>> { return this.get<Role>("/roles", params); } async getRole(id: number): Promise<Role> { const response: AxiosResponse<Role> = await this.api.get(`/roles/${id}`); return response.data; } async createRole(data: CreateRoleRequest): Promise<Role> { return this.post<Role>("/roles", data); } async updateRole( id: number, data: Partial<CreateRoleRequest> ): Promise<Role> { return this.put<Role>(`/roles/${id}`, data); } async deleteRole(id: number): Promise<void> { return this.delete(`/roles/${id}`); } // ========== ATTACHMENTS ========== async getAttachments( params?: PaginationParams ): Promise<ApiResponse<Attachment[]>> { return this.get<Attachment>("/attachments", params); } async getAttachment(id: number): Promise<Attachment> { const response: AxiosResponse<Attachment> = await this.api.get( `/attachments/${id}` ); return response.data; } async createAttachment(data: CreateAttachmentRequest): Promise<Attachment> { return this.post<Attachment>("/attachments", data); } async updateAttachment( id: number, data: Partial<CreateAttachmentRequest> ): Promise<Attachment> { return this.put<Attachment>(`/attachments/${id}`, data); } async deleteAttachment(id: number): Promise<void> { return this.delete(`/attachments/${id}`); } // ========== IMAGE GALLERY ========== async getImageGallery( params?: PaginationParams ): Promise<ApiResponse<ImageGallery[]>> { return this.get<ImageGallery>("/image-gallery", params); } async getImage(id: number): Promise<ImageGallery> { const response: AxiosResponse<ImageGallery> = await this.api.get( `/image-gallery/${id}` ); return response.data; } async createImage( data: CreateImageRequest, imageFile?: Buffer, filename?: string ): Promise<ImageGallery> { if (imageFile && filename) { const formData = new FormData(); formData.append("type", data.type); formData.append("uploaded_to", data.uploaded_to.toString()); if (data.name) formData.append("name", data.name); formData.append("image", imageFile, filename); return this.postMultipart<ImageGallery>("/image-gallery", formData); } else { return this.post<ImageGallery>("/image-gallery", data); } } async updateImage( id: number, data: { name?: string }, imageFile?: Buffer, filename?: string ): Promise<ImageGallery> { if (imageFile && filename) { const formData = new FormData(); if (data.name) formData.append("name", data.name); formData.append("image", imageFile, filename); return this.postMultipart<ImageGallery>(`/image-gallery/${id}`, formData); } else { return this.put<ImageGallery>(`/image-gallery/${id}`, data); } } async deleteImage(id: number): Promise<void> { return this.delete(`/image-gallery/${id}`); } // ========== SEARCH ========== async search( query: string, params?: { page?: number; count?: number } ): Promise<ApiResponse<SearchResult[]>> { const searchParams = { query, ...params }; const response: AxiosResponse<ApiResponse<SearchResult[]>> = await this.api.get("/search", { params: searchParams }); return response.data; } // ========== CONTENT PERMISSIONS ========== async getContentPermissions( contentType: string, contentId: number ): Promise<ContentPermissions> { const response: AxiosResponse<ContentPermissions> = await this.api.get( `/content-permissions/${contentType}/${contentId}` ); return response.data; } async updateContentPermissions( contentType: string, contentId: number, permissions: Partial<ContentPermissions> ): Promise<ContentPermissions> { return this.put<ContentPermissions>( `/content-permissions/${contentType}/${contentId}`, permissions ); } // ========== AUDIT LOG ========== async getAuditLog( params?: PaginationParams ): Promise<ApiResponse<AuditLogEntry[]>> { return this.get<AuditLogEntry>("/audit-log", params); } // ========== RECYCLE BIN ========== async getRecycleBin( params?: PaginationParams ): Promise<ApiResponse<RecycleBinItem[]>> { return this.get<RecycleBinItem>("/recycle-bin", params); } async restoreFromRecycleBin( deletionId: number ): Promise<{ restore_count: number }> { return this.put<{ restore_count: number }>(`/recycle-bin/${deletionId}`); } async permanentlyDelete( deletionId: number ): Promise<{ delete_count: number }> { const response: AxiosResponse<{ delete_count: number }> = await this.api.delete(`/recycle-bin/${deletionId}`); return response.data; } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lautarobarba/bookstack_mcp_server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server