@stackql/provider-utils 0.1.4 → 0.1.6
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.
- package/package.json +1 -1
- package/src/docgen/generator.js +2 -1
- package/src/docgen/helpers.js +47 -93
- package/src/docgen/resource/examples/delete-example.js +4 -2
- package/src/docgen/resource/examples/exec-example.js +3 -1
- package/src/docgen/resource/examples/insert-example.js +6 -17
- package/src/docgen/resource/examples/select-example.js +6 -2
- package/src/docgen/resource/examples/update-example.js +5 -1
- package/src/docgen/resource/fields.js +2 -1
- package/src/docgen/resource/methods.js +0 -1
package/package.json
CHANGED
package/src/docgen/generator.js
CHANGED
|
@@ -126,7 +126,8 @@ async function createDocsForService(yamlFilePath, providerName, serviceName, ser
|
|
|
126
126
|
let dereferencedAPI;
|
|
127
127
|
|
|
128
128
|
try {
|
|
129
|
-
dereferencedAPI = await deno_openapi_dereferencer.dereferenceApi(api, "$", ignorePaths);
|
|
129
|
+
// dereferencedAPI = await deno_openapi_dereferencer.dereferenceApi(api, "$", ignorePaths);
|
|
130
|
+
const dereferencedAPI = await SwaggerParser.dereference(api);
|
|
130
131
|
dereferencedAPI = await deno_openapi_dereferencer.flattenAllOf(dereferencedAPI);
|
|
131
132
|
} catch (error) {
|
|
132
133
|
console.error("error in dereferencing or flattening:", error);
|
package/src/docgen/helpers.js
CHANGED
|
@@ -23,41 +23,29 @@ export function getIndefiniteArticle(resourceName) {
|
|
|
23
23
|
return article;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
description = description.replace(/\s+/g, ' ');
|
|
50
|
-
|
|
51
|
-
// Escape pipe characters to prevent breaking markdown tables
|
|
52
|
-
description = description.replace(/\|/g, '\\|');
|
|
53
|
-
|
|
54
|
-
// Remove any trailing commas, spaces, and line breaks
|
|
55
|
-
description = description.replace(/,s*$/, '').trim();
|
|
56
|
-
|
|
57
|
-
description = description.replace(/</g, '{');
|
|
58
|
-
description = description.replace(/>/g, '}');
|
|
59
|
-
|
|
60
|
-
return description;
|
|
26
|
+
export function sanitizeHtml(text) {
|
|
27
|
+
return text
|
|
28
|
+
// Replace "<" unless it's followed by "a", "/a", "b", "/b", "strong", or "/strong"
|
|
29
|
+
.replace(/<(?!\/?(?:a|b|strong)\b)/gi, '<')
|
|
30
|
+
// Replace ">" unless it's preceded by "</a", "<a ...>", "</b", "<b ...>", "</strong", or "<strong ...>"
|
|
31
|
+
.replace(/(?<!<\/?(?:a|b|strong)[^>]*)>/gi, '>')
|
|
32
|
+
// Add quotes around unquoted href values (within <a ...>)
|
|
33
|
+
.replace(/(<a\b[^>]*?)href=([^"' \t\r\n>]+)/gi, '$1href="$2"')
|
|
34
|
+
// Wrap backticked text with <code>
|
|
35
|
+
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
36
|
+
// Replace { and }
|
|
37
|
+
.replace(/{/g, '{')
|
|
38
|
+
.replace(/}/g, '}')
|
|
39
|
+
// Escape backslash
|
|
40
|
+
.replace(/\\/g, '\\\\')
|
|
41
|
+
// Replace " with " UNLESS inside <code>...</code> OR inside an href="...".
|
|
42
|
+
// The alternation matches either a whole <code>...</code> block, an href="...",
|
|
43
|
+
// or a bare " to replace.
|
|
44
|
+
.replace(/(<code>[\s\S]*?<\/code>)|(\bhref="[^"]*")|"/gi, (m, code, href) => {
|
|
45
|
+
if (code) return code; // keep code blocks untouched
|
|
46
|
+
if (href) return href; // keep href="..." quotes untouched
|
|
47
|
+
return '"'; // everything else: replace "
|
|
48
|
+
});
|
|
61
49
|
}
|
|
62
50
|
|
|
63
51
|
export function getSqlMethodsWithOrderedFields(resourceData, dereferencedAPI, sqlVerb) {
|
|
@@ -249,47 +237,13 @@ function formatProperties(respProps) {
|
|
|
249
237
|
// Store formatted property details
|
|
250
238
|
allProperties[propName] = {
|
|
251
239
|
type: typeString,
|
|
252
|
-
description: escapeHtml(fullDescription),
|
|
240
|
+
// description: escapeHtml(fullDescription),
|
|
241
|
+
description: fullDescription
|
|
253
242
|
};
|
|
254
243
|
}
|
|
255
244
|
return allProperties;
|
|
256
245
|
}
|
|
257
246
|
|
|
258
|
-
function escapeHtml(text) {
|
|
259
|
-
if (!text) return '';
|
|
260
|
-
return text
|
|
261
|
-
.replace(/&/g, '&')
|
|
262
|
-
.replace(/</g, '<')
|
|
263
|
-
.replace(/>/g, '>')
|
|
264
|
-
.replace(/"/g, '"')
|
|
265
|
-
.replace(/'/g, ''');
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
export function sanitizeHtml(text) {
|
|
269
|
-
return text
|
|
270
|
-
// Replace "<" unless it's followed by "a", "/a", "b", "/b", "strong", or "/strong"
|
|
271
|
-
.replace(/<(?!\/?(?:a|b|strong)\b)/gi, '<')
|
|
272
|
-
// Replace ">" unless it's preceded by "</a", "<a ...>", "</b", "<b ...>", "</strong", or "<strong ...>"
|
|
273
|
-
.replace(/(?<!<\/?(?:a|b|strong)[^>]*)>/gi, '>')
|
|
274
|
-
// Add quotes around unquoted href values (within <a ...>)
|
|
275
|
-
.replace(/(<a\b[^>]*?)href=([^"' \t\r\n>]+)/gi, '$1href="$2"')
|
|
276
|
-
// Wrap backticked text with <code>
|
|
277
|
-
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
278
|
-
// Replace { and }
|
|
279
|
-
.replace(/{/g, '{')
|
|
280
|
-
.replace(/}/g, '}')
|
|
281
|
-
// Escape backslash
|
|
282
|
-
.replace(/\\/g, '\\\\')
|
|
283
|
-
// Replace " with " UNLESS inside <code>...</code> OR inside an href="...".
|
|
284
|
-
// The alternation matches either a whole <code>...</code> block, an href="...",
|
|
285
|
-
// or a bare " to replace.
|
|
286
|
-
.replace(/(<code>[\s\S]*?<\/code>)|(\bhref="[^"]*")|"/gi, (m, code, href) => {
|
|
287
|
-
if (code) return code; // keep code blocks untouched
|
|
288
|
-
if (href) return href; // keep href="..." quotes untouched
|
|
289
|
-
return '"'; // everything else: replace "
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
|
|
293
247
|
function getRequiredServerVars(dereferencedAPI) {
|
|
294
248
|
const serverVars = {};
|
|
295
249
|
|
|
@@ -389,7 +343,7 @@ function getHttpOperationInfo(dereferencedAPI, path, httpVerb, mediaType, openAP
|
|
|
389
343
|
}
|
|
390
344
|
|
|
391
345
|
// Get operation description and replace curly braces with HTML entities
|
|
392
|
-
const opDescription = (dereferencedAPI.paths[path][httpVerb].description || '').replace(/\{/g, '{').replace(/\}/g, '}');
|
|
346
|
+
const opDescription = (dereferencedAPI.paths[path][httpVerb].description || ''); // .replace(/\{/g, '{').replace(/\}/g, '}');
|
|
393
347
|
|
|
394
348
|
// Extract request body if it exists
|
|
395
349
|
let requestBody = {};
|
|
@@ -498,26 +452,26 @@ function getHttpOperationParams(dereferencedAPI, path, httpVerb) {
|
|
|
498
452
|
|
|
499
453
|
let additionalDescriptionParts = [];
|
|
500
454
|
|
|
501
|
-
for (const [fieldName, fieldValue] of Object.entries(param.schema)) {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
}
|
|
455
|
+
// for (const [fieldName, fieldValue] of Object.entries(param.schema)) {
|
|
456
|
+
// if (fieldName === 'type' || fieldName === 'format' || fieldName === 'description' || fieldName === 'pattern') {
|
|
457
|
+
// continue;
|
|
458
|
+
// }
|
|
459
|
+
|
|
460
|
+
// let formattedValue;
|
|
461
|
+
// if (Array.isArray(fieldValue)) {
|
|
462
|
+
// formattedValue = `[${fieldValue.join(', ')}]`;
|
|
463
|
+
// } else if (typeof fieldValue === 'object' && fieldValue !== null) {
|
|
464
|
+
// formattedValue = JSON.stringify(fieldValue);
|
|
465
|
+
// } else {
|
|
466
|
+
// formattedValue = String(fieldValue);
|
|
467
|
+
// }
|
|
468
|
+
|
|
469
|
+
// if (fieldName === 'pattern') {
|
|
470
|
+
// additionalDescriptionParts.push(`pattern: <code>${formattedValue}</code>`);
|
|
471
|
+
// } else {
|
|
472
|
+
// additionalDescriptionParts.push(`${fieldName}: ${formattedValue}`);
|
|
473
|
+
// }
|
|
474
|
+
// }
|
|
521
475
|
|
|
522
476
|
// Add any fields from the parameter itself that might contain metadata
|
|
523
477
|
for (const [fieldName, fieldValue] of Object.entries(param)) {
|
|
@@ -551,7 +505,7 @@ function getHttpOperationParams(dereferencedAPI, path, httpVerb) {
|
|
|
551
505
|
// Create the parameter details object
|
|
552
506
|
const paramDetails = {
|
|
553
507
|
type: typeString,
|
|
554
|
-
description: description
|
|
508
|
+
description: description
|
|
555
509
|
};
|
|
556
510
|
|
|
557
511
|
// Add to the appropriate category based on required flag
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/docgen/resource/examples/delete-example.js
|
|
2
2
|
import {
|
|
3
3
|
getSqlMethodsWithOrderedFields,
|
|
4
|
+
sanitizeHtml,
|
|
4
5
|
} from '../../helpers.js';
|
|
5
6
|
|
|
6
7
|
export function createDeleteExamples(providerName, serviceName, resourceName, resourceData, dereferencedAPI) {
|
|
@@ -29,8 +30,9 @@ export function createDeleteExamples(providerName, serviceName, resourceName, re
|
|
|
29
30
|
content += '<TabItem value="' + methodName + '">\n\n';
|
|
30
31
|
|
|
31
32
|
// Add method description
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const opDescription = methodDetails.opDescription || 'No description available.';
|
|
34
|
+
content += sanitizeHtml(opDescription);
|
|
35
|
+
|
|
34
36
|
// Create SQL example
|
|
35
37
|
content += '\n\n```sql\nDELETE FROM ' + providerName + '.' + serviceName + '.' + resourceName;
|
|
36
38
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/docgen/resource/examples/exec-example.js
|
|
2
2
|
import {
|
|
3
3
|
getSqlMethodsWithOrderedFields,
|
|
4
|
+
sanitizeHtml
|
|
4
5
|
} from '../../helpers.js';
|
|
5
6
|
|
|
6
7
|
export function createExecExamples(providerName, serviceName, resourceName, resourceData, dereferencedAPI) {
|
|
@@ -29,7 +30,8 @@ export function createExecExamples(providerName, serviceName, resourceName, reso
|
|
|
29
30
|
content += '<TabItem value="' + methodName + '">\n\n';
|
|
30
31
|
|
|
31
32
|
// Add method description
|
|
32
|
-
|
|
33
|
+
const opDescription = methodDetails.opDescription || methodDetails.respDescription || 'No description available.';
|
|
34
|
+
content += sanitizeHtml(opDescription);
|
|
33
35
|
|
|
34
36
|
// Create SQL example
|
|
35
37
|
content += '\n\n```sql\nEXEC ' + providerName + '.' + serviceName + '.' + resourceName + '.' + methodName + ' \n';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/docgen/resource/examples/insert-example.js
|
|
2
2
|
import {
|
|
3
3
|
getSqlMethodsWithOrderedFields,
|
|
4
|
+
sanitizeHtml
|
|
4
5
|
} from '../../helpers.js';
|
|
5
6
|
|
|
6
7
|
export function createInsertExamples(providerName, serviceName, resourceName, resourceData, dereferencedAPI) {
|
|
@@ -31,7 +32,11 @@ export function createInsertExamples(providerName, serviceName, resourceName, re
|
|
|
31
32
|
// Create each method tab content
|
|
32
33
|
Object.entries(insertMethods).forEach(([methodName, methodDetails]) => {
|
|
33
34
|
content += '<TabItem value="' + methodName + '">\n\n';
|
|
34
|
-
|
|
35
|
+
|
|
36
|
+
// Add method description
|
|
37
|
+
const opDescription = methodDetails.opDescription || 'No description available.';
|
|
38
|
+
content += sanitizeHtml(opDescription);
|
|
39
|
+
// content += methodDetails.opDescription || 'No description available.';
|
|
35
40
|
|
|
36
41
|
// Create SQL example
|
|
37
42
|
content += '\n\n```sql\nINSERT INTO ' + providerName + '.' + serviceName + '.' + resourceName + ' (\n';
|
|
@@ -107,22 +112,6 @@ export function createInsertExamples(providerName, serviceName, resourceName, re
|
|
|
107
112
|
content += '\n;\n```\n</TabItem>\n';
|
|
108
113
|
});
|
|
109
114
|
|
|
110
|
-
|
|
111
|
-
// {
|
|
112
|
-
// "code": {
|
|
113
|
-
// "type": "string",
|
|
114
|
-
// "description": " (example: 000123)"
|
|
115
|
-
// },
|
|
116
|
-
// "createdOn": {
|
|
117
|
-
// "type": "integer (int64)",
|
|
118
|
-
// "description": "Timestamp that specifies when the statement execution started. The timestamp is expressed in milliseconds since the epoch."
|
|
119
|
-
// },
|
|
120
|
-
// "data": {
|
|
121
|
-
// "type": "array",
|
|
122
|
-
// "description": "Result set data."
|
|
123
|
-
// },
|
|
124
|
-
// }
|
|
125
|
-
|
|
126
115
|
// Create manifest tab
|
|
127
116
|
content += '<TabItem value="manifest">\n\n';
|
|
128
117
|
content += '```yaml\n# Description fields are for documentation purposes\n- name: ' + resourceName + '\n props:\n';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/docgen/resource/examples/select-example.js
|
|
2
2
|
import {
|
|
3
3
|
getSqlMethodsWithOrderedFields,
|
|
4
|
+
sanitizeHtml
|
|
4
5
|
} from '../../helpers.js';
|
|
5
6
|
|
|
6
7
|
export function createSelectExamples(providerName, serviceName, resourceName, resourceData, dereferencedAPI) {
|
|
@@ -27,8 +28,11 @@ export function createSelectExamples(providerName, serviceName, resourceName, re
|
|
|
27
28
|
// Create each tab content
|
|
28
29
|
Object.entries(selectMethods).forEach(([methodName, methodDetails]) => {
|
|
29
30
|
content += '<TabItem value="' + methodName + '">\n\n';
|
|
30
|
-
content += methodDetails.opDescription || 'No description available.';
|
|
31
|
-
|
|
31
|
+
// content += methodDetails.opDescription || 'No description available.';
|
|
32
|
+
// Add method description
|
|
33
|
+
const opDescription = methodDetails.opDescription || methodDetails.respDescription || 'No description available.';
|
|
34
|
+
content += sanitizeHtml(opDescription);
|
|
35
|
+
|
|
32
36
|
// Create SQL example
|
|
33
37
|
content += '\n\n```sql\nSELECT\n';
|
|
34
38
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/docgen/resource/examples/update-example.js
|
|
2
2
|
import {
|
|
3
3
|
getSqlMethodsWithOrderedFields,
|
|
4
|
+
sanitizeHtml
|
|
4
5
|
} from '../../helpers.js';
|
|
5
6
|
|
|
6
7
|
export function createUpdateExamples(providerName, serviceName, resourceName, resourceData, dereferencedAPI, isReplace = false) {
|
|
@@ -33,8 +34,11 @@ export function createUpdateExamples(providerName, serviceName, resourceName, re
|
|
|
33
34
|
Object.entries(updateMethods).forEach(([methodName, methodDetails]) => {
|
|
34
35
|
content += '<TabItem value="' + methodName + '">\n\n';
|
|
35
36
|
|
|
37
|
+
// // Add method description
|
|
38
|
+
// content += methodDetails.opDescription || methodDetails.respDescription || 'No description available.';
|
|
36
39
|
// Add method description
|
|
37
|
-
|
|
40
|
+
const opDescription = methodDetails.opDescription || 'No description available.';
|
|
41
|
+
content += sanitizeHtml(opDescription);
|
|
38
42
|
|
|
39
43
|
// Create SQL example
|
|
40
44
|
content += '\n\n```sql\n';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/docgen/resource/fields.js
|
|
2
2
|
import {
|
|
3
3
|
getSqlMethodsWithOrderedFields,
|
|
4
|
+
sanitizeHtml,
|
|
4
5
|
} from '../helpers.js';
|
|
5
6
|
|
|
6
7
|
const mdCodeAnchor = "`";
|
|
@@ -58,7 +59,7 @@ export function createFieldsSection(resourceData, dereferencedAPI) {
|
|
|
58
59
|
content += `\n<tr>
|
|
59
60
|
<td><CopyableCode code="${propName}" /></td>
|
|
60
61
|
<td><code>${propData.type}</code></td>
|
|
61
|
-
<td>${propData.description}</td>
|
|
62
|
+
<td>${sanitizeHtml(propData.description)}</td>
|
|
62
63
|
</tr>`;
|
|
63
64
|
}
|
|
64
65
|
|