@stackql/provider-utils 0.2.0 → 0.2.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackql/provider-utils",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Utilities for building StackQL providers from OpenAPI specifications.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -18,10 +18,11 @@ export async function generateDocs(options) {
18
18
  console.log(`documenting ${providerName}...`);
19
19
 
20
20
  const docsDir = path.join(outputDir, `docs`);
21
+ const servicesDir = path.join(docsDir, `services`);
21
22
 
22
23
  // Remove directory if it exists, then create it fresh
23
24
  fs.existsSync(docsDir) && fs.rmSync(docsDir, { recursive: true, force: true });
24
- fs.mkdirSync(docsDir, { recursive: true });
25
+ fs.mkdirSync(servicesDir, { recursive: true });
25
26
 
26
27
  // Check for provider data files
27
28
  console.log(providerDataDir);
@@ -58,16 +59,16 @@ export async function generateDocs(options) {
58
59
  servicesForIndex.push(serviceName);
59
60
  const filePath = path.join(serviceDir, file);
60
61
  totalServicesCount++;
61
- const serviceFolder = `${docsDir}/${serviceName}`;
62
+ const serviceFolder = `${servicesDir}/${serviceName}`;
62
63
  await createDocsForService(filePath, providerName, serviceName, serviceFolder);
63
64
  }
64
65
 
65
66
  console.log(`Processed ${totalServicesCount} services`);
66
67
 
67
68
  // Count total resources
68
- totalResourcesCount = fs.readdirSync(`${docsDir}`, { withFileTypes: true })
69
+ totalResourcesCount = fs.readdirSync(`${servicesDir}`, { withFileTypes: true })
69
70
  .filter(dirent => dirent.isDirectory())
70
- .map(dirent => fs.readdirSync(`${docsDir}/${dirent.name}`).length)
71
+ .map(dirent => fs.readdirSync(`${servicesDir}/${dirent.name}`).length)
71
72
  .reduce((a, b) => a + b, 0);
72
73
 
73
74
  console.log(`Processed ${totalResourcesCount} resources`);
@@ -264,12 +265,12 @@ ${secondColumnLinks}
264
265
  function generateResourceLinks(providerName, serviceName, resources) {
265
266
  // Generate resource links for the service index
266
267
  const resourceLinks = resources.map((resource) => {
267
- return `<a href="/${serviceName}/${resource.name}/">${resource.name}</a>`;
268
+ return `<a href="/services/${serviceName}/${resource.name}/">${resource.name}</a>`;
268
269
  });
269
270
  return resourceLinks.join('<br />\n');
270
271
  }
271
272
 
272
273
  // Function to convert services to markdown links
273
274
  function servicesToMarkdown(providerName, servicesList) {
274
- return servicesList.map(service => `<a href="/${service}/">${service}</a><br />`).join('\n');
275
+ return servicesList.map(service => `<a href="/services/${service}/">${service}</a><br />`).join('\n');
275
276
  }
@@ -25,53 +25,12 @@ export function getIndefiniteArticle(resourceName) {
25
25
 
26
26
  export function sanitizeHtml(text) {
27
27
  return text
28
- // Replace "<" unless it's followed by "a", "/a", "b", "/b", "strong"
29
- .replace(/<(?!\/?(?:a|b|strong)\b)/gi, '&lt;')
30
- // Replace ">" unless it's preceded by "</a", "<a ...>", "</b", "<b ...>", "</strong", or "<strong ...>"
31
- .replace(/(?<!<\/?(?:a|b|strong)[^>]*)>/gi, '&gt;')
32
- // Add quotes around unquoted href values (within <a ...>)
33
- .replace(/(<a\b[^>]*?)href=([^"' \t\r\n>]+)/gi, '$1href="$2"')
34
- // Special handling for code tags - remove them if they contain * or _
35
- .replace(/<code>([\s\S]*?)<\/code>/gi, (match, content) => {
36
- if (content.includes('*') || content.includes('_')) {
37
- // If code block has problematic characters, remove the code tags
38
- // and escape the special characters
39
- return content
40
- .replace(/\*/g, '&ast;') // Escape asterisks
41
- .replace(/_/g, '&lowbar;') // Escape underscores
42
- .replace(/\[/g, '&#91;') // Escape brackets
43
- .replace(/\]/g, '&#93;')
44
- .replace(/\(/g, '&#40;') // Escape parentheses
45
- .replace(/\)/g, '&#41;');
46
- }
47
- // Otherwise keep the code tags
48
- return match;
49
- })
50
- // Wrap backticked text with <code> but only if it doesn't contain * or _
51
- .replace(/`([^`]+)`/g, (match, content) => {
52
- if (content.includes('*') || content.includes('_')) {
53
- // If backticked content has problematic characters, don't add code tags
54
- return content
55
- .replace(/\*/g, '&ast;')
56
- .replace(/_/g, '&lowbar;')
57
- .replace(/\[/g, '&#91;')
58
- .replace(/\]/g, '&#93;')
59
- .replace(/\(/g, '&#40;')
60
- .replace(/\)/g, '&#41;');
61
- }
62
- return `<code>${content}</code>`;
63
- })
64
- // Replace { and }
65
28
  .replace(/{/g, '&#123;')
66
29
  .replace(/}/g, '&#125;')
67
- // Escape backslash
68
- .replace(/\\/g, '\\\\')
69
- // Replace " with &quot; UNLESS inside <code>...</code> OR inside an href="...".
70
- .replace(/(<code>[\s\S]*?<\/code>)|(\bhref="[^"]*")|"/gi, (m, code, href) => {
71
- if (code) return code; // keep code blocks untouched
72
- if (href) return href; // keep href="..." quotes untouched
73
- return '&quot;'; // everything else: replace "
74
- });
30
+ .replace(/>/g, '&gt;')
31
+ .replace(/</g, '&lt;')
32
+ // edge case
33
+ .replace(/&#125;_&#123;/g, '&#125;&#95;&#123;')
75
34
  }
76
35
 
77
36
  export function getSqlMethodsWithOrderedFields(resourceData, dereferencedAPI, sqlVerb) {
@@ -427,30 +386,37 @@ function getHttpOperationInfo(dereferencedAPI, path, httpVerb, mediaType, openAP
427
386
  }
428
387
 
429
388
  const schema = responseObj.content[mediaType].schema;
430
-
389
+
390
+ const { respProps, respDescription } = getHttpRespBody(schema, objectKey);
391
+
392
+ return {
393
+ respProps,
394
+ respDescription: responseObj.description ? responseObj.description : respDescription,
395
+ opDescription,
396
+ requestBody
397
+ };
398
+ }
399
+
400
+ function getHttpRespBody(schema, objectKey) {
401
+
431
402
  if (schema.type === 'array') {
432
403
  return {
433
- respProps: schema.items.properties || {},
434
- respDescription: schema.items.description || responseObj.description || '',
435
- opDescription,
436
- requestBody
437
- };
404
+ respProps: schema.items.properties || {},
405
+ respDescription: schema.items.description || '',
406
+ }
438
407
  } else if (schema.type === 'object') {
439
408
  return {
440
- respProps: schema.properties || {},
441
- respDescription: schema.description || responseObj.description || '',
442
- opDescription,
443
- requestBody
409
+ respProps: schema.properties || {},
410
+ respDescription: schema.description || '',
444
411
  };
445
412
  } else {
446
- // For primitive types or when schema structure is unexpected
447
413
  return {
448
414
  respProps: {},
449
- respDescription: schema.description || responseObj.description || '',
450
- opDescription,
451
- requestBody
415
+ respDescription: '',
452
416
  };
453
417
  }
418
+
419
+
454
420
  }
455
421
 
456
422
  function getHttpOperationParams(dereferencedAPI, path, httpVerb) {