Skip to content

Commit a3a21f8

Browse files
authored
Merge pull request #1 from nkmr-jp/feature-add-auth
Add feature that POST request support and command line interface.
2 parents ba603fb + f1c25e7 commit a3a21f8

File tree

8 files changed

+299
-85
lines changed

8 files changed

+299
-85
lines changed

README.md

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,53 @@ npm i -g @nkmr-jp/api-to-go
99
```
1010

1111
# Usage
12-
add config file `.api-to-go.yml`.
13-
```yaml
12+
```sh
13+
$ api-to-go --help
14+
Usage: api-to-go [options] <url> [body]
15+
16+
Convert REST API's JSON payload to Golang struct.
17+
18+
Arguments:
19+
url URL (required)
20+
body HTTP request body. specify by json string or file(json|yml).
21+
22+
Options:
23+
-v, --version output the current version
24+
-H, --headers <string> http request headers. specify by json string or file(json|yml).
25+
-X, --method <string> specify request method to use.
26+
--config <string> location of client config files. (default: "./.api-to-go.yml")
27+
-D, --debug enable debug mode
28+
-h, --help display help for command
29+
```
30+
31+
32+
# Quick Start
33+
34+
Add config file `.api-to-go.yml`.
35+
```yml
1436
api.github.com:
37+
docs:
38+
- https://docs.github.com/en/rest
1539
format:
1640
- /users/{user}
1741
- /users/{user}/repos
1842
```
19-
run command.
43+
44+
Run command.
2045
```sh
2146
cd [your project dir]
2247
api-to-go https://api.github.com/users/github/repos
23-
# > format: /users/{user}/repos
24-
# > generated: api.github.com/users/user/repos.go
25-
# > saved: api.github.com/users/user/repos_sample.json
48+
# > Status: 200 OK
49+
# > Request: GET https://api.github.com/users/github/repos
50+
# > Format: /users/{user}/repos
51+
# > Docs: https://docs.github.com/en/rest
52+
53+
# > Response Body:
54+
# > - api.github.com/users/user/repos.go:1
55+
# > - api.github.com/users/user/repos.json:1
2656
```
27-
check generated files and directories.
57+
58+
Generated files and directories.
2859
```sh
2960
tree -a .
3061
# > .
@@ -33,19 +64,26 @@ check generated files and directories.
3364
# > └── users
3465
# > └── user
3566
# > ├── repos.go
36-
# > └── repos_sample.json
67+
# > └── repos.json
3768
```
38-
check generated struct file `./api.github.com/users/user/repos.go`.
69+
70+
Generated struct file `./api.github.com/users/user/repos.go`.
3971
```go
72+
// Generated Code But Editable.
73+
// Format The Code with `go fmt` or something and edit it manually to use it.
74+
//
75+
// Generated by: api-to-go (https://github.com/nkmr-jp/api-to-go).
76+
4077
package user
4178
4279
import "time"
4380
44-
// Repos is the go struct of api's payload.
45-
//
46-
// url: https://api.github.com/users/{user}/repos
47-
// example: https://api.github.com/users/github/repos
81+
// Repos represents the response body from an HTTP request.
4882
//
83+
// Status: 200 OK
84+
// Request: GET https://api.github.com/users/github/repos
85+
// Format: /users/{user}/repos
86+
// Docs: https://docs.github.com/en/rest
4987
type Repos []struct {
5088
ID int `json:"id"`
5189
NodeID string `json:"node_id"`
@@ -118,6 +156,7 @@ type Repos []struct {
118156
License interface{} `json:"license"`
119157
AllowForking bool `json:"allow_forking"`
120158
IsTemplate bool `json:"is_template"`
159+
WebCommitSignoffRequired bool `json:"web_commit_signoff_required"`
121160
Topics []interface{} `json:"topics"`
122161
Visibility string `json:"visibility"`
123162
Forks int `json:"forks"`

bin/api-to-go.js

Lines changed: 17 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,20 @@
11
#! /usr/bin/env node
2-
const fetch = require('node-fetch');
3-
const fs = require('fs');
4-
const jsonToGo = require('../vendor/json-to-go.js');
5-
const buildPath = require('../src/buildPath');
2+
const run = require('../src/run');
3+
const {Command} = require('commander');
4+
const program = new Command();
5+
const packageJson = require('../package.json');
66

7-
function run(url) {
8-
const apiUrl = url.replace(/\/$/, '')
9-
fetch(apiUrl)
10-
.then(res => res.json())
11-
.then(json => {
12-
const url = new URL(apiUrl);
13-
const path = buildPath(url)
14-
const res = jsonToGo(JSON.stringify(json), path.struct);
15-
const content = _buildContent(res.go, path, url)
16-
fs.mkdirSync(path.dir, {recursive: true})
17-
fs.writeFile(path.jsonFilePath, JSON.stringify(json, null, "\t"), (err) => {
18-
if (err) throw err;
19-
console.log(`saved: ${path.jsonFilePath}`)
20-
});
21-
fs.writeFile(path.goFilePath, content, (err) => {
22-
if (err) throw err;
23-
console.log(`generated: ${path.goFilePath}`)
24-
});
25-
}
26-
);
27-
}
7+
// See: https://github.com/tj/commander.js
8+
program
9+
.name('api-to-go')
10+
.version(packageJson.version,'-v, --version', 'output the current version')
11+
.description(packageJson.description)
12+
.argument('<url>', 'URL (required)')
13+
.argument('[body]', 'HTTP request body. specify by json string or file(json|yml).')
14+
.option('-H, --headers <string>', 'http request headers. specify by json string or file(json|yml).')
15+
.option('-X, --method <string>', 'specify request method to use.')
16+
.option('--config <string>', 'location of client config files.',"./.api-to-go.yml")
17+
.option('-D, --debug', 'enable debug mode')
18+
.action(run)
2819

29-
function _buildContent(struct, path, url) {
30-
let content = `package ${path.pkg}\n\n`
31-
if (struct.indexOf('time.') !== -1) {
32-
content = `${content}import "time"\n\n`
33-
}
34-
let comment = `// ${path.struct} is the go struct of api's payload.`
35-
if (path.path.pathFormat) {
36-
comment += `\n//\n// url: ${url.origin}${path.path.pathFormat}`
37-
comment += `\n// example: ${url.href}`
38-
} else {
39-
comment += `\n//\n// url: ${url.href}`
40-
}
41-
content = `${content}${comment}\n//\n${struct}`
42-
return content
43-
}
44-
45-
function _capitalize(str) {
46-
const lower = str.toLowerCase();
47-
return str.charAt(0).toUpperCase() + lower.slice(1);
48-
}
49-
50-
if (process.argv.length !== 3) {
51-
console.log("parameter is wrong.")
52-
return
53-
}
54-
55-
run(process.argv[2])
20+
program.parse();

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"api-to-go": "bin/api-to-go.js"
1919
},
2020
"dependencies": {
21+
"commander": "^9.4.0",
2122
"js-yaml": "^4.1.0",
2223
"node-fetch": "2"
2324
},

src/buildPath.js

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
const yaml = require("js-yaml");
2-
const fs = require("fs");
1+
const {loadYaml, loadConfig} = require("./common");
32

4-
function buildPath(url, configFile = "./.api-to-go.yml") {
3+
function buildPath(url, configFile) {
54
const path = _buildPath(url, configFile)
65
const pathArr = path.replacedUrl.split("/")
76
const pkg = pathArr[pathArr.length - 2].replace(/\./g, '')
@@ -14,15 +13,16 @@ function buildPath(url, configFile = "./.api-to-go.yml") {
1413
struct,
1514
pkg,
1615
dir,
17-
jsonFilePath: `${dir}/${last}_sample.json`,
18-
goFilePath: `${dir}/${last}.go`
16+
jsonFilePath: `${dir}/${last}.json`,
17+
goFilePath: `${dir}/${last}.go`,
18+
paramJsonFilePath: `${dir}/${last}_param.json`,
19+
paramGoFilePath: `${dir}/${last}_param.go`,
1920
}
2021
}
2122

2223
function _buildPath(url, configFile) {
23-
const cfg = _loadConfig(configFile)
24-
const hostCfg = cfg?.[url.hostname]
25-
let ret ={
24+
const hostCfg = loadConfig(url, configFile)
25+
let ret = {
2626
pathname: url.pathname,
2727
pathFormat: null,
2828
replacedPath: url.pathname,
@@ -63,7 +63,6 @@ function _replacePath(pathname, format) {
6363
if (replacedArr.length === 0) return
6464

6565
const replacedPath = replacedArr.join("/")
66-
console.log(`format: ${format}`)
6766
return {
6867
pathname: pathname,
6968
pathFormat: format,
@@ -76,12 +75,4 @@ function _capitalize(str) {
7675
return str.charAt(0).toUpperCase() + lower.slice(1);
7776
}
7877

79-
function _loadConfig(configFile) {
80-
try {
81-
return yaml.load(fs.readFileSync(configFile, 'utf8'));
82-
} catch (e) {
83-
console.log(e);
84-
}
85-
}
86-
8778
module.exports = buildPath;

src/buildPath.test.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ test('build path', () => {
44
const expected = {
55
"dir": "api.github.com/users/user",
66
"goFilePath": "api.github.com/users/user/repos.go",
7-
"jsonFilePath": "api.github.com/users/user/repos_sample.json",
7+
"jsonFilePath": "api.github.com/users/user/repos.json",
8+
"paramGoFilePath": "api.github.com/users/user/repos_param.go",
9+
"paramJsonFilePath": "api.github.com/users/user/repos_param.json",
810
"path": {
911
"pathFormat": "/users/{user}/repos",
1012
"pathname": "/users/github/repos",
@@ -16,7 +18,7 @@ test('build path', () => {
1618
}
1719
const received = buildPath(
1820
new URL("https://api.github.com/users/github/repos"),
19-
"./.api-to-go.test.yaml"
21+
"./.api-to-go.test.yml"
2022
)
2123
expect(received).toEqual(expected);
2224
});
@@ -30,7 +32,7 @@ test('build path without format setting', () => {
3032
}
3133
const received = buildPath(
3234
new URL("https://api.github.com/organizations"),
33-
"./.api-to-go.test.yaml"
35+
"./.api-to-go.test.yml"
3436
)
3537
expect(received.path).toEqual(expected);
3638
});

src/common.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const yaml = require("js-yaml");
2+
const fs = require("fs");
3+
const path = require('path')
4+
5+
exports.loadJsonOrYaml = file => {
6+
switch (path.extname(file)) {
7+
case '.json':
8+
return this.loadJson(file)
9+
case '.yml':
10+
return this.loadYaml(file)
11+
case '.yaml':
12+
return this.loadYaml(file)
13+
default:
14+
throw new Error(`${file} is not json or yaml file`);
15+
}
16+
}
17+
18+
exports.loadJson = file => {
19+
return JSON.parse(this.loadFile(file));
20+
};
21+
22+
exports.loadYaml = file => {
23+
return yaml.load(this.loadFile(file));
24+
}
25+
26+
exports.loadFile = file => {
27+
if (!fs.existsSync(file)) {
28+
throw new Error(`${file} is not exists.`);
29+
}
30+
return fs.readFileSync(file, 'utf8');
31+
};
32+
33+
exports.isJsonString = str => {
34+
try {
35+
JSON.parse(str);
36+
} catch (e) {
37+
return false;
38+
}
39+
return true;
40+
};
41+
42+
exports.isYamlString = str => {
43+
try {
44+
yaml.load(str);
45+
} catch (e) {
46+
return false;
47+
}
48+
return true;
49+
};
50+
51+
exports.loadConfig = (url, configFile) => {
52+
return this.loadYaml(configFile)?.[url.hostname]
53+
}

0 commit comments

Comments
 (0)