From 5982f222093f3756ee3600090575d94ee6718249 Mon Sep 17 00:00:00 2001 From: Rahul De Date: Sun, 15 Dec 2024 19:05:35 +0000 Subject: [PATCH] [names] use x-cli-name --- README.md | 94 ++++------------------------------------------------- api.yaml | 10 +++--- lib.go | 14 ++++---- lib_test.go | 6 ++-- 4 files changed, 22 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index cf79dd8..a180aaa 100644 --- a/README.md +++ b/README.md @@ -25,106 +25,26 @@ Experimental, in dev flux and looking for design/usage feedback! go get github.com/lispyclouds/climate ``` -### How it works and usage +### Rationale climate allows the server to influence the CLI behaviour by using OpenAPI's [extensions](https://swagger.io/docs/specification/v3_0/openapi-extensions/). It encourages [spec-first](https://www.atlassian.com/blog/technology/spec-first-api-development) practices thereby keeping both users and maintenance manageable. It does just enough to handle the spec and nothing more. Overall, the way it works: - Each operation is converted to a Cobra command - Each parameter is converted to a flag with its corresponding type -- Request bodies are a flag as of now, subject to change +- Request bodies are a flag as of now, subject to change. Name defaults to `climate-data` unless specified via `x-cli-name` - The provided handlers are attached to each command, grouped and attached to the rootCmd Influenced by some of the ideas behind [restish](https://rest.sh/) it uses the following extensions as of now: -- `x-cli-aliases`: A list of strings which would be used as the alternate names for: - - Operations: If set, will prefer the first of the list otherwise the `operationId`. Will use the rest as cobra aliases - - Request Body: Same preference as above but would a default of `climate-data` as the name of the param if not set +- `x-cli-aliases`: A list of strings which would be used as the alternate names for an operation - `x-cli-group`: A string to allow grouping subcommands together. All operations in the same group would become subcommands in that group name - `x-cli-hidden`: A boolean to hide the operation from the CLI menu. Same behaviour as a cobra command hide: it's present and expects a handler - `x-cli-ignored`: A boolean to tell climate to omit the operation completely +- `x-cli-name`: A string to specify a differnt name. Applies to operations and request bodies as of now -Given an OpenAPI spec in `api.yaml`: - -```yaml -openapi: "3.0.0" - -info: - title: My calculator - version: "0.1.0" - description: My awesome calc! - -paths: - "/add/{n1}/{n2}": - get: - operationId: AddGet - summary: Adds two numbers - x-cli-group: ops - x-cli-aliases: - - add-get - - ag - - parameters: - - name: n1 - required: true - in: path - description: The first number - schema: - type: integer - - name: n2 - required: true - in: path - description: The second number - schema: - type: integer - post: - operationId: AddPost - summary: Adds two numbers via POST - x-cli-group: ops - x-cli-aliases: - - add-post - - ap - - requestBody: - description: The numbers map - required: true - x-cli-aliases: - - nmap - content: - application/json: - schema: - $ref: "#/components/schemas/NumbersMap" - "/health": - get: - operationId: HealthCheck - summary: Returns Ok if all is well - x-cli-aliases: - - ping - "/meta": - get: - operationId: GetMeta - summary: Returns meta - x-cli-ignored: true - "/info": - get: - operationId: GetInfo - summary: Returns info - x-cli-group: info - -components: - schemas: - NumbersMap: - type: object - required: - - n1 - - n2 - properties: - n1: - type: integer - description: The first number - n2: - type: integer - description: The second number -``` +### Usage + +Given an OpenAPI spec like [api.yaml](/api.yaml) Load the spec: diff --git a/api.yaml b/api.yaml index c4b1b6e..0c07826 100644 --- a/api.yaml +++ b/api.yaml @@ -10,9 +10,9 @@ paths: get: operationId: AddGet summary: Adds two numbers + x-cli-name: add-get x-cli-group: ops x-cli-aliases: - - add-get - ag parameters: @@ -31,16 +31,15 @@ paths: post: operationId: AddPost summary: Adds two numbers via POST + x-cli-name: add-post x-cli-group: ops x-cli-aliases: - - add-post - ap requestBody: description: The numebers map required: true - x-cli-aliases: - - nmap + x-cli-name: nmap content: application/json: schema: @@ -49,8 +48,7 @@ paths: get: operationId: HealthCheck summary: Returns Ok if all is well - x-cli-aliases: - - ping + x-cli-name: ping "/meta": get: operationId: GetMeta diff --git a/lib.go b/lib.go index 82dad44..0567978 100644 --- a/lib.go +++ b/lib.go @@ -47,6 +47,7 @@ type extensions struct { aliases []string group string ignored bool + name string } func parseExtensions(exts *orderedmap.Map[string, *yaml.Node]) (*extensions, error) { @@ -71,6 +72,8 @@ func parseExtensions(exts *orderedmap.Map[string, *yaml.Node]) (*extensions, err ex.group = opts.(string) case "x-cli-ignored": ex.ignored = opts.(bool) + case "x-cli-name": + ex.name = opts.(string) } } @@ -138,8 +141,8 @@ func addRequestBody(cmd *cobra.Command, op *v3.Operation, handlerData *HandlerDa } paramName := "climate-data" - if aliases := bExts.aliases; len(aliases) > 0 { - paramName = aliases[0] + if altName := bExts.name; altName != "" { + paramName = altName } // TODO: Handle all the different MIME types and schemas from body.Content @@ -210,6 +213,7 @@ func BootstrapV3(rootCmd *cobra.Command, model libopenapi.DocumentModel[v3.Docum } cmd.Hidden = exts.hidden + cmd.Aliases = exts.aliases cmd.Short = op.Description if op.Summary != "" { cmd.Short = op.Summary @@ -219,11 +223,9 @@ func BootstrapV3(rootCmd *cobra.Command, model libopenapi.DocumentModel[v3.Docum handler(opts, args, hData) } - // TODO: hammock on better ways to handle aliases, prefers the first one as of now cmd.Use = op.OperationId // default - if aliases := exts.aliases; len(exts.aliases) > 0 { - cmd.Use = aliases[0] - cmd.Aliases = aliases + if altName := exts.name; altName != "" { + cmd.Use = altName } if g := exts.group; g != "" { diff --git a/lib_test.go b/lib_test.go index 9d0b4bc..6cf70fc 100644 --- a/lib_test.go +++ b/lib_test.go @@ -83,17 +83,17 @@ func TestBootstrapV3(t *testing.T) { "calc/ops/add-get": { "Use": "add-get", "Short": "Adds two numbers", - "Aliases": []string{"add-get", "ag"}, + "Aliases": []string{"ag"}, }, "calc/ops/add-post": { "Use": "add-post", "Short": "Adds two numbers via POST", - "Aliases": []string{"add-post", "ap"}, + "Aliases": []string{"ap"}, }, "calc/ping": { "Use": "ping", "Short": "Returns Ok if all is well", - "Aliases": []string{"ping"}, + "Aliases": noAlias, }, }