# OpenRPC Manager Implementation Plan ## 1. Understanding the Requirements The task requires us to: - Create an OpenRPC Manager (ORPCManager) - Read JSON files from services in pkg/openrpc - Create a model for OpenRPC spec in a separate file - Read the OpenRPC specs into the model - Keep these models in memory in the ORPCManager - Create supporting methods like list_methods - Create a command in @cmd/ to test this behavior ## 2. Project Structure Here's the proposed file structure for our implementation: ``` pkg/ openrpc/ models/ spec.go # OpenRPC specification model manager.go # ORPCManager implementation cmd/ orpctest/ main.go # Test command for the ORPCManager ``` ## 3. Implementation Details ### 3.1 OpenRPC Specification Model (pkg/openrpc/models/spec.go) We'll create a Go struct model that represents the OpenRPC specification based on the structure observed in zinit.json: ```mermaid classDiagram class OpenRPCSpec { +string OpenRPC +InfoObject Info +Server[] Servers +Method[] Methods } class InfoObject { +string Version +string Title +string Description +LicenseObject License } class LicenseObject { +string Name } class Server { +string Name +string URL } class Method { +string Name +string Description +Parameter[] Params +ResultObject Result +Example[] Examples +ErrorObject[] Errors } class Parameter { +string Name +string Description +bool Required +SchemaObject Schema } class ResultObject { +string Name +string Description +SchemaObject Schema } class SchemaObject { +string Type +map[string]interface{} Properties +SchemaObject Items +map[string]SchemaObject AdditionalProperties } class Example { +string Name +map[string]interface{}[] Params +ExampleResultObject Result } class ExampleResultObject { +string Name +interface{} Value } class ErrorObject { +int Code +string Message +string Data } OpenRPCSpec --> InfoObject OpenRPCSpec --> Server OpenRPCSpec --> Method Method --> Parameter Method --> ResultObject Method --> Example Method --> ErrorObject Parameter --> SchemaObject ResultObject --> SchemaObject Example --> ExampleResultObject ``` ### 3.2 OpenRPC Manager (pkg/openrpc/manager.go) The ORPCManager will be responsible for: - Loading OpenRPC specifications from JSON files - Storing and managing these specifications in memory - Providing methods to access and manipulate the specifications ```mermaid classDiagram class ORPCManager { -map[string]*OpenRPCSpec specs +NewORPCManager() *ORPCManager +LoadSpecs(dir string) error +LoadSpec(path string) error +GetSpec(name string) *OpenRPCSpec +ListSpecs() []string +ListMethods(specName string) []string +GetMethod(specName string, methodName string) *Method } ORPCManager --> OpenRPCSpec ``` ### 3.3 Test Command (cmd/orpctest/main.go) We'll create a command-line tool to test the ORPCManager functionality: - Initialize the ORPCManager - Load specifications from the pkg/openrpc/services directory - List available specifications - List methods for each specification - Display details for specific methods ## 4. Implementation Steps 1. **Create the OpenRPC Specification Model**: - Define the Go structs for the OpenRPC specification - Implement JSON marshaling/unmarshaling - Add validation functions 2. **Implement the ORPCManager**: - Create the manager struct with a map to store specifications - Implement methods to load specifications from files - Implement methods to access and manipulate specifications 3. **Create the Test Command**: - Implement a command-line interface to test the ORPCManager - Add options to list specifications, methods, and display details 4. **Write Tests**: - Write unit tests for the OpenRPC model - Write unit tests for the ORPCManager - Write integration tests for the entire system ## 5. Detailed Method Specifications ### 5.1 ORPCManager Methods #### NewORPCManager() - Creates a new instance of the ORPCManager - Initializes the specs map #### LoadSpecs(dir string) error - Reads all JSON files in the specified directory - For each file, calls LoadSpec() - Returns an error if any file fails to load #### LoadSpec(path string) error - Reads the JSON file at the specified path - Parses the JSON into an OpenRPCSpec struct - Validates the specification - Stores the specification in the specs map using the filename (without extension) as the key - Returns an error if any step fails #### GetSpec(name string) *OpenRPCSpec - Returns the OpenRPCSpec with the specified name - Returns nil if the specification doesn't exist #### ListSpecs() []string - Returns a list of all loaded specification names #### ListMethods(specName string) []string - Returns a list of all method names in the specified specification - Returns an empty list if the specification doesn't exist #### GetMethod(specName string, methodName string) *Method - Returns the Method with the specified name from the specified specification - Returns nil if the specification or method doesn't exist ## 6. Example Usage ```go // Initialize the ORPCManager manager := openrpc.NewORPCManager() // Load all specifications from the services directory err := manager.LoadSpecs("pkg/openrpc/services") if err != nil { log.Fatalf("Failed to load specifications: %v", err) } // List all loaded specifications specs := manager.ListSpecs() fmt.Println("Loaded specifications:") for _, spec := range specs { fmt.Printf("- %s\n", spec) } // List all methods in the zinit specification methods := manager.ListMethods("zinit") fmt.Println("\nMethods in zinit specification:") for _, method := range methods { fmt.Printf("- %s\n", method) } // Get details for a specific method method := manager.GetMethod("zinit", "service_list") if method != nil { fmt.Printf("\nDetails for method 'service_list':\n") fmt.Printf("Description: %s\n", method.Description) fmt.Printf("Parameters: %d\n", len(method.Params)) fmt.Printf("Examples: %d\n", len(method.Examples)) }