Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
a0ffc7c4d7 | |||
d82c58e608 | |||
5d3cfe2f93 | |||
8de7fc795e |
14
changelog.md
14
changelog.md
@ -1,5 +1,19 @@
|
||||
# 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
|
||||
|
||||
- Improved the project description in `package.json` and `npmextra.json`.
|
||||
- Added comprehensive usage instructions and examples in `readme.md`.
|
||||
|
||||
## 2024-07-01 - 1.0.2 - fix(core)
|
||||
No changes in the project files
|
||||
|
||||
|
@ -5,10 +5,20 @@
|
||||
"githost": "code.foss.global",
|
||||
"gitscope": "apiclient.xyz",
|
||||
"gitrepo": "ghost",
|
||||
"description": "an unofficial ghost api package",
|
||||
"description": "An unofficial Ghost CMS API package enabling content and admin functionality for managing posts.",
|
||||
"npmPackagename": "@apiclient.xyz/ghost",
|
||||
"license": "MIT",
|
||||
"projectDomain": "apiclient.xyz"
|
||||
"projectDomain": "apiclient.xyz",
|
||||
"keywords": [
|
||||
"Ghost CMS",
|
||||
"API client",
|
||||
"content management",
|
||||
"admin API",
|
||||
"content API",
|
||||
"TypeScript",
|
||||
"post management",
|
||||
"blog management"
|
||||
]
|
||||
}
|
||||
},
|
||||
"npmci": {
|
||||
|
14
package.json
14
package.json
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@apiclient.xyz/ghost",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.0",
|
||||
"private": false,
|
||||
"description": "an unofficial ghost api package",
|
||||
"description": "An unofficial Ghost CMS API package enabling content and admin functionality for managing posts.",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
"type": "module",
|
||||
@ -48,5 +48,15 @@
|
||||
"cli.js",
|
||||
"npmextra.json",
|
||||
"readme.md"
|
||||
],
|
||||
"keywords": [
|
||||
"Ghost CMS",
|
||||
"API client",
|
||||
"content management",
|
||||
"admin API",
|
||||
"content API",
|
||||
"TypeScript",
|
||||
"post management",
|
||||
"blog management"
|
||||
]
|
||||
}
|
||||
|
279
readme.md
279
readme.md
@ -1,31 +1,262 @@
|
||||
# @apiclient.xyz/ghost
|
||||
an unofficial ghost api package
|
||||
An unofficial Ghost API package
|
||||
|
||||
## Availabililty and Links
|
||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@apiclient.xyz/ghost)
|
||||
* [gitlab.com (source)](https://code.foss.global/apiclient.xyz/ghost)
|
||||
* [github.com (source mirror)](https://github.com/apiclient.xyz/ghost)
|
||||
* [docs (typedoc)](https://apiclient.xyz.gitlab.io/ghost/)
|
||||
## Install
|
||||
To install the @apiclient.xyz/ghost package, you can use npm or yarn. Make sure you're using a package manager that supports ESM and TypeScript.
|
||||
|
||||
## Status for master
|
||||
NPM:
|
||||
```bash
|
||||
npm install @apiclient.xyz/ghost
|
||||
```
|
||||
|
||||
Status Category | Status Badge
|
||||
-- | --
|
||||
GitLab Pipelines | [](https://lossless.cloud)
|
||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
||||
npm | [](https://lossless.cloud)
|
||||
Snyk | [](https://lossless.cloud)
|
||||
TypeScript Support | [](https://lossless.cloud)
|
||||
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
Code Style | [](https://lossless.cloud)
|
||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
||||
Yarn:
|
||||
```bash
|
||||
yarn add @apiclient.xyz/ghost
|
||||
```
|
||||
|
||||
## Usage
|
||||
Use TypeScript for best in class intellisense
|
||||
For further information read the linked docs at the top of this readme.
|
||||
|
||||
## Legal
|
||||
> MIT licensed | **©** [Task Venture Capital GmbH](https://task.vc)
|
||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
||||
Below is a detailed guide on how to use the `@apiclient.xyz/ghost` package in your TypeScript projects. We will cover everything from initialization to advanced usage scenarios.
|
||||
|
||||
### Initialization
|
||||
|
||||
First, you need to import the necessary classes and initialize the Ghost instance with the required API keys.
|
||||
|
||||
```typescript
|
||||
import { Ghost } from '@apiclient.xyz/ghost';
|
||||
|
||||
// Initialize the Ghost instance
|
||||
const ghostInstance = new Ghost({
|
||||
baseUrl: 'https://your-ghost-url.com',
|
||||
contentApiKey: 'your-content-api-key',
|
||||
adminApiKey: 'your-admin-api-key'
|
||||
});
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
#### Fetching Posts
|
||||
|
||||
You can fetch posts with the following method. This will give you an array of `Post` instances.
|
||||
|
||||
```typescript
|
||||
// Fetch all posts
|
||||
const posts = await ghostInstance.getPosts();
|
||||
|
||||
// Print titles of all posts
|
||||
posts.forEach(post => {
|
||||
console.log(post.getTitle());
|
||||
});
|
||||
```
|
||||
|
||||
#### Fetching a Single Post by ID
|
||||
|
||||
To fetch a single post by its ID:
|
||||
|
||||
```typescript
|
||||
const postId = 'your-post-id';
|
||||
const post = await ghostInstance.getPostById(postId);
|
||||
|
||||
console.log(post.getTitle());
|
||||
console.log(post.getHtml());
|
||||
```
|
||||
|
||||
### Post Class Methods
|
||||
|
||||
The `Post` class has several methods that can be useful for different scenarios.
|
||||
|
||||
#### Getting Post Data
|
||||
|
||||
These methods allow you to retrieve various parts of the post data.
|
||||
|
||||
```typescript
|
||||
const postId = post.getId();
|
||||
const postTitle = post.getTitle();
|
||||
const postHtml = post.getHtml();
|
||||
const postExcerpt = post.getExcerpt();
|
||||
const postFeatureImage = post.getFeatureImage();
|
||||
|
||||
console.log(`ID: ${postId}`);
|
||||
console.log(`Title: ${postTitle}`);
|
||||
console.log(`HTML: ${postHtml}`);
|
||||
console.log(`Excerpt: ${postExcerpt}`);
|
||||
console.log(`Feature Image: ${postFeatureImage}`);
|
||||
```
|
||||
|
||||
#### Updating a Post
|
||||
|
||||
To update a post, you can use the `update` method. Make sure you have the necessary permissions and fields.
|
||||
|
||||
```typescript
|
||||
const updatedPostData = {
|
||||
...post.toJson(),
|
||||
title: 'Updated Title',
|
||||
html: '<p>Updated HTML content</p>'
|
||||
};
|
||||
|
||||
await post.update(updatedPostData);
|
||||
console.log('Post updated successfully');
|
||||
```
|
||||
|
||||
#### Deleting a Post
|
||||
|
||||
To delete a post:
|
||||
|
||||
```typescript
|
||||
await post.delete();
|
||||
console.log('Post deleted successfully');
|
||||
```
|
||||
|
||||
### Advanced Scenarios
|
||||
|
||||
#### Creating a New Post
|
||||
|
||||
You can create a new post using the `createPost` method of the `Ghost` class.
|
||||
|
||||
```typescript
|
||||
const newPostData = {
|
||||
id: 'new-post-id',
|
||||
title: 'New Post Title',
|
||||
html: '<p>This is the content of the new post.</p>',
|
||||
excerpt: 'New post excerpt',
|
||||
feature_image: 'https://your-image-url.com/image.jpg'
|
||||
};
|
||||
|
||||
const newPost = await ghostInstance.createPost(newPostData);
|
||||
|
||||
console.log('New post created successfully');
|
||||
console.log(`ID: ${newPost.getId()}`);
|
||||
console.log(`Title: ${newPost.getTitle()}`);
|
||||
```
|
||||
|
||||
#### Error Handling
|
||||
|
||||
Both the `Ghost` and `Post` classes throw errors that you can catch and handle.
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const posts = await ghostInstance.getPosts();
|
||||
console.log('Posts fetched successfully');
|
||||
} catch (error) {
|
||||
console.error('Error fetching posts:', error);
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, for updating or deleting a post:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await post.update({ title: 'Updated Title' });
|
||||
console.log('Post updated successfully');
|
||||
} catch (error) {
|
||||
console.error('Error updating post:', error);
|
||||
}
|
||||
|
||||
try {
|
||||
await post.delete();
|
||||
console.log('Post deleted successfully');
|
||||
} catch (error) {
|
||||
console.error('Error deleting post:', error);
|
||||
}
|
||||
```
|
||||
|
||||
#### Fetching Posts with Filters and Options
|
||||
|
||||
The `getPosts` method can accept various filters and options.
|
||||
|
||||
```typescript
|
||||
const filteredPosts = await ghostInstance.getPosts({ limit: 10, include: 'tags,authors' });
|
||||
|
||||
filteredPosts.forEach(post => {
|
||||
console.log(post.getTitle());
|
||||
});
|
||||
```
|
||||
|
||||
### Example Projects
|
||||
|
||||
To give you a comprehensive understanding, let's look at a couple of example projects.
|
||||
|
||||
#### Example 1: A Basic Blog
|
||||
|
||||
In this scenario, we will create a simple script to fetch all posts and display their titles.
|
||||
|
||||
```typescript
|
||||
import { Ghost } from '@apiclient.xyz/ghost';
|
||||
|
||||
(async () => {
|
||||
const ghostInstance = new Ghost({
|
||||
baseUrl: 'https://your-ghost-url.com',
|
||||
contentApiKey: 'your-content-api-key',
|
||||
adminApiKey: 'your-admin-api-key'
|
||||
});
|
||||
|
||||
try {
|
||||
const posts = await ghostInstance.getPosts();
|
||||
posts.forEach(post => console.log(post.getTitle()));
|
||||
} catch (error) {
|
||||
console.error('Error fetching posts:', error);
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
#### Example 2: Post Management Tool
|
||||
|
||||
In this example, let's create a tool that can fetch, create, update, and delete posts.
|
||||
|
||||
```typescript
|
||||
import { Ghost, Post, IPostOptions } from '@apiclient.xyz/ghost';
|
||||
|
||||
const ghostInstance = new Ghost({
|
||||
baseUrl: 'https://your-ghost-url.com',
|
||||
contentApiKey: 'your-content-api-key',
|
||||
adminApiKey: 'your-admin-api-key'
|
||||
});
|
||||
|
||||
(async () => {
|
||||
// Fetch posts
|
||||
const posts = await ghostInstance.getPosts();
|
||||
console.log('Fetched posts:');
|
||||
posts.forEach(post => console.log(post.getTitle()));
|
||||
|
||||
// Create a new post
|
||||
const newPostData: IPostOptions = {
|
||||
id: 'new-post-id',
|
||||
title: 'New Post Title',
|
||||
html: '<p>This is the content of the new post.</p>',
|
||||
};
|
||||
|
||||
const newPost = await ghostInstance.createPost(newPostData);
|
||||
console.log('New post created:', newPost.getTitle());
|
||||
|
||||
// Update the new post
|
||||
const updatedPost = await newPost.update({ title: 'Updated Post Title' });
|
||||
console.log('Post updated:', updatedPost.getTitle());
|
||||
|
||||
// Delete the new post
|
||||
await updatedPost.delete();
|
||||
console.log('Post deleted');
|
||||
})();
|
||||
```
|
||||
|
||||
### Unit Tests
|
||||
|
||||
This package includes unit tests written using the `@push.rocks/tapbundle` and `@push.rocks/qenv` libraries. Here is how you can run them.
|
||||
|
||||
1. Install the development dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Run the tests:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
The `@apiclient.xyz/ghost` package provides a comprehensive and type-safe way to interact with the Ghost CMS API using TypeScript. The features provided by the `Ghost` and `Post` classes allow for a wide range of interactions, from basic CRUD operations to advanced filtering and error handling.
|
||||
|
||||
For more information, please refer to the [documentation](https://apiclient.xyz.gitlab.io/ghost/).
|
||||
undefined
|
10
test/test.ts
10
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()
|
||||
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@apiclient.xyz/ghost',
|
||||
version: '1.0.2',
|
||||
description: 'an unofficial ghost api package'
|
||||
version: '1.1.0',
|
||||
description: 'An unofficial Ghost CMS API package enabling content and admin functionality for managing posts.'
|
||||
}
|
||||
|
@ -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<Post[]> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user