This commit is contained in:
2025-09-02 08:52:51 +02:00
parent 3af0aef6c1
commit 418a38527a
8 changed files with 81 additions and 50 deletions

View File

@@ -0,0 +1,2 @@
example
client_example

View File

@@ -1,13 +1,13 @@
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run #!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
import net.unix import net.unix
import x.json2 import json
import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.hero.heromodels.openrpc import freeflowuniverse.herolib.hero.heromodels.openrpc
fn send_request(mut conn unix.StreamConn, request openrpc.JsonRpcRequest) ! { fn send_request(mut conn unix.StreamConn, request openrpc.JsonRpcRequest) ! {
request_json := json2.encode(request) request_json := json.encode(request)
conn.write_string(request_json)! conn.write_string(request_json)!
} }
@@ -32,8 +32,8 @@ console.print_header('Test 1: Discover OpenRPC Specification')
discover_request := openrpc.JsonRpcRequest{ discover_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0' jsonrpc: '2.0'
method: 'discover' method: 'discover'
params: json2.null params: 'null'
id: json2.Any(1) id: '1'
} }
send_request(mut conn, discover_request)! send_request(mut conn, discover_request)!
@@ -47,8 +47,8 @@ comment_json := '{"comment": "This is a test comment from OpenRPC client", "pare
create_request := openrpc.JsonRpcRequest{ create_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0' jsonrpc: '2.0'
method: 'comment_set' method: 'comment_set'
params: json2.raw_decode(comment_json)! params: comment_json
id: json2.Any(2) id: '2'
} }
send_request(mut conn, create_request)! send_request(mut conn, create_request)!
@@ -60,8 +60,8 @@ console.print_header('Test 3: List All Comments')
list_request := openrpc.JsonRpcRequest{ list_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0' jsonrpc: '2.0'
method: 'comment_list' method: 'comment_list'
params: json2.null params: 'null'
id: json2.Any(3) id: '3'
} }
send_request(mut conn, list_request)! send_request(mut conn, list_request)!
@@ -75,8 +75,8 @@ get_args_json := '{"author": 1}'
get_request := openrpc.JsonRpcRequest{ get_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0' jsonrpc: '2.0'
method: 'comment_get' method: 'comment_get'
params: json2.raw_decode(get_args_json)! params: get_args_json
id: json2.Any(4) id: '4'
} }
send_request(mut conn, get_request)! send_request(mut conn, get_request)!

View File

@@ -1,17 +1,22 @@
module openrpc module openrpc
import x.json2 import json
import freeflowuniverse.herolib.hero.heromodels import freeflowuniverse.herolib.hero.heromodels
import freeflowuniverse.herolib.core.redisclient import freeflowuniverse.herolib.core.redisclient
// comment_get retrieves comments based on the provided arguments // comment_get retrieves comments based on the provided arguments
fn (mut server RPCServer) comment_get(params json2.Any) !json2.Any { fn (mut server RPCServer) comment_get(params string) !string {
args := json2.decode[CommentGetArgs](params.json_str())! // Handle empty params
if params == 'null' || params == '{}' {
return error('No valid search criteria provided. Please specify id, author, or parent.')
}
args := json.decode(CommentGetArgs, params)!
// If ID is provided, get specific comment // If ID is provided, get specific comment
if id := args.id { if id := args.id {
comment := heromodels.comment_get(id)! comment := heromodels.comment_get(id)!
return json2.encode(comment) return json.encode(comment)
} }
// If author is provided, find comments by author // If author is provided, find comments by author
@@ -28,15 +33,15 @@ fn (mut server RPCServer) comment_get(params json2.Any) !json2.Any {
} }
// comment_set creates or updates a comment // comment_set creates or updates a comment
fn (mut server RPCServer) comment_set(params json2.Any) !json2.Any { fn (mut server RPCServer) comment_set(params string) !string {
comment_arg := json2.decode[heromodels.CommentArg](params.json_str())! comment_arg := json.decode(heromodels.CommentArg, params)!
id := heromodels.comment_set(comment_arg)! id := heromodels.comment_set(comment_arg)!
return json2.encode({'id': id}) return json.encode({'id': id})
} }
// comment_delete removes a comment by ID // comment_delete removes a comment by ID
fn (mut server RPCServer) comment_delete(params json2.Any) !json2.Any { fn (mut server RPCServer) comment_delete(params string) !string {
args := json2.decode[CommentDeleteArgs](params.json_str())! args := json.decode(CommentDeleteArgs, params)!
// Check if comment exists // Check if comment exists
if !heromodels.comment_exist(args.id)! { if !heromodels.comment_exist(args.id)! {
@@ -48,11 +53,11 @@ fn (mut server RPCServer) comment_delete(params json2.Any) !json2.Any {
redis.hdel('db:comments:data', args.id.str())! redis.hdel('db:comments:data', args.id.str())!
result_json := '{"success": true, "id": ${args.id}}' result_json := '{"success": true, "id": ${args.id}}'
return json2.raw_decode(result_json)! return result_json
} }
// comment_list returns all comment IDs // comment_list returns all comment IDs
fn (mut server RPCServer) comment_list() !json2.Any { fn (mut server RPCServer) comment_list() !string {
mut redis := redisclient.core_get()! mut redis := redisclient.core_get()!
keys := redis.hkeys('db:comments:data')! keys := redis.hkeys('db:comments:data')!
mut ids := []u32{} mut ids := []u32{}
@@ -61,11 +66,11 @@ fn (mut server RPCServer) comment_list() !json2.Any {
ids << key.u32() ids << key.u32()
} }
return json2.encode(ids) return json.encode(ids)
} }
// Helper function to get comments by author // Helper function to get comments by author
fn (mut server RPCServer) get_comments_by_author(author u32) !json2.Any { fn (mut server RPCServer) get_comments_by_author(author u32) !string {
mut redis := redisclient.core_get()! mut redis := redisclient.core_get()!
all_data := redis.hgetall('db:comments:data')! all_data := redis.hgetall('db:comments:data')!
mut matching_comments := []heromodels.Comment{} mut matching_comments := []heromodels.Comment{}
@@ -77,11 +82,11 @@ fn (mut server RPCServer) get_comments_by_author(author u32) !json2.Any {
} }
} }
return json2.encode(matching_comments) return json.encode(matching_comments)
} }
// Helper function to get comments by parent // Helper function to get comments by parent
fn (mut server RPCServer) get_comments_by_parent(parent u32) !json2.Any { fn (mut server RPCServer) get_comments_by_parent(parent u32) !string {
mut redis := redisclient.core_get()! mut redis := redisclient.core_get()!
all_data := redis.hgetall('db:comments:data')! all_data := redis.hgetall('db:comments:data')!
mut matching_comments := []heromodels.Comment{} mut matching_comments := []heromodels.Comment{}
@@ -93,5 +98,5 @@ fn (mut server RPCServer) get_comments_by_parent(parent u32) !json2.Any {
} }
} }
return json2.encode(matching_comments) return json.encode(matching_comments)
} }

View File

@@ -1,9 +1,7 @@
module openrpc module openrpc
import freeflowuniverse.herolib.schemas.openrpc
import x.json2
// discover returns the OpenRPC specification for the HeroModels service // discover returns the OpenRPC specification for the HeroModels service
fn (mut server RPCServer) discover() !json2.Any { fn (mut server RPCServer) discover() !string {
spec_json := $tmpl("openrpc.json") spec_json := $tmpl("openrpc.json")
return openrpc.decode_json_any(spec_json)! return spec_json
} }

View File

@@ -1,6 +1,7 @@
module openrpc module openrpc
import json import json
import x.json2 { Any }
import net.unix import net.unix
import os import os
import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.ui.console
@@ -69,7 +70,7 @@ fn (mut server RPCServer) handle_connection(mut conn unix.StreamConn) {
// Process the JSON-RPC request // Process the JSON-RPC request
response := server.process_request(request_data) or { response := server.process_request(request_data) or {
server.create_error_response(-32603, 'Internal error: ${err}', json2.null) server.create_error_response(-32603, 'Internal error: ${err}', 'null')
} }
// Send response // Send response
@@ -81,19 +82,38 @@ fn (mut server RPCServer) handle_connection(mut conn unix.StreamConn) {
} }
fn (mut server RPCServer) process_request(request_data string) !string { fn (mut server RPCServer) process_request(request_data string) !string {
// Parse JSON-RPC request // Parse JSON-RPC request manually to handle params properly
request := json2.decode[JsonRpcRequest](request_data)! request_map := json.decode(map[string]Any, request_data)!
jsonrpc := request_map['jsonrpc']!.str()
method := request_map['method']!.str()
id := request_map['id']!.str()
// Handle params - convert to string representation
params_str := if 'params' in request_map {
params_any := request_map['params']!
match params_any {
string {
params_any
}
else {
json.encode(params_any)
}
}
} else {
'null'
}
// Route to appropriate method // Route to appropriate method
result := match request.method { result := match method {
'comment_get' { 'comment_get' {
server.comment_get(request.params)! server.comment_get(params_str)!
} }
'comment_set' { 'comment_set' {
server.comment_set(request.params)! server.comment_set(params_str)!
} }
'comment_delete' { 'comment_delete' {
server.comment_delete(request.params)! server.comment_delete(params_str)!
} }
'comment_list' { 'comment_list' {
server.comment_list()! server.comment_list()!
@@ -102,32 +122,32 @@ fn (mut server RPCServer) process_request(request_data string) !string {
server.discover()! server.discover()!
} }
else { else {
return server.create_error_response(-32601, 'Method not found', request.id) return server.create_error_response(-32601, 'Method not found', id)
} }
} }
return server.create_success_response(result, request.id) return server.create_success_response(result, id)
} }
fn (mut server RPCServer) create_success_response(result json2.Any, id json2.Any) string { fn (mut server RPCServer) create_success_response(result string, id string) string {
response := JsonRpcResponse{ response := JsonRpcResponse{
jsonrpc: '2.0' jsonrpc: '2.0'
result: result result: result
id: id id: id
} }
return json2.encode(response) return json.encode(response)
} }
fn (mut server RPCServer) create_error_response(code int, message string, id json2.Any) string { fn (mut server RPCServer) create_error_response(code int, message string, id string) string {
error := JsonRpcError{ error := JsonRpcError{
code: code code: code
message: message message: message
data: json2.null data: 'null'
} }
response := JsonRpcResponse{ response := JsonRpcResponse{
jsonrpc: '2.0' jsonrpc: '2.0'
error: error error: error
id: id id: id
} }
return json2.encode(response) return json.encode(response)
} }

View File

@@ -1,23 +1,23 @@
module openrpc module openrpc
import x.json2 import json
// JSON-RPC 2.0 request structure // JSON-RPC 2.0 request structure
pub struct JsonRpcRequest { pub struct JsonRpcRequest {
pub: pub:
jsonrpc string = '2.0' jsonrpc string = '2.0'
method string method string
params json2.Any params string
id json2.Any id string
} }
// JSON-RPC 2.0 response structure // JSON-RPC 2.0 response structure
pub struct JsonRpcResponse { pub struct JsonRpcResponse {
pub: pub:
jsonrpc string = '2.0' jsonrpc string = '2.0'
result json2.Any result string
error ?JsonRpcError error ?JsonRpcError
id json2.Any id string
} }
// JSON-RPC 2.0 error structure // JSON-RPC 2.0 error structure
@@ -25,7 +25,7 @@ pub struct JsonRpcError {
pub: pub:
code int code int
message string message string
data json2.Any data string
} }
// Comment-specific argument structures // Comment-specific argument structures

View File

@@ -9,6 +9,12 @@ pub fn decode_json_any(data string) !Any {
return json2.decode[json2.Any](data)! return json2.decode[json2.Any](data)!
} }
pub fn decode_json_string(data string) !string {
mut o := decode(data)!
return json.encode(o)!
}
pub fn decode(data string) !OpenRPC { pub fn decode(data string) !OpenRPC {
// mut object := json.decode[OpenRPC](data) or { return error('Failed to decode json\n=======\n${data}\n===========\n${err}') } // mut object := json.decode[OpenRPC](data) or { return error('Failed to decode json\n=======\n${data}\n===========\n${err}') }