spring-api-scanner 0.2.1 → 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/dist/openapi.d.ts +1 -0
- package/dist/ui.js +97 -6
- package/package.json +1 -1
package/dist/openapi.d.ts
CHANGED
package/dist/ui.js
CHANGED
|
@@ -26,7 +26,7 @@ export function buildUiModel(input) {
|
|
|
26
26
|
})),
|
|
27
27
|
requestSchema,
|
|
28
28
|
responseSchema,
|
|
29
|
-
curl: buildCurl(endpoint)
|
|
29
|
+
curl: buildCurl(endpoint, requestSchema, input.openapi.components.schemas)
|
|
30
30
|
};
|
|
31
31
|
});
|
|
32
32
|
return {
|
|
@@ -474,16 +474,107 @@ function pickResponseSchema(responses, openapi) {
|
|
|
474
474
|
const best = responses["200"] ?? responses["201"];
|
|
475
475
|
return deref(best?.content?.["application/json"]?.schema, openapi);
|
|
476
476
|
}
|
|
477
|
-
function buildCurl(endpoint) {
|
|
478
|
-
|
|
477
|
+
function buildCurl(endpoint, requestSchema, schemas) {
|
|
478
|
+
// Build URL with query parameters
|
|
479
|
+
let urlPath = endpoint.fullPath;
|
|
480
|
+
// Replace path variables with placeholder values
|
|
481
|
+
for (const pv of endpoint.pathVariables) {
|
|
482
|
+
const placeholder = getExampleValueForType(pv.type);
|
|
483
|
+
urlPath = urlPath.replace(`{${pv.name}}`, String(placeholder));
|
|
484
|
+
}
|
|
485
|
+
// Add query parameters to URL
|
|
486
|
+
const queryParts = [];
|
|
487
|
+
for (const qp of endpoint.queryParams) {
|
|
488
|
+
const exampleValue = getExampleValueForType(qp.type);
|
|
489
|
+
queryParts.push(`${qp.name}=${encodeURIComponent(String(exampleValue))}`);
|
|
490
|
+
}
|
|
491
|
+
if (queryParts.length > 0) {
|
|
492
|
+
urlPath += `?${queryParts.join("&")}`;
|
|
493
|
+
}
|
|
494
|
+
const parts = [`curl -X ${endpoint.httpMethod} "http://localhost:3000${urlPath}"`];
|
|
495
|
+
// Add headers
|
|
479
496
|
for (const header of endpoint.headers) {
|
|
480
|
-
|
|
497
|
+
const exampleValue = getExampleValueForType(header.type);
|
|
498
|
+
parts.push(`-H "${header.name}: ${exampleValue}"`);
|
|
481
499
|
}
|
|
500
|
+
// Add request body with generated example
|
|
482
501
|
if (endpoint.requestBody) {
|
|
483
502
|
parts.push('-H "Content-Type: application/json"');
|
|
484
|
-
|
|
503
|
+
const exampleBody = generateExampleFromSchema(requestSchema, schemas);
|
|
504
|
+
const bodyJson = JSON.stringify(exampleBody, null, 2);
|
|
505
|
+
// Escape the JSON for shell
|
|
506
|
+
const escapedBody = bodyJson.replace(/'/g, "'\"'\"'");
|
|
507
|
+
parts.push(`-d '${escapedBody}'`);
|
|
508
|
+
}
|
|
509
|
+
return parts.join(" \\\n ");
|
|
510
|
+
}
|
|
511
|
+
function getExampleValueForType(type) {
|
|
512
|
+
const cleanType = type.replace("?", "").trim();
|
|
513
|
+
switch (cleanType) {
|
|
514
|
+
case "String":
|
|
515
|
+
return "example";
|
|
516
|
+
case "Long":
|
|
517
|
+
case "Int":
|
|
518
|
+
return 123;
|
|
519
|
+
case "Boolean":
|
|
520
|
+
return true;
|
|
521
|
+
case "Double":
|
|
522
|
+
case "Float":
|
|
523
|
+
return 123.45;
|
|
524
|
+
default:
|
|
525
|
+
return "<value>";
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
function generateExampleFromSchema(schema, schemas, visited = new Set()) {
|
|
529
|
+
if (!schema) {
|
|
530
|
+
return {};
|
|
531
|
+
}
|
|
532
|
+
// Handle $ref references
|
|
533
|
+
if (schema.$ref) {
|
|
534
|
+
const refName = schema.$ref.split("/").pop();
|
|
535
|
+
if (refName && schemas && !visited.has(refName)) {
|
|
536
|
+
visited.add(refName);
|
|
537
|
+
const resolved = schemas[refName];
|
|
538
|
+
if (resolved) {
|
|
539
|
+
return generateExampleFromSchema(resolved, schemas, visited);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return {};
|
|
543
|
+
}
|
|
544
|
+
// Handle enums - use first enum value
|
|
545
|
+
if (schema.enum && schema.enum.length > 0) {
|
|
546
|
+
return schema.enum[0];
|
|
547
|
+
}
|
|
548
|
+
// Handle arrays
|
|
549
|
+
if (schema.type === "array" && schema.items) {
|
|
550
|
+
return [generateExampleFromSchema(schema.items, schemas, visited)];
|
|
551
|
+
}
|
|
552
|
+
// Handle objects
|
|
553
|
+
if (schema.type === "object" || schema.properties) {
|
|
554
|
+
const result = {};
|
|
555
|
+
if (schema.properties) {
|
|
556
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
557
|
+
result[key] = generateExampleFromSchema(propSchema, schemas, visited);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
// Handle primitives based on type and format
|
|
563
|
+
switch (schema.type) {
|
|
564
|
+
case "string":
|
|
565
|
+
if (schema.format === "date-time") {
|
|
566
|
+
return "2026-01-01T00:00:00Z";
|
|
567
|
+
}
|
|
568
|
+
return "example";
|
|
569
|
+
case "integer":
|
|
570
|
+
return 123;
|
|
571
|
+
case "number":
|
|
572
|
+
return 123.45;
|
|
573
|
+
case "boolean":
|
|
574
|
+
return true;
|
|
575
|
+
default:
|
|
576
|
+
return null;
|
|
485
577
|
}
|
|
486
|
-
return parts.join(" \\\n+");
|
|
487
578
|
}
|
|
488
579
|
function guessController(sourceFile) {
|
|
489
580
|
const file = sourceFile.replaceAll("\\", "/").split("/").at(-1) ?? sourceFile;
|