...
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals -no-skip-unused run
|
||||
|
||||
import freeflowuniverse.herolib.hero.heromodels.rpc
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
import time
|
||||
|
||||
fn main() {
|
||||
// Start the server in a background thread with authentication disabled for testing
|
||||
spawn fn () {
|
||||
rpc.start(
|
||||
spawn fn () ! {
|
||||
heromodels.new(reset: true, name: 'test')!
|
||||
heromodels.server_start(
|
||||
name: 'test'
|
||||
port: 8086
|
||||
auth_enabled: false // Disable auth for testing
|
||||
cors_enabled: true
|
||||
reset: true
|
||||
reset: true
|
||||
allowed_origins: [
|
||||
'http://localhost:5173',
|
||||
]
|
||||
|
||||
25
lib/hero/db/decode.v
Normal file
25
lib/hero/db/decode.v
Normal file
@@ -0,0 +1,25 @@
|
||||
module db
|
||||
|
||||
import x.json2
|
||||
import json
|
||||
|
||||
pub fn decode_int(data string) !int {
|
||||
return json2.decode[int](data) or { return error('Failed to decode int: ${data}') }
|
||||
}
|
||||
|
||||
pub fn decode_u32(data string) !u32 {
|
||||
return json2.decode[u32](data) or { return error('Failed to decode u32: ${data}') }
|
||||
}
|
||||
|
||||
pub fn decode_bool(data string) !bool {
|
||||
return json2.decode[bool](data) or { return error('Failed to decode bool: ${data}') }
|
||||
}
|
||||
|
||||
pub fn decode_generic[T](data string) !T {
|
||||
mut r := json.decode(T, data) or {
|
||||
println('Failed to decode T: \n***\n${data}\n***\n${err}')
|
||||
println(T{})
|
||||
return error('Failed to decode T: ${data}\n${err}')
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -3,6 +3,9 @@ module heromodels
|
||||
import freeflowuniverse.herolib.data.encoder
|
||||
import freeflowuniverse.herolib.data.ourtime
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Response, new_error, new_response, new_response_false, new_response_ok, new_response_true, new_response_int }
|
||||
import freeflowuniverse.herolib.hero.user { UserRef }
|
||||
import json
|
||||
|
||||
// Calendar represents a collection of events
|
||||
@[heap]
|
||||
@@ -135,7 +138,48 @@ pub fn (mut self DBCalendar) get(id u32) !Calendar {
|
||||
}
|
||||
|
||||
pub fn (mut self DBCalendar) list() ![]Calendar {
|
||||
r:= self.db.list[Calendar]()!.map(self.get(it)!)
|
||||
r := self.db.list[Calendar]()!.map(self.get(it)!)
|
||||
println(r)
|
||||
return r
|
||||
}
|
||||
|
||||
pub fn calendar_handle(mut f ModelsFactory, rpcid int, servercontext map[string]string, userref UserRef, method string, params string) !Response {
|
||||
match method {
|
||||
'get' {
|
||||
id := db.decode_u32(params)!
|
||||
res := f.calendar.get(id)!
|
||||
return new_response(rpcid, json.encode(res))
|
||||
}
|
||||
'set' {
|
||||
mut o := db.decode_generic[Calendar](params)!
|
||||
o=f.calendar.set(o)!
|
||||
return new_response_int(rpcid,int(o.id))
|
||||
}
|
||||
'delete' {
|
||||
id := db.decode_u32(params)!
|
||||
f.calendar.delete(id)!
|
||||
return new_response_ok(rpcid)
|
||||
}
|
||||
'exist' {
|
||||
id := db.decode_u32(params)!
|
||||
if f.calendar.exist(id)! {
|
||||
return new_response_true(rpcid)
|
||||
} else {
|
||||
return new_response_false(rpcid)
|
||||
}
|
||||
}
|
||||
'list' {
|
||||
req := jsonrpc.new_request(method, '') // no params
|
||||
res := f.calendar.list()!
|
||||
return new_response(req.id, json.encode(res))
|
||||
}
|
||||
else {
|
||||
println('Method not found on calendar: ${method}')
|
||||
$dbg;
|
||||
return new_error(rpcid,
|
||||
code: 32601
|
||||
message: 'Method ${method} not found on calendar'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
module heromodels
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
import freeflowuniverse.herolib.hero.user { UserRef }
|
||||
import freeflowuniverse.herolib.core.redisclient
|
||||
import freeflowuniverse.herolib.schemas.openrpc { Handler, new_handler }
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
const openrpc_path = os.join_path(os.dir(@FILE), 'openrpc.json')
|
||||
|
||||
__global (
|
||||
rpc_heromodels map[string]&ModelsFactory
|
||||
@@ -19,11 +26,13 @@ pub mut:
|
||||
project_issue DBProjectIssue
|
||||
chat_group DBChatGroup
|
||||
chat_message DBChatMessage
|
||||
rpc_handler &Handler
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct NewArgs {
|
||||
name string @[required]
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
reset bool
|
||||
redis ?&redisclient.Redis
|
||||
}
|
||||
@@ -33,6 +42,7 @@ pub fn new(args NewArgs) !&ModelsFactory {
|
||||
if args.reset {
|
||||
mydb.redis.flushdb()!
|
||||
}
|
||||
mut h := new_handler(openrpc_path)!
|
||||
mut f := ModelsFactory{
|
||||
comments: DBComments{
|
||||
db: &mydb
|
||||
@@ -61,7 +71,47 @@ pub fn new(args NewArgs) !&ModelsFactory {
|
||||
chat_message: DBChatMessage{
|
||||
db: &mydb
|
||||
}
|
||||
rpc_handler: &h
|
||||
}
|
||||
|
||||
// openrpc handler can be used by any server, has even embedded unix sockets and simple http server
|
||||
f.rpc_handler.register_api_handler('heromodels', group_api_handler)
|
||||
f.rpc_handler.servercontext['heromodels_instance'] = args.name // pass name to handler
|
||||
|
||||
rpc_heromodels[args.name] = &f
|
||||
return rpc_heromodels[args.name] or { panic('bug') }
|
||||
}
|
||||
|
||||
pub fn get(name string) !&ModelsFactory {
|
||||
mut f := rpc_heromodels[name] or {
|
||||
return error('No heromodels factory with name ${name} found')
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
pub fn group_api_handler(rpcid int, servercontext map[string]string, actorname string, methodname string, params string) !jsonrpc.Response {
|
||||
instance := servercontext['heromodels_instance'] or {
|
||||
return jsonrpc.new_error(rpcid,
|
||||
code: 32606
|
||||
message: 'heromodels_instance for modeldb not found on servercontext.'
|
||||
)
|
||||
}
|
||||
user_id := servercontext['user'] or { '' } // can be 0 if no authentication
|
||||
userref := UserRef{
|
||||
id: user_id.u32()
|
||||
}
|
||||
console.print_debug('heromodels handle: ${rpcid}: ${instance} - ${actorname} - ${methodname} - ${params} - user:${user_id}')
|
||||
mut f := get(instance)!
|
||||
match actorname {
|
||||
'calendar' {
|
||||
return calendar_handle(mut f, rpcid, servercontext, userref, methodname, params)!
|
||||
}
|
||||
else {
|
||||
return jsonrpc.new_error(rpcid,
|
||||
code: 32111
|
||||
data: '${params}'
|
||||
message: 'Actor ${actorname} not found on heromodels'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
lib/hero/heromodels/factory_server.v
Normal file
34
lib/hero/heromodels/factory_server.v
Normal file
@@ -0,0 +1,34 @@
|
||||
module heromodels
|
||||
|
||||
import freeflowuniverse.herolib.hero.heroserver
|
||||
import os
|
||||
|
||||
// Start heromodels server using heroserver
|
||||
@[params]
|
||||
pub struct ServerArgs {
|
||||
pub mut:
|
||||
port int = 8080
|
||||
host string = 'localhost'
|
||||
auth_enabled bool = true
|
||||
cors_enabled bool = true
|
||||
reset bool
|
||||
allowed_origins []string = ['*'] // Default allows all origins
|
||||
name string
|
||||
}
|
||||
|
||||
pub fn server_start(args ServerArgs) ! {
|
||||
// Create a new heroserver instance
|
||||
mut server := heroserver.new(
|
||||
port: args.port
|
||||
host: args.host
|
||||
auth_enabled: args.auth_enabled
|
||||
cors_enabled: args.cors_enabled
|
||||
allowed_origins: args.allowed_origins
|
||||
)!
|
||||
|
||||
mut f := get(args.name)!
|
||||
server.register_handler('heromodels', f.rpc_handler)!
|
||||
|
||||
// Start the server
|
||||
server.start()!
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import freeflowuniverse.herolib.schemas.openrpc { Handler }
|
||||
import freeflowuniverse.herolib.hero.heroserver
|
||||
import os
|
||||
|
||||
const openrpc_path = os.join_path(os.dir(@FILE), 'openrpc.json')
|
||||
|
||||
// Create a new heromodels handler for heroserver
|
||||
pub fn new_heromodels_handler() !&Handler {
|
||||
mut handler := openrpc.new_handler(openrpc_path)!
|
||||
|
||||
// Register all comment methods
|
||||
handler.register_procedure_handle('comment_get', comment_get)
|
||||
handler.register_procedure_handle('comment_set', comment_set)
|
||||
handler.register_procedure_handle('comment_delete', comment_delete)
|
||||
handler.register_procedure_handle('comment_list', comment_list)
|
||||
|
||||
// Register all calendar methods
|
||||
handler.register_procedure_handle('calendar_get', calendar_get)
|
||||
handler.register_procedure_handle('calendar_set', calendar_set)
|
||||
handler.register_procedure_handle('calendar_delete', calendar_delete)
|
||||
handler.register_procedure_handle('calendar_list', calendar_list)
|
||||
|
||||
// Register all calendar event methods
|
||||
handler.register_procedure_handle('calendar_event_get', calendar_event_get)
|
||||
handler.register_procedure_handle('calendar_event_set', calendar_event_set)
|
||||
handler.register_procedure_handle('calendar_event_delete', calendar_event_delete)
|
||||
handler.register_procedure_handle('calendar_event_list', calendar_event_list)
|
||||
|
||||
// Register all chat group methods
|
||||
handler.register_procedure_handle('chat_group_get', chat_group_get)
|
||||
handler.register_procedure_handle('chat_group_set', chat_group_set)
|
||||
handler.register_procedure_handle('chat_group_delete', chat_group_delete)
|
||||
handler.register_procedure_handle('chat_group_list', chat_group_list)
|
||||
|
||||
// Register all chat message methods
|
||||
handler.register_procedure_handle('chat_message_get', chat_message_get)
|
||||
handler.register_procedure_handle('chat_message_set', chat_message_set)
|
||||
handler.register_procedure_handle('chat_message_delete', chat_message_delete)
|
||||
handler.register_procedure_handle('chat_message_list', chat_message_list)
|
||||
|
||||
// Register all group methods
|
||||
handler.register_procedure_handle('group_get', group_get)
|
||||
handler.register_procedure_handle('group_set', group_set)
|
||||
handler.register_procedure_handle('group_delete', group_delete)
|
||||
handler.register_procedure_handle('group_list', group_list)
|
||||
|
||||
// Register all project issue methods
|
||||
handler.register_procedure_handle('project_issue_get', project_issue_get)
|
||||
handler.register_procedure_handle('project_issue_set', project_issue_set)
|
||||
handler.register_procedure_handle('project_issue_delete', project_issue_delete)
|
||||
handler.register_procedure_handle('project_issue_list', project_issue_list)
|
||||
|
||||
// Register all project methods
|
||||
handler.register_procedure_handle('project_get', project_get)
|
||||
handler.register_procedure_handle('project_set', project_set)
|
||||
handler.register_procedure_handle('project_delete', project_delete)
|
||||
handler.register_procedure_handle('project_list', project_list)
|
||||
|
||||
// Register all user methods
|
||||
handler.register_procedure_handle('user_get', user_get)
|
||||
handler.register_procedure_handle('user_set', user_set)
|
||||
handler.register_procedure_handle('user_delete', user_delete)
|
||||
handler.register_procedure_handle('user_list', user_list)
|
||||
|
||||
return &handler
|
||||
}
|
||||
|
||||
// Start heromodels server using heroserver
|
||||
@[params]
|
||||
pub struct ServerArgs {
|
||||
pub mut:
|
||||
port int = 8080
|
||||
host string = 'localhost'
|
||||
auth_enabled bool = true
|
||||
cors_enabled bool = true
|
||||
reset bool
|
||||
allowed_origins []string = ['*'] // Default allows all origins
|
||||
name string
|
||||
}
|
||||
|
||||
pub fn start(args ServerArgs) ! {
|
||||
// Create a new heroserver instance
|
||||
mut server := heroserver.new(
|
||||
port: args.port
|
||||
host: args.host
|
||||
auth_enabled: args.auth_enabled
|
||||
cors_enabled: args.cors_enabled
|
||||
allowed_origins: args.allowed_origins
|
||||
)!
|
||||
|
||||
// Create and register the heromodels handler
|
||||
handler := new_heromodels_handler()!
|
||||
handler.params['name'] = args.name
|
||||
server.register_handler('heromodels', handler)!
|
||||
|
||||
// Start the server
|
||||
server.start()!
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
|
||||
// Calendar-specific argument structures
|
||||
@[params]
|
||||
pub struct CalendarGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CalendarSetArgs {
|
||||
pub mut:
|
||||
name string @[required]
|
||||
description string
|
||||
color string
|
||||
timezone string
|
||||
is_public bool
|
||||
events []u32
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CalendarDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn calendar_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CalendarGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
calendar := mydb.calendar.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(calendar))
|
||||
}
|
||||
|
||||
pub fn calendar_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CalendarSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut calendar_obj := mydb.calendar.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
color: payload.color
|
||||
timezone: payload.timezone
|
||||
is_public: payload.is_public
|
||||
events: payload.events
|
||||
)!
|
||||
|
||||
calendar_obj = mydb.calendar.set(calendar_obj)!
|
||||
|
||||
return new_response_u32(request.id, calendar_obj.id)
|
||||
}
|
||||
|
||||
pub fn calendar_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CalendarDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.calendar.delete(payload.id)!
|
||||
|
||||
// returns
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn calendar_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
calendars := mydb.calendar.list()!
|
||||
return jsonrpc.new_response(request.id, json.encode(calendars))
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
|
||||
fn convert_iso_to_ourtime(iso_time string) !string {
|
||||
if iso_time.trim_space() == '' {
|
||||
return error('Empty time string')
|
||||
}
|
||||
|
||||
// Remove the 'Z' suffix if present
|
||||
mut cleaned := iso_time.replace('Z', '')
|
||||
|
||||
// Remove milliseconds (.000) if present
|
||||
if cleaned.contains('.') {
|
||||
cleaned = cleaned.all_before_last('.')
|
||||
}
|
||||
|
||||
// Replace 'T' with space
|
||||
cleaned = cleaned.replace('T', ' ')
|
||||
|
||||
return cleaned
|
||||
}
|
||||
|
||||
// CalendarEvent-specific argument structures
|
||||
|
||||
@[params]
|
||||
pub struct CalendarEventGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CalendarEventSetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
description string
|
||||
title string
|
||||
start_time string // use ourtime module to go from string to epoch
|
||||
end_time string // use ourtime module to go from string to epoch
|
||||
location string
|
||||
attendees []u32 // IDs of user groups
|
||||
fs_items []u32 // IDs of linked files or dirs
|
||||
calendar_id u32 // Associated calendar
|
||||
status heromodels.EventStatus
|
||||
is_all_day bool
|
||||
is_recurring bool
|
||||
recurrence []heromodels.RecurrenceRule
|
||||
reminder_mins []int // Minutes before event for reminders
|
||||
color string // Hex color code
|
||||
timezone string
|
||||
securitypolicy u32
|
||||
tags []string
|
||||
comments []db.CommentArg
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CalendarEventDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn calendar_event_get(handlerparams map[string]string, request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CalendarEventGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
name := handlerparams['name'] or { 'default' }
|
||||
mut mydb := heromodels.get(name)!
|
||||
calendar_event := mydb.calendar_event.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(calendar_event))
|
||||
}
|
||||
|
||||
pub fn calendar_event_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CalendarEventSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new() or { return jsonrpc.internal_error }
|
||||
start_time_converted := convert_iso_to_ourtime(payload.start_time) or {
|
||||
return jsonrpc.internal_error
|
||||
}
|
||||
end_time_converted := convert_iso_to_ourtime(payload.end_time) or {
|
||||
return jsonrpc.internal_error
|
||||
}
|
||||
|
||||
mut calendar_event_obj := mydb.calendar_event.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
title: payload.title
|
||||
start_time: start_time_converted
|
||||
end_time: end_time_converted
|
||||
location: payload.location
|
||||
attendees: payload.attendees
|
||||
fs_items: payload.fs_items
|
||||
calendar_id: payload.calendar_id
|
||||
status: payload.status
|
||||
is_all_day: payload.is_all_day
|
||||
is_recurring: payload.is_recurring
|
||||
recurrence: payload.recurrence
|
||||
reminder_mins: payload.reminder_mins
|
||||
color: payload.color
|
||||
timezone: payload.timezone
|
||||
securitypolicy: payload.securitypolicy
|
||||
tags: payload.tags
|
||||
comments: payload.comments
|
||||
) or { return jsonrpc.internal_error }
|
||||
|
||||
calendar_event_obj = mydb.calendar_event.set(calendar_event_obj) or {
|
||||
return jsonrpc.internal_error
|
||||
}
|
||||
|
||||
return new_response_u32(request.id, calendar_event_obj.id)
|
||||
}
|
||||
|
||||
pub fn calendar_event_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CalendarEventDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.calendar_event.delete(payload.id)!
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
// List all calendar events
|
||||
pub fn calendar_event_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
calendar_events := mydb.calendar_event.list()!
|
||||
return jsonrpc.new_response(request.id, json.encode(calendar_events))
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
// ChatGroup-specific argument structures
|
||||
|
||||
@[params]
|
||||
pub struct ChatGroupGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ChatGroupSetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
description string
|
||||
chat_type heromodels.ChatType
|
||||
last_activity i64
|
||||
is_archived bool
|
||||
securitypolicy u32
|
||||
tags []string
|
||||
comments []db.CommentArg
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ChatGroupDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn chat_group_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ChatGroupGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
chat_group := mydb.chat_group.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(chat_group))
|
||||
}
|
||||
|
||||
pub fn chat_group_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ChatGroupSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut chat_group_obj := mydb.chat_group.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
chat_type: payload.chat_type
|
||||
last_activity: payload.last_activity
|
||||
is_archived: payload.is_archived
|
||||
securitypolicy: payload.securitypolicy
|
||||
tags: payload.tags
|
||||
comments: payload.comments
|
||||
)!
|
||||
|
||||
chat_group_obj=mydb.chat_group.set( chat_group_obj)!
|
||||
|
||||
return new_response_u32(request.id, chat_group_obj.id)
|
||||
}
|
||||
|
||||
pub fn chat_group_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ChatGroupDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.chat_group.delete(payload.id)!
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn chat_group_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
chat_groups := mydb.chat_group.list()!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(chat_groups))
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
// ChatMessage-specific argument structures
|
||||
|
||||
@[params]
|
||||
pub struct ChatMessageGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ChatMessageSetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
description string
|
||||
content string
|
||||
chat_group_id u32
|
||||
sender_id u32
|
||||
parent_messages []heromodels.MessageLink
|
||||
fs_files []u32
|
||||
message_type heromodels.MessageType
|
||||
status heromodels.MessageStatus
|
||||
reactions []heromodels.MessageReaction
|
||||
mentions []u32
|
||||
securitypolicy u32
|
||||
tags []string
|
||||
comments []db.CommentArg
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ChatMessageDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn chat_message_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ChatMessageGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
chat_message := mydb.chat_message.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(chat_message))
|
||||
}
|
||||
|
||||
pub fn chat_message_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ChatMessageSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut chat_message_obj := mydb.chat_message.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
content: payload.content
|
||||
chat_group_id: payload.chat_group_id
|
||||
sender_id: payload.sender_id
|
||||
parent_messages: payload.parent_messages
|
||||
fs_files: payload.fs_files
|
||||
message_type: payload.message_type
|
||||
status: payload.status
|
||||
reactions: payload.reactions
|
||||
mentions: payload.mentions
|
||||
securitypolicy: payload.securitypolicy
|
||||
tags: payload.tags
|
||||
comments: payload.comments
|
||||
)!
|
||||
|
||||
chat_message_obj=mydb.chat_message.set( chat_message_obj)!
|
||||
|
||||
return new_response_u32(request.id, chat_message_obj.id)
|
||||
}
|
||||
|
||||
pub fn chat_message_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ChatMessageDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.chat_message.delete(payload.id)!
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn chat_message_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
chat_messages := mydb.chat_message.list()!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(chat_messages))
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
|
||||
// Comment-specific argument structures
|
||||
@[params]
|
||||
pub struct CommentGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CommentSetArgs {
|
||||
pub mut:
|
||||
comment string @[required]
|
||||
parent u32
|
||||
author u32
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct CommentDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn comment_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CommentGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
comment := mydb.comments.get(payload.id) or {
|
||||
// Return proper JSON-RPC error instead of panicking
|
||||
return jsonrpc.new_error(request.id, jsonrpc.RPCError{
|
||||
code: -32000 // Server error
|
||||
message: 'Comment not found'
|
||||
data: 'Comment with ID ${payload.id} does not exist'
|
||||
})
|
||||
}
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(comment))
|
||||
}
|
||||
|
||||
pub fn comment_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CommentSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut comment_obj := mydb.comments.new(
|
||||
comment: payload.comment
|
||||
parent: payload.parent
|
||||
author: payload.author
|
||||
)!
|
||||
|
||||
comment_obj = mydb.comments.set(comment_obj)!
|
||||
|
||||
return new_response_u32(request.id, comment_obj.id)
|
||||
}
|
||||
|
||||
pub fn comment_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[CommentDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.comments.delete(payload.id) or {
|
||||
// Return proper JSON-RPC error instead of panicking
|
||||
return jsonrpc.new_error(request.id, jsonrpc.RPCError{
|
||||
code: -32000 // Server error
|
||||
message: 'Comment not found'
|
||||
data: 'Comment with ID ${payload.id} does not exist or could not be deleted'
|
||||
})
|
||||
}
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn comment_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
comments := mydb.comments.list() or {
|
||||
// Return proper JSON-RPC error instead of panicking
|
||||
return jsonrpc.new_error(request.id, jsonrpc.RPCError{
|
||||
code: -32000 // Server error
|
||||
message: 'Failed to list comments'
|
||||
data: 'Error occurred while retrieving comments: ${err}'
|
||||
})
|
||||
}
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(comments))
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
|
||||
// Group-specific argument structures
|
||||
@[params]
|
||||
pub struct GroupGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct GroupSetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
description string
|
||||
members []heromodels.GroupMember
|
||||
subgroups []u32
|
||||
parent_group u32
|
||||
is_public bool
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct GroupDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn group_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[GroupGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
group := mydb.group.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(group))
|
||||
}
|
||||
|
||||
pub fn group_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[GroupSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut group_obj := mydb.group.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
members: payload.members
|
||||
subgroups: payload.subgroups
|
||||
parent_group: payload.parent_group
|
||||
is_public: payload.is_public
|
||||
)!
|
||||
|
||||
group_obj=mydb.group.set( group_obj)!
|
||||
|
||||
return new_response_u32(request.id, group_obj.id)
|
||||
}
|
||||
|
||||
pub fn group_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[GroupDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.group.delete(payload.id)!
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn group_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
groups := mydb.group.list()!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(groups))
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
|
||||
// Project-specific argument structures
|
||||
@[params]
|
||||
pub struct ProjectGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ProjectSetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
description string
|
||||
swimlanes []heromodels.Swimlane
|
||||
milestones []heromodels.Milestone
|
||||
issues []string
|
||||
fs_files []u32
|
||||
status heromodels.ProjectStatus
|
||||
start_date string // Use ourtime module to convert to epoch
|
||||
end_date string // Use ourtime module to convert to epoch
|
||||
securitypolicy u32
|
||||
tags []string
|
||||
comments []db.CommentArg
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ProjectDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn project_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ProjectGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
project := mydb.project.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(project))
|
||||
}
|
||||
|
||||
pub fn project_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ProjectSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut project_obj := mydb.project.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
swimlanes: payload.swimlanes
|
||||
milestones: payload.milestones
|
||||
issues: payload.issues
|
||||
fs_files: payload.fs_files
|
||||
status: payload.status
|
||||
start_date: payload.start_date
|
||||
end_date: payload.end_date
|
||||
securitypolicy: payload.securitypolicy
|
||||
tags: payload.tags
|
||||
comments: payload.comments
|
||||
)!
|
||||
|
||||
project_obj = mydb.project.set(project_obj)!
|
||||
|
||||
return new_response_u32(request.id, project_obj.id)
|
||||
}
|
||||
|
||||
pub fn project_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ProjectDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.project.delete(payload.id)!
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn project_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
projects := mydb.project.list()!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(projects))
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
import freeflowuniverse.herolib.hero.db
|
||||
// ProjectIssue-specific argument structures
|
||||
|
||||
@[params]
|
||||
pub struct ProjectIssueGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ProjectIssueSetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
description string
|
||||
title string
|
||||
project_id u32
|
||||
issue_type heromodels.IssueType
|
||||
priority heromodels.IssuePriority
|
||||
status heromodels.IssueStatus
|
||||
swimlane string
|
||||
assignees []u32
|
||||
reporter u32
|
||||
milestone string
|
||||
deadline string // Use ourtime module to convert to epoch
|
||||
estimate int
|
||||
fs_files []u32
|
||||
parent_id u32
|
||||
children []u32
|
||||
securitypolicy u32
|
||||
tags []string
|
||||
comments []db.CommentArg
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ProjectIssueDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn project_issue_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ProjectIssueGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
project_issue := mydb.project_issue.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(project_issue))
|
||||
}
|
||||
|
||||
pub fn project_issue_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ProjectIssueSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut project_issue_obj := mydb.project_issue.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
title: payload.title
|
||||
project_id: payload.project_id
|
||||
issue_type: payload.issue_type
|
||||
priority: payload.priority
|
||||
status: payload.status
|
||||
swimlane: payload.swimlane
|
||||
assignees: payload.assignees
|
||||
reporter: payload.reporter
|
||||
milestone: payload.milestone
|
||||
deadline: payload.deadline
|
||||
estimate: payload.estimate
|
||||
fs_files: payload.fs_files
|
||||
parent_id: payload.parent_id
|
||||
children: payload.children
|
||||
securitypolicy: payload.securitypolicy
|
||||
tags: payload.tags
|
||||
comments: payload.comments
|
||||
)!
|
||||
|
||||
project_issue_obj=mydb.project_issue.set( project_issue_obj)!
|
||||
|
||||
return new_response_u32(request.id, project_issue_obj.id)
|
||||
}
|
||||
|
||||
pub fn project_issue_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[ProjectIssueDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.project_issue.delete(payload.id)!
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn project_issue_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
project_issues := mydb.project_issue.list()!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(project_issues))
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
module rpc
|
||||
|
||||
import json
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc { Request, Response, new_response_true, new_response_u32 }
|
||||
import freeflowuniverse.herolib.hero.heromodels
|
||||
|
||||
// User-specific argument structures
|
||||
@[params]
|
||||
pub struct UserGetArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct UserSetArgs {
|
||||
pub mut:
|
||||
name string @[required]
|
||||
description string
|
||||
email string
|
||||
public_key string // for encryption/signing
|
||||
phone string
|
||||
address string
|
||||
avatar_url string
|
||||
bio string
|
||||
timezone string
|
||||
status heromodels.UserStatus
|
||||
securitypolicy u32
|
||||
tags u32
|
||||
comments []u32
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct UserDeleteArgs {
|
||||
pub mut:
|
||||
id u32 @[required]
|
||||
}
|
||||
|
||||
pub fn user_get(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[UserGetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
user := mydb.user.get(payload.id)!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(user))
|
||||
}
|
||||
|
||||
pub fn user_set(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[UserSetArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mut user_obj := mydb.user.new(
|
||||
name: payload.name
|
||||
description: payload.description
|
||||
email: payload.email
|
||||
public_key: payload.public_key
|
||||
phone: payload.phone
|
||||
address: payload.address
|
||||
avatar_url: payload.avatar_url
|
||||
bio: payload.bio
|
||||
timezone: payload.timezone
|
||||
status: payload.status
|
||||
securitypolicy: payload.securitypolicy
|
||||
tags: payload.tags
|
||||
comments: payload.comments
|
||||
)!
|
||||
|
||||
user_obj=mydb.user.set( user_obj)!
|
||||
|
||||
return new_response_u32(request.id, user_obj.id)
|
||||
}
|
||||
|
||||
pub fn user_delete(request Request) !Response {
|
||||
payload := jsonrpc.decode_payload[UserDeleteArgs](request.params) or {
|
||||
return jsonrpc.invalid_params
|
||||
}
|
||||
|
||||
mut mydb := heromodels.new()!
|
||||
mydb.user.delete(payload.id)!
|
||||
|
||||
return new_response_true(request.id) // return true as jsonrpc (bool)
|
||||
}
|
||||
|
||||
pub fn user_list(request Request) !Response {
|
||||
mut mydb := heromodels.new()!
|
||||
users := mydb.user.list()!
|
||||
|
||||
return jsonrpc.new_response(request.id, json.encode(users))
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import json
|
||||
import net.http
|
||||
import veb
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
@['/auth/:action']
|
||||
pub fn (mut server HeroServer) auth_handler(mut ctx Context, action string) !veb.Result {
|
||||
@@ -88,10 +89,22 @@ pub fn (mut server HeroServer) api_handler(mut ctx Context, handler_type string)
|
||||
}
|
||||
|
||||
// Parse JSON-RPC request
|
||||
request := jsonrpc.decode_request(ctx.req.data) or {
|
||||
mut request := jsonrpc.decode_request(ctx.req.data) or {
|
||||
return ctx.request_error('Invalid JSON-RPC request: ${err}')
|
||||
}
|
||||
|
||||
if request.method.count('.') == 0 {
|
||||
return ctx.request_error('Invalid method format, expected actor.method')
|
||||
} else if request.method.count('.') == 1 {
|
||||
request.method = '${handler_type.to_lower()}.${request.method}'
|
||||
} else {
|
||||
if request.method.count('.') > 1 {
|
||||
return ctx.request_error('Invalid method format, too many dots. ${ctx.req.method}')
|
||||
}
|
||||
}
|
||||
console.print_debug('Handling request: ${request.method} with params: ${request.params}')
|
||||
// $dbg;
|
||||
|
||||
// Handle the request using the OpenRPC handler
|
||||
response := handler.handle(request) or { return ctx.server_error('Handler error: ${err}') }
|
||||
|
||||
|
||||
11
lib/hero/user/user.v
Normal file
11
lib/hero/user/user.v
Normal file
@@ -0,0 +1,11 @@
|
||||
module user
|
||||
|
||||
@[heap]
|
||||
pub struct UserRef {
|
||||
pub mut:
|
||||
id u32
|
||||
public_key string
|
||||
name string
|
||||
email string
|
||||
roles []string
|
||||
}
|
||||
@@ -11,8 +11,9 @@ import x.json2 as json
|
||||
pub struct Handler {
|
||||
pub mut:
|
||||
// A map where keys are method names and values are the corresponding procedure handler functions
|
||||
procedures map[string]ProcedureHandler
|
||||
params map[string]string
|
||||
procedures map[string]ProcedureHandler
|
||||
procedures_group map[string]ProcedureHandlerGroup
|
||||
servercontext map[string]string
|
||||
}
|
||||
|
||||
// ProcedureHandler is a function type that processes a JSON-RPC request payload and returns a response.
|
||||
@@ -23,6 +24,8 @@ pub mut:
|
||||
// If an error occurs during any of these steps, it should be returned.
|
||||
pub type ProcedureHandler = fn (request Request) !Response
|
||||
|
||||
pub type ProcedureHandlerGroup = fn (rpcid int, servercontext map[string]string, actorname string, methodname string, params string) !Response
|
||||
|
||||
// new_handler creates a new JSON-RPC handler with the specified procedure handlers.
|
||||
//
|
||||
// Parameters:
|
||||
@@ -62,13 +65,22 @@ pub fn (mut handler Handler) register_procedure_void[T](method string, function
|
||||
handler.procedures[procedure.method] = procedure.handle
|
||||
}
|
||||
|
||||
// // register_procedure registers a new procedure handler for the specified method.
|
||||
// //
|
||||
// // Parameters:
|
||||
// // - method: The name of the method to register
|
||||
// // - procedure: The procedure handler function to register
|
||||
// pub fn (mut handler Handler) register_procedure(method string, procedure ProcedureHandler) {
|
||||
// handler.procedures[method] = procedure
|
||||
// }
|
||||
|
||||
// register_procedure registers a new procedure handler for the specified method.
|
||||
//
|
||||
// Parameters:
|
||||
// - method: The name of the method to register
|
||||
// - procedure: The procedure handler function to register
|
||||
pub fn (mut handler Handler) register_procedure_handle(method string, procedure ProcedureHandler) {
|
||||
handler.procedures[method] = procedure
|
||||
// - procedure: The procedure handler group function to register
|
||||
pub fn (mut handler Handler) register_api_handler(groupname string, procedure_group ProcedureHandlerGroup) {
|
||||
handler.procedures_group[groupname] = procedure_group
|
||||
}
|
||||
|
||||
pub struct Procedure[T, U] {
|
||||
@@ -158,12 +170,46 @@ fn error_to_jsonrpc(err IError) !RPCError {
|
||||
// Returns:
|
||||
// - The JSON-RPC response as a string, or an error if processing fails
|
||||
pub fn (handler Handler) handle(request Request) !Response {
|
||||
if request.method.contains('.') {
|
||||
parts := request.method.split('.')
|
||||
mut groupname := ''
|
||||
mut actorname := ''
|
||||
mut methodname := ''
|
||||
if parts.len == 2 {
|
||||
groupname = 'default'
|
||||
actorname = parts[0]
|
||||
methodname = parts[1]
|
||||
} else if parts.len == 3 {
|
||||
groupname = parts[0]
|
||||
actorname = parts[1]
|
||||
methodname = parts[2]
|
||||
} else {
|
||||
return new_error(request.id, invalid_params)
|
||||
}
|
||||
procedure_group := handler.procedures_group[groupname] or {
|
||||
return new_error(request.id, RPCError{
|
||||
code: -32602
|
||||
message: 'Could not find procedure group ${groupname} in function on rpc request.'
|
||||
data: '${request}'
|
||||
})
|
||||
}
|
||||
return procedure_group(request.id, handler.servercontext, actorname, methodname,
|
||||
request.params) or {
|
||||
// Return proper JSON-RPC error instead of panicking
|
||||
return new_error(request.id, RPCError{
|
||||
code: -32603
|
||||
message: 'Error in function on rpc request.'
|
||||
data: '${request}\n${err}'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
procedure_func := handler.procedures[request.method] or {
|
||||
return new_error(request.id, method_not_found)
|
||||
}
|
||||
|
||||
// Execute the procedure handler with the request payload
|
||||
return procedure_func(handler.params, request) or {
|
||||
return procedure_func(request) or {
|
||||
// Return proper JSON-RPC error instead of panicking
|
||||
return new_error(request.id, RPCError{
|
||||
code: -32603
|
||||
|
||||
@@ -51,6 +51,7 @@ pub const internal_error = RPCError{
|
||||
// RPCError represents a JSON-RPC 2.0 error object as defined in the specification.
|
||||
// Error objects contain a code, message, and optional data field to provide
|
||||
// more information about the error that occurred.
|
||||
@[params]
|
||||
pub struct RPCError {
|
||||
pub mut:
|
||||
// Numeric error code. Predefined codes are in the range -32768 to -32000.
|
||||
|
||||
@@ -22,8 +22,6 @@ pub mut:
|
||||
// An identifier established by the client that must be included in the response
|
||||
// This is used to correlate requests with their corresponding responses
|
||||
id int @[required]
|
||||
|
||||
handler_params map[string]string
|
||||
}
|
||||
|
||||
// new_request creates a new JSON-RPC request with the specified method and parameters.
|
||||
@@ -52,7 +50,19 @@ pub fn new_request(method string, params string) Request {
|
||||
// Returns:
|
||||
// - A Request object or an error if parsing fails
|
||||
pub fn decode_request(data string) !Request {
|
||||
return json2.decode[Request](data)!
|
||||
mut r2 := json2.decode[json2.Any](data)!
|
||||
mut r3 := r2.as_map()
|
||||
a := r3['jsonrpc'].str()
|
||||
b := r3['method'].str()
|
||||
c := r3['params'].str()
|
||||
d := r3['id'].int()
|
||||
mut r4 := Request{
|
||||
jsonrpc: a
|
||||
method: b
|
||||
params: c
|
||||
id: d
|
||||
}
|
||||
return r4
|
||||
}
|
||||
|
||||
// encode serializes the Request object into a JSON string.
|
||||
|
||||
@@ -48,6 +48,14 @@ pub fn new_response_true(id int) Response {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_response_ok(id int) Response {
|
||||
return Response{
|
||||
jsonrpc: jsonrpc_version
|
||||
result: ''
|
||||
id: id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_response_false(id int) Response {
|
||||
return Response{
|
||||
jsonrpc: jsonrpc_version
|
||||
@@ -88,6 +96,9 @@ pub fn new_error_response(id int, error RPCError) Response {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// decode_response parses a JSON string into a Response object.
|
||||
// This function handles the complex validation rules for JSON-RPC responses.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user