Skip to content

Commit 010a0b8

Browse files
committed
Add support for URLs instead of files, and fix request bodies rendering
1 parent 3a07f78 commit 010a0b8

4 files changed

Lines changed: 84 additions & 45 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ npm install -g openapi3-generator
2020
### From the command-line interface (CLI)
2121

2222
```bash
23-
Usage: og [options] <openapiFile> <template>
23+
Usage: og [options] <openapiFileOrURL> <template>
2424

2525

2626
Options:

cli.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ const parseOutput = dir => path.resolve(dir);
1818

1919
program
2020
.version(packageInfo.version)
21-
.arguments('<openapiFile> <template>')
21+
.arguments('<openapiFileOrURL> <template>')
2222
.action((openapiFilePath, tmpl) => {
23-
openapiFile = path.resolve(openapiFilePath);
23+
if (!openapiFilePath.startsWith('http:') && !openapiFilePath.startsWith('https:')) {
24+
openapiFile = path.resolve(openapiFilePath);
25+
} else {
26+
openapiFile = openapiFilePath;
27+
}
28+
2429
template = tmpl;
2530
})
2631
.option('-o, --output <outputDir>', 'directory where to put the generated files (defaults to current directory)', parseOutput, process.cwd())

lib/beautifier.js

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const resolveAllOf = (schema) => {
1717
schemas.push(s);
1818
});
1919

20-
return resolveAllOf(_.merge({}, ...schemas));
20+
return resolveAllOf(_.merge(...schemas));
2121
}
2222

2323
if (schema.properties) {
@@ -31,36 +31,55 @@ const resolveAllOf = (schema) => {
3131
transformed[key] = schema.properties[key];
3232
}
3333

34-
return {
35-
...schema,
36-
...{ properties: transformed }
37-
};
34+
schema.properties = transformed;
35+
36+
return schema;
3837
}
3938

4039
return schema;
4140
};
4241

43-
const stringify = json => JSON.stringify(json || '', null, 2);
4442
const generateExample = schema => OpenAPISampler.sample(schema);
4543

44+
const beautifySchema = (schema) => {
45+
resolveAllOf(schema);
46+
if (!schema.example) schema.generatedExample = generateExample(schema);
47+
48+
_.each(schema.properties, (prop) => {
49+
if (prop.description) prop.descriptionAsHTML = md.render(prop.description || '');
50+
if (prop.properties) beautifySchema(prop);
51+
});
52+
_.each(schema.additionalProperties, (prop) => {
53+
if (prop.description) prop.descriptionAsHTML = md.render(prop.description || '');
54+
if (prop.additionalProperties) beautifySchema(prop);
55+
});
56+
57+
return schema;
58+
};
59+
4660
const beautifyOperation = (operation) => {
4761
operation.summaryAsHTML = md.render(operation.summary || '');
4862
operation.descriptionAsHTML = md.render(operation.description || '');
4963

64+
if (operation.requestBody) {
65+
_.each(operation.requestBody.content, (contentType) => {
66+
if (contentType.schema) {
67+
contentType.schema = beautifySchema(contentType.schema);
68+
}
69+
});
70+
}
71+
5072
if (operation.parameters) {
73+
operation.parameters = operation.parameters.filter(p => p.in !== 'body');
5174
operation.parameters.filter(p => p.schema).forEach(param => resolveAllOf(param.schema));
5275

53-
if (operation.requestBody) {
54-
operation.parameters = operation.parameters.filter(p => p.in !== 'body');
55-
}
56-
57-
operation.parameters.forEach((param, index) => {
76+
operation.parameters.forEach((param) => {
5877
param.descriptionAsHTML = md.render(param.description || '');
5978
});
6079
}
6180

6281
if (operation.responses) {
63-
_.each(operation.responses, (response, responseCode) => {
82+
_.each(operation.responses, (response) => {
6483
if (response.content && response.content.schema) {
6584
resolveAllOf(response.content.schema);
6685
}
@@ -73,17 +92,6 @@ const beautifyOperation = (operation) => {
7392
return operation;
7493
};
7594

76-
const beautifySchema = (schema) => {
77-
_.each(schema.properties, (prop, propName) => {
78-
if (prop.description) prop.descriptionAsHTML = md.render(prop.description || '');
79-
if (prop.properties) beautifySchema(prop);
80-
});
81-
_.each(schema.additionalProperties, (prop, propName) => {
82-
if (prop.description) prop.descriptionAsHTML = md.render(prop.description || '');
83-
if (prop.additionalProperties) beautifySchema(prop);
84-
});
85-
};
86-
8795
const cleanBrackets = text => {
8896
let finalText = text;
8997

@@ -98,6 +106,16 @@ module.exports = (openapi) => {
98106
openapi.info = openapi.info || {};
99107
openapi.info.descriptionAsHTML = md.render(openapi.info.description || '');
100108

109+
if (!openapi.components) openapi.components = {};
110+
if (!openapi.components.schemas) {
111+
openapi.__noSchemas = true;
112+
openapi.components.schemas = {};
113+
}
114+
115+
_.each(openapi.components.schemas, (schema, schemaName) => {
116+
openapi.components.schemas[schemaName] = beautifySchema(schema);
117+
});
118+
101119
if (openapi.servers) {
102120
_.each(openapi.servers, server => {
103121
server.descriptionAsHTML = md.render(server.description || '');
@@ -141,23 +159,6 @@ module.exports = (openapi) => {
141159

142160
openapi.endpoints = _.unique(_.pluck(openapi.paths, 'endpointName'));
143161

144-
if (!openapi.components) openapi.components = {};
145-
if (!openapi.components.schemas) {
146-
openapi.__noSchemas = true;
147-
openapi.components.schemas = {};
148-
}
149-
150-
_.each(openapi.components.schemas, (schema, schemaName) => {
151-
schema = resolveAllOf(schema);
152-
if (schema.example) {
153-
schema.formattedExample = stringify(schema.example);
154-
} else {
155-
schema.generatedExample = stringify(generateExample(schema));
156-
}
157-
openapi.components.schemas[schemaName] = schema;
158-
beautifySchema(schema);
159-
});
160-
161162
const commonPrefix = sharedStart(Object.keys(openapi.paths));
162163
const levels = commonPrefix.split('/').length - 1;
163164
openapi.__commonPrefix = commonPrefix.split('/').slice(0, levels).join('/');

lib/bundler.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,46 @@
11
const fs = require('fs');
22
const path = require('path');
3+
const http = require('http');
4+
const https = require('https');
35
const YAML = require('js-yaml');
46
const RefParser = require('json-schema-ref-parser');
57
const validator = require('oas-validator');
68

7-
async function getFileContent (filePath) {
9+
const handleHTTPResponse = (url, res, resolve, reject) => {
10+
if (res.statusCode >= 400) return reject(`Can't get file ${url}`);
11+
12+
res.setEncoding('utf8');
13+
let rawData = '';
14+
res.on('data', (chunk) => { rawData += chunk; });
15+
res.on('end', () => { resolve(rawData); });
16+
res.on('error', reject);
17+
};
18+
19+
function getContentFromURL (url) {
20+
return new Promise((resolve, reject) => {
21+
if (url.startsWith('http:')) {
22+
http.get(url, (res) => {
23+
handleHTTPResponse(url, res, resolve, reject);
24+
}).on('error', reject);
25+
} else if (url.startsWith('https:')) {
26+
https.get(url, (res) => {
27+
handleHTTPResponse(url, res, resolve, reject);
28+
}).on('error', reject);
29+
} else {
30+
reject('Protocol not supported.');
31+
}
32+
});
33+
}
34+
35+
function getFileContent (filePath) {
836
return new Promise((resolve, reject) => {
937
fs.readFile(path.resolve(__dirname, filePath), (err, content) => {
10-
if (err) return reject(err);
38+
if (err) {
39+
getContentFromURL(filePath)
40+
.catch(reject)
41+
.then(content => resolve(content));
42+
return;
43+
}
1144
resolve(content);
1245
});
1346
});

0 commit comments

Comments
 (0)