@magicpages/ghost-typesense-webhook 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,107 +1,99 @@
1
- # Ghost Typesense Webhook Handler
1
+ # @magicpages/ghost-typesense-webhook
2
2
 
3
- A production-ready Netlify Function that keeps your [Typesense](https://typesense.org/) search index synchronized with your [Ghost](https://ghost.org/) blog content in real-time. This webhook handler automatically processes content updates from Ghost and reflects them in your Typesense search index.
3
+ A Netlify Function that handles Ghost webhooks to keep your Typesense search index in sync with your Ghost content in real-time.
4
4
 
5
- [![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/magicpages/ghost-typesense)
5
+ ## Installation
6
6
 
7
- ## Features
7
+ ```bash
8
+ npm install @magicpages/ghost-typesense-webhook
9
+ ```
8
10
 
9
- The webhook handler provides seamless integration between Ghost and Typesense. It enables real-time content synchronization and automatic handling of post publishing, updates, unpublishing, and deleting. The handler implements type-safe request processing with runtime validation and includes comprehensive error handling and logging capabilities.
11
+ ## Usage with Netlify
10
12
 
11
- ## Deployment
13
+ 1. Install the package in your Netlify project
14
+ 2. Create a `netlify.toml` configuration:
12
15
 
13
- ### Option 1: One-Click Deploy (Recommended)
16
+ ```toml
17
+ [functions]
18
+ directory = "netlify/functions"
19
+ node_bundler = "esbuild"
14
20
 
15
- 1. Click the "Deploy to Netlify" button above
16
- 2. Connect your GitHub account
17
- 3. Configure the required environment variables
18
- 4. Deploy the function
21
+ [functions.ghost-typesense]
22
+ external_node_modules = ["@netlify/functions"]
23
+ ```
19
24
 
20
- ### Option 2: Manual Deployment
25
+ 3. Create the function in your Netlify functions directory:
21
26
 
22
- 1. Clone the repository:
23
- ```bash
24
- git clone https://github.com/magicpages/ghost-typesense.git
25
- cd ghost-typesense
27
+ ```typescript
28
+ // netlify/functions/ghost-typesense.ts
29
+ import { handler } from '@magicpages/ghost-typesense-webhook';
30
+ export { handler };
26
31
  ```
27
32
 
28
- 2. Install dependencies:
29
- ```bash
30
- npm install
31
- ```
33
+ 4. Configure environment variables in your Netlify dashboard:
32
34
 
33
- 3. Build the project:
34
- ```bash
35
- npm run build
35
+ ```env
36
+ GHOST_URL=https://your-ghost-blog.com
37
+ GHOST_ADMIN_API_KEY=your-admin-api-key
38
+ GHOST_WEBHOOK_SECRET=your-webhook-secret
39
+ TYPESENSE_HOST=your-typesense-host
40
+ TYPESENSE_PORT=443
41
+ TYPESENSE_PROTOCOL=https
42
+ TYPESENSE_API_KEY=your-typesense-api-key
43
+ TYPESENSE_COLLECTION_NAME=posts
36
44
  ```
37
45
 
38
- 4. Deploy using the Netlify CLI:
39
- ```bash
40
- netlify deploy --prod
41
- ```
46
+ 5. Configure the webhook in Ghost Admin:
47
+ - Go to Settings > Integrations
48
+ - Create a new Custom Integration
49
+ - Add a webhook with the following settings:
50
+ - Event: Post published/updated/unpublished
51
+ - Target URL: Your Netlify function URL (e.g., `https://your-site.netlify.app/.netlify/functions/ghost-typesense`)
42
52
 
43
- ## Configuration
53
+ ## Environment Variables
44
54
 
45
- ### Environment Variables
55
+ | Variable | Description |
56
+ |----------|-------------|
57
+ | `GHOST_URL` | URL of your Ghost blog |
58
+ | `GHOST_ADMIN_API_KEY` | Ghost Admin API key |
59
+ | `GHOST_WEBHOOK_SECRET` | Secret for validating webhook requests |
60
+ | `TYPESENSE_HOST` | Typesense server host |
61
+ | `TYPESENSE_PORT` | Typesense server port |
62
+ | `TYPESENSE_PROTOCOL` | Typesense server protocol (http/https) |
63
+ | `TYPESENSE_API_KEY` | Typesense API key |
64
+ | `TYPESENSE_COLLECTION_NAME` | Name of the Typesense collection |
46
65
 
47
- Configure the following environment variables in your Netlify dashboard:
66
+ ## Webhook Events
48
67
 
49
- | Variable | Description | Example |
50
- |----------|-------------|---------|
51
- | `GHOST_URL` | Your Ghost blog URL | `https://blog.example.com` |
52
- | `GHOST_CONTENT_API_KEY` | Ghost Content API key | `1234abcd...` |
53
- | `TYPESENSE_HOST` | Typesense server host | `search.example.com` |
54
- | `TYPESENSE_API_KEY` | Typesense API key (full API access, not search-only) | `xyz789...` |
55
- | `COLLECTION_NAME` | Typesense collection name | `posts` |
56
- | `WEBHOOK_SECRET` | A secure random string to validate webhook requests | `your-secret-key` |
68
+ The handler processes the following Ghost webhook events:
57
69
 
58
- ### Ghost Integration Setup
70
+ - `post.published`: Adds or updates the post in Typesense
71
+ - `post.updated`: Updates the post in Typesense
72
+ - `post.unpublished`: Removes the post from Typesense
73
+ - `post.deleted`: Removes the post from Typesense
59
74
 
60
- 1. Access your Ghost Admin panel
61
- 2. Navigate to Settings → Integrations
62
- 3. Click "Add custom integration"
63
- 4. Name your integration (e.g., "Typesense Search")
64
- 5. Copy the Content API Key
65
- 6. Generate a secure random string for your webhook secret:
66
- ```bash
67
- openssl rand -hex 32
68
- ```
69
- 7. Under Webhooks, add the following webhooks:
75
+ ## Security
70
76
 
71
- | Name | Event | Target URL |
72
- |------|--------|------------|
73
- | Post published | Post published | `https://your-netlify-site.netlify.app/.netlify/functions/handler?secret=your-secret-key` |
74
- | Post updated | Post updated | `https://your-netlify-site.netlify.app/.netlify/functions/handler?secret=your-secret-key` |
75
- | Post unpublished | Post unpublished | `https://your-netlify-site.netlify.app/.netlify/functions/handler?secret=your-secret-key` |
76
- | Post deleted | Post deleted | `https://your-netlify-site.netlify.app/.netlify/functions/handler?secret=your-secret-key` |
77
+ The webhook handler validates incoming requests using the `GHOST_WEBHOOK_SECRET`. Make sure to:
77
78
 
78
- Make sure to replace `your-secret-key` with the same secure random string you set in your Netlify environment variables.
79
+ 1. Generate a secure random string for your webhook secret
80
+ 2. Configure the same secret in both Ghost and your environment variables
81
+ 3. Keep your secret secure and never commit it to version control
79
82
 
80
- ## Local Development
83
+ ## Error Handling
81
84
 
82
- 1. Install dependencies:
83
- ```bash
84
- npm install
85
- ```
85
+ The handler includes comprehensive error handling:
86
86
 
87
- 2. Create a `.env` file with your configuration:
88
- ```env
89
- GHOST_URL=https://your-blog.ghost.io
90
- GHOST_CONTENT_API_KEY=your_content_api_key
91
- TYPESENSE_HOST=your_typesense_host
92
- TYPESENSE_API_KEY=your_typesense_api_key
93
- COLLECTION_NAME=posts
94
- WEBHOOK_SECRET=your-development-secret
95
- ```
87
+ - Validates webhook signatures
88
+ - Validates request payloads
89
+ - Handles Ghost API errors
90
+ - Handles Typesense errors
91
+ - Returns appropriate HTTP status codes
96
92
 
97
- 3. Start the development server:
98
- ```bash
99
- npm run dev
100
- ```
93
+ ## TypeScript Support
101
94
 
102
- 4. Send webhook events to the local server from a local Ghost instance, including your secret:
103
- `http://localhost:8888/.netlify/functions/handler?secret=your-development-secret`
95
+ This package is written in TypeScript and includes full type definitions. It uses strict type checking and provides comprehensive type safety for all APIs.
104
96
 
105
97
  ## License
106
98
 
107
- This project is licensed under the MIT License - see the [LICENSE](../../LICENSE) file for details.
99
+ MIT - see the [LICENSE](../../LICENSE) file for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magicpages/ghost-typesense-webhook",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Webhook handler for real-time Ghost content synchronization with Typesense",
5
5
  "author": "MagicPages",
6
6
  "license": "MIT",
@@ -127,6 +127,8 @@ describe('Webhook Handler', () => {
127
127
  visibility: 'public',
128
128
  updated_at: '2024-02-09T12:00:00.000Z',
129
129
  published_at: '2024-02-09T12:00:00.000Z',
130
+ url: 'https://test.com/test-post-1',
131
+ excerpt: 'Test excerpt',
130
132
  custom_excerpt: 'Test excerpt',
131
133
  feature_image: null
132
134
  }
@@ -157,6 +159,8 @@ describe('Webhook Handler', () => {
157
159
  visibility: 'public',
158
160
  updated_at: '2024-02-09T12:00:00.000Z',
159
161
  published_at: '2024-02-09T12:00:00.000Z',
162
+ url: 'https://test.com/test-post-1',
163
+ excerpt: 'Test excerpt',
160
164
  custom_excerpt: 'Test excerpt',
161
165
  feature_image: null
162
166
  }
package/src/handler.ts CHANGED
@@ -20,11 +20,13 @@ const WebhookSchema = z.object({
20
20
  id: z.string(),
21
21
  title: z.string(),
22
22
  slug: z.string(),
23
+ url: z.string().url(),
23
24
  html: z.string(),
24
25
  status: z.string(),
25
26
  visibility: z.string(),
26
27
  updated_at: z.string(),
27
28
  published_at: z.string().nullable(),
29
+ excerpt: z.string().nullable(),
28
30
  custom_excerpt: z.string().nullable().optional(),
29
31
  feature_image: z.string().nullable().optional(),
30
32
  tags: z.array(z.object({