hc-hello-world-plugin

command
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2025 License: Apache-2.0, Apache-2.0 Imports: 6 Imported by: 0

README ΒΆ

Hello World Plugin - Complete Apito SDK Showcase

This plugin demonstrates the complete capabilities of the Apito Plugin SDK, serving as both a comprehensive example and a migration guide for developers building plugins for the Apito Engine.

πŸš€ What This Plugin Demonstrates

Complete SDK Feature Coverage

This plugin showcases every major SDK feature in production-ready examples:

  • βœ… GraphQL Queries & Mutations with complex type definitions
  • βœ… REST API Endpoints with full CRUD operations
  • βœ… Custom Functions for business logic
  • βœ… Complex Object Types with nested structures
  • βœ… Automatic Argument Parsing and type conversion
  • βœ… Context & Authentication handling
  • βœ… Error Handling & Validation patterns
  • βœ… Debug Support with VSCode integration

πŸ“Š Migration Impact

Code Reduction Statistics
  • Original Version: 675 lines of boilerplate code
  • SDK Version: 310 lines of business logic
  • Reduction: 54% fewer lines (365 lines eliminated)
  • Boilerplate Eliminated: ~400 lines of HashiCorp plugin, gRPC, and protobuf setup
Developer Experience Improvements
  • ⚑ 5x Faster Development: Focus on business logic, not infrastructure
  • πŸ”§ Zero Boilerplate: SDK handles all plugin communication
  • πŸ›‘οΈ Type Safety: Built-in helpers prevent runtime errors
  • πŸ› Easy Debugging: Native debugging support with delve
  • πŸ“š Self-Documenting: Schema definitions serve as documentation

🎯 Core Features Demonstrated

1. GraphQL Schema with Complex Types
Simple Queries
// Basic string query with arguments
plugin.RegisterQuery("helloWorldQueryFahim",
    sdk.FieldWithArgs("String", "Hello World Plugin Query", map[string]interface{}{
        "name": sdk.StringArg("Name to greet (optional)"),
        "object": sdk.ObjectArg("Object argument", map[string]interface{}{
            "name": sdk.StringProperty("Object name"),
            "age":  sdk.IntProperty("Object age"),
        }),
        "arrayofObjects": sdk.ListArg("Object", "Array of objects"),
    }),
    helloWorldResolver)
Complex Object Types
// Define reusable object types
userType := sdk.NewObjectType("User", "A user in the system").
    AddStringField("id", "User ID", false).
    AddStringField("name", "User's full name", false).
    AddStringField("email", "User's email address", true).
    AddObjectField("address", "User's address", addressType, true).
    AddObjectListField("tags", "User tags", tagType, true, false).
    AddBooleanField("active", "Whether the user is active", false).
    Build()

// Use in queries
plugin.RegisterQuery("getUserProfile",
    sdk.ComplexObjectFieldWithArgs("Get user profile", userType, map[string]interface{}{
        "userId": sdk.StringArg("User ID to fetch"),
    }),
    getUserProfileResolver)
Paginated Responses
// Built-in pagination support
paginatedProductType := sdk.PaginatedResponseType("Product")
plugin.RegisterQuery("getProductsPaginated",
    sdk.ComplexObjectFieldWithArgs("Get paginated products", paginatedProductType, map[string]interface{}{
        "page":     sdk.IntArg("Page number (1-based)"),
        "pageSize": sdk.IntArg("Number of items per page"),
        "category": sdk.StringArg("Filter by category"),
    }),
    getProductsPaginatedResolver)
2. REST API Endpoints - Complete CRUD
Simple GET Endpoint
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "GET",
    Path:        "/hello",
    Description: "Simple hello endpoint",
    Schema:      map[string]interface{}{},
}, helloRESTHandler)
Resource Management (Full CRUD)
// CREATE - POST /users
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "POST",
    Path:        "/users",
    Description: "Create a new user",
    Schema: map[string]interface{}{
        "name":     "string",
        "email":    "string",
        "username": "string",
        "active":   "boolean",
    },
}, createUserRESTHandler)

// READ - GET /users/:id
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "GET",
    Path:        "/users/:id",
    Description: "Get user by ID with query parameters",
    Schema: map[string]interface{}{
        "include_profile": "boolean",
        "format":          "string",
    },
}, getUserRESTHandler)

// UPDATE - PUT /users/:id
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "PUT",
    Path:        "/users/:id",
    Description: "Update user by ID",
    Schema: map[string]interface{}{
        "name":   "string",
        "email":  "string",
        "active": "boolean",
    },
}, updateUserRESTHandler)

// DELETE - DELETE /users/:id
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "DELETE",
    Path:        "/users/:id",
    Description: "Delete user by ID",
    Schema:      map[string]interface{}{},
}, deleteUserRESTHandler)
Advanced REST Features
// Pagination and Search
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "GET",
    Path:        "/users",
    Description: "List users with pagination",
    Schema: map[string]interface{}{
        "page":     "integer",
        "pageSize": "integer",
        "search":   "string",
        "active":   "boolean",
    },
}, listUsersRESTHandler)

// File Upload Simulation
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "POST",
    Path:        "/upload",
    Description: "Handle file upload with metadata",
    Schema: map[string]interface{}{
        "filename":    "string",
        "content":     "string",
        "tags":        "array",
        "description": "string",
    },
}, uploadFileRESTHandler)

// Complex Nested Data
plugin.RegisterRESTAPI(sdk.RESTEndpoint{
    Method:      "POST",
    Path:        "/complex-data",
    Description: "Handle complex nested JSON data",
    Schema: map[string]interface{}{
        "user": map[string]interface{}{
            "name":  "string",
            "email": "string",
            "address": map[string]interface{}{
                "street": "string",
                "city":   "string",
                "zip":    "string",
            },
        },
        "preferences": "array",
        "metadata":    "object",
    },
}, processComplexDataRESTHandler)
3. Resolver Implementation Patterns
Type-Safe Argument Extraction
func getUserRESTHandler(ctx context.Context, args map[string]interface{}) (interface{}, error) {
    // Extract path parameters
    userID := sdk.GetStringArg(args, ":id", "unknown")

    // Extract query parameters with defaults
    includeProfile := sdk.GetBoolArg(args, "include_profile", false)
    format := sdk.GetStringArg(args, "format", "json")

    // Business logic here...

    return response, nil
}
GraphQL Resolver Pattern
func getUserProfileResolver(ctx context.Context, rawArgs map[string]interface{}) (interface{}, error) {
    // Automatic argument parsing based on schema
    args := sdk.ParseArgsForResolver("getUserProfile", rawArgs)
    userID := sdk.GetStringArg(args, "userId", "default-user")

    // Access context data
    pluginID := sdk.GetPluginID(rawArgs)
    projectID := sdk.GetProjectID(rawArgs)

    // Return complex object matching schema
    return map[string]interface{}{
        "id":       userID,
        "name":     "John Doe",
        "email":    "john@example.com",
        "address": map[string]interface{}{
            "street": "123 Main St",
            "city":   "New York",
            "state":  "NY",
            "zip":    "10001",
        },
        "active": true,
    }, nil
}
4. Data Types & Validation
Supported Types
  • πŸ”Έ Primitives: String, Int, Boolean, Float
  • πŸ”Έ Objects: Complex nested structures
  • πŸ”Έ Arrays: Lists of primitives or objects
  • πŸ”Έ Object Arrays: Complex array processing with ArrayObjectArg
  • πŸ”Έ Enums: Predefined value sets
  • πŸ”Έ Custom Types: User-defined complex types
Automatic Type Conversion
// The SDK automatically handles type conversion
name := sdk.GetStringArg(args, "name", "default")           // string
age := sdk.GetIntArg(args, "age", 0)                       // int
active := sdk.GetBoolArg(args, "active", true)             // bool
price := sdk.GetFloatArg(args, "price", 0.0)               // float64
tags := sdk.GetArrayArg(args, "tags")                      // []interface{}
user := sdk.GetObjectArg(args, "user")                     // map[string]interface{}
users := sdk.GetArrayObjectArg(args, "users")              // []map[string]interface{}

πŸ› οΈ Development Guide

Quick Start
  1. Initialize Plugin
plugin := sdk.Init("your-plugin-name", "1.0.0", "your-api-key")
  1. Register GraphQL Schemas
plugin.RegisterQuery("queryName", schema, resolverFunction)
plugin.RegisterMutation("mutationName", schema, resolverFunction)
  1. Register REST APIs
plugin.RegisterRESTAPI(sdk.RESTEndpoint{...}, handlerFunction)
  1. Start Server
plugin.Serve()
Build & Deploy
# Development build
go build -o your-plugin .

# Production build with optimizations
go build -ldflags="-s -w" -o your-plugin .

# Test the plugin directly
./your-plugin

# The Apito Engine will load it automatically via plugins.yml
Testing Your Plugin
GraphQL Queries
# Test GraphQL via engine
curl -X POST http://localhost:5050/v3/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ helloWorldQueryFahim(name: \"Developer\") }"
  }'
REST API Endpoints
# Test simple GET
curl http://localhost:5050/plugins/hc-hello-world-plugin/hello

# Test POST with data
curl -X POST http://localhost:5050/plugins/hc-hello-world-plugin/users \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john@example.com",
    "username": "johndoe"
  }'

# Test with path parameters
curl http://localhost:5050/plugins/hc-hello-world-plugin/users/123?include_profile=true

πŸ› Debug Support

This plugin includes full debug support with VSCode integration:

Debug Setup
  1. Enable Debug Mode: Set debug: true in plugins.yml
  2. Start Engine: Plugin logs PID for attachment
  3. Attach Debugger: Use provided debug scripts
  4. Set Breakpoints: Debug resolvers in real-time
Debug Scripts Included
  • runDebug.sh - Attach delve to running plugin
  • killDebug.sh - Clean up debug processes
  • DEBUG_GUIDE.md - Complete debugging instructions

πŸ“– API Documentation

Available Endpoints
GraphQL Queries
  • helloWorldQueryFahim - Simple greeting with arguments
  • getUserProfile - Complex user object
  • getUsers - Array of users with filtering
  • getProduct - Product with arrays and metadata
  • getProductsPaginated - Paginated product listing
GraphQL Mutations
  • createUser - User creation with validation
  • processBulkTags - Array object processing example
REST Endpoints
  • GET /hello - Simple greeting
  • POST /custom-hello - Custom greeting with parameters
  • GET /users - List users with pagination and search
  • GET /users/:id - Get user with profile option
  • POST /users - Create new user
  • PUT /users/:id - Update user
  • DELETE /users/:id - Delete user
  • POST /upload - File upload simulation
  • POST /complex-data - Complex nested data processing
  • GET /status - Plugin health and metrics
Response Formats
Success Response
{
  "success": true,
  "data": { ... },
  "message": "Operation completed successfully"
}
Error Response
{
  "success": false,
  "error": "Error description",
  "code": 400
}
Paginated Response
{
  "success": true,
  "data": [...],
  "pagination": {
    "page": 1,
    "pageSize": 10,
    "total": 50,
    "totalPages": 5
  }
}

πŸ”§ Configuration

Plugin Configuration (plugins.yml)
hc-hello-world-plugin:
  id: "hc-hello-world-plugin"
  language: "go"
  title: "Hello World Plugin (SDK Showcase)"
  description: "Complete SDK feature demonstration"
  type: "internal"
  enable: true
  debug: true
  version: "2.0.0"
  env_vars:
    - key: "DEBUG_MODE"
      value: "true"

πŸ“‹ Migration Guide

From Original Plugin System
  1. Replace Boilerplate: Remove all HashiCorp plugin setup code
  2. Use SDK Init: Replace handshake config with sdk.Init()
  3. Simplify Schemas: Use SDK's declarative schema builders
  4. Update Resolvers: Use SDK's automatic argument parsing
  5. Add Type Safety: Leverage SDK's type helpers
Benefits After Migration
  • βœ… 54% Less Code: Focus on business logic
  • βœ… Type Safety: Prevent runtime errors
  • βœ… Better Testing: Isolated resolver functions
  • βœ… Easier Debugging: Native debug support
  • βœ… Self-Documenting: Schema serves as API docs

πŸŽ“ Best Practices

Schema Design
  • Use descriptive names and descriptions
  • Define reusable object types
  • Implement proper validation
  • Support pagination for lists
Error Handling
  • Return structured error responses
  • Include helpful error messages
  • Use appropriate HTTP status codes
  • Log errors for debugging
Performance
  • Use type helpers for efficient parsing
  • Implement caching where appropriate
  • Avoid heavy operations in resolvers
  • Use context for request cancellation
Security
  • Validate all inputs
  • Sanitize user data
  • Use context for authentication
  • Implement rate limiting

πŸ“š Learning Resources

SDK Documentation
  • main.go - Complete SDK implementation (1200+ lines)
  • DEBUG_README.md - Debug setup and troubleshooting
  • OBJECT_TYPES_GUIDE.md - Advanced type system usage

πŸš€ Get Started

  1. Clone this plugin as a starting point
  2. Modify the schemas to match your business logic
  3. Implement your resolvers using the provided patterns
  4. Test with both GraphQL and REST APIs
  5. Deploy using the Apito Engine

This plugin demonstrates the complete power of the Apito Plugin SDK - same functionality, 54% less code, infinite possibilities!

Documentation ΒΆ

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL