diff --git a/changelog.md b/changelog.md index d366194..39b09c8 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2024-07-06 - 1.1.0 - feat(core) +Enhanced post fetching and creation with additional metadata and support for HTML source + +- Added support for fetching posts with included tags and authors. +- Implemented helper method to create posts directly from HTML content. +- Enhanced Post class to include additional metadata such as visibility, created_at, updated_at, published_at, etc. +- Modified getPosts method in Ghost class to include tags and authors in the response. + ## 2024-07-01 - 1.0.3 - fix(docs) Updated the project keywords and readme content for better clarity and SEO diff --git a/test/test.ts b/test/test.ts index cb96f12..9ef2e16 100644 --- a/test/test.ts +++ b/test/test.ts @@ -19,7 +19,15 @@ tap.test('should get posts', async () => { const posts = await testGhostInstance.getPosts(); expect(posts).toBeArray(); expect(posts[0]).toBeInstanceOf(ghost.Post); - console.log(posts.map((post) => post.getTitle())); + console.log(JSON.stringify(posts[0].postData, null, 2)); + posts.map((post) => { + // console.log(JSON.stringify(post.postData, null, 2)); + console.log(`-> ${post.getTitle()}`); + console.log(`by ${post.getAuthor().name}`) + console.log(post.getExcerpt()); + console.log(`===============`) + }) + }) tap.start() diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index bfaaf43..eea6a32 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@apiclient.xyz/ghost', - version: '1.0.3', + version: '1.1.0', description: 'An unofficial Ghost CMS API package enabling content and admin functionality for managing posts.' } diff --git a/ts/classes.ghost.ts b/ts/classes.ghost.ts index ca2197b..0efe02e 100644 --- a/ts/classes.ghost.ts +++ b/ts/classes.ghost.ts @@ -18,19 +18,19 @@ export class Ghost { this.adminApi = new plugins.GhostAdminAPI({ url: this.options.baseUrl, key: this.options.adminApiKey, - version: "v3" + version: 'v3', }); this.contentApi = new plugins.GhostContentAPI({ url: this.options.baseUrl, key: this.options.contentApiKey, - version: "v3" + version: 'v3', }); } public async getPosts(limit: number = 1000): Promise { try { - const postsData = await this.contentApi.posts.browse({ limit }); + const postsData = await this.contentApi.posts.browse({ limit, include: 'tags,authors' }); return postsData.map((postData: IPostOptions) => new Post(this, postData)); } catch (error) { console.error('Error fetching posts:', error); @@ -57,4 +57,12 @@ export class Ghost { throw error; } } + + public async createPostFromHtml(optionsArg: { title: string; html: string }) { + const postData = await this.adminApi.posts.add( + { title: optionsArg.title, html: optionsArg.html }, + { source: 'html' } // Tell the API to use HTML as the content source, instead of Lexical + ); + return new Post(this, postData); + } } diff --git a/ts/classes.post.ts b/ts/classes.post.ts index f6679bd..04dc0fb 100644 --- a/ts/classes.post.ts +++ b/ts/classes.post.ts @@ -1,18 +1,89 @@ import type { Ghost } from './classes.ghost.js'; import * as plugins from './ghost.plugins.js'; +export interface IAuthor { + id: string; + name: string; + slug: string; + profile_image?: string; + cover_image?: string; + bio?: string; + website?: string; + location?: string; + facebook?: string; + twitter?: string; + meta_title?: string; + meta_description?: string; + url: string; +} + +export interface ITag { + id: string; + name: string; + slug: string; + description?: string; + feature_image?: string; + visibility: string; + og_image?: string; + og_title?: string; + og_description?: string; + twitter_image?: string; + twitter_title?: string; + twitter_description?: string; + meta_title?: string; + meta_description?: string; + codeinjection_head?: string; + codeinjection_foot?: string; + canonical_url?: string; + accent_color?: string; + url: string; +} + export interface IPostOptions { id: string; + uuid: string; title: string; + slug: string; html: string; - excerpt?: string; + comment_id: string; feature_image?: string; + featured: boolean; + visibility: string; + created_at: string; + updated_at: string; + published_at: string; + custom_excerpt?: string; + codeinjection_head?: string | null; + codeinjection_foot?: string | null; + custom_template?: string | null; + canonical_url?: string | null; + url: string; + excerpt?: string; + reading_time: number; + access: boolean; + comments: boolean; + og_image?: string | null; + og_title?: string | null; + og_description?: string | null; + twitter_image?: string | null; + twitter_title?: string | null; + twitter_description?: string | null; + meta_title?: string | null; + meta_description?: string | null; + email_subject?: string | null; + frontmatter?: string | null; + feature_image_alt?: string | null; + feature_image_caption?: string | null; + authors: IAuthor[]; + tags: ITag[]; + primary_author: IAuthor; + primary_tag: ITag; [key: string]: any; // To allow for additional properties } export class Post { public ghostInstanceRef: Ghost; - private postData: IPostOptions; + public postData: IPostOptions; constructor(ghostInstanceRefArg: Ghost, postData: IPostOptions) { this.ghostInstanceRef = ghostInstanceRefArg; @@ -39,6 +110,10 @@ export class Post { return this.postData.feature_image; } + public getAuthor(): IAuthor { + return this.postData.primary_author; + } + public toJson(): IPostOptions { return this.postData; }