BREAKING CHANGE(classes.ghost): Remove Settings and Webhooks browse/read APIs, remove noisy console.error logs, and update tests/docs

This commit is contained in:
2025-10-08 09:14:45 +00:00
parent 7251e90395
commit b3f08fb64c
11 changed files with 24 additions and 244 deletions

View File

@@ -1,5 +1,14 @@
# Changelog # Changelog
## 2025-10-08 - 2.0.0 - BREAKING CHANGE(classes.ghost)
Remove Settings and Webhooks browse/read APIs, remove noisy console.error logs, and update tests/docs
- Removed Settings API methods from Ghost: getSettings and updateSettings (breaking change).
- Removed Webhooks browsing/reading methods from Ghost: getWebhooks and getWebhookById. createWebhook, updateWebhook and deleteWebhook remain.
- Removed test/test.settings.node.ts and simplified test/test.webhook.node.ts to only exercise create/update/delete webhook flows without feature-availability guarding.
- Stripped console.error debug logging across multiple classes (Author, Ghost, Member, Page, Post, Tag) to reduce noisy runtime output.
- Updated README: removed 'Site Settings' section and clarified webhook API limitations supported by the underlying Ghost Admin SDK.
## 2025-10-07 - 1.4.1 - fix(tests) ## 2025-10-07 - 1.4.1 - fix(tests)
Remove updated_at from post and page update test payloads Remove updated_at from post and page update test payloads

View File

@@ -404,42 +404,11 @@ await newMember.update({
await newMember.delete(); await newMember.delete();
``` ```
#### Site Settings
Read and update Ghost site settings.
```typescript
// Get all settings
const settings = await ghostInstance.getSettings();
console.log(settings);
// Update settings
await ghostInstance.updateSettings([
{
key: 'title',
value: 'My Updated Site Title'
},
{
key: 'description',
value: 'My site description'
}
]);
```
#### Webhooks Management #### Webhooks Management
Manage webhooks for Ghost events. Manage webhooks for Ghost events. Note: The Ghost Admin API only supports creating, updating, and deleting webhooks (browsing and reading individual webhooks are not supported by the underlying SDK).
```typescript ```typescript
// Get all webhooks
const webhooks = await ghostInstance.getWebhooks();
webhooks.forEach(webhook => {
console.log(`${webhook.name}: ${webhook.target_url}`);
});
// Get webhook by ID
const webhook = await ghostInstance.getWebhookById('webhook-id');
// Create a webhook // Create a webhook
const newWebhook = await ghostInstance.createWebhook({ const newWebhook = await ghostInstance.createWebhook({
event: 'post.published', event: 'post.published',

View File

@@ -1,62 +0,0 @@
import { expect, tap } from '@push.rocks/tapbundle';
import * as qenv from '@push.rocks/qenv';
const testQenv = new qenv.Qenv('./', './.nogit/');
import * as ghost from '../ts/index.js';
let testGhostInstance: ghost.Ghost;
tap.test('initialize Ghost instance', async () => {
testGhostInstance = new ghost.Ghost({
baseUrl: 'http://localhost:2368',
adminApiKey: await testQenv.getEnvVarOnDemand('ADMIN_APIKEY'),
contentApiKey: await testQenv.getEnvVarOnDemand('CONTENT_APIKEY'),
});
expect(testGhostInstance).toBeInstanceOf(ghost.Ghost);
});
tap.test('should get settings', async () => {
try {
const settings = await testGhostInstance.getSettings();
expect(settings).toBeTruthy();
console.log(`Retrieved ${settings.settings?.length || 0} settings`);
if (settings.settings && settings.settings.length > 0) {
console.log(`Sample setting: ${settings.settings[0].key}`);
}
} catch (error: any) {
if (error.message?.includes('undefined') || error.statusCode === 403) {
console.log('Settings API not available in this Ghost version - skipping test');
} else {
throw error;
}
}
});
tap.test('should update settings', async () => {
try {
const settings = await testGhostInstance.getSettings();
if (settings.settings && settings.settings.length > 0) {
const titleSetting = settings.settings.find((s: any) => s.key === 'title');
if (titleSetting) {
const originalTitle = titleSetting.value;
const updated = await testGhostInstance.updateSettings([
{
key: 'title',
value: originalTitle
}
]);
expect(updated).toBeTruthy();
console.log('Settings updated successfully');
}
}
} catch (error: any) {
if (error.message?.includes('undefined') || error.statusCode === 403) {
console.log('Settings API not available - skipping test');
} else {
throw error;
}
}
});
export default tap.start();

View File

@@ -16,25 +16,7 @@ tap.test('initialize Ghost instance', async () => {
expect(testGhostInstance).toBeInstanceOf(ghost.Ghost); expect(testGhostInstance).toBeInstanceOf(ghost.Ghost);
}); });
tap.test('should get all webhooks', async () => {
try {
const webhooks = await testGhostInstance.getWebhooks();
expect(webhooks).toBeArray();
console.log(`Found ${webhooks.length} webhooks`);
if (webhooks.length > 0) {
console.log(`First webhook: ${webhooks[0].name || 'unnamed'}`);
}
} catch (error: any) {
if (error.message?.includes('not a function') || error.statusCode === 403) {
console.log('Webhooks API not available in this Ghost version - skipping test');
} else {
throw error;
}
}
});
tap.test('should create webhook', async () => { tap.test('should create webhook', async () => {
try {
const timestamp = Date.now(); const timestamp = Date.now();
createdWebhook = await testGhostInstance.createWebhook({ createdWebhook = await testGhostInstance.createWebhook({
event: 'post.published', event: 'post.published',
@@ -43,64 +25,17 @@ tap.test('should create webhook', async () => {
}); });
expect(createdWebhook).toBeTruthy(); expect(createdWebhook).toBeTruthy();
expect(createdWebhook.id).toBeTruthy(); expect(createdWebhook.id).toBeTruthy();
console.log(`Created webhook: ${createdWebhook.id}`);
} catch (error: any) {
if (error.message?.includes('not a function') || error.statusCode === 403) {
console.log('Webhooks API not available - skipping test');
} else {
throw error;
}
}
});
tap.test('should get webhook by ID', async () => {
if (createdWebhook) {
try {
const webhook = await testGhostInstance.getWebhookById(createdWebhook.id);
expect(webhook).toBeTruthy();
expect(webhook.id).toEqual(createdWebhook.id);
console.log(`Got webhook by ID: ${webhook.id}`);
} catch (error: any) {
if (error.message?.includes('not a function') || error.statusCode === 403) {
console.log('Webhooks API not available - skipping test');
} else {
throw error;
}
}
}
}); });
tap.test('should update webhook', async () => { tap.test('should update webhook', async () => {
if (createdWebhook) {
try {
const updatedWebhook = await testGhostInstance.updateWebhook(createdWebhook.id, { const updatedWebhook = await testGhostInstance.updateWebhook(createdWebhook.id, {
target_url: 'https://example.com/webhook/updated' target_url: 'https://example.com/webhook/updated'
}); });
expect(updatedWebhook).toBeTruthy(); expect(updatedWebhook).toBeTruthy();
console.log(`Updated webhook: ${updatedWebhook.id}`);
} catch (error: any) {
if (error.message?.includes('not a function') || error.statusCode === 403) {
console.log('Webhooks API not available - skipping test');
} else {
throw error;
}
}
}
}); });
tap.test('should delete webhook', async () => { tap.test('should delete webhook', async () => {
if (createdWebhook) {
try {
await testGhostInstance.deleteWebhook(createdWebhook.id); await testGhostInstance.deleteWebhook(createdWebhook.id);
console.log(`Deleted webhook: ${createdWebhook.id}`);
} catch (error: any) {
if (error.message?.includes('not a function') || error.statusCode === 403) {
console.log('Webhooks API not available - skipping test');
} else {
throw error;
}
}
}
}); });
export default tap.start(); export default tap.start();

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@apiclient.xyz/ghost', name: '@apiclient.xyz/ghost',
version: '1.4.1', version: '2.0.0',
description: 'An unofficial Ghost CMS API package enabling content and admin functionality for managing posts.' description: 'An unofficial Ghost CMS API package enabling content and admin functionality for managing posts.'
} }

View File

@@ -43,7 +43,6 @@ export class Author {
this.authorData = updatedAuthorData; this.authorData = updatedAuthorData;
return this; return this;
} catch (error) { } catch (error) {
console.error('Error updating author:', error);
throw error; throw error;
} }
} }

View File

@@ -65,7 +65,6 @@ export class Ghost {
}); });
return postsData.map((postData: IPost) => new Post(this, postData)); return postsData.map((postData: IPost) => new Post(this, postData));
} catch (error) { } catch (error) {
console.error('Error fetching posts:', error);
throw error; throw error;
} }
} }
@@ -75,7 +74,6 @@ export class Ghost {
const postData = await this.contentApi.posts.read({ id }); const postData = await this.contentApi.posts.read({ id });
return new Post(this, postData); return new Post(this, postData);
} catch (error) { } catch (error) {
console.error(`Error fetching post with id ${id}:`, error);
throw error; throw error;
} }
} }
@@ -85,7 +83,6 @@ export class Ghost {
const createdPostData = await this.adminApi.posts.add(postData); const createdPostData = await this.adminApi.posts.add(postData);
return new Post(this, createdPostData); return new Post(this, createdPostData);
} catch (error) { } catch (error) {
console.error('Error creating post:', error);
throw error; throw error;
} }
} }
@@ -110,7 +107,6 @@ export class Ghost {
return tagsData; return tagsData;
} catch (error) { } catch (error) {
console.error('Error fetching tags:', error);
throw error; throw error;
} }
} }
@@ -120,7 +116,6 @@ export class Ghost {
const tagData = await this.contentApi.tags.read({ id }); const tagData = await this.contentApi.tags.read({ id });
return new Tag(this, tagData); return new Tag(this, tagData);
} catch (error) { } catch (error) {
console.error(`Error fetching tag with id ${id}:`, error);
throw error; throw error;
} }
} }
@@ -130,7 +125,6 @@ export class Ghost {
const tagData = await this.contentApi.tags.read({ slug }); const tagData = await this.contentApi.tags.read({ slug });
return new Tag(this, tagData); return new Tag(this, tagData);
} catch (error) { } catch (error) {
console.error(`Error fetching tag with slug ${slug}:`, error);
throw error; throw error;
} }
} }
@@ -140,7 +134,6 @@ export class Ghost {
const createdTagData = await this.adminApi.tags.add(tagData); const createdTagData = await this.adminApi.tags.add(tagData);
return new Tag(this, createdTagData); return new Tag(this, createdTagData);
} catch (error) { } catch (error) {
console.error('Error creating tag:', error);
throw error; throw error;
} }
} }
@@ -159,7 +152,6 @@ export class Ghost {
return authorsData.map((author: IAuthor) => new Author(this, author)); return authorsData.map((author: IAuthor) => new Author(this, author));
} catch (error) { } catch (error) {
console.error('Error fetching authors:', error);
throw error; throw error;
} }
} }
@@ -169,7 +161,6 @@ export class Ghost {
const authorData = await this.contentApi.authors.read({ id }); const authorData = await this.contentApi.authors.read({ id });
return new Author(this, authorData); return new Author(this, authorData);
} catch (error) { } catch (error) {
console.error(`Error fetching author with id ${id}:`, error);
throw error; throw error;
} }
} }
@@ -179,7 +170,6 @@ export class Ghost {
const authorData = await this.contentApi.authors.read({ slug }); const authorData = await this.contentApi.authors.read({ slug });
return new Author(this, authorData); return new Author(this, authorData);
} catch (error) { } catch (error) {
console.error(`Error fetching author with slug ${slug}:`, error);
throw error; throw error;
} }
} }
@@ -198,7 +188,6 @@ export class Ghost {
return pagesData.map((pageData: IPage) => new Page(this, pageData)); return pagesData.map((pageData: IPage) => new Page(this, pageData));
} catch (error) { } catch (error) {
console.error('Error fetching pages:', error);
throw error; throw error;
} }
} }
@@ -208,7 +197,6 @@ export class Ghost {
const pageData = await this.contentApi.pages.read({ id }); const pageData = await this.contentApi.pages.read({ id });
return new Page(this, pageData); return new Page(this, pageData);
} catch (error) { } catch (error) {
console.error(`Error fetching page with id ${id}:`, error);
throw error; throw error;
} }
} }
@@ -218,7 +206,6 @@ export class Ghost {
const pageData = await this.contentApi.pages.read({ slug }); const pageData = await this.contentApi.pages.read({ slug });
return new Page(this, pageData); return new Page(this, pageData);
} catch (error) { } catch (error) {
console.error(`Error fetching page with slug ${slug}:`, error);
throw error; throw error;
} }
} }
@@ -228,7 +215,6 @@ export class Ghost {
const createdPageData = await this.adminApi.pages.add(pageData); const createdPageData = await this.adminApi.pages.add(pageData);
return new Page(this, createdPageData); return new Page(this, createdPageData);
} catch (error) { } catch (error) {
console.error('Error creating page:', error);
throw error; throw error;
} }
} }
@@ -243,7 +229,6 @@ export class Ghost {
}); });
return postsData.map((postData: IPost) => new Post(this, postData)); return postsData.map((postData: IPost) => new Post(this, postData));
} catch (error) { } catch (error) {
console.error('Error searching posts:', error);
throw error; throw error;
} }
} }
@@ -253,7 +238,6 @@ export class Ghost {
const result = await this.adminApi.images.upload({ file: filePath }); const result = await this.adminApi.images.upload({ file: filePath });
return result.url; return result.url;
} catch (error) { } catch (error) {
console.error('Error uploading image:', error);
throw error; throw error;
} }
} }
@@ -266,7 +250,6 @@ export class Ghost {
}); });
return await Promise.all(updatePromises); return await Promise.all(updatePromises);
} catch (error) { } catch (error) {
console.error('Error bulk updating posts:', error);
throw error; throw error;
} }
} }
@@ -279,7 +262,6 @@ export class Ghost {
}); });
await Promise.all(deletePromises); await Promise.all(deletePromises);
} catch (error) { } catch (error) {
console.error('Error bulk deleting posts:', error);
throw error; throw error;
} }
} }
@@ -302,7 +284,6 @@ export class Ghost {
return postsData.map((postData: IPost) => new Post(this, postData)); return postsData.map((postData: IPost) => new Post(this, postData));
} catch (error) { } catch (error) {
console.error('Error fetching related posts:', error);
throw error; throw error;
} }
} }
@@ -321,7 +302,6 @@ export class Ghost {
return membersData.map((member: IMember) => new Member(this, member)); return membersData.map((member: IMember) => new Member(this, member));
} catch (error) { } catch (error) {
console.error('Error fetching members:', error);
throw error; throw error;
} }
} }
@@ -331,7 +311,6 @@ export class Ghost {
const memberData = await this.adminApi.members.read({ id }); const memberData = await this.adminApi.members.read({ id });
return new Member(this, memberData); return new Member(this, memberData);
} catch (error) { } catch (error) {
console.error(`Error fetching member with id ${id}:`, error);
throw error; throw error;
} }
} }
@@ -341,7 +320,6 @@ export class Ghost {
const memberData = await this.adminApi.members.read({ email }); const memberData = await this.adminApi.members.read({ email });
return new Member(this, memberData); return new Member(this, memberData);
} catch (error) { } catch (error) {
console.error(`Error fetching member with email ${email}:`, error);
throw error; throw error;
} }
} }
@@ -351,43 +329,6 @@ export class Ghost {
const createdMemberData = await this.adminApi.members.add(memberData); const createdMemberData = await this.adminApi.members.add(memberData);
return new Member(this, createdMemberData); return new Member(this, createdMemberData);
} catch (error) { } catch (error) {
console.error('Error creating member:', error);
throw error;
}
}
public async getSettings(): Promise<any> {
try {
return await this.adminApi.settings.browse();
} catch (error) {
console.error('Error fetching settings:', error);
throw error;
}
}
public async updateSettings(settings: any[]): Promise<any> {
try {
return await this.adminApi.settings.edit(settings);
} catch (error) {
console.error('Error updating settings:', error);
throw error;
}
}
public async getWebhooks(): Promise<any[]> {
try {
return await this.adminApi.webhooks.browse();
} catch (error) {
console.error('Error fetching webhooks:', error);
throw error;
}
}
public async getWebhookById(id: string): Promise<any> {
try {
return await this.adminApi.webhooks.read({ id });
} catch (error) {
console.error(`Error fetching webhook with id ${id}:`, error);
throw error; throw error;
} }
} }
@@ -403,7 +344,6 @@ export class Ghost {
try { try {
return await this.adminApi.webhooks.add(webhookData); return await this.adminApi.webhooks.add(webhookData);
} catch (error) { } catch (error) {
console.error('Error creating webhook:', error);
throw error; throw error;
} }
} }
@@ -412,7 +352,6 @@ export class Ghost {
try { try {
return await this.adminApi.webhooks.edit({ ...webhookData, id }); return await this.adminApi.webhooks.edit({ ...webhookData, id });
} catch (error) { } catch (error) {
console.error('Error updating webhook:', error);
throw error; throw error;
} }
} }
@@ -421,7 +360,6 @@ export class Ghost {
try { try {
await this.adminApi.webhooks.delete({ id }); await this.adminApi.webhooks.delete({ id });
} catch (error) { } catch (error) {
console.error(`Error deleting webhook with id ${id}:`, error);
throw error; throw error;
} }
} }

View File

@@ -71,7 +71,6 @@ export class Member {
this.memberData = updatedMemberData; this.memberData = updatedMemberData;
return this; return this;
} catch (error) { } catch (error) {
console.error('Error updating member:', error);
throw error; throw error;
} }
} }
@@ -80,7 +79,6 @@ export class Member {
try { try {
await this.ghostInstanceRef.adminApi.members.delete({ id: this.getId() }); await this.ghostInstanceRef.adminApi.members.delete({ id: this.getId() });
} catch (error) { } catch (error) {
console.error(`Error deleting member with id ${this.getId()}:`, error);
throw error; throw error;
} }
} }

View File

@@ -49,7 +49,6 @@ export class Page {
this.pageData = updatedPageData; this.pageData = updatedPageData;
return this; return this;
} catch (error) { } catch (error) {
console.error('Error updating page:', error);
throw error; throw error;
} }
} }
@@ -58,7 +57,6 @@ export class Page {
try { try {
await this.ghostInstanceRef.adminApi.pages.delete({ id: this.getId() }); await this.ghostInstanceRef.adminApi.pages.delete({ id: this.getId() });
} catch (error) { } catch (error) {
console.error(`Error deleting page with id ${this.getId()}:`, error);
throw error; throw error;
} }
} }

View File

@@ -124,7 +124,6 @@ export class Post {
this.postData = updatedPostData; this.postData = updatedPostData;
return this; return this;
} catch (error) { } catch (error) {
console.error('Error updating post:', error);
throw error; throw error;
} }
} }
@@ -133,7 +132,6 @@ export class Post {
try { try {
await this.ghostInstanceRef.adminApi.posts.delete({ id: this.getId() }); await this.ghostInstanceRef.adminApi.posts.delete({ id: this.getId() });
} catch (error) { } catch (error) {
console.error(`Error deleting post with id ${this.getId()}:`, error);
throw error; throw error;
} }
} }

View File

@@ -39,7 +39,6 @@ export class Tag {
this.tagData = updatedTagData; this.tagData = updatedTagData;
return this; return this;
} catch (error) { } catch (error) {
console.error('Error updating tag:', error);
throw error; throw error;
} }
} }
@@ -48,7 +47,6 @@ export class Tag {
try { try {
await this.ghostInstanceRef.adminApi.tags.delete({ id: this.getId() }); await this.ghostInstanceRef.adminApi.tags.delete({ id: this.getId() });
} catch (error) { } catch (error) {
console.error(`Error deleting tag with id ${this.getId()}:`, error);
throw error; throw error;
} }
} }