Skip to content

Commit 5593baf

Browse files
committed
feat: add library AJV , check example for schema (types , limit , required)
1 parent ff10b07 commit 5593baf

File tree

12 files changed

+325
-161
lines changed

12 files changed

+325
-161
lines changed

example/ExampleGeneratedExamplesWithRequerides.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ paths:
2929
application/json:
3030
schema:
3131
$ref: '#/components/schemas/ErrorResponse'
32+
examples:
33+
GeneratedExampleErrorResponse:
34+
value:
35+
code: 500
36+
message: Internal server error
3237
components:
3338
schemas:
3439
UsersList:

index.js

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
#!/usr/bin/env node
22

3-
'use strict'
3+
'use strict';
44

55
const _ = require('lodash');
6-
const { getName, getProperty } = require('./src/utils/schemaUtils');
6+
const fs = require('fs');
7+
const path = require('path');
8+
const { getName ,getNameExample, getProperty } = require('./src/utils/schemaUtils');
9+
10+
const { verifyProperties , errorsList} = require('./src/utils/verifyProperties')
11+
712
const createComponent = require("./src/generator/createComponent")();
813

914
const argv = require('yargs')(process.argv.slice(2))
1015
.usage('Usage: $0 -f [file]')
1116
.option('f', {
1217
alias: 'file',
1318
describe: 'Path to openapi file',
14-
type: 'string'
19+
type: 'string',
20+
demandOption: true // Hacer que el archivo sea obligatorio
1521
})
1622
.example('\x1b[32m $0 -f /path/to/openapi.yaml \x1b[0m')
1723
.example('\x1b[32m $0 -f /path/to/openapi.yml \x1b[0m')
@@ -21,82 +27,75 @@ const argv = require('yargs')(process.argv.slice(2))
2127

2228
global.definition = require('./src/parser/definition.js')();
2329

24-
Object.keys(global.definition.paths).forEach(path => {
25-
26-
Object.keys(global.definition.paths[path]).forEach(method => {
27-
28-
const methodObj = global.definition.paths[path][method];
29-
30-
Object.keys(methodObj.responses ?? []).forEach(key => {
31-
32-
const response = methodObj.responses[key];
33-
const property = getProperty(response, path, method, key);
34-
const schemaPath = `${property}.content.application/json.schema`;
35-
const nameExample = getName(schemaPath, key);
36-
37-
38-
if(_.get(global.definition, schemaPath)?.['example'] || !_.get(global.definition, schemaPath)?.['$ref']){
39-
40-
const exampleKey = `${property}.content.application/json.examples.${nameExample}`;
4130

42-
if(_.get(global.definition, schemaPath)?.['example']){
31+
function generateExample(property, schemaPath, nameExample, example , nameSchema) {
32+
const exampleKey = `${property}.content.application/json.examples.${nameExample}`;
33+
const routeKey = createComponent(definition, example, exampleKey);
4334

44-
const example = _.get(global.definition, schemaPath)?.['example'];
45-
const routeKey = createComponent(global.definition, example, exampleKey);
4635

47-
_.unset(global.definition, `${property}.content.application/json.schema.example`)
48-
_.set(global.definition, `${property}.content.application/json.examples.${nameExample}`, { $ref: routeKey });
36+
const validate = verifyProperties(example, schemaPath , nameSchema , exampleKey);
4937

50-
require('./src/utils/sucess')(`Example generated for ${exampleKey}`)
5138

52-
}
53-
54-
}
39+
if (!validate) {
40+
return;
41+
}
5542

56-
if (_.get(global.definition, `${property}.content.application/json.example`)) {
43+
_.unset(definition, `${property}.content.application/json.example`);
44+
_.set(definition, exampleKey, { $ref: routeKey });
5745

58-
const exampleKey = `${property}.content.application/json.examples.${nameExample}`;
59-
const example = _.get(global.definition, `${property}.content.application/json.example`);
46+
47+
require('./src/utils/sucess')(`Example generated in ${exampleKey.replace('paths./', '#/').replace(/\./g, '/')}`);
6048

61-
const routeKey = createComponent(global.definition, example, exampleKey);
49+
}
6250

63-
if(_.get(global.definition, `${property}.content.application/json.example`)){
6451

65-
_.unset(global.definition, `${property}.content.application/json.example`)
66-
_.set(global.definition, `${property}.content.application/json.examples.${nameExample}`, { $ref: routeKey });
52+
Object.keys(definition.paths).forEach(path => {
53+
Object.keys(definition.paths[path]).forEach(method => {
54+
const methodObj = definition.paths[path][method];
6755

68-
require('./src/utils/sucess')(`Example generated for ${exampleKey}`)
56+
Object.keys(methodObj.responses ?? []).forEach(key => {
57+
const response = methodObj.responses[key];
58+
const property = getProperty(response, path, method, key);
59+
const schemaPath = `${property}.content.application/json.schema`;
6960

70-
}
7161

72-
}
62+
const nameExample = getNameExample(schemaPath);
63+
const schema = _.get(definition, schemaPath);
64+
const schemaDetails = require('./src/parser/refs.js')(schema, definition);
7365

74-
if (response?.['$ref'] && !_.get(global.definition, `${property}.content.application/json.examples`)) {
75-
76-
if(_.get(global.definition, `${property}.content.application/json.example`)){
77-
_.unset(global.definition, `${property}.content.application/json.example`)
66+
67+
if (schema) {
68+
if (schema.example) {
69+
generateExample(property, schemaDetails, nameExample, schema.example , getName(schemaPath));
7870
}
7971

80-
const exampleKey = `${property}.content.application/json.examples.${nameExample}`;
81-
82-
require('./src/generator/examples.js')(_.get(global.definition, schemaPath), global.definition, exampleKey);
83-
84-
85-
} else if (_.get(response, 'content.application/json.schema') && !_.get(response, 'content.application/json.examples')) {
86-
87-
const schemaPath = `${property}.content.application/json.schema`;
88-
const exampleKey = `${property}.content.application/json.examples.${nameExample}`;
89-
90-
if(_.get(global.definition, `${property}.content.application/json.example`)){
91-
_.unset(global.definition, `${property}.content.application/json.example`)
72+
if (_.get(response, 'content.application/json.example')) {
73+
generateExample(property, schemaDetails, nameExample, _.get(response, 'content.application/json.example') , getName(schemaPath));
9274
}
9375

76+
if (response?.['$ref'] && !_.get(definition, `${property}.content.application/json.examples`)) {
77+
console.log('entro')
78+
if (_.get(response, 'content.application/json.example')) {
79+
_.unset(definition, `${property}.content.application/json.example`);
80+
}
81+
require('./src/generator/examples.js')(schema, definition, `${property}.content.application/json.examples.${nameExample}` , schemaDetails , getName(schemaPath))
82+
}
83+
}
9484

95-
require('./src/generator/examples.js')(_.get(global.definition, schemaPath), global.definition, exampleKey);
85+
if (response?.['content']?.['application/json']?.schema && !response?.['content']?.['application/json']?.examples) {
86+
require('./src/generator/examples.js')(schema, definition, `${property}.content.application/json.examples.${nameExample}` , schemaDetails , getName(schemaPath))
9687
}
9788
});
9889
});
9990
});
10091

10192

93+
if (errorsList.length !== 0) {
94+
console.error('Errors found in the examples:');
95+
console.log(errorsList);
96+
}
97+
98+
99+
100+
102101
require('./src/generator/file.js')();

package-lock.json

Lines changed: 52 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
{
22
"name": "Convert schemas to examples",
3-
"version": "1.0.1",
3+
"version": "1.1.0",
44
"scripts": {
55
"test": "mocha",
66
"debug": "node --inspect-brk index.js -f ./index.yaml"
77
},
88
"dependencies": {
9+
"ajv": "^8.17.1",
10+
"ajv-keywords": "^5.1.0",
911
"chai": "^5.1.1",
1012
"js-yaml": "^4.1.0",
1113
"lodash": "^4.17.21",

src/generator/buildExample.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function mergeAndDeduplicate(value1, value2) {
2626

2727
module.exports = function () {
2828
return function buildExample (schema, definition, depth = 0) {
29-
const example = { properties: {}, required: [], example: {} };
29+
const example = { properties: {} ,example: {} };
3030

3131
if (depth > MAX_DEPTH_LEVEL) {
3232
return example;
@@ -50,7 +50,9 @@ module.exports = function () {
5050

5151
example.example = mergeAndDeduplicate(example.example, example.properties);
5252

53-
return example;
53+
54+
55+
return example
5456
}
5557
}()
5658

src/generator/examples.js

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,74 @@
11
"use strict";
22

33
const _ = require("lodash");
4-
const setExample = require('./setExample')()
5-
4+
const setExample = require('./setExample')();
5+
const { verifyProperties } = require('../utils/verifyProperties');
6+
const { exit } = require("yargs");
67

78
module.exports = (function () {
8-
return function addExampleToSchema(schema, definition, exampleKey) {
99

10-
const buildExample = require('./buildExample')(schema, definition);
10+
return function addExampleToSchema(schema, definition, exampleKey, schemaDetails , nameSchema) {
11+
12+
const buildExample = require('./buildExample')(schema, definition);
1113
const example = cleanEmptyValues(buildExample);
14+
15+
let isValid = true;
16+
17+
if (schema?.allOf || schema?.oneOf || schema?.anyOf) {
18+
isValid = validateComposedSchemas(schema, definition , exampleKey);
19+
}
20+
21+
if (schema.$ref) {
22+
isValid = validateReference(schema, definition , exampleKey);
23+
}
24+
25+
isValid = verifyProperties(example.example, schemaDetails, nameSchema , exampleKey);
26+
27+
if (!isValid) {
28+
require('../utils/warning')(`Error in the generated example for ${exampleKey}`);
29+
return;
30+
}
1231

13-
if (!setExample(definition, example.example, exampleKey, example.required)) {
1432

15-
if(!setExample(definition, example.properties, exampleKey, example.required)){
33+
setExample(definition, example.example, exampleKey);
34+
35+
};
36+
})();
37+
38+
const validateReference = (schema, definition , exampleKey) => {
39+
40+
let isValid = true;
41+
42+
const refSchema = require('../parser/references.low')(schema , definition);
43+
44+
if (refSchema?.allOf || refSchema?.oneOf || refSchema?.anyOf) {
45+
if ( !validateComposedSchemas(refSchema, definition , exampleKey) ) {
46+
isValid = false;
47+
}
48+
}
49+
50+
return isValid;
51+
};
52+
53+
const validateComposedSchemas = (schema, definition , exampleKey) => {
54+
let isValid = true;
55+
56+
const schemasToCheck = schema.allOf || schema.oneOf || schema.anyOf;
57+
58+
schemasToCheck.forEach((element, index) => {
59+
60+
const subExample = require('./buildExample')(element, definition);
61+
const subSchema = require('../parser/refs')(element, definition);
1662

17-
_.unset(definition, `components.examples.${exampleKey.split('.').pop()}`);
63+
const subNameSchema = element.$ref ? element?.$ref.split('/').pop() : 'AnonymousSchema';
1864

19-
require('../utils/warning')(`Example not generated for ${exampleKey}`);
20-
}
65+
if (!verifyProperties(subExample.example, subSchema, subNameSchema , exampleKey)) {
66+
isValid = false;
2167
}
22-
}})();
68+
});
2369

70+
return isValid;
71+
};
2472

2573
const cleanEmptyValues = (data) => {
2674
if (Array.isArray(data)) {
@@ -41,4 +89,4 @@ const cleanEmptyValues = (data) => {
4189
} else {
4290
return data;
4391
}
44-
};
92+
};

0 commit comments

Comments
 (0)