init
This commit is contained in:
commit
91a950e72f
17 changed files with 2724 additions and 0 deletions
423
templates.go
Normal file
423
templates.go
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
package main
|
||||
|
||||
// HookInfo describes a plugin hook
|
||||
type HookInfo struct {
|
||||
Name string `json:"name"`
|
||||
Label string `json:"label"`
|
||||
Description string `json:"description"`
|
||||
Pattern string `json:"pattern"` // event, validation, transform
|
||||
TestData map[string]any `json:"test_data"`
|
||||
}
|
||||
|
||||
// Available hooks
|
||||
var hooks = []HookInfo{
|
||||
{
|
||||
Name: "post.published",
|
||||
Label: "Post Published",
|
||||
Description: "Triggered when a post is published",
|
||||
Pattern: "event",
|
||||
TestData: map[string]any{
|
||||
"post": map[string]any{
|
||||
"slug": "hello-world",
|
||||
"title": "Hello World",
|
||||
"url": "/hello-world",
|
||||
"excerpt": "This is a test post for plugin development.",
|
||||
"publishedAt": "2024-01-15T10:30:00Z",
|
||||
"tags": []string{"test", "development"},
|
||||
"readingTime": 3,
|
||||
},
|
||||
"author": map[string]any{
|
||||
"name": "Test Author",
|
||||
"email": "author@example.com",
|
||||
},
|
||||
"blog": map[string]any{
|
||||
"name": "Test Blog",
|
||||
"url": "https://test.writekit.dev",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "post.updated",
|
||||
Label: "Post Updated",
|
||||
Description: "Triggered when a post is updated",
|
||||
Pattern: "event",
|
||||
TestData: map[string]any{
|
||||
"post": map[string]any{
|
||||
"slug": "hello-world",
|
||||
"title": "Hello World (Updated)",
|
||||
"url": "/hello-world",
|
||||
"excerpt": "This is a test post that was updated.",
|
||||
"publishedAt": "2024-01-15T10:30:00Z",
|
||||
"updatedAt": "2024-01-16T14:00:00Z",
|
||||
"tags": []string{"test", "development", "updated"},
|
||||
},
|
||||
"author": map[string]any{
|
||||
"name": "Test Author",
|
||||
"email": "author@example.com",
|
||||
},
|
||||
"changes": map[string]any{
|
||||
"title": map[string]any{"old": "Hello World", "new": "Hello World (Updated)"},
|
||||
"content": true,
|
||||
"tags": map[string]any{"added": []string{"updated"}, "removed": []string{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "comment.validate",
|
||||
Label: "Comment Validate",
|
||||
Description: "Validate comments before creation",
|
||||
Pattern: "validation",
|
||||
TestData: map[string]any{
|
||||
"content": "This is a test comment for moderation.",
|
||||
"authorName": "Test User",
|
||||
"authorEmail": "user@example.com",
|
||||
"postSlug": "hello-world",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "comment.created",
|
||||
Label: "Comment Created",
|
||||
Description: "Triggered when a comment is created",
|
||||
Pattern: "event",
|
||||
TestData: map[string]any{
|
||||
"comment": map[string]any{
|
||||
"id": "test-comment-123",
|
||||
"content": "Great post! Thanks for sharing.",
|
||||
"authorName": "Test User",
|
||||
"authorEmail": "user@example.com",
|
||||
"postSlug": "hello-world",
|
||||
"createdAt": "2024-01-15T12:00:00Z",
|
||||
},
|
||||
"post": map[string]any{
|
||||
"slug": "hello-world",
|
||||
"title": "Hello World",
|
||||
"url": "/hello-world",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "member.subscribed",
|
||||
Label: "Member Subscribed",
|
||||
Description: "Triggered when a member subscribes",
|
||||
Pattern: "event",
|
||||
TestData: map[string]any{
|
||||
"member": map[string]any{
|
||||
"email": "subscriber@example.com",
|
||||
"name": "New Subscriber",
|
||||
"subscribedAt": "2024-01-15T09:00:00Z",
|
||||
},
|
||||
"tier": map[string]any{
|
||||
"name": "Free",
|
||||
"price": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "content.render",
|
||||
Label: "Content Render",
|
||||
Description: "Transform rendered HTML",
|
||||
Pattern: "transform",
|
||||
TestData: map[string]any{
|
||||
"html": "<h1>Hello World</h1><p>This is test content.</p><pre><code>const x = 1;</code></pre>",
|
||||
"post": map[string]any{
|
||||
"slug": "hello-world",
|
||||
"title": "Hello World",
|
||||
"tags": []string{"test"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "asset.uploaded",
|
||||
Label: "Asset Uploaded",
|
||||
Description: "Triggered when an asset is uploaded",
|
||||
Pattern: "event",
|
||||
TestData: map[string]any{
|
||||
"id": "asset-123",
|
||||
"url": "https://cdn.example.com/image.webp",
|
||||
"contentType": "image/webp",
|
||||
"size": 102400,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "analytics.sync",
|
||||
Label: "Analytics Sync",
|
||||
Description: "Sync analytics data periodically",
|
||||
Pattern: "event",
|
||||
TestData: map[string]any{
|
||||
"period": map[string]any{
|
||||
"start": "2024-01-08T00:00:00Z",
|
||||
"end": "2024-01-15T00:00:00Z",
|
||||
},
|
||||
"pageviews": 1250,
|
||||
"visitors": 890,
|
||||
"topPages": []map[string]any{
|
||||
{"path": "/hello-world", "views": 450},
|
||||
{"path": "/about", "views": 230},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Templates organized by hook and language
|
||||
var templates = map[string]map[string]string{
|
||||
"post.published": {
|
||||
"typescript": `export const onPostPublished = (event: PostPublishedEvent): void => {
|
||||
Runner.log("Post published: " + event.post.title);
|
||||
|
||||
// Example: Send Slack notification
|
||||
Runner.httpRequest({
|
||||
url: Runner.secrets.SLACK_WEBHOOK,
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
text: "New post: " + event.post.title + "\n" + event.post.url,
|
||||
}),
|
||||
});
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
func OnPostPublished(event PostPublishedEvent) error {
|
||||
Runner.Log("Post published: " + event.Post.Title)
|
||||
|
||||
// Example: Send Slack notification
|
||||
Runner.HttpRequest(Runner.Secrets.SlackWebhook, "POST", []byte("{\"text\":\"New post published\"}"))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
"post.updated": {
|
||||
"typescript": `export const onPostUpdated = (event: PostUpdatedEvent): void => {
|
||||
Runner.log("Post updated: " + event.post.title);
|
||||
|
||||
// Example: Sync to external CMS
|
||||
if (event.changes.content) {
|
||||
Runner.httpRequest({
|
||||
url: "https://api.example.com/sync",
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
slug: event.post.slug,
|
||||
title: event.post.title,
|
||||
url: event.post.url,
|
||||
}),
|
||||
});
|
||||
}
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
func OnPostUpdated(event PostUpdatedEvent) error {
|
||||
Runner.Log("Post updated: " + event.Post.Title)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
"comment.validate": {
|
||||
"typescript": `export const validateComment = (input: CommentInput): ValidationResult => {
|
||||
// Example: Simple spam check
|
||||
const spamWords = ["buy now", "click here", "free money"];
|
||||
const content = input.content.toLowerCase();
|
||||
|
||||
for (const word of spamWords) {
|
||||
if (content.includes(word)) {
|
||||
return { allowed: false, reason: "Comment flagged as spam" };
|
||||
}
|
||||
}
|
||||
|
||||
// Example: Check minimum length
|
||||
if (input.content.length < 10) {
|
||||
return { allowed: false, reason: "Comment too short" };
|
||||
}
|
||||
|
||||
return { allowed: true };
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
import "strings"
|
||||
|
||||
func ValidateComment(input CommentInput) (ValidationResult, error) {
|
||||
// Example: Simple spam check
|
||||
spamWords := []string{"buy now", "click here", "free money"}
|
||||
content := strings.ToLower(input.Content)
|
||||
|
||||
for _, word := range spamWords {
|
||||
if strings.Contains(content, word) {
|
||||
return ValidationResult{Allowed: false, Reason: "Spam detected"}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return ValidationResult{Allowed: true}, nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
"comment.created": {
|
||||
"typescript": `export const onCommentCreated = (event: CommentCreatedEvent): void => {
|
||||
Runner.log("New comment on: " + event.post.title);
|
||||
|
||||
// Example: Send notification
|
||||
Runner.httpRequest({
|
||||
url: Runner.secrets.SLACK_WEBHOOK,
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
text: "New comment by " + event.comment.authorName + " on \"" + event.post.title + "\"",
|
||||
}),
|
||||
});
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
func OnCommentCreated(event CommentCreatedEvent) error {
|
||||
Runner.Log("New comment on: " + event.Post.Title)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
"member.subscribed": {
|
||||
"typescript": `export const onMemberSubscribed = (event: MemberSubscribedEvent): void => {
|
||||
Runner.log("New subscriber: " + event.member.email);
|
||||
|
||||
// Example: Add to email list
|
||||
Runner.httpRequest({
|
||||
url: "https://api.buttondown.email/v1/subscribers",
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Token " + Runner.secrets.BUTTONDOWN_API_KEY,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: event.member.email,
|
||||
notes: "Subscribed from blog",
|
||||
}),
|
||||
});
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
func OnMemberSubscribed(event MemberSubscribedEvent) error {
|
||||
Runner.Log("New subscriber: " + event.Member.Email)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
"content.render": {
|
||||
"typescript": `export const renderContent = (input: ContentRenderInput): ContentRenderOutput => {
|
||||
let html = input.html;
|
||||
|
||||
// Example: Add copy button to code blocks
|
||||
html = html.replace(
|
||||
/<pre><code/g,
|
||||
'<pre class="relative group"><button class="copy-btn absolute top-2 right-2 opacity-0 group-hover:opacity-100">Copy</button><code'
|
||||
);
|
||||
|
||||
// Example: Make external links open in new tab
|
||||
html = html.replace(
|
||||
/<a href="(https?:\/\/[^"]+)"/g,
|
||||
'<a href="$1" target="_blank" rel="noopener"'
|
||||
);
|
||||
|
||||
return { html };
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
import "strings"
|
||||
|
||||
func RenderContent(input ContentRenderInput) (ContentRenderOutput, error) {
|
||||
html := input.Html
|
||||
|
||||
// Example: Add copy button to code blocks
|
||||
html = strings.ReplaceAll(html, "<pre><code", "<pre class=\"relative\"><button class=\"copy-btn\">Copy</button><code")
|
||||
|
||||
return ContentRenderOutput{Html: html}, nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
"asset.uploaded": {
|
||||
"typescript": `export const onAssetUploaded = (event: AssetUploadedEvent): void => {
|
||||
Runner.log("Asset uploaded: " + event.url);
|
||||
|
||||
// Example: Backup to external storage
|
||||
if (event.contentType.startsWith("image/")) {
|
||||
Runner.httpRequest({
|
||||
url: "https://api.cloudinary.com/v1_1/demo/image/upload",
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
file: event.url,
|
||||
folder: "blog-backups",
|
||||
}),
|
||||
});
|
||||
}
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
func OnAssetUploaded(event AssetUploadedEvent) error {
|
||||
Runner.Log("Asset uploaded: " + event.Url)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
"analytics.sync": {
|
||||
"typescript": `export const onAnalyticsSync = (event: AnalyticsSyncEvent): void => {
|
||||
Runner.log("Analytics sync: " + event.pageviews + " pageviews");
|
||||
|
||||
// Example: Push to external analytics
|
||||
Runner.httpRequest({
|
||||
url: "https://api.example.com/analytics",
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + Runner.secrets.ANALYTICS_KEY,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
period: event.period,
|
||||
pageviews: event.pageviews,
|
||||
visitors: event.visitors,
|
||||
topPages: event.topPages,
|
||||
}),
|
||||
});
|
||||
};
|
||||
`,
|
||||
"go": `package main
|
||||
|
||||
func OnAnalyticsSync(event AnalyticsSyncEvent) error {
|
||||
Runner.Log("Analytics sync completed")
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
// GetTemplate returns the template for a specific hook and language
|
||||
func GetTemplate(hook, language string) string {
|
||||
if hookTemplates, ok := templates[hook]; ok {
|
||||
if template, ok := hookTemplates[language]; ok {
|
||||
return template
|
||||
}
|
||||
}
|
||||
// Default fallback
|
||||
return templates["post.published"]["typescript"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue