Skip to content

rpc.openrpc #

OpenRPC

OpenRPC V library. Model for OpenRPC, client code generation, and specification generation from code.

Definitions

  • OpenRPC Specifications: Specifications that define standards for describing JSON-RPC API's.

  • OpenRPC Document: "A document that defines or describes an API conforming to the OpenRPC Specification."

  • OpenRPC Client: An API Client (using either HTTP or Websocket) that governs functions (one per RPC Method defined in OpenRPC Document) to communicate with RPC servers and perform RPCs.

OpenRPC Document Generation

The OpenRPC Document Generator generates a JSON-RPC API description conforming to OpenRPC Specifications, from an OpenRPC Client module written in V.

To use the document generator, you need to have a V module with at least one V file.

The recommended way to generate an OpenRPC document for a V module is to use the OpenRPC CLI. Note below: if you are not using the openrpc cli as a binary executable, replace openrpc with path_to_crystallib.core.openrpc/cli/cli.v in the commands below

openrpc docgen .

Running this command in a V client module's directory will generate an OpenRPC document from the code in the module and output it to a openrpc.json file in the same directory. See annotation code for openrpc document generation for information on how to format V client module to be compatible for OpenRPC Document Generation.

The following output parameter and source path argument can be used to generate an OpenRPC Document for a module that is in a different directory, and output the document in a desired path.

openrpc docgen -o <output_path> <source_path>

Run openrpc docgen help for more information. The CLI also has flags for filtering files and directories on input source, or choosing to generate document for only public struct and functions.

Annotating code for OpenRPC Document Generation

The docgen module uses the codeparser module to parse the source code for document generation. Therefore, the V code from which an OpenRPC Document will be generated must conform to the V Annotation guidelines for code parsing, such that the document generator can harvest method and schema information such as descriptions from the comments in the code.

Below is an example OpenRPC compliant JSON Method and Schema descriptions generated from a properly annotated v file.

// this is a description of the struct
struct Example {
    field0 string // this comment describes field0
    field1 int // this comment describes field1
}

// some_function is described by the words following the functions name
// - param0: this sentence after the colon describes param0
// - param1: this sentence after the colon describes param1
// returns the desired result, this sentence after the comma describes 'the desired result'
fn some_function(param0 string, param1 int) result []string {}

The following OpenRPC JSON Descriptions are generated from the above code:

// schema generated from Example struct
{
    'name': 'Example'
    'description': 'this is a description of the struct'
    'properties': [
        'field0': {
            'type': 'string'
        },
        'field1': {
            'type': 'int'
        }
    ]
}

// method generated from some_function function
{
    'name': 'some_function'
    'description': 'is described by the words following the functions name'
    'params': [
        {
            'name': 'param0'
            'description': 'this sentence after the colon describes param0'
            'schema': {
                'type': 'string'
            }
        },
        {
            'name': 'param1'
            'description': 'this sentence after the colon describes param1'
            'schema': {
                'type': 'int'
            }
        }
    ]
    'result': {
        'name': 'the desired result'
        'description': 'this sentence after the comma describes \'the desired result\''
        'schema': {
            'type': 'array'
            'items': {
                'type': 'string'
            }
        }
    }
}

Examples

The best way to understand how the document generation works is through the examples in this module

Pet Store Example

Run this command from the root of the openrpc module.

    v run cli/cli.v docgen -t 'PetStore API' -o examples/petstore_client -f 'client.v' examples/petstore_client

This generates an OpenRPC Document called PetStore API from the code in examples/petstore_client, excluding the client.v file, and writes it to examples/petstore_client/openrpc.json

fn decode #

fn decode(data string) !OpenRPC

fn docgen #

fn docgen(config DocGenConfig) !OpenRPC

docgen returns OpenRPC Document struct for JSON-RPC API defined in the config params. returns generated OpenRPC struct which can be encoded into json using OpenRPC.encode()

fn export_playground #

fn export_playground(config PlaygroundConfig) !

fn fn_to_method #

fn fn_to_method(function Function) Method

fn_to_method turns a codemodel function into a openrpc method description

fn generate_example_val #

fn generate_example_val(field StructField) string

fn new_playground #

fn new_playground(config PlaygroundConfig) !&Playground

fn parse_example_pairing #

fn parse_example_pairing(text_ string) !ExamplePairing

fn parse_pairing_params #

fn parse_pairing_params(text_ string) []ExampleRef

fn parse_pairing_result #

fn parse_pairing_result(text_ string) ExampleRef

fn parse_struct_example #

fn parse_struct_example(structure Struct) Example

fn prune #

fn prune(obj Any) Any

prune recursively prunes a map of Any type, pruning map keys where the value is the default value of the variable. this treats undefined values as null, which is ok for openrpc document encoding.

fn result_to_descriptor #

fn result_to_descriptor(result codemodel.Result) ContentDescriptorRef

get_param_descriptors returns content descriptors generated for a list of params

fn (ContentDescriptorRef) to_result #

fn (cd ContentDescriptorRef) to_result() !codemodel.Result

struct Components #

struct Components {
pub mut:
	content_descriptors     map[string]ContentDescriptorRef @[json: contentDescriptors] // An object to hold reusable Content Descriptor Objects.
	schemas                 map[string]SchemaRef // An object to hold reusable Schema Objects.
	examples                map[string]Example   // An object to hold reusable Example Objects.
	links                   map[string]Link      // An object to hold reusable Link Objects.
	error                   map[string]Error     // An object to hold reusable Error Objects.
	example_pairing_objects map[string]ExamplePairing @[json: examplePairingObjects] // An object to hold reusable Example Pairing Objects.
	tags                    map[string]Tag // An object to hold reusable Tag Objects.
}

Todo: enforce regex requirementsHolds a set of reusable objects for different aspects of the OpenRPC. All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object. All the fixed fields declared above are objects that MUST use keys that match the regular expression: ^[a-zA-Z0-9.-_]+$

struct Contact #

struct Contact {
	name  string @[omitempty] // The identifying name of the contact person/organization.
	email string @[omitempty] // The URL pointing to the contact information. MUST be in the format of a URL.
	url   string @[omitempty] // The email address of the contact person/organization. MUST be in the format of an email address.
}

Contact information for the exposed API.

struct ContentDescriptor #

struct ContentDescriptor {
pub mut:
	name        string    @[omitempty] // Name of the content that is being described. If the content described is a method parameter assignable by-name, this field SHALL define the parameter’s key (ie name).
	summary     string    @[omitempty] // A short summary of the content that is being described.
	description string    @[omitempty] // A verbose explanation of the content descriptor behavior.
	required    bool      @[omitempty] // Determines if the content is a required field. Default value is false.
	schema      SchemaRef @[omitempty] // Schema that describes the content.
	deprecated  bool      @[omitempty] // Specifies that the content is deprecated and SHOULD be transitioned out of usage. Default value is false.
}

Content Descriptors are objects that do just as they suggest - describe content. They are reusable ways of describing either parameters or result. They MUST have a schema.

fn (ContentDescriptor) to_code #

fn (cd ContentDescriptor) to_code() !codemodel.Param

struct DocGenConfig #

@[params]
struct DocGenConfig {
	title         string // Title of the JSON-RPC API
	description   string // Description of the JSON-RPC API
	version       string = '1.0.0' // OpenRPC Version used
	source        string   // Source code directory to generate doc from
	strict        bool     // Strict mode generates document for only methods and struct with the attribute `openrpc`
	exclude_dirs  []string // directories to be excluded when parsing source for document generation
	exclude_files []string // files to be excluded when parsing source for document generation
	only_pub      bool     // excludes all non-public declarations from document generation
}

configuration parameters for OpenRPC Document generation.

struct Error #

struct Error {
	code    int    // A Number that indicates the error type that occurred. This MUST be an integer. The error codes from and including -32768 to -32000 are reserved for pre-defined errors. These pre-defined errors SHOULD be assumed to be returned from any JSON-RPC api.
	message string // A String providing a short description of the error. The message SHOULD be limited to a concise single sentence.
	data    string // A Primitive or Structured value that contains additional information about the error. This may be omitted. The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).
}

Todo: handle any type for data fieldDefines an application level error.

struct Example #

struct Example {
	name           string @[omitempty]                      // Cannonical name of the example.
	summary        string @[omitempty]                      // Short description for the example.
	description    string @[omitempty]                      // A verbose explanation of the example.
	value          string @[omitempty]                      // Embedded literal example. The value field and externalValue field are mutually exclusive. To represent examples of media types that cannot naturally represented in JSON, use a string value to contain the example, escaping where necessary.
	external_value string @[json: externalValue; omitempty] // A URL that points to the literal example. This provides the capability to reference examples that cannot easily be included in JSON documents. The value field and externalValue field are mutually exclusive.
}

The Example object is an object that defines an example that is intended to match the schema of a given Content Descriptor. Question: how to handle any type for value?

struct ExamplePairing #

struct ExamplePairing {
pub mut:
	name        string       @[omitempty] // Name for the example pairing.
	description string       @[omitempty] // A verbose explanation of the example pairing.
	summary     string       @[omitempty] // Short description for the example pairing.
	params      []ExampleRef @[omitempty] // Example parameters.
	result      ExampleRef   @[omitempty] // Example result. When undefined, the example pairing represents usage of the method as a notification.
}

The Example Pairing object consists of a set of example params and result. The result is what you can expect from the JSON-RPC service given the exact params.

struct ExternalDocs #

struct ExternalDocs {
	description string // A verbose explanation of the target documentation.
	url         string // The URL for the target documentation. Value MUST be in the format of a URL.
}

Allows referencing an external resource for extended documentation.

struct Info #

struct Info {
pub:
	title            string // The title of the application.
	description      string // A verbose description of the application.
	terms_of_service string  @[json: termsOfService] // A URL to the Terms of Service for the API. MUST be in the format of a URL.
	contact          Contact @[omitempty]            // The contact information for the exposed API.
	license          License @[omitempty]            // The license information for the exposed API.
	version          string  @[omitempty]            // The version of the OpenRPC document (which is distinct from the OpenRPC Specification version or the API implementation version).
}

The object provides metadata about the API. The metadata MAY be used by the clients if needed, and MAY be presented in editing or documentation generation tools for convenience.

struct License #

struct License {
	name string @[omitempty] // The license name used for the API.
	url  string @[omitempty] // A URL to the license used for the API. MUST be in the format of a URL.
}

License information for the exposed API.

struct Method #

struct Method {
pub mut:
	name            string                 @[omitempty]                       // The cannonical name for the method. The name MUST be unique within the methods array.
	tags            []TagRef               @[omitempty]                       // A list of tags for API documentation control. Tags can be used for logical grouping of methods by resources or any other qualifier.
	summary         string                 @[omitempty]                       // A short summary of what the method does.
	description     string                 @[omitempty]                       // A verbose explanation of the method behavior.
	external_docs   ExternalDocs           @[json: externalDocs; omitempty]   // Additional external documentation for this method.
	params          []ContentDescriptorRef @[omitempty]                       // A list of parameters that are applicable for this method. The list MUST NOT include duplicated parameters and therefore require name to be unique. The list can use the Reference Object to link to parameters that are defined by the Content Descriptor Object. All optional params (content descriptor objects with “required”: false) MUST be positioned after all required params in the list.
	result          ContentDescriptorRef   @[omitempty]                       // The description of the result returned by the method. If defined, it MUST be a Content Descriptor or Reference Object. If undefined, the method MUST only be used as a notification.
	deprecated      bool                   @[omitempty]                       // Declares this method to be deprecated. Consumers SHOULD refrain from usage of the declared method. Default value is false.
	servers         []Server               @[omitempty]                       // An alternative servers array to service this method. If an alternative servers array is specified at the Root level, it will be overridden by this value.
	errors          []ErrorRef             @[omitempty]                       // A list of custom application defined errors that MAY be returned. The Errors MUST have unique error codes.
	links           []LinkRef              @[omitempty]                       // A list of possible links from this method call.
	param_structure ParamStructure         @[json: paramStructure; omitempty] // The expected format of the parameters. As per the JSON-RPC 2.0 specification, the params of a JSON-RPC request object may be an array, object, or either (represented as by-position, by-name, and either respectively). When a method has a paramStructure value of by-name, callers of the method MUST send a JSON-RPC request object whose params field is an object. Further, the key names of the params object MUST be the same as the contentDescriptor.names for the given method. Defaults to "either".
	examples        []ExamplePairing       @[omitempty]                       // Array of Example Pairing Object where each example includes a valid params-to-result Content Descriptor pairing.
}

Describes the interface for the given method name. The method name is used as the method field of the JSON-RPC body. It therefore MUST be unique.

Todo: make result optional once issue is solved: https://github.com/vlang/v/issues/18001

fn (Method) to_code #

fn (method Method) to_code() !Function

struct OpenRPC #

struct OpenRPC {
pub mut:
	openrpc       string = '1.0.0' // This string MUST be the semantic version number of the OpenRPC Specification version that the OpenRPC document uses.
	info          Info       // Provides metadata about the API.
	servers       []Server   // An array of Server Objects, which provide connectivity information to a target server.
	methods       []Method   // The available methods for the API.
	components    Components // An element to hold various schemas for the specification.
	external_docs []ExternalDocs @[json: externalDocs] // Additional external documentation.
}

This is the root object of the OpenRPC document. The contents of this object represent a whole OpenRPC document. How this object is constructed or stored is outside the scope of the OpenRPC Specification.

fn (OpenRPC) encode #

fn (doc OpenRPC) encode() !string

encode encodes an OpenRPC document struct into json string. eliminates undefined variable by calling prune on the initial encoding.

fn (OpenRPC) generate_client_file #

fn (o OpenRPC) generate_client_file(object_map map[string]Struct) !CodeFile

generate_structs geenrates struct codes for schemas defined in an openrpc document

fn (OpenRPC) generate_client_test_file #

fn (o OpenRPC) generate_client_test_file(methods_map map[string]Function, object_map map[string]Struct) !CodeFile

generate_structs generates struct codes for schemas defined in an openrpc document

fn (OpenRPC) generate_code #

fn (o OpenRPC) generate_code(receiver Struct, methods_map map[string]Function, objects_map map[string]Struct) !OpenRPCCode

fn (OpenRPC) generate_handler_file #

fn (o OpenRPC) generate_handler_file(receiver Struct, method_map map[string]Function, object_map map[string]Struct) !CodeFile

fn (OpenRPC) generate_handler_test_file #

fn (o OpenRPC) generate_handler_test_file(receiver Struct, method_map map[string]Function, object_map map[string]Struct) !CodeFile

fn (OpenRPC) generate_model #

fn (o OpenRPC) generate_model() ![]CodeItem

generate_structs geenrates struct codes for schemas defined in an openrpc document

fn (OpenRPC) generate_server_file #

fn (o OpenRPC) generate_server_file() !CodeFile

pub fn run_wsserver(port int) ! { mut logger := log.Logger(&log.Log{level: .debug}) mut handler := AccountantHandler{get(name: 'accountant')!} mut server := rpcwebsocket.new_rpcwsserver(port, handler.handle_ws, logger)! server.run()! }

fn (OpenRPC) generate_server_test_file #

fn (o OpenRPC) generate_server_test_file() !CodeFile

struct OpenRPCCode #

struct OpenRPCCode {
pub mut:
	openrpc_json File
	handler      CodeFile
	handler_test CodeFile
	client       CodeFile
	client_test  CodeFile
	server       CodeFile
	server_test  CodeFile
}

struct Playground #

struct Playground {
	vweb.Context
	build pathlib.Path @[vweb_global]
}

fn (Playground) index #

fn (mut pg Playground) index() vweb.Result

struct PlaygroundConfig #

@[params]
struct PlaygroundConfig {
pub:
	dest  pathlib.Path @[required]
	specs []pathlib.Path
}

struct Server #

struct Server {
pub:
	name        string                    @[omitempty] // A name to be used as the cannonical name for the server.
	url         RuntimeExpression         @[omitempty] // A URL to the target host. This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the OpenRPC document is being served. Server Variables are passed into the Runtime Expression to produce a server URL.
	summary     string                    @[omitempty] // A short summary of what the server is.
	description string                    @[omitempty] // An optional string describing the host designated by the URL.
	variables   map[string]ServerVariable @[omitempty] // A map between a variable name and its value. The value is passed into the Runtime Expression to produce a server URL.
}

An object representing a Server.

Todo: make variables field optional bug fixed: https://github.com/vlang/v/issues/18000

Todo: server name is required but not for version 1.0.0

struct ServerVariable #

struct ServerVariable {
	enum_       []string @[json: 'enum']              // An enumeration of string values to be used if the substitution options are from a limited set.
	default_    string   @[json: 'default'; required] // The default value to use for substitution, which SHALL be sent if an alternate value is not supplied. Note this behavior is different than the Schema Object’s treatment of default values, because in those cases parameter values are optional.
	description string   @[omitempty]                 // An optional description for the server variable. GitHub Flavored Markdown syntax MAY be used for rich text representation.
}

An object representing a Server Variable for server URL template substitution.

struct Tag #

struct Tag {
	name          string // The name of the tag.
	summary       string // A short summary of the tag.
	description   string // A verbose explanation for the tag.
	external_docs ExternalDocs @[json: externalDocs] // Additional external documentation for this tag.
}

Adds metadata to a single tag that is used by the Method Object. It is not mandatory to have a Tag Object per tag defined in the Method Object instances.