init
This commit is contained in:
commit
91a950e72f
17 changed files with 2724 additions and 0 deletions
267
sdk.go
Normal file
267
sdk.go
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// SDKFunction describes a function in the SDK
|
||||
type SDKFunction struct {
|
||||
Name string `json:"name"`
|
||||
Signature string `json:"signature"`
|
||||
InsertText string `json:"insertText"`
|
||||
Documentation string `json:"documentation"`
|
||||
}
|
||||
|
||||
// SDKNamespace describes a namespace with functions
|
||||
type SDKNamespace struct {
|
||||
Functions []SDKFunction `json:"functions,omitempty"`
|
||||
}
|
||||
|
||||
// SDKField describes a field in an event type
|
||||
type SDKField struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Doc string `json:"doc,omitempty"`
|
||||
}
|
||||
|
||||
// SDKEventType describes an event type with nested fields
|
||||
type SDKEventType struct {
|
||||
Fields []SDKField `json:"fields"`
|
||||
}
|
||||
|
||||
// SDKHookType maps hook names to their event types
|
||||
type SDKHookTypes map[string]SDKEventType
|
||||
|
||||
// SDKSchema is the complete SDK schema for a language
|
||||
type SDKSchema struct {
|
||||
Runner SDKNamespace `json:"Runner"`
|
||||
Events SDKHookTypes `json:"events"`
|
||||
}
|
||||
|
||||
// Event type definitions per hook (language-agnostic field names, language-specific in schema)
|
||||
var hookEventFields = map[string][]SDKField{
|
||||
"post.published": {
|
||||
{Name: "post", Type: "Post", Doc: "The published post"},
|
||||
{Name: "author", Type: "Author", Doc: "Post author"},
|
||||
{Name: "blog", Type: "Blog", Doc: "Blog info"},
|
||||
},
|
||||
"post.updated": {
|
||||
{Name: "post", Type: "Post", Doc: "The updated post"},
|
||||
{Name: "author", Type: "Author", Doc: "Post author"},
|
||||
{Name: "changes", Type: "Changes", Doc: "What changed"},
|
||||
},
|
||||
"comment.validate": {
|
||||
{Name: "content", Type: "string", Doc: "Comment content"},
|
||||
{Name: "authorName", Type: "string", Doc: "Author name"},
|
||||
{Name: "authorEmail", Type: "string", Doc: "Author email"},
|
||||
{Name: "postSlug", Type: "string", Doc: "Post slug"},
|
||||
},
|
||||
"comment.created": {
|
||||
{Name: "comment", Type: "Comment", Doc: "The created comment"},
|
||||
{Name: "post", Type: "Post", Doc: "The post"},
|
||||
},
|
||||
"member.subscribed": {
|
||||
{Name: "member", Type: "Member", Doc: "The subscriber"},
|
||||
{Name: "tier", Type: "Tier", Doc: "Subscription tier"},
|
||||
},
|
||||
"content.render": {
|
||||
{Name: "html", Type: "string", Doc: "HTML content to transform"},
|
||||
{Name: "post", Type: "Post", Doc: "Post metadata"},
|
||||
},
|
||||
"asset.uploaded": {
|
||||
{Name: "id", Type: "string", Doc: "Asset ID"},
|
||||
{Name: "url", Type: "string", Doc: "Asset URL"},
|
||||
{Name: "contentType", Type: "string", Doc: "MIME type"},
|
||||
{Name: "size", Type: "int", Doc: "Size in bytes"},
|
||||
{Name: "width", Type: "int", Doc: "Image width (if image)"},
|
||||
{Name: "height", Type: "int", Doc: "Image height (if image)"},
|
||||
},
|
||||
"analytics.sync": {
|
||||
{Name: "period", Type: "Period", Doc: "Time period"},
|
||||
{Name: "pageviews", Type: "int", Doc: "Total pageviews"},
|
||||
{Name: "visitors", Type: "int", Doc: "Unique visitors"},
|
||||
{Name: "topPages", Type: "[]PageView", Doc: "Top pages"},
|
||||
},
|
||||
}
|
||||
|
||||
// Nested type definitions
|
||||
var nestedTypes = map[string][]SDKField{
|
||||
"Post": {
|
||||
{Name: "slug", Type: "string"},
|
||||
{Name: "title", Type: "string"},
|
||||
{Name: "url", Type: "string"},
|
||||
{Name: "excerpt", Type: "string"},
|
||||
{Name: "publishedAt", Type: "string"},
|
||||
{Name: "updatedAt", Type: "string"},
|
||||
{Name: "tags", Type: "[]string"},
|
||||
{Name: "readingTime", Type: "int"},
|
||||
},
|
||||
"Author": {
|
||||
{Name: "name", Type: "string"},
|
||||
{Name: "email", Type: "string"},
|
||||
{Name: "avatar", Type: "string"},
|
||||
},
|
||||
"Blog": {
|
||||
{Name: "name", Type: "string"},
|
||||
{Name: "url", Type: "string"},
|
||||
},
|
||||
"Comment": {
|
||||
{Name: "id", Type: "string"},
|
||||
{Name: "content", Type: "string"},
|
||||
{Name: "authorName", Type: "string"},
|
||||
{Name: "authorEmail", Type: "string"},
|
||||
{Name: "postSlug", Type: "string"},
|
||||
{Name: "parentId", Type: "string"},
|
||||
{Name: "createdAt", Type: "string"},
|
||||
},
|
||||
"Member": {
|
||||
{Name: "email", Type: "string"},
|
||||
{Name: "name", Type: "string"},
|
||||
{Name: "subscribedAt", Type: "string"},
|
||||
},
|
||||
"Tier": {
|
||||
{Name: "name", Type: "string"},
|
||||
{Name: "price", Type: "int"},
|
||||
},
|
||||
"Changes": {
|
||||
{Name: "title", Type: "TitleChange"},
|
||||
{Name: "content", Type: "bool"},
|
||||
{Name: "tags", Type: "TagChanges"},
|
||||
},
|
||||
"TitleChange": {
|
||||
{Name: "old", Type: "string"},
|
||||
{Name: "new", Type: "string"},
|
||||
},
|
||||
"TagChanges": {
|
||||
{Name: "added", Type: "[]string"},
|
||||
{Name: "removed", Type: "[]string"},
|
||||
},
|
||||
"Period": {
|
||||
{Name: "start", Type: "string"},
|
||||
{Name: "end", Type: "string"},
|
||||
},
|
||||
"PageView": {
|
||||
{Name: "path", Type: "string"},
|
||||
{Name: "views", Type: "int"},
|
||||
},
|
||||
}
|
||||
|
||||
func buildEventTypes(lang string) SDKHookTypes {
|
||||
events := make(SDKHookTypes)
|
||||
for hook, fields := range hookEventFields {
|
||||
// Convert field names for Go (PascalCase)
|
||||
if lang == "go" {
|
||||
converted := make([]SDKField, len(fields))
|
||||
for i, f := range fields {
|
||||
converted[i] = SDKField{
|
||||
Name: toPascalCase(f.Name),
|
||||
Type: f.Type,
|
||||
Doc: f.Doc,
|
||||
}
|
||||
}
|
||||
events[hook] = SDKEventType{Fields: converted}
|
||||
} else {
|
||||
events[hook] = SDKEventType{Fields: fields}
|
||||
}
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
func toPascalCase(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
// Simple: just capitalize first letter
|
||||
return string(s[0]-32) + s[1:]
|
||||
}
|
||||
|
||||
// SDK schemas for each language
|
||||
var sdkSchemas = map[string]SDKSchema{
|
||||
"typescript": {
|
||||
Runner: SDKNamespace{
|
||||
Functions: []SDKFunction{
|
||||
{
|
||||
Name: "log",
|
||||
Signature: "log(message: string): void",
|
||||
InsertText: "log(${1:message})",
|
||||
Documentation: "Log a message to the plugin console",
|
||||
},
|
||||
{
|
||||
Name: "httpRequest",
|
||||
Signature: "httpRequest(options: HttpRequestOptions): HttpResponse",
|
||||
InsertText: "httpRequest({\n url: ${1:url},\n method: \"${2:POST}\",\n headers: { \"Content-Type\": \"application/json\" },\n body: ${3:body}\n})",
|
||||
Documentation: "Make an HTTP request to an external service",
|
||||
},
|
||||
},
|
||||
},
|
||||
Events: buildEventTypes("typescript"),
|
||||
},
|
||||
"go": {
|
||||
Runner: SDKNamespace{
|
||||
Functions: []SDKFunction{
|
||||
{
|
||||
Name: "Log",
|
||||
Signature: "Log(message string)",
|
||||
InsertText: "Log(${1:message})",
|
||||
Documentation: "Log a message to the plugin console",
|
||||
},
|
||||
{
|
||||
Name: "HttpRequest",
|
||||
Signature: "HttpRequest(url string, method string, body []byte) (*Response, error)",
|
||||
InsertText: "HttpRequest(${1:url}, \"${2:POST}\", []byte(${3:body}))",
|
||||
Documentation: "Make an HTTP request to an external service",
|
||||
},
|
||||
},
|
||||
},
|
||||
Events: buildEventTypes("go"),
|
||||
},
|
||||
}
|
||||
|
||||
// Also expose nested types
|
||||
type FullSDKResponse struct {
|
||||
Runner SDKNamespace `json:"Runner"`
|
||||
Events SDKHookTypes `json:"events"`
|
||||
NestedTypes map[string][]SDKField `json:"nestedTypes"`
|
||||
}
|
||||
|
||||
func sdkHandler(w http.ResponseWriter, r *http.Request) {
|
||||
language := r.URL.Query().Get("language")
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if language != "" {
|
||||
if schema, ok := sdkSchemas[language]; ok {
|
||||
// Convert nested types for the language
|
||||
convertedNested := make(map[string][]SDKField)
|
||||
for typeName, fields := range nestedTypes {
|
||||
if language == "go" {
|
||||
converted := make([]SDKField, len(fields))
|
||||
for i, f := range fields {
|
||||
converted[i] = SDKField{
|
||||
Name: toPascalCase(f.Name),
|
||||
Type: f.Type,
|
||||
Doc: f.Doc,
|
||||
}
|
||||
}
|
||||
convertedNested[typeName] = converted
|
||||
} else {
|
||||
convertedNested[typeName] = fields
|
||||
}
|
||||
}
|
||||
|
||||
response := FullSDKResponse{
|
||||
Runner: schema.Runner,
|
||||
Events: schema.Events,
|
||||
NestedTypes: convertedNested,
|
||||
}
|
||||
json.NewEncoder(w).Encode(response)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Unknown language", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Return all schemas (without nested types for brevity)
|
||||
json.NewEncoder(w).Encode(sdkSchemas)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue