{"id":18403727,"url":"https://github.com/russellluo/kun","last_synced_at":"2025-04-07T07:32:47.700Z","repository":{"id":41857705,"uuid":"260721436","full_name":"RussellLuo/kun","owner":"RussellLuo","description":"A communication toolkit for Go services.","archived":false,"fork":false,"pushed_at":"2023-05-16T02:01:04.000Z","size":770,"stargazers_count":93,"open_issues_count":4,"forks_count":16,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-22T14:41:30.164Z","etag":null,"topics":["go-kit","gokit","golang","grpc","http"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/RussellLuo/kun","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RussellLuo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-02T15:52:45.000Z","updated_at":"2024-11-04T07:35:30.000Z","dependencies_parsed_at":"2024-06-18T18:28:26.811Z","dependency_job_id":"e7e462d4-5850-4ad6-9482-ba613c45751f","html_url":"https://github.com/RussellLuo/kun","commit_stats":null,"previous_names":["russellluo/kok"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fkun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fkun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fkun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fkun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RussellLuo","download_url":"https://codeload.github.com/RussellLuo/kun/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247612515,"owners_count":20966768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go-kit","gokit","golang","grpc","http"],"created_at":"2024-11-06T02:48:01.915Z","updated_at":"2025-04-07T07:32:45.530Z","avatar_url":"https://github.com/RussellLuo.png","language":"Go","readme":"# kun\n\nkun is a communication toolkit for Go services. It concentrates on handling the communications between Go services, to free developers to focus on the business logic.\n\nUltimately, kun may support the following communication types:\n\n- In-process function call\n- RPC (e.g., HTTP and gRPC)\n- Asynchronous messaging\n- Cron Jobs\n\n中文博客：[Go 服务通信工具 Kun](http://russellluo.com/2021/12/kun.html)。\n\n\n## The Zen of kun\n\n- **Focus on the most valuable things**\n\n    Service communication is important, but is less important than the service itself (i.e., your business value).\n\n    Furthermore, it should be effortless to change the communication types.\n\n- **Write code in Go whenever possible**\n\n    Prefer Go to other DSLs (e.g., [OpenAPI](https://spec.openapis.org/oas/latest.html), [Protocol Buffers](https://developers.google.com/protocol-buffers) or [AsyncAPI](https://www.asyncapi.com/)) for service definitions.\n\n- **Maintainability counts**\n\n    Embrace the spirit of [the Clean Architecture][1] for non-trivial applications.\n\n\n## Features\n\n1. Code Generation Tool\n\n    - [x] HTTP\n        + [x] HTTP Server\n        + [x] HTTP Client\n        + [x] [OAS2][2] Document\n    - [x] gRPC\n        + [x] Protocol Buffers\n        + [x] gRPC Server\n        + [ ] gRPC Client\n    - [x] Event\n        + [x] Event Subscriber\n        + [x] Event Publisher\n   - [x] Cron\n       + [x] Cron Jobs\n\n2. Useful Packages\n\n    - [appx](pkg/appx): Application framework for HTTP and CRON applications (a wrapper of [appx][3]).\n    - [prometheus](pkg/prometheus): Prometheus metrics utilities.\n    - [trace](pkg/trace): A thin wrapper of [x/net/trace][4] for Go kit.\n    - [werror](pkg/werror): Classified business errors.\n\n\n## How it works\n\n### HTTP Generation\n\n![http-generation](docs/http-generation.png)\n\n### gRPC Generation\n\n![grpc-generation](docs/grpc-generation.png)\n\n\n## Installation\n\n```bash\n$ go install github.com/RussellLuo/kun/cmd/kungen@latest\n```\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Usage \u003c/summary\u003e\n\n```bash\n$ kungen -h\nkungen [flags] source-file interface-name\n  -flat\n    \twhether to use flat layout (default true)\n  -fmt\n    \twhether to make code formatted (default true)\n  -force\n    \twhether to remove previously generated files before generating new ones\n  -out string\n    \toutput directory (default \".\")\n  -snake\n    \twhether to use snake-case for default names (default true)\n  -trace\n    \twhether to enable tracing\n```\n\n\u003c/details\u003e\n\n\n## Quick Start\n\n### HTTP\n\n**NOTE**: The following code is located in [helloworld](examples/helloworld).\n\n1. Define the interface\n\n    ```go\n    type Service interface {\n        SayHello(ctx context.Context, name string) (message string, err error)\n    }\n    ```\n\n2. Implement the service\n\n    ```go\n    type Greeter struct{}\n\n    func (g *Greeter) SayHello(ctx context.Context, name string) (string, error) {\n        return \"Hello \" + name, nil\n    }\n    ```\n\n3. Add HTTP annotations\n\n    ```go\n    type Service interface {\n        //kun:op POST /messages\n        SayHello(ctx context.Context, name string) (message string, err error)\n    }\n    ```\n\n4. Generate the HTTP code\n\n    ```bash\n    $ cd examples/helloworld\n    $ kungen ./service.go Service\n    ```\n\n5. Consume the service\n\n    Run the HTTP server:\n\n    ```bash\n    $ go run cmd/main.go\n    2020/09/15 18:06:22 transport=HTTP addr=:8080\n    ```\n\n    Consume by [HTTPie](https://github.com/jakubroztocil/httpie):\n\n    ```bash\n    $ http POST :8080/messages name=Tracey\n    HTTP/1.1 200 OK\n    Content-Length: 27\n    Content-Type: application/json; charset=utf-8\n    Date: Tue, 15 Sep 2020 10:06:34 GMT\n\n    {\n        \"message\": \"Hello Tracey\"\n    }\n    ```\n\n6. See the OAS documentation\n\n    \u003cdetails\u003e\n      \u003csummary\u003e (Click to expand) \u003c/summary\u003e\n\n    ```bash\n    $ http GET :8080/api\n    HTTP/1.1 200 OK\n    Content-Length: 848\n    Content-Type: text/plain; charset=utf-8\n    Date: Tue, 15 Sep 2020 10:08:24 GMT\n\n    swagger: \"2.0\"\n    info:\n      title: \"No Title\"\n      version: \"0.0.0\"\n      description: \"Service is used for saying hello.\"\n      license:\n        name: \"MIT\"\n    host: \"example.com\"\n    basePath: \"/\"\n    schemes:\n      - \"https\"\n    consumes:\n      - \"application/json\"\n    produces:\n      - \"application/json\"\n\n    paths:\n      /messages:\n        post:\n          description: \"SayHello says hello to the given name.\"\n          operationId: \"SayHello\"\n          parameters:\n            - name: body\n              in: body\n              schema:\n                $ref: \"#/definitions/SayHelloRequestBody\"\n\n          produces:\n            - application/json; charset=utf-8\n          responses:\n            200:\n              description: \"\"\n              schema:\n                $ref: \"#/definitions/SayHelloResponse\"\n\n\n    definitions:\n      SayHelloRequestBody:\n        type: object\n        properties:\n          name:\n            type: string\n      SayHelloResponse:\n        type: object\n        properties:\n          message:\n            type: string\n    ```\n\n    \u003c/details\u003e\n\n### gRPC\n\n**NOTE**: The following code is located in [helloworldgrpc](examples/helloworldgrpc).\n\n1. Define the interface\n\n    ```go\n    type Service interface {\n        SayHello(ctx context.Context, name string) (message string, err error)\n    }\n    ```\n\n2. Implement the service\n\n    ```go\n    type Greeter struct{}\n\n    func (g *Greeter) SayHello(ctx context.Context, name string) (string, error) {\n        return \"Hello \" + name, nil\n    }\n    ```\n\n3. Add gRPC annotations\n\n    ```go\n    type Service interface {\n        //kun:grpc\n        SayHello(ctx context.Context, name string) (message string, err error)\n    }\n    ```\n\n4. Generate the gRPC code\n\n    ```bash\n    $ cd examples/helloworldgrpc\n    $ kungen ./service.go Service\n    ```\n\n5. Consume the service\n\n    Run the gRPC server:\n\n    ```bash\n    $ go run cmd/main.go\n    2020/09/15 18:06:22 transport=HTTP addr=:8080\n    ```\n\n    Consume by [grpcurl](https://github.com/fullstorydev/grpcurl):\n\n    ```bash\n    $ grpcurl -plaintext -d '{\"name\": \"Tracey\"}' :8080 pb.Service/SayHello\n    {\n      \"message\": \"Hello Tracey\"\n    }\n    ```\n\nSee more examples [here](examples).\n\n\n## HTTP\n\n### Annotations\n\n#### Define the HTTP request operation\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:op \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:op \u003cmethod\u003e \u003cpattern\u003e\n```\n\nIf a Go method needs to correspond to more than one URI (or HTTP method), you can specify multiple `//kun:op` directives, which will produce multiple HTTP request operations.\n\nNote that there are only three possible differences among these HTTP request operations:\n\n- HTTP method\n- URI\n- Path parameters (defined in URI)\n\n##### Arguments\n\n- **method**: The request method.\n- **pattern**: The request URI.\n    + NOTE: All variables in **pattern** will automatically be bound to their corresponding method arguments (match by names in *lower camel case*), as **path** parameters, if these variables have not yet been specified explicitly by `//kun:param`.\n\n##### Examples\n\n- Single operation:\n\n    ```go\n    type Service interface {\n        //kun:op DELETE /users/{id}\n        DeleteUser(ctx context.Context, id int) (err error)\n    }\n\n    // HTTP request:\n    // $ http DELETE /users/101\n    ```\n\n- Multiple operations:\n\n    ```go\n    type Service interface {\n        //kun:op GET /messages/{messageID}\n        //kun:op GET /users/{userID}/messages/{messageID}\n        GetMessage(ctx context.Context, userID string, messageID string) (text string, err error)\n    }\n\n    // See a runnable example in examples/messaging.\n\n    // HTTP request:\n    // $ http GET /messages/123456\n    // $ http GET /users/me/messages/123456\n    ```\n\n\u003c/details\u003e\n\n#### Define the HTTP request parameters\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:param \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:param \u003cargName\u003e [\u003cparameter\u003e [, \u003cparameter2\u003e [, ...]]]\n```\n\nIf multiple method arguments are involved, you may need to apply multiple bindings. This can be done by adding a new `//kun:param` directive, or by appending the binding to the end of the last `//kun:param` directive in a semicolon-separated list.\n\n##### Arguments\n\n- **argName**: The name of the method argument.\n    + *Argument aggregation*: By specifying multiple `\u003cparameter\u003e`s in a comma-separated list, multiple request parameters (each one is of basic type or repeated basic type) can be aggregated into one method argument (of any type).\n    + *Blank identifier*: By specifying the **argName** with a double underscore prefix `__`, the corresponding request parameter(s) will not be mapped to any method argument. See [here](https://github.com/RussellLuo/kun/issues/15) for more details.\n- **parameter**: The definition of a single request parameter, to which the method argument will be mapped.\n    + Syntax: `in=\u003cin\u003e name=\u003cname\u003e required=\u003crequired\u003e type=\u003ctype\u003e descr=\u003cdescr\u003e`\n    + Options:\n        - **in**:\n            + **path**: The request parameter is a [path parameter](https://swagger.io/docs/specification/describing-parameters/#path-parameters).\n                - Optional: All variables in **pattern** will automatically be bound to their corresponding method arguments (match by names in *lower camel case*), as **path** parameters.\n            + **query**: The request parameter is a [query parameter](https://swagger.io/docs/specification/describing-parameters/#query-parameters).\n                - To receive values from a multi-valued query parameter, the method argument can be defined as a slice of basic type.\n            + **header**: The request parameter is a [header parameter](https://swagger.io/docs/specification/describing-parameters/#header-parameters).\n                - To receive values from a multi-valued header parameter, the method argument can be defined as a slice of basic type.\n            + **cookie**: The request parameter is a [cookie parameter](https://swagger.io/docs/specification/describing-parameters/#cookie-parameters).\n                - Not supported yet.\n            + **request**: The request parameter is a property of Go's [http.Request](https://golang.org/pkg/net/http/#Request).\n                - This is a special case, and only one property `RemoteAddr` is available now.\n                - Note that parameters located in **request** have no relationship with OAS.\n        - **name**: The name of the request parameter.\n            + Optional: Defaults to **argName** (snake-case, or lower-camel-case if `-snake=false`) if not specified.\n        - **required**: Determines whether this parameter is mandatory.\n            + Optional: Defaults to `false`, if not specified.\n            + If the parameter location is **path**, this property will be set to `true` internally, whether it's specified or not.\n        - **type**: The OAS type of the request parameter.\n            + Optional: Defaults to the type of the method argument, if not specified.\n        - **descr**: The OAS description of the request parameter.\n            + Optional: Defaults to `\"\"`, if not specified.\n\n##### Examples\n\n- Bind request parameters to simple arguments:\n\n    ```go\n    type Service interface {\n        //kun:op PUT /users/{id}\n        //kun:param name in=header name=X-User-Name\n        UpdateUser(ctx context.Context, id int, name string) (err error)\n    }\n\n    // HTTP request:\n    // $ http PUT /users/101 X-User-Name:tracey\n    ```\n\n- Bind multiple request parameters to a struct according to tags:\n\n    ```go\n    type User struct {\n        ID   int    `kun:\"in=path\"`  // name defaults to snake case `id`\n        Name string `kun:\"in=query\"` // name defaults to snake case `name`\n        Age  int    `kun:\"in=header name=X-User-Age\"`\n    }\n\n    type Service interface {\n        //kun:op PUT /users/{id}\n        //kun:param user\n        UpdateUser(ctx context.Context, user User) (err error)\n    }\n\n    // HTTP request:\n    // $ http PUT /users/101?name=tracey X-User-Age:1\n    ```\n\n- Bind multiple query parameters to a struct with no tags:\n\n    ```go\n    type User struct {\n        Name    string   // equivalent to `kun:\"in=query name=name\"`\n        Age     int      // equivalent to `kun:\"in=query name=age\"`\n        Hobbies []string // equivalent to `kun:\"in=query name=hobbies\"`\n    }\n\n    type Service interface {\n        //kun:op POST /users\n        //kun:param user\n        CreateUser(ctx context.Context, user User) (err error)\n    }\n\n    // HTTP request:\n    // $ http POST /users?name=tracey\u0026age=1\u0026hobbies=music\u0026hobbies=sport\n    ```\n\n- Argument aggregation:\n\n    ```go\n    type Service interface {\n        //kun:op POST /logs\n        //kun:param ip in=header name=X-Forwarded-For, in=request name=RemoteAddr\n        Log(ctx context.Context, ip net.IP) (err error)\n    }\n\n    // The equivalent annotations =\u003e\n    // (using backslash-continued annotations)\n    type Service interface {\n        //kun:op POST /logs\n        //kun:param ip in=header name=X-Forwarded-For, \\\n        //             in=request name=RemoteAddr\n        Log(ctx context.Context, ip net.IP) (err error)\n    }\n\n    // You must customize the decoding of `ip` later (conventionally in another file named `codec.go`).\n    // See a runnable example in examples/usersvc.\n\n    // HTTP request:\n    // $ http POST /logs\n    ```\n\n- Multiple bindings in a single `//kun:param`:\n\n    ```go\n    type Service interface {\n        //kun:op POST /users\n        //kun:param name; age; ip in=header name=X-Forwarded-For, in=request name=RemoteAddr\n        CreateUser(ctx context.Context, name string, age int, ip net.IP) (err error)\n    }\n\n    // The equivalent annotations =\u003e\n    // (using backslash-continued annotations)\n\n    type Service interface {\n        //kun:op POST /users\n        //kun:param name; \\\n        //          age; \\\n        //          ip in=header name=X-Forwarded-For, in=request name=RemoteAddr\n        CreateUser(ctx context.Context, name string, age int, ip net.IP) (err error)\n    }\n\n    // HTTP request:\n    // $ http POST /users?name=tracey\u0026age=1\n    ```\n\n\u003c/details\u003e\n\n#### Define the HTTP request body\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:body \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:body \u003cfield\u003e\n```\n\nor\n\n```\n//kun:body \u003cmanipulation\u003e [; \u003cmanipulation2\u003e [; ...]]\n```\n\n##### Arguments\n\n- **field**: The name of the method argument whose value is mapped to the HTTP request body.\n    + Optional: When omitted, a struct containing all the arguments (except context.Context), which are not located in **path**/**query**/**header**, will automatically be mapped to the HTTP request body.\n    + The special name `-` can be used, to define that there is no HTTP request body. As a result, every argument, which is not located in **path**/**query**/**header**, will automatically be mapped to one or more query parameters.\n- **manipulation**:\n    + Syntax: `\u003cargName\u003e name=\u003cname\u003e type=\u003ctype\u003e descr=\u003cdescr\u003e required=\u003crequired\u003e`\n    + Options:\n        - **argName**: The name of the method argument to be manipulated.\n        - **name**: The name of the request parameter.\n            + Optional: Defaults to **argName** (snake-case, or lower-camel-case if `-snake=false`) if not specified.\n        - **type**: The OAS type of the request parameter.\n            + Optional: Defaults to the type of the method argument, if not specified.\n        - **descr**: The OAS description of the request parameter.\n            + Optional: Defaults to `\"\"`, if not specified.\n        - **required**: Determines whether this parameter is mandatory.\n            + Optional: Defaults to `false`, if not specified.\n\n##### Examples\n\n- Omitted:\n\n    ```go\n    type Service interface {\n        //kun:op POST /users\n        CreateUser(ctx context.Context, name string, age int) (err error)\n    }\n\n    // HTTP request:\n    // $ http POST /users name=tracey age=1\n    ```\n\n- Specified as a normal argument:\n\n    ```go\n    type User struct {\n        Name string `json:\"name\"`\n        Age  int    `json:\"age\"`\n    }\n\n    type Service interface {\n        //kun:op POST /users\n        //kun:body user\n        CreateUser(ctx context.Context, user User) (err error)\n    }\n\n    // HTTP request:\n    // $ http POST /users name=tracey age=1\n    ```\n\n- Specified as `-`:\n\n    ```go\n    type User struct {\n        Name    string\n        Age     int\n        Hobbies []string `kun:\"name=hobby\"`\n    }\n\n    type Service interface {\n        //kun:op POST /users\n        //kun:body -\n        CreateUser(ctx context.Context, user User) (err error)\n    }\n\n    // HTTP request:\n    // $ http POST /users?name=tracey\u0026age=1\u0026hobby=music\u0026hobby=sport\n    ```\n\n- Manipulation:\n\n    ```go\n    type Service interface {\n        //kun:op POST /users\n        //kun:body age name=user_age type=string descr='The user age'\n        CreateUser(ctx context.Context, name string, age int) (err error)\n    }\n\n    // HTTP request:\n    // $ http POST /users name=tracey user_age=1\n    ```\n\n\u003c/details\u003e\n\n#### Define the success HTTP response\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:success \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:success statusCode=\u003cstatusCode\u003e body=\u003cbody\u003e manip=`\u003cmanipulation\u003e [; \u003cmanipulation2\u003e [; ...]]`\n```\n\n##### Arguments\n\n- **statusCode**: The status code of the success HTTP response.\n    + Optional: Defaults to `200`, if not specified.\n- **body**: The name of the response field whose value is mapped to the HTTP response body.\n    + Optional: When omitted, a struct containing all the results (except error) will automatically be mapped to the HTTP response body.\n- **manipulation**:\n    + Syntax: `\u003cargName\u003e name=\u003cname\u003e type=\u003ctype\u003e descr=\u003cdescr\u003e`\n    + Not supported yet.\n\n##### Examples\n\n```go\ntype User struct {\n    Name string `json:\"name\"`\n    Age  int    `json:\"age\"`\n}\n\ntype Service interface {\n    //kun:op POST /users\n    //kun:success statusCode=201 body=user\n    CreateUser(ctx context.Context) (user User, err error)\n}\n```\n\n\u003c/details\u003e\n\n#### Define the OAS metadata\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:oas \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:oas \u003cproperty\u003e=\u003cvalue\u003e\n```\n\n##### Arguments\n\n- **property**: The property to set. Supported properties:\n    + **docsPath**: The URL path to the OAS documentation itself.\n        - Optional: Defaults to `\"/api\"` if not specified.\n    + **title**: The `title` field of Info Object, see [Basic Structure](https://swagger.io/docs/specification/2-0/basic-structure/).\n        - Optional: Defaults to `\"No Title\"` if not specified.\n    + **version**: The `version` field of Info Object, see [Basic Structure](https://swagger.io/docs/specification/2-0/basic-structure/).\n        - Optional: Defaults to `\"0.0.0\"` if not specified.\n    + **description**: The `description` field of Info Object, see [Basic Structure](https://swagger.io/docs/specification/2-0/basic-structure/).\n        - Unavailable: Automatically extracted from the Go documentation of the interface definition.\n    + **basePath**: The `basePath` property, see [API Host and Base URL](https://swagger.io/docs/specification/2-0/api-host-and-base-path/).\n    + **tags**: A list of tags (comma-separated), see [Grouping Operations With Tags](https://swagger.io/docs/specification/2-0/grouping-operations-with-tags/).\n- **value**: The value of the property.\n\n##### Examples\n\n```go\n// This is the API documentation of User.\n//kun:oas docsPath=/api-docs\n//kun:oas title=User-API\n//kun:oas version=1.0.0\n//kun:oas basePath=/v1\n//kun:oas tags=user\ntype Service interface {\n    //kun:op POST /users\n    CreateUser(ctx context.Context, name string, age int) (err error)\n}\n```\n\n\u003c/details\u003e\n\n#### Define the annotation alias\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:alias \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:alias \u003cname\u003e=`\u003cvalue\u003e`\n```\n\n##### Arguments\n\n- **name**: The name of the alias.\n- **value**: The string value that the alias represents.\n\n##### Examples\n\n```go\ntype Service interface {\n    //kun:op POST /users\n    //kun:param operatorID in=header name=Authorization required=true\n    CreateUser(ctx context.Context, operatorID int) (err error)\n\n    //kun:op DELETE /users/{id}\n    //kun:param operatorID in=header name=Authorization required=true\n    DeleteUser(ctx context.Context, id, operatorID int) (err error)\n}\n\n// The equivalent annotations =\u003e\n\n//kun:alias opID=`operatorID in=header name=Authorization required=true`\ntype Service interface {\n    //kun:op POST /users\n    //kun:param $opID\n    CreateUser(ctx context.Context, operatorID int) (err error)\n\n    //kun:op DELETE /users/{id}\n    //kun:param $opID\n    DeleteUser(ctx context.Context, id, operatorID int) (err error)\n}\n```\n\n\u003c/details\u003e\n\n### Encoding and decoding\n\nSee the [HTTP Codec](https://github.com/RussellLuo/kun/blob/master/pkg/httpcodec/codec.go#L8-L23) interface.\n\nAlso see [here](https://github.com/RussellLuo/kun/issues/8) for examples.\n\n\n### OAS Schema\n\nSee the [OAS Schema](https://github.com/RussellLuo/kun/blob/master/pkg/oas2/schema.go#L18-L21) interface.\n\n\n## gRPC\n\n### Annotations\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:grpc \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:grpc request=\u003crequest\u003e response=\u003cresponse\u003e\n```\n\n##### Arguments\n\n- **request**: The name of the method argument, whose value will be mapped to the gRPC request.\n    + Optional: When omitted, a struct containing all the arguments (except context.Context) will automatically be mapped to the gRPC request.\n- **response**: The name of the method result, whose value will be mapped to the gRPC response.\n    + Optional: When omitted, a struct containing all the results (except error) will automatically be mapped to the gRPC response.\n\n##### Examples\n\n- Omitted:\n\n    ```go\n    type Service interface {\n        //kun:grpc\n        CreateUser(ctx context.Context, name string, age int) (err error)\n    }\n\n    // gRPC request:\n    // $ grpcurl -d '{\"name\": \"tracey\", \"age\": 1}' ... pb.Service/CreateUser\n    ```\n\n- Specified:\n\n    ```go\n    type User struct {\n        Name string `json:\"name\"`\n        Age  int    `json:\"age\"`\n    }\n\n    type Service interface {\n        //kun:grpc request=user\n        CreateUser(ctx context.Context, user User) (err error)\n    }\n\n    // gRPC request:\n    // $ grpcurl -d '{\"name\": \"tracey\", \"age\": 1}' ... pb.Service/CreateUser\n    ```\n\n\u003c/details\u003e\n\n\n## Event\n\n### Annotations\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:event \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:event type=\u003ctype\u003e data=\u003cdata\u003e\n```\n\n##### Arguments\n\n- **type**: The type of the event.\n    + Optional: Defaults to the name of the corresponding method (snake-case, or lower-camel-case if `-snake=false`) if not specified.\n- **data**: The name of the method argument whose value is mapped to the event data.\n    + Optional: When omitted, a struct containing all the arguments (except context.Context) will automatically be mapped to the event data.\n\n##### Examples\n\n- Omitted:\n\n    ```go\n    type Service interface {\n        //kun:event\n        EventCreated(ctx context.Context, id int) (err error)\n    }\n\n    // event: {\"type\": \"event_created\", \"data\": `{\"id\": 1}`}\n    ```\n\n- Specified:\n\n    ```go\n    type Data struct {\n        ID int `json:\"id\"`\n    }\n\n    type Service interface {\n        //kun:event type=created data=data\n        EventCreated(ctx context.Context, data Data) (err error)\n    }\n\n    // event: {\"type\": \"created\", \"data\": `{\"id\": 1}`}\n    ```\n\n\u003c/details\u003e\n\n\n## Cron\n\n### Annotations\n\n\u003cdetails open\u003e\n  \u003csummary\u003e Directive //kun:cron \u003c/summary\u003e\n\n##### Syntax\n\n```\n//kun:cron name=\u003cname\u003e expr=\u003cexpr\u003e\n```\n\n##### Arguments\n\n- **name**: The job name.\n    + Optional: Defaults to the name of the corresponding method (snake-case, or lower-camel-case if `-snake=false`) if not specified.\n- **expr**: The cron expression.\n    + Required: [Three formats are supported](https://pkg.go.dev/github.com/RussellLuo/micron#Job).\n\n##### Examples\n\n- Name omitted:\n\n    ```go\n    type Service interface {\n        //kun:cron expr='@every 5s'\n        SendEmail(ctx context.Context) error\n    }\n\n    // job: {\"name\": \"send_email\", \"expr\": \"@every 5s\"}\n    ```\n\n- Name specified:\n\n    ```go\n    type Service interface {\n        //kun:cron name=send expr='@every 5s'\n        SendEmail(ctx context.Context) error\n    }\n\n    // job: {\"name\": \"send\", \"expr\": \"@every 5s\"}\n    ```\n\n\u003c/details\u003e\n\n\n## Documentation\n\nCheckout the [Godoc][5].\n\n\n## License\n\n[MIT](LICENSE)\n\n\n[1]: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html\n[2]: https://swagger.io/specification/v2/\n[3]: https://github.com/RussellLuo/appx\n[4]: https://pkg.go.dev/golang.org/x/net/trace\n[5]: https://pkg.go.dev/github.com/RussellLuo/kun\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frussellluo%2Fkun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frussellluo%2Fkun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frussellluo%2Fkun/lists"}