Skip to content

Commit 2624387

Browse files
committed
[doc] add doc
1 parent 95e5313 commit 2624387

File tree

1 file changed

+167
-3
lines changed

1 file changed

+167
-3
lines changed

README.md

Lines changed: 167 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,173 @@
11
# climate
22

33
Go is a fantastic language to build CLI tooling, specially the ones for interacting with an API server. `<your tool>ctl` anyone?
4-
54
But if you're tired of building bespoke CLIs everytime or think that the swagger codegen isn't just good enough, look no further.
65

7-
What if you can influence the CLI behaviour from the server?
6+
What if you can influence the CLI behaviour from the server? This enables you to bootstrap your [cobra](https://cobra.dev/) CLI tooling from an [OpenAPI](https://swagger.io/specification/) spec.
7+
8+
## Getting started
9+
10+
### Status
11+
12+
Experimental, in dev flux and looking for design/usage feedback!
13+
14+
### Installation
15+
16+
```bash
17+
go get github.com/lispyclouds/climate
18+
```
19+
20+
### How it works and usage
21+
22+
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.
23+
24+
Overall, the way it works:
25+
- Each operation is converted to a Cobra command
26+
- Each parameter is converted to a flag with its corresponding type
27+
- Request bodies are a flag as of now, subject to change
28+
- The provided handlers are attached to each command, grouped and attached to the rootCmd
29+
30+
Influenced by some of the ideas behind [restish](https://rest.sh/) it uses the following extensions as of now:
31+
- `x-cli-aliases`: A list of strings which would be used as the alternate names for:
32+
- Operations: If set, will prefer the first of the list otherwise the `operationId`. Will use the rest as cobra aliases
33+
- Request Body: Same preference as above but would a default of `climate-data` as the name of the param if not set
34+
- `x-cli-group`: A string to allow grouping subcommands together. All operations in the same group would become subcommands in that group name
35+
- `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
36+
- `x-cli-ignored`: A boolean to tell climate to omit the operation completely
37+
38+
Given an OpenAPI spec in `api.yaml`:
39+
40+
```yaml
41+
openapi: "3.0.0"
42+
43+
info:
44+
title: My calculator
45+
version: "0.1.0"
46+
description: My awesome calc!
47+
48+
paths:
49+
"/add/{n1}/{n2}":
50+
get:
51+
operationId: AddGet
52+
summary: Adds two numbers
53+
x-cli-group: ops
54+
x-cli-aliases:
55+
- add-get
56+
- ag
57+
58+
parameters:
59+
- name: n1
60+
required: true
61+
in: path
62+
description: The first number
63+
schema:
64+
type: integer
65+
- name: n2
66+
required: true
67+
in: path
68+
description: The second number
69+
schema:
70+
type: integer
71+
post:
72+
operationId: AddPost
73+
summary: Adds two numbers via POST
74+
x-cli-group: ops
75+
x-cli-aliases:
76+
- add-post
77+
- ap
78+
79+
requestBody:
80+
description: The numebers map
81+
required: true
82+
x-cli-aliases:
83+
- nmap
84+
content:
85+
application/json:
86+
schema:
87+
$ref: "#/components/schemas/NumbersMap"
88+
"/health":
89+
get:
90+
operationId: HealthCheck
91+
summary: Returns Ok if all is well
92+
x-cli-aliases:
93+
- ping
94+
"/meta":
95+
get:
96+
operationId: GetMeta
97+
summary: Returns meta
98+
x-cli-ignored: true
99+
"/info":
100+
get:
101+
operationId: GetInfo
102+
summary: Returns info
103+
x-cli-group: info
104+
105+
components:
106+
schemas:
107+
NumbersMap:
108+
type: object
109+
required:
110+
- n1
111+
- n2
112+
properties:
113+
n1:
114+
type: integer
115+
description: The first number
116+
n2:
117+
type: integer
118+
description: The second number
119+
```
120+
121+
Load the spec:
122+
123+
```go
124+
model, err := climate.LoadFileV3("api.yaml") // or climate.LoadV3 with []byte
125+
```
126+
127+
Define a cobra root command:
128+
129+
```go
130+
rootCmd := &cobra.Command{
131+
Use: "calc",
132+
Short: "My Calc",
133+
Long: "My Calc powered by OpenAPI",
134+
}
135+
```
136+
137+
Define one or more handler functions of the following signature:
138+
```go
139+
func handler(opts *cobra.Command, args []string, data climate.HandlerData) {
140+
// do something more useful
141+
slog.Info("called!", "data", fmt.Sprintf("%+v", data))
142+
}
143+
```
144+
145+
Define the handlers for the necessary operations. These map to the `operationId` field of each operation:
146+
147+
```go
148+
handlers := map[string]Handler{
149+
"AddGet": handler,
150+
"AddPost": handler,
151+
"HealthCheck": handler,
152+
"GetInfo": handler,
153+
}
154+
```
155+
156+
Bootstrap the root command:
157+
158+
```go
159+
err := climate.BootstrapV3(rootCmd, *model, handlers)
160+
```
161+
162+
Continue adding more commands and/or execute:
163+
164+
```go
165+
// add more commands not from the spec
166+
167+
rootCmd.Execute()
168+
```
169+
170+
## License
171+
Copyright © 2024- Rahul De
8172

9-
## Docs coming soon, work in progress.
173+
Distributed under the MIT License. See LICENSE.

0 commit comments

Comments
 (0)