genpjrpc
genpjrpc - is a go code generator for pjrpc router and openapi (swagger) spec.
It's scans Go code with rpc service description including every usaged type and generates pjrpc
go code like protoc (gRPC) generator and generates openapi (swagger) specification.
See example in _examples/genpjrpc with go:generate command.
Install
go install gitlab.com/pjrpc/pjrpc/cmd/genpjrpc@latest
Usage
- You have to created package with RPC transport models, it must be allowed to marshal/unmarshal with JSON package.
- After that you can create interface with methods of your RPC service:
func Method(model.Req) model.Resp
.
- Now you can generate RPC wrappers for your future service with openapi spec.
cd ./package/with/service
genpjrpc -search.name=InterfaceName -print.place.path_swagger_file=./api/swagger.json
This command generated files:
# Go wrappers for server register func and real server interface.
./package/with/service/rpcserver/pjrpc_server_hello_service.go
# Go wrappers for client to the rpc serice.
./package/with/service/rpcclient/pjrpc_client_hello_service.go
# OpenAPI spec with rpc methods and every used type.
./package/with/service/api/swagger.json
Try to keep your transport models simple without system dependencies.
Your models will be scanned recursively so just not generate a new code into model's package.
go:generate
Also you can use go:generate
magic comment in the package with service interface.
// Service documentation.
//go:generate genpjrpc -search.name=Service -print.place.path_swagger_file=./api/swagger.json
type Service interface{
func Method(model.In) model.Out
}
After that you can run go generate ./...
command in the root of the project.
Restrictions
Supported types
- named types
- struct
- pointers
- slices
- basic types (bool, int, intX, uint, uintX, floatX, string)
- enum (named basic type with several constant values)
- any / any
- map[string]AnyType
- time.Time - it will be converted as string with RFC3339 format.
- github.com/google/uuid.UUID (string+uuid), github.com/shopspring/decimal.Decimal (string)
Hack: if you have special type with MarshalJSON/UnmarshalJSON methods from basic Go type, then you can use genpjrpc
struct tag.
Also you can use -search.known_types_path
flag to pass file with your rules of type convertor.
Example of the known_types.json
:
{
"github.com/google/uuid.UUID": { // Import Path + Type (host/project/repo.Type)
"basic_type": "string", // Golang basic type.
"format": "uuid" // OpenAPI type format (see Data Types in https://swagger.io/specification/).
}
}
Use named Go types only as the argument/return of methods.
type In string
type Slice []string
type Out struct {}
Names
Name of the method
Interface method's names will be converted to RPC methods by snake_case converter.
func HelloWorld(In) Out -> `hello_world` method.
You can set your special name by magic comment with param method_name
.
Field of the Struct.
Field's name will be converted in name for json.Decoder/Encoder.
You can use json:"name"
tag in the field otherwise origin Go field's name will be used.
Generator features
You can put a magic comment around interface-srvice's method to pass genpjrpc params:
//genpjrpc:params method_name=special_method_name swagger_tags=Swagger,Tags
- method_name - allows to set your own name of the method.
- swagger_tags - allows to set tags in openapi spec for method.
Full example:
type NamedType struct {
Field decimal.Decimal `json:"field,omitempty" genpjrpc:"type:string,deprecated:true"`
}
- json.field - will be the name of the object's property.
- json.omitempty - will mark object's property as optional.
- genpjrpc.type - basic type of the type with own MarshalJSON, UnmarshalJSON methods.
- genpjrpc.deprecated - will mark object's property as deprecated.
Feel free to skip any of them.
Pre filled openapi spec
You can pass your own openapi spec as a base of the generator.
For example you can set info
, servers
, security
and components.securitySchemes
.
You have to create the swagger_data
with openapi spec binded to rpc service.
Example of the swagger_data.json
:
{
"InterfaceServiceName": {
"info": {
"title": "Title of the Service"
},
"servers": [
{
"url": "/rpc"
}
],
"components": {
"securitySchemes": {
"basicAuth": {
"type": "http",
"description": "basic auth of the service",
"scheme": "basic"
}
}
},
"security": [
{
"basicAuth": []
}
]
}
}
After that you can put this file in the config parameter:
genpjrpc -print.content.swagger_data_path=/path/to/swagger_data.json
Config
You can see help with genpjrpc -h
command.
-config string
path to config file
-example_config
prints example of the json config
-example_env
prints example of the env config
-log.debug
prints debug messages of the generator
-log.no_color
prints log messages without color
-log.pretty
prints pretty log messages (default true)
-log.quiet
does not print any messages other than errors
-print.content.hide_version
do not prints app version in the generated files
-print.content.swagger_data_path string
path to file with swagger additional data
-print.content.swagger_info_version string
version of the service in the swagger spec 'info.version' (default "v0.0.0-unknown")
-print.content.tags_clients string
prints additional tags to client generated file, example: 'go:build some_tag'
-print.content.tags_server string
prints additional tags to server generated file, example: 'go:build some_tag'
-print.content.with_service_name
adds service name as prefix of the method name
-print.place.path_client string
path to write generated file with client side code (default "./rpcclient")
-print.place.path_server string
path to write generated file with server side code (default "./rpcserver")
-print.place.path_swagger_file string
path to file with swagger spec (/path/to/swagger.json)
-print.place.stdout
prints generated files to stdout
-search.name string
Name of the interface to generate rpc service
-search.path string
directory of the searching (default ".")
-search.known_types_path string
path to file with known types
-timeout duration
timeout for analysis and code printer (default 1m0s)
-version
prints version of the app
You can set the empty string in print.place.path_client
or print.place.path_server
flags
to disable generator of this files. Or you can set the same directory,
BUT avoid to generate it inside model's package.
Also you can pass json config file in -config=/path/to/config.json
flag.
JSON config example
{
"Log": {
"Debug": false,
"Quiet": false,
"Pretty": true,
"NoColor": false
},
"Search": {
"Name": "",
"Path": ".",
"KnownTypesPath": ""
},
"Print": {
"Place": {
"Stdout": false,
"PathServer": "./rpcserver",
"PathClient": "./rpcclient",
"PathSwaggerFile": ""
},
"Content": {
"HideVersion": false,
"TagsServer": "",
"TagsClients": "",
"WithServiceName": false,
"SwaggerDataPath": "",
"SwaggerInfoVersion": "v0.0.0-unknown"
}
}
}