239 lines
6.4 KiB
Markdown
239 lines
6.4 KiB
Markdown
# 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))
|
|
} |