Skip to content

Commit 8de46cc

Browse files
committed
💥 Supports structure generation for each request method and request parameter.
- Supports generation of structures for each request method - Supports generation of Query Parameter structure - Changed the generated file name and structure name
1 parent ddfafbc commit 8de46cc

File tree

15 files changed

+311
-46
lines changed

15 files changed

+311
-46
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ api-to-go https://api.github.com/users/github/repos
5151
# > Docs: https://docs.github.com/en/rest
5252
5353
# > Response Body:
54-
# > - api.github.com/users/user/repos.go:1
55-
# > - api.github.com/users/user/repos.json:1
54+
# > - api.github.com/users/user/repos_get.go:1
55+
# > - api.github.com/users/user/repos_get.json:1
5656
```
5757
5858
Generated files and directories.
@@ -63,8 +63,8 @@ Generated files and directories.
6363
# > └── api.github.com
6464
# > └── users
6565
# > └── user
66-
# > ├── repos.go
67-
# > └── repos.json
66+
# > ├── repos_get.go
67+
# > └── repos_get.json
6868
```
6969
7070
Generated struct file `./api.github.com/users/user/repos.go`.
@@ -78,13 +78,13 @@ package user
7878
7979
import "time"
8080
81-
// Repos represents the response body from an HTTP request.
81+
// ReposGet is the structure of the HTTP Response Body.
8282
//
8383
// Status: 200 OK
8484
// Request: GET https://api.github.com/users/github/repos
8585
// Format: /users/{user}/repos
8686
// Docs: https://docs.github.com/en/rest
87-
type Repos []struct {
87+
type ReposGet []struct {
8888
ID int `json:"id"`
8989
NodeID string `json:"node_id"`
9090
Name string `json:"name"`

src/buildPath.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
const {loadYaml, loadConfig} = require("./common");
1+
const {loadYaml, loadConfig, capitalize} = require("./common");
22

33
function buildPath(url, configFile, opts) {
44
const path = _buildPath(url, configFile)
55
const pathArr = path.replacedUrl.split("/")
66
const pkg = pathArr[pathArr.length - 2].replace(/\./g, '')
77
const last = pathArr[pathArr.length - 1] || "index"
8-
const struct = _capitalize(last)
8+
const struct = capitalize(last)
99
pathArr.pop()
1010
const dir = pathArr.join("/")
1111
let method = opts?.method.toLowerCase()
@@ -74,9 +74,4 @@ function _replacePath(pathname, format) {
7474
}
7575
}
7676

77-
function _capitalize(str) {
78-
const lower = str.toLowerCase();
79-
return str.charAt(0).toUpperCase() + lower.slice(1);
80-
}
81-
8277
module.exports = buildPath;

src/common.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ exports.loadFile = file => {
2020
return fs.readFileSync(file, 'utf8');
2121
};
2222

23+
exports.capitalize = str => {
24+
const lower = str.toLowerCase();
25+
return str.charAt(0).toUpperCase() + lower.slice(1);
26+
}
27+
2328
exports.isJsonString = str => {
2429
try {
2530
JSON.parse(str);

src/run.js

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const fetch = require('node-fetch');
22
const fs = require('fs');
33
const jsonToGo = require('../vendor/json-to-go.js');
44
const buildPath = require('./buildPath');
5-
const {isJsonString, loadConfig, loadFile, loadJson} = require("./common");
5+
const {isJsonString, loadConfig, loadFile, loadJson, capitalize} = require("./common");
66

77
let cliOpts
88

@@ -35,16 +35,26 @@ function run(urlStr, body, options) {
3535
return res.json()
3636
})
3737
.then(json => {
38-
const struct = jsonToGo(JSON.stringify(json), path.struct);
39-
const content = buildContent(struct.go, path, comment)
38+
let method = capitalize(opts?.method)
39+
const struct = jsonToGo(JSON.stringify(json), path.struct + method);
40+
const content = buildContent(struct.go, path, comment,"")
4041
write(json, path, content)
4142

4243
if (opts?.body) {
43-
const paramStruct = jsonToGo(opts?.body, path.struct + "Param");
44-
const paramContent = buildContent(
45-
paramStruct.go, path, buildComment(url, path, opts.method), true
44+
const bodyStruct = jsonToGo(opts?.body, path.struct + method + "Body");
45+
const bodyContent = buildContent(
46+
bodyStruct.go, path, buildComment(url, path, opts.method), "body"
4647
)
47-
writeParam(JSON.stringify(JSON.parse(opts?.body), null, "\t"), path, paramContent)
48+
writeBodyParam(JSON.stringify(JSON.parse(opts?.body), null, "\t"), path, bodyContent)
49+
}
50+
if (url?.search) {
51+
const queryJson = queryToJson(new URLSearchParams(url.search))
52+
const queryStr = JSON.stringify(queryJson, null, "\t")
53+
const queryStruct = jsonToGo(queryStr, path.struct + method + "Query");
54+
const queryContent = buildContent(
55+
queryStruct.go, path, buildComment(url, path, opts.method), "query"
56+
)
57+
writeQueryParam(queryStr, path, queryContent)
4858
}
4959
}, () => {
5060
console.log()
@@ -69,17 +79,30 @@ function write(json, path, content) {
6979
console.log(` - ${path.jsonFilePath}:1`)
7080
}
7181

72-
function writeParam(json, path, content) {
73-
fs.writeFile(path.paramJsonFilePath, json, (err) => {
82+
function writeBodyParam(json, path, content) {
83+
fs.writeFile(path.bodyJsonFilePath, json, (err) => {
7484
if (err) throw err;
7585
});
76-
fs.writeFile(path.paramGoFilePath, content, (err) => {
86+
fs.writeFile(path.bodyGoFilePath, content, (err) => {
7787
if (err) throw err;
7888
});
7989
console.log()
8090
console.log("Request Body Parameter:")
81-
console.log(` - ${path.paramGoFilePath}:1`)
82-
console.log(` - ${path.paramJsonFilePath}:1`)
91+
console.log(` - ${path.bodyGoFilePath}:1`)
92+
console.log(` - ${path.bodyJsonFilePath}:1`)
93+
}
94+
95+
function writeQueryParam(json, path, content) {
96+
fs.writeFile(path.queryJsonFilePath, json, (err) => {
97+
if (err) throw err;
98+
});
99+
fs.writeFile(path.queryGoFilePath, content, (err) => {
100+
if (err) throw err;
101+
});
102+
console.log()
103+
console.log("Request Query Parameter:")
104+
console.log(` - ${path.queryGoFilePath}:1`)
105+
console.log(` - ${path.queryJsonFilePath}:1`)
83106
}
84107

85108
function buildOpts(body, cliOpts) {
@@ -116,7 +139,7 @@ function buildOpts(body, cliOpts) {
116139
return opts
117140
}
118141

119-
function buildContent(go, path, comment, isParam = false) {
142+
function buildContent(go, path, comment, paramType) {
120143
let content = `// Generated Code But Editable.
121144
// Format The Code with \`go fmt\` or something and edit it manually to use it.
122145
//
@@ -127,10 +150,12 @@ function buildContent(go, path, comment, isParam = false) {
127150
if (go.indexOf('time.') !== -1) {
128151
content += `import "time"\n\n`
129152
}
130-
if (isParam) {
131-
content += `// ${go.split(" ")[1]} is the HTTP request's body parameter.\n//`
132-
} else {
133-
content += `// ${go.split(" ")[1]} represents the response body from an HTTP request.\n//`
153+
if (paramType === "body") {
154+
content += `// ${go.split(" ")[1]} is the structure of the the HTTP Request Body Parameter.\n//`
155+
} else if (paramType === "query") {
156+
content += `// ${go.split(" ")[1]} is the structure of the HTTP Request Query Parameter.\n//`
157+
}else{
158+
content += `// ${go.split(" ")[1]} is the structure of the HTTP Response Body.\n//`
134159
}
135160
content += comment
136161
content += go
@@ -154,4 +179,12 @@ function buildComment(url, path, method, res = false) {
154179
return `${comment}\n`
155180
}
156181

182+
function queryToJson(query) {
183+
const json = {}
184+
for (const [key, value] of query.entries()) {
185+
json[key] = value
186+
}
187+
return json
188+
}
189+
157190
module.exports = run;

tests/api-to-go.bats

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,44 +18,53 @@ teardown(){
1818
write_doc_details "api-to-go"
1919
}
2020

21-
@test "Command with valid URL should succeed" {
22-
COMMAND="$API_TO_GO $BASE_URL/posts/1"
21+
@test "Command with Path parameters" {
22+
COMMAND="$API_TO_GO $BASE_URL/todos/1"
2323
run eval "$COMMAND"
2424
[ "$status" -eq 0 ]
2525

26-
assert_files_match /posts/post.go
27-
assert_files_match /posts/post.json
26+
assert_files_match /todos/todo_get.go
27+
assert_files_match /todos/todo_get.json
2828
}
2929

30-
@test "Command with URL and JSON body" {
31-
DATA='{"title": "foo", "body": "bar", "userId": 1}'
32-
COMMAND="$API_TO_GO $BASE_URL/posts '$DATA'"
30+
@test "Command with Query parameters" {
31+
QUERY='?userId=1&completed=false'
32+
COMMAND="$API_TO_GO $BASE_URL/todos$QUERY"
3333
run eval "$COMMAND"
3434
[ "$status" -eq 0 ]
3535

36-
assert_files_match /posts.go
37-
assert_files_match /posts.json
36+
assert_files_match /todos_get.go
37+
assert_files_match /todos_get.json
38+
assert_files_match /todos_get_query.go
39+
assert_files_match /todos_get_query.json
3840
}
3941

40-
41-
@test "Command with URL" {
42-
COMMAND="$API_TO_GO $BASE_URL/posts"
42+
@test "Command with Body parameters" {
43+
DATA=' {
44+
"userId": 1,
45+
"id": 1,
46+
"title": "delectus aut autem",
47+
"completed": false
48+
}'
49+
COMMAND="$API_TO_GO $BASE_URL/todos '$DATA'"
4350
run eval "$COMMAND"
4451
[ "$status" -eq 0 ]
4552

46-
assert_files_match /posts.go
47-
assert_files_match /posts.json
53+
assert_files_match /todos_post.go
54+
assert_files_match /todos_post.json
55+
assert_files_match /todos_post_body.go
56+
assert_files_match /todos_post_body.json
4857
}
4958

5059
@test "Command with custom headers" {
5160
HEADERS='{"Content-Type": "application/json"}'
52-
COMMAND="$API_TO_GO --headers '$HEADERS' $BASE_URL/posts/1"
61+
COMMAND="$API_TO_GO --headers '$HEADERS' $BASE_URL/todos/1"
5362
run eval "$COMMAND"
5463
[ "$status" -eq 0 ]
5564
}
5665

5766
@test "Command with GET method" {
58-
COMMAND="$API_TO_GO --method GET $BASE_URL/posts/1"
67+
COMMAND="$API_TO_GO --method GET $BASE_URL/todos/1"
5968
run eval "$COMMAND"
6069
[ "$status" -eq 0 ]
6170
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Generated Code But Editable.
2+
// Format The Code with `go fmt` or something and edit it manually to use it.
3+
//
4+
// Generated by: api-to-go (https://github.com/nkmr-jp/api-to-go).
5+
6+
package todos
7+
8+
// TodoGet is the HTTP Response Body.
9+
//
10+
// Status: 200 OK
11+
// Request: GET https://jsonplaceholder.typicode.com/todos/1
12+
// Format: /todos/{todo}
13+
// Docs: https://jsonplaceholder.typicode.com/
14+
type TodoGet struct {
15+
UserID int `json:"userId"`
16+
ID int `json:"id"`
17+
Title string `json:"title"`
18+
Completed bool `json:"completed"`
19+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"userId": 1,
3+
"id": 1,
4+
"title": "delectus aut autem",
5+
"completed": false
6+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Generated Code But Editable.
2+
// Format The Code with `go fmt` or something and edit it manually to use it.
3+
//
4+
// Generated by: api-to-go (https://github.com/nkmr-jp/api-to-go).
5+
6+
package jsonplaceholdertypicodecom
7+
8+
// TodosGet is the HTTP Response Body.
9+
//
10+
// Status: 200 OK
11+
// Request: GET https://jsonplaceholder.typicode.com/todos?userId=1
12+
// Docs: https://jsonplaceholder.typicode.com/
13+
type TodosGet []struct {
14+
UserID int `json:"userId"`
15+
ID int `json:"id"`
16+
Title string `json:"title"`
17+
Completed bool `json:"completed"`
18+
}

0 commit comments

Comments
 (0)