Repository: BRIKEV/express-jsdoc-swagger
Pull request #2 (2020-05-24 18:16:14)

Components refs
Added reference between two jsdoc components.


Patch:
diff --git a/index.js b/index.js
index 8a0af1d..5e3dc07 100644
--- a/index.js
+++ b/index.js
@@ -5,7 +5,7 @@ const readFiles = require('./consumers/readFiles');
 const globFilesMatches = require('./consumers/globFilesMatches');
 const getOnlyComments = require('./consumers/getOnlyComments');
 const jsdocInfo = require('./consumers/jsdocInfo');
-const { getBasicInfo, getPaths } = require('./transforms');
+const { getBasicInfo, getPaths, getComponents } = require('./transforms');
 
 /**
  * Generator options
@@ -39,6 +39,7 @@ const expressJSDocSwagger = app => {
       .then(jsdocInfo())
       .then(data => {
         swaggerObject = getPaths(swaggerObject, data);
+        swaggerObject = getComponents(swaggerObject, data);
       })
       .catch(err => console.log(err));
 
diff --git a/transforms/components/index.js b/transforms/components/index.js
index 27a3d32..32e5803 100644
--- a/transforms/components/index.js
+++ b/transforms/components/index.js
@@ -1,6 +1,8 @@
 const { getTagInfo, getTagsInfo } = require('../utils/tags');
+const validateTypes = require('../utils/validateTypes');
 
 const REQUIRED = 'required';
+const REF_ROUTE = '#/components/schemas/';
 
 const getPropertyName = ({ name: propertyName }) => {
   const [name] = propertyName.split('.');
@@ -11,12 +13,14 @@ const formatProperties = properties => {
   if (!properties || !Array.isArray(properties)) return {};
   return properties.reduce((acum, property) => {
     const name = getPropertyName(property);
+    const isValidType = validateTypes(property.type.name);
     const [description, format] = property.description.split(' - ');
+    const propertyName = property.type.name;
     return {
       ...acum,
       [name]: {
-        type: property.type.name,
         description,
+        ...(isValidType ? { type: propertyName } : { $ref: `${REF_ROUTE}${propertyName}` }),
         ...(format ? { format } : {}),
       },
     };
diff --git a/transforms/index.js b/transforms/index.js
index 14be549..258480d 100644
--- a/transforms/index.js
+++ b/transforms/index.js
@@ -1,7 +1,9 @@
 const getBasicInfo = require('./basic');
 const getPaths = require('./paths');
+const getComponents = require('./components');
 
 module.exports = {
   getBasicInfo,
   getPaths,
+  getComponents,
 };
diff --git a/transforms/paths/index.js b/transforms/paths/index.js
index fb48d34..dc0b0f8 100644
--- a/transforms/paths/index.js
+++ b/transforms/paths/index.js
@@ -29,10 +29,9 @@ const parsePath = path => {
 
 const parsePaths = (swaggerObject = {}, paths = []) => {
   if (!paths || !Array.isArray(paths)) return { paths: {} };
-  const pathObject = paths.reduce((acum, item) => {
-    const newPaths = { ...parsePath(item) };
-    return newPaths;
-  }, {});
+  const pathObject = paths.reduce((acum, item) => ({
+    ...acum, ...parsePath(item),
+  }), {});
   return {
     ...swaggerObject,
     paths: pathObject,
diff --git a/transforms/utils/validateTypes.js b/transforms/utils/validateTypes.js
new file mode 100644
index 0000000..79d042f
--- /dev/null
+++ b/transforms/utils/validateTypes.js
@@ -0,0 +1,10 @@
+const TYPES = [
+  'integer',
+  'number',
+  'string',
+  'boolean',
+];
+
+const validateTypes = type => TYPES.includes(type);
+
+module.exports = validateTypes;


Test patch:
diff --git a/test/transforms/components/index.test.js b/test/transforms/components/index.test.js
index c3b4c8e..5afbb7d 100644
--- a/test/transforms/components/index.test.js
+++ b/test/transforms/components/index.test.js
@@ -176,4 +176,65 @@ describe('parseComponents method', () => {
     const result = parseComponents({}, parsedJSDocs);
     expect(result).toEqual(expected);
   });
+
+  it('Should parse one reference between two jsdoc components', () => {
+    const jsodInput = [`
+      /**
+       * A song
+       * @typedef {object} Song
+       * @property {string} title.required - The title
+       * @property {string} artist - The artist
+       * @property {number} year - The year - int64
+       */
+    `,
+    `
+      /**
+       * Album
+       * @typedef {object} Album
+       * @property {Song} firstSong
+       */
+    `];
+    const expected = {
+      components: {
+        schemas: {
+          Song: {
+            type: 'object',
+            required: [
+              'title',
+            ],
+            description: 'A song',
+            properties: {
+              title: {
+                type: 'string',
+                description: 'The title',
+              },
+              artist: {
+                type: 'string',
+                description: 'The artist',
+              },
+              year: {
+                type: 'number',
+                description: 'The year',
+                format: 'int64',
+              },
+            },
+          },
+          Album: {
+            type: 'object',
+            required: [],
+            description: 'Album',
+            properties: {
+              firstSong: {
+                $ref: '#/components/schemas/Song',
+                description: '',
+              },
+            },
+          },
+        },
+      },
+    };
+    const parsedJSDocs = jsdocInfo()(jsodInput);
+    const result = parseComponents({}, parsedJSDocs);
+    expect(result).toEqual(expected);
+  });
 });