swaggie 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,13 +8,14 @@ var _swagger = require('../swagger');
8
8
 
9
9
 
10
10
 
11
-
12
11
  var _utils = require('../utils');
13
12
  var _createBarrel = require('./createBarrel');
14
13
 
15
14
 
16
15
 
17
16
 
17
+ var _jsDocs = require('./jsDocs');
18
+
18
19
  /**
19
20
  * Function that will analyze paths in the spec and generate the code for all the operations.
20
21
  */
@@ -121,10 +122,8 @@ function prepareClient(
121
122
  });
122
123
  }
123
124
 
124
- const docs = getOperationDocs(op);
125
125
  return {
126
- docs,
127
- hasJSDocs: docs.length > 0 || params.length > 0,
126
+ jsDocs: _jsDocs.prepareJsDocsForOperation.call(void 0, op, params),
128
127
  returnType,
129
128
  responseContentType,
130
129
  method: op.method.toUpperCase(),
@@ -313,40 +312,3 @@ function getRequestBody(reqBody) {
313
312
  }
314
313
  return null;
315
314
  }
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
@@ -4,6 +4,7 @@ var _swagger = require('../swagger');
4
4
 
5
5
  var _utils = require('../utils');
6
6
  var _refsHelper = require('./refsHelper');
7
+ var _jsDocs = require('./jsDocs');
7
8
 
8
9
  /**
9
10
  * Generates TypeScript code with all the types for the given OpenAPI 3 document.
@@ -60,7 +61,7 @@ function renderSchema(
60
61
 
61
62
  const result = [];
62
63
  if (_nullishCoalesce(schema.description, () => ( schema.title))) {
63
- result.push(renderComment(_nullishCoalesce(schema.description, () => ( schema.title))));
64
+ result.push(_jsDocs.renderComment.call(void 0, _nullishCoalesce(schema.description, () => ( schema.title))));
64
65
  }
65
66
 
66
67
  if ('x-enumNames' in schema || 'x-enum-varnames' in schema) {
@@ -197,7 +198,7 @@ function renderTypeProp(
197
198
  const type = _swagger.getTypeFromSchema.call(void 0, definition, options);
198
199
 
199
200
  if ('description' in definition || 'title' in definition) {
200
- lines.push(renderComment(_nullishCoalesce(definition.description, () => ( definition.title))));
201
+ lines.push(_jsDocs.renderComment.call(void 0, _nullishCoalesce(definition.description, () => ( definition.title))));
201
202
  }
202
203
  const optionalMark = required ? '' : '?';
203
204
  // If prop name is not a valid identifier, we need to wrap it in quotes.
@@ -208,20 +209,6 @@ function renderTypeProp(
208
209
  return lines.join('\n');
209
210
  }
210
211
 
211
- function renderComment(comment) {
212
- if (!comment) {
213
- return null;
214
- }
215
-
216
- const commentLines = comment.split('\n');
217
-
218
- if (commentLines.length === 1) {
219
- return `/** ${comment.trim()} */`;
220
- }
221
-
222
- return ` /**\n${commentLines.map((line) => ` * ${line.trim()}`).join('\n')}\n */`;
223
- } exports.renderComment = renderComment;
224
-
225
212
  function getMergedCompositeObjects(schema) {
226
213
  const { allOf, oneOf, anyOf, ...safeSchema } = schema;
227
214
  const composite = allOf || oneOf || anyOf || [];
@@ -0,0 +1,98 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+ /**
5
+ * Prepares content for the operation docs. We will use description and summary if they are defined
6
+ * in the spec. Additionally we will add deprecation tag if the operation is deprecated.
7
+ * This function should include JSDocs asterisks to make comments look nice.
8
+ */
9
+ function getOperationDocs(
10
+ op
11
+ ) {
12
+ const result = [];
13
+ const summary = _optionalChain([op, 'access', _ => _.summary, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]);
14
+ const description = _optionalChain([op, 'access', _4 => _4.description, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]);
15
+ if (summary) {
16
+ // We want to include summary only if it's not a subset of description
17
+ if (!description || !description.startsWith(summary)) {
18
+ result.push(summary);
19
+ }
20
+ }
21
+ if (description) {
22
+ result.push(description);
23
+ }
24
+ if (op.deprecated) {
25
+ result.push('@deprecated');
26
+ }
27
+ return result;
28
+ }
29
+
30
+ /**
31
+ * Strips specific HTML tags and converts them to a simple markdown.
32
+ * Unknown or unclosed tags are encoded to HTML entities.
33
+ * @param str - The string to strip the tags from.
34
+ */
35
+ function stripSpecificHtmlTags(str) {
36
+ // Replace specific problematic tags with better alternatives
37
+ return (
38
+ str
39
+ .replace(/<br\s*\/?>/gi, '\n')
40
+ .replace(/<\/p>/gi, '\n')
41
+ .replace(/<p(\s[^>]*)?>/gi, '')
42
+ .replace(/<b>(.*?)<\/b>/gi, '**$1**')
43
+ .replace(/<strong>(.*?)<\/strong>/gi, '**$1**')
44
+ .replace(/<i>(.*?)<\/i>/gi, '*$1*')
45
+ .replace(/<em>(.*?)<\/em>/gi, '*$1*')
46
+ .replace(/<code>(.*?)<\/code>/gi, '`$1`')
47
+ .replace(/<pre>(.*?)<\/pre>/gi, '`$1`')
48
+ // Replace h1 - h6 with markdown headers
49
+ .replace(
50
+ /<h([1-6])>(.*?)<\/h\1>/gi,
51
+ (match, level, content) => '#'.repeat(parseInt(level)) + ' ' + content + '\n'
52
+ )
53
+ // Replace links with markdown links
54
+ .replace(/<a href="([^"]+)">([^<]+)<\/a>/gi, '[$2]($1)')
55
+ .replace(/\n{3,}/g, '\n\n')
56
+ .replace(/\<=/g, '&le;')
57
+ .replace(/\>=/g, '&ge;')
58
+ .replace(/\</g, '&lt;')
59
+ .replace(/\>/g, '&gt;')
60
+ .trim()
61
+ );
62
+ }
63
+
64
+ function prepareJsDocsForOperation(
65
+ op,
66
+ params
67
+ ) {
68
+ const docs = getOperationDocs(op);
69
+ if (docs.length === 0 && params.length === 0) {
70
+ return null;
71
+ }
72
+
73
+ const result = docs;
74
+ for (const param of params) {
75
+ const paramLine = `@param ${param.name} ${param.optional ? '(optional)' : ''} ${
76
+ param.name !== param.originalName ? `(API name: ${param.originalName})` : ''
77
+ }`;
78
+ result.push(paramLine);
79
+ }
80
+ return renderComment(result.join('\n'));
81
+ } exports.prepareJsDocsForOperation = prepareJsDocsForOperation;
82
+
83
+ function renderComment(comment) {
84
+ if (!comment) {
85
+ return null;
86
+ }
87
+
88
+ const mdComment = stripSpecificHtmlTags(comment);
89
+ const commentLines = mdComment.split('\n');
90
+
91
+ if (commentLines.length === 1) {
92
+ return `/** ${mdComment.trim()} */`;
93
+ }
94
+
95
+ return ` /**\n${commentLines
96
+ .map((line) => (line.trim() === '' ? ' *' : ` * ${line.trim()}`))
97
+ .join('\n')}\n */`;
98
+ } exports.renderComment = renderComment;
@@ -53,6 +53,20 @@ const reservedKeywords = new Set([
53
53
  'while',
54
54
  'with',
55
55
  'yield',
56
+
57
+ // Some of the variables that are used internally in the generated code. We can't allow
58
+ // user to use them as parameter names.
59
+ '$config',
60
+ 'axios',
61
+ 'cacheUrl',
62
+ 'config',
63
+ 'data',
64
+ 'error',
65
+ 'http',
66
+ 'key',
67
+ 'mutate',
68
+ 'url',
69
+ 'xior',
56
70
  ]);
57
71
 
58
72
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swaggie",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Generate TypeScript REST client code from an OpenAPI spec",
5
5
  "author": {
6
6
  "name": "Piotr Dabrowski",
@@ -60,10 +60,10 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/js-yaml": "4.0.9",
63
- "@types/node": "24.2.0",
63
+ "@types/node": "24.3.0",
64
64
  "openapi-types": "^12.1.3",
65
65
  "sucrase": "3.35.0",
66
- "tsx": "^4.20.3",
66
+ "tsx": "^4.20.5",
67
67
  "typescript": "5.9.2"
68
68
  }
69
69
  }
@@ -1,15 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- */
12
- <% } %>
13
3
  <%= it.name %>(<% it.parameters.forEach((parameter) => { %>
14
4
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
15
5
  <% }); %>
@@ -1,15 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- */
12
- <% } %>
13
3
  <%= it.name %>(<% it.parameters.forEach((parameter) => { %>
14
4
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
15
5
  <% }); %>
@@ -1,16 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- * @return Success
12
- */
13
- <% } %>
14
3
  <%= it.name %>(<% it.parameters.forEach((parameter) => { %>
15
4
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
16
5
  <% }); %>
@@ -1,16 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- * @return Success
12
- */
13
- <% } %>
14
3
  <%= it.name %>(
15
4
  <% it.parameters.forEach((parameter) => { %>
16
5
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
@@ -1,15 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name != parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- */
12
- <% } %>
13
3
  <%= it.name %>(<% it.parameters.forEach((parameter) => { %>
14
4
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
15
5
  <% }); %>
@@ -1,15 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- */
12
- <% } %>
13
3
  export function <%= it.swrOpName %>(<% it.parameters.forEach((parameter) => { %>
14
4
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
15
5
  <% }); %>
@@ -1,15 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- */
12
- <% } %>
13
3
  <%= it.name %>(<% it.parameters.forEach((parameter) => { %>
14
4
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
15
5
  <% }); %>
@@ -1,17 +1,16 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%
2
+ if (it.jsDocs) {
3
+ const additionalParams = ` * @param $config (optional) Additional configuration for TanStack Query
4
+ * @param $httpConfig (optional) Additional configuration for xior request (actually executes the request)`;
9
5
 
10
- <% }); -%>
11
- * @param $config (optional) Additional configuration for TanStack Query
12
- * @param $httpConfig (optional) Additional configuration for xior request (actually executes the request)
13
- */
6
+ // Replace the closing */ with newline + additional params + closing */
7
+ const modifiedDocs = it.jsDocs.replace(/(\s*)\*\/\s*$/, `\n${additionalParams}\n */`);
8
+ -%>
9
+ <%~ modifiedDocs %>
10
+ <% } else { -%>
11
+ <%~ it.jsDocs %>
14
12
  <% } %>
13
+
15
14
  export function <%= it.rqOpName %><TData = <%~ it.returnType %>, TError = Error>(<% it.parameters.forEach((parameter) => { %>
16
15
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
17
16
  <% }); %>
@@ -1,15 +1,5 @@
1
- <% if(it.hasJSDocs) { %>
2
- /**
3
- <% if(it.docs && it.docs.length > 0) { %>
4
- * <%~ it.docs.join('\n * ') %>
5
- <% } %>
6
-
7
- <% it.parameters.forEach((parameter) => { %>
8
- * @param <%= parameter.name %> <%= parameter.optional ? '(optional)' : '' %> <%= parameter.name !== parameter.originalName ? `(API name: ${parameter.originalName})` : '' %>
1
+ <%~ it.jsDocs %>
9
2
 
10
- <% }); -%>
11
- */
12
- <% } %>
13
3
  <%= it.name %>(<% it.parameters.forEach((parameter) => { %>
14
4
  <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,
15
5
  <% }); %>