Skip to content

Commit

Permalink
Support multiple files, upgrade protobufjs
Browse files Browse the repository at this point in the history
  • Loading branch information
JennieJi committed Apr 22, 2020
1 parent 8c90875 commit 4e559ed
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 138 deletions.
121 changes: 62 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
protobuf2swagger
===
# protobuf2swagger

Work in progress project for saving some life, update not garrenteed. Welcome for pull request :).

Expand All @@ -8,13 +7,13 @@ Then you may render it easily with [SwaggerUI](https://github.com/swagger-api/sw

# What is supported

- convert *enum*, *message* into components, paths will reference to the components schema
- basic types mapping to JS type *number*, *string*, *boolean* ( long types will be mapped to *string*)
- convert _enum_, _message_ into components, paths will reference to the components schema
- basic types mapping to JS type _number_, _string_, _boolean_ ( long types will be mapped to _string_)
- recognize fields:
- [OperationObject](https://swagger.io/specification/#operationObject).requestBody.$proto
Replace requestBody with a [Reference Object](https://swagger.io/specification/#referenceObject)
- [OperationObject](https://swagger.io/specification/#operationObject).responses.$proto
Replace responses['200'] with a [Reference Object](https://swagger.io/specification/#referenceObject)
- [OperationObject](https://swagger.io/specification/#operationObject).requestBody.\$proto
Replace requestBody with a [Reference Object](https://swagger.io/specification/#referenceObject)
- [OperationObject](https://swagger.io/specification/#operationObject).responses.\$proto
Replace responses['200'] with a [Reference Object](https://swagger.io/specification/#referenceObject)

# Install

Expand All @@ -24,58 +23,66 @@ Then you may render it easily with [SwaggerUI](https://github.com/swagger-api/sw

`protobuf2swagger [config_file]`

| Argument | Description |
| --- | --- |
| Argument | Description |
| ----------- | --------------------------------------------------------------------------------------------- |
| config_file | Customize configuration file. Default to **protobuf2swagger.config.js** under current folder. |

For options may check `protobuf2swagger --help`. (Nothing there yet, seriously.)

## Config File

Example:

```javascript
module.exports = {
file: 'test.proto',
dist: 'apischema.json',
customSchema: { // Similar to openapi v3 format
// or multiple files
files: ['test1.proto', 'test2.proto'],
dist: 'apischema.json',
customSchema: {
// Similar to openapi v3 format
info: {
title: 'API',
version: '1.0.0',
contact: {
name: 'Jennie Ji',
email: '[email protected]',
url: 'jennieji.github.io'
url: 'jennieji.github.io',
},
},
tags: [{
name: 'test',
description: ''
}],
tags: [
{
name: 'test',
description: '',
},
],
paths: {
'/api/test': {
get: {
requestBody: {
$proto: 'GetDataRequest', // Tell me the protobuf message name
$proto: 'GetDataRequest', // Tell me the protobuf message name
},
responses: {
$proto: 'GetDataResponse', // Tell me the protobuf message name
}
}
}
},
},
},
},
components: {
securitySchemes: {
cookieAuth: {
type: 'apiKey',
in: 'cookie',
name: 'token'
}
}
name: 'token',
},
},
},
security: [{
cookieAuth: []
}]
}
security: [
{
cookieAuth: [],
},
],
},
};
```

Expand All @@ -87,27 +94,28 @@ index.html (modified from swagger-ui-dist)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta charset="UTF-8" />
<title>API Document</title>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.22.2/swagger-ui.css" >
<link
rel="stylesheet"
type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.22.2/swagger-ui.css"
/>
<style>
html
{
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
*:after {
box-sizing: inherit;
}
body
{
margin:0;
body {
margin: 0;
background: #fafafa;
}
</style>
Expand All @@ -116,28 +124,23 @@ index.html (modified from swagger-ui-dist)
<body>
<div id="swagger-ui"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.22.2/swagger-ui-bundle.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.22.2/swagger-ui-standalone-preset.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.22.2/swagger-ui-bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.22.2/swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "./apischema.json", // Path to the generated schema JSON file
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
}
</script>
window.onload = function () {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: './apischema.json', // Path to the generated schema JSON file
dom_id: '#swagger-ui',
deepLinking: true,
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
layout: 'StandaloneLayout',
});
// End Swagger UI call region
window.ui = ui;
};
</script>
</body>
</html>
```
Expand All @@ -152,4 +155,4 @@ app.use(express.static(__dirname /* path to index.html */));
app.listen(3000);

console.info('Served at port 3000');
```
```
20 changes: 11 additions & 9 deletions bin/protobuf2swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@ const program = require('commander');
const fs = require('fs');
const convert = require('../utils/convert.js');

program.version('0.0.0', '-v --version')
.arguments('[config_file]')
.usage('[config_file]')
.on('--help', () => {
console.log('\n');
console.log('config_file Customize configuration file. Default to protobuf2swagger.config.js under current folder.')
})
.parse(process.argv);
program
.version('0.0.0', '-v --version')
.arguments('[config_file]')
.usage('[config_file]')
.on('--help', () => {
console.log('\n');
console.log(
'config_file Customize configuration file. Default to protobuf2swagger.config.js under current folder.'
);
})
.parse(process.argv);

const [configPath] = program.args;
const cwd = process.cwd();
const DEFAULT_CONFIG_PATH = 'protobuf2swagger.config.js';
const config = require(path.resolve(cwd, configPath || DEFAULT_CONFIG_PATH));


(async () => {
const content = await convert(config);
const dist = config.dist ? path.resolve(cwd, config.dist) : cwd;
Expand Down
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "protobuf2swagger",
"version": "0.0.0-alpha.1",
"version": "0.0.1",
"description": "Convert protobuf to swagger open api v3 format",
"main": "index.js",
"bin": {
Expand All @@ -20,6 +20,6 @@
"license": "MIT",
"dependencies": {
"commander": "^2.20.0",
"protobufjs": "^6.8.8"
"protobufjs": "^6.9.0"
}
}
55 changes: 35 additions & 20 deletions utils/convert.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,53 @@
const protobuf = require('protobufjs');
const protobufjs = require('protobufjs');
const fs = require('fs');
const processPaths = require('./processPaths.js');
const processComponents = require('./processComponents');

const OPENAPI_VERSION = '3.0.0';

async function convert({
file,
customSchema
}) {
// TODO: custom schema validate
const rootProto = await protobuf.parse(fs.readFileSync(file).toString(), {
alternateCommentMode: true
});
async function convert({ file, files, customSchema }) {
const protobuf = new protobufjs.Root();
if (file) {
protobuf.loadSync(file, {
alternateCommentMode: true,
});
}
if (files) {
files.forEach((file) => {
protobuf.loadSync(file, {
alternateCommentMode: true,
});
});
}
const { paths: rawPaths, components: rawComponents } = customSchema;
const schemas = Object.assign(
processComponents(flattenPath(protobuf.nested)),
(rawComponents && rawComponents.schemas) || {}
);
return {
...customSchema,
openapi: OPENAPI_VERSION,
paths: processPaths(rawPaths),
components: {
...(rawComponents || {}),
schemas: {
...processComponents(getProtoByPath(rootProto)),
...(rawComponents || {}).schemas,
}
}
schemas,
},
};
}

function getProtoByPath(proto) {
return proto.package
.split('.')
.reduce((data, path) => data.get(path), proto.root)
.nested;
function flattenPath(protobuf) {
let flattened = {};
Object.keys(protobuf).forEach((key) => {
const val = protobuf[key];
if (val.nested) {
Object.entries(flattenPath(val.nested)).forEach(([type, def]) => {
flattened[`${key}.${type}`] = def;
});
} else {
flattened[key] = val;
}
});
return flattened;
}

module.exports = convert;
module.exports = convert;
Loading

0 comments on commit 4e559ed

Please sign in to comment.