Compare commits
1 Commits
developmen
...
herodb_cli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55ebaa4d68 |
34
examples/clients/herodb.vsh
Normal file
34
examples/clients/herodb.vsh
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -enable-globals run
|
||||||
|
|
||||||
|
import incubaid.herolib.clients.herodb
|
||||||
|
|
||||||
|
// Initialize the client
|
||||||
|
mut client := herodb.new(herodb.Config{
|
||||||
|
url: 'http://localhost:3000'
|
||||||
|
})!
|
||||||
|
|
||||||
|
println('Connecting to HeroDB at ${client.server_url}...')
|
||||||
|
|
||||||
|
// List instances
|
||||||
|
instances := client.list_instances()!
|
||||||
|
|
||||||
|
println('Found ${instances.len} instances:')
|
||||||
|
|
||||||
|
for instance in instances {
|
||||||
|
println('----------------------------------------')
|
||||||
|
println('Index: ${instance.index}')
|
||||||
|
println('Name: ${instance.name}')
|
||||||
|
println('Created At: ${instance.created_at}')
|
||||||
|
|
||||||
|
// Parse backend info
|
||||||
|
backend := instance.get_backend_info() or {
|
||||||
|
println('Backend: Unknown/Error (${err})')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
println('Backend Type: ${backend.type_name}')
|
||||||
|
if backend.path != '' {
|
||||||
|
println('Backend Path: ${backend.path}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println('----------------------------------------')
|
||||||
52
lib/clients/herodb/README.md
Normal file
52
lib/clients/herodb/README.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# HeroDB Client
|
||||||
|
|
||||||
|
A V client library for interacting with the HeroDB JSON-RPC API.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Connects to HeroDB's JSON-RPC server (default port 3000).
|
||||||
|
- Lists running database instances.
|
||||||
|
- Parses polymorphic backend types (InMemory, Redb, LanceDb).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```v
|
||||||
|
import incubaid.herolib.clients.herodb
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Initialize the client
|
||||||
|
mut client := herodb.new(herodb.Config{
|
||||||
|
url: 'http://localhost:3000'
|
||||||
|
})!
|
||||||
|
|
||||||
|
// List instances
|
||||||
|
instances := client.list_instances()!
|
||||||
|
|
||||||
|
for instance in instances {
|
||||||
|
println('Index: ${instance.index}')
|
||||||
|
println('Name: ${instance.name}')
|
||||||
|
|
||||||
|
// Parse backend info
|
||||||
|
backend := instance.get_backend_info()!
|
||||||
|
println('Backend: ${backend.type_name}')
|
||||||
|
if backend.path != '' {
|
||||||
|
println('Path: ${backend.path}')
|
||||||
|
}
|
||||||
|
println('---')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### `fn new(cfg Config) !HeroDB`
|
||||||
|
|
||||||
|
Creates a new HeroDB client instance.
|
||||||
|
|
||||||
|
### `fn (mut self HeroDB) list_instances() ![]InstanceMetadata`
|
||||||
|
|
||||||
|
Retrieves a list of all currently loaded database instances.
|
||||||
|
|
||||||
|
### `fn (m InstanceMetadata) get_backend_info() !BackendInfo`
|
||||||
|
|
||||||
|
Helper method to parse the `backend_type` field from `InstanceMetadata` into a structured `BackendInfo` object.
|
||||||
127
lib/clients/herodb/herodb.v
Normal file
127
lib/clients/herodb/herodb.v
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
module herodb
|
||||||
|
|
||||||
|
import json
|
||||||
|
import incubaid.herolib.core.httpconnection
|
||||||
|
|
||||||
|
// JSON-RPC 2.0 Structures
|
||||||
|
|
||||||
|
struct JsonRpcRequest {
|
||||||
|
jsonrpc string = '2.0'
|
||||||
|
method string
|
||||||
|
params []string
|
||||||
|
id int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct JsonRpcResponse[T] {
|
||||||
|
jsonrpc string
|
||||||
|
result T
|
||||||
|
error ?JsonRpcError
|
||||||
|
id int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct JsonRpcError {
|
||||||
|
code int
|
||||||
|
message string
|
||||||
|
data string
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeroDB Specific Structures
|
||||||
|
|
||||||
|
pub struct InstanceMetadata {
|
||||||
|
pub:
|
||||||
|
index int
|
||||||
|
name string
|
||||||
|
// backend_type can be a string ("InMemory") or an object ({"Redb": "path"}).
|
||||||
|
// We use the `raw` attribute to capture the raw JSON and parse it manually.
|
||||||
|
backend_type string @[raw]
|
||||||
|
created_at string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper struct to represent the parsed backend info in a usable way
|
||||||
|
pub struct BackendInfo {
|
||||||
|
pub:
|
||||||
|
type_name string // "InMemory", "Redb", "LanceDb"
|
||||||
|
path string // Empty for InMemory
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HeroDB {
|
||||||
|
pub:
|
||||||
|
server_url string
|
||||||
|
pub mut:
|
||||||
|
conn ?&httpconnection.HTTPConnection
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Config {
|
||||||
|
pub:
|
||||||
|
url string = 'http://localhost:3000'
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(cfg Config) !HeroDB {
|
||||||
|
return HeroDB{
|
||||||
|
server_url: cfg.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self HeroDB) connection() !&httpconnection.HTTPConnection {
|
||||||
|
if mut conn := self.conn {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
mut new_conn := httpconnection.new(
|
||||||
|
name: 'herodb'
|
||||||
|
url: self.server_url
|
||||||
|
retry: 3
|
||||||
|
)!
|
||||||
|
self.conn = new_conn
|
||||||
|
return new_conn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut self HeroDB) rpc_call[T](method string) !T {
|
||||||
|
mut conn := self.connection()!
|
||||||
|
|
||||||
|
req := JsonRpcRequest{
|
||||||
|
method: method
|
||||||
|
id: 1
|
||||||
|
params: []
|
||||||
|
}
|
||||||
|
|
||||||
|
response := conn.post_json_generic[JsonRpcResponse[T]](
|
||||||
|
method: .post
|
||||||
|
prefix: ''
|
||||||
|
data: json.encode(req)
|
||||||
|
dataformat: .json
|
||||||
|
)!
|
||||||
|
|
||||||
|
if err := response.error {
|
||||||
|
return error('RPC Error ${err.code}: ${err.message}')
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self HeroDB) list_instances() ![]InstanceMetadata {
|
||||||
|
return self.rpc_call[[]InstanceMetadata]('db_listInstances')!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (m InstanceMetadata) get_backend_info() !BackendInfo {
|
||||||
|
if m.backend_type.len == 0 {
|
||||||
|
return error('empty backend_type')
|
||||||
|
}
|
||||||
|
if m.backend_type[0] == `"` {
|
||||||
|
// It's a string
|
||||||
|
val := json.decode(string, m.backend_type)!
|
||||||
|
return BackendInfo{
|
||||||
|
type_name: val
|
||||||
|
}
|
||||||
|
} else if m.backend_type[0] == `{` {
|
||||||
|
// It's an object
|
||||||
|
val := json.decode(map[string]string, m.backend_type)!
|
||||||
|
for k, v in val {
|
||||||
|
return BackendInfo{
|
||||||
|
type_name: k
|
||||||
|
path: v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error('unknown backend_type format: ${m.backend_type}')
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user