@@ -43,6 +43,8 @@ const DEFAULT_TEMPLATE = {
43
43
// Add more properties as needed
44
44
} ;
45
45
46
+
47
+
46
48
module . exports = function ( RED ) {
47
49
"use strict" ;
48
50
@@ -56,130 +58,7 @@ module.exports = function(RED) {
56
58
url . length > 1 && url . endsWith ( "/" ) ? url . slice ( 0 , - 1 ) : url ;
57
59
const regexColons = / \/ : \w * / g;
58
60
59
- /*
60
- RED.httpNode.get("/http-api/swagger.json", (req, res) => {
61
- const {
62
- httpNodeRoot,
63
- swagger: { parameters: additionalParams = [], template: resp = { ...DEFAULT_TEMPLATE } } = {}
64
- } = RED.settings;
65
- const { basePath = httpNodeRoot } = resp;
66
- resp.basePath = stripTerminalSlash(basePath);
67
- resp.paths = {};
68
-
69
- RED.nodes.eachNode(node => {
70
- const { name, type, method, swaggerDoc, url } = node;
71
-
72
- if (type === "http in") {
73
- const swagger = RED.nodes.getNode(swaggerDoc);
74
- const endPoint = ensureLeadingSlash(url.replace(regexColons, convToSwaggerPath));
75
- if (!resp.paths[endPoint]) resp.paths[endPoint] = {};
76
-
77
- const {
78
- summary = name || method + " " + endPoint,
79
- description = "",
80
- tags = "",
81
- consumes,
82
- produces,
83
- deprecated,
84
- parameters = [],
85
- responses = {
86
- default: {
87
- description: ""
88
- }
89
- }
90
- } = swagger || {};
91
-
92
- const aryTags = csvStrToArray(tags),
93
- aryConsumes = csvStrToArray(consumes),
94
- aryProduces = csvStrToArray(produces);
95
-
96
- resp.paths[endPoint][method] = {
97
- summary,
98
- description,
99
- tags: aryTags,
100
- consumes: aryConsumes,
101
- produces: aryProduces,
102
- deprecated,
103
- parameters: [...parameters, ...additionalParams],
104
- responses
105
- };
106
- }
107
- });
108
- res.json(resp);
109
- });
110
-
111
- RED.httpNode.get("/http-api/swagger.json", (req, res) => {
112
- // Use the default template as the base for the response
113
- const openApiSpec = { ...DEFAULT_TEMPLATE };
114
-
115
- // Iterate over each node that could have associated API documentation
116
- RED.nodes.eachNode(node => {
117
- if (node.type === "http in") {
118
- // Get the Swagger documentation node associated with this http in node
119
- const swaggerDocNode = RED.nodes.getNode(node.swaggerDoc);
120
-
121
- if (swaggerDocNode) {
122
- // Construct the path for the endpoint
123
- const path = ensureLeadingSlash(node.url.replace(regexColons, convToSwaggerPath));
124
-
125
- // Initialize the path object if not already initialized
126
- if (!openApiSpec.paths[path]) {
127
- openApiSpec.paths[path] = {};
128
- }
129
-
130
- // Define the operation object for this method and path
131
- const operation = {
132
- summary: swaggerDocNode.summary || `${node.method.toUpperCase()} ${path}`,
133
- description: swaggerDocNode.description || '',
134
- tags: csvStrToArray(swaggerDocNode.tags),
135
- parameters: [], // This will need to be populated based on your parameter definitions
136
- responses: {} // This will need to be populated based on your response definitions
137
- };
138
-
139
- // Populate parameters array
140
- // You'll need to construct your parameter objects according to OpenAPI 3.0
141
- // For example:
142
- swaggerDocNode.parameters.forEach(param => {
143
- operation.parameters.push({
144
- name: param.name,
145
- in: param.in, // 'query', 'header', 'path' or 'cookie'
146
- description: param.description,
147
- required: param.required,
148
- schema: {
149
- type: param.type
150
- // More schema properties can be set here
151
- }
152
- });
153
- });
154
-
155
- // Populate responses object
156
- // You'll need to map your response objects to status codes
157
- // For example:
158
- console.log(swaggerDocNode); // Should log true if it's an array
159
61
160
- swaggerDocNode.responses.forEach(resp => {
161
- operation.responses[resp.code] = {
162
- description: resp.description,
163
- content: {
164
- 'application/json': {
165
- schema: {
166
- // Define the schema for the response
167
- }
168
- }
169
- }
170
- };
171
- });
172
-
173
- // Add the operation to the path in the spec
174
- openApiSpec.paths[path][node.method.toLowerCase()] = operation;
175
- }
176
- }
177
- });
178
-
179
- // Send the OpenAPI Specification as JSON
180
- res.json(openApiSpec);
181
- });
182
- */
183
62
184
63
RED . httpNode . get ( "/http-api/swagger.json" , ( req , res ) => {
185
64
const {
@@ -257,10 +136,31 @@ module.exports = function(RED) {
257
136
}
258
137
}
259
138
} ) ;
260
-
139
+ // Final cleanup to remove empty sections
140
+ cleanupOpenAPISpec ( resp ) ;
261
141
res . json ( resp ) ;
262
142
} ) ;
263
143
144
+ function cleanupOpenAPISpec ( spec ) {
145
+ // Clean up components
146
+ if ( spec . components ) {
147
+ [ 'schemas' , 'responses' , 'parameters' , 'securitySchemes' ] . forEach ( key => {
148
+ if ( spec . components [ key ] && Object . keys ( spec . components [ key ] ) . length === 0 ) {
149
+ delete spec . components [ key ] ;
150
+ }
151
+ } ) ;
152
+
153
+ // If all components are empty, remove the components object itself
154
+ if ( Object . keys ( spec . components ) . length === 0 ) {
155
+ delete spec . components ;
156
+ }
157
+ }
158
+
159
+ // Clean up empty tags array
160
+ if ( Array . isArray ( spec . tags ) && spec . tags . length === 0 ) {
161
+ delete spec . tags ;
162
+ }
163
+ }
264
164
265
165
function SwaggerDoc ( n ) {
266
166
RED . nodes . createNode ( this , n ) ;
0 commit comments