Implemented post patch and put call body to be able to parse from model
Some checks failed
Build / build (push) Has been cancelled
Some checks failed
Build / build (push) Has been cancelled
This commit is contained in:
@@ -27,5 +27,12 @@ namespace Nodify.Calculator
|
||||
get => _responseModelClassName;
|
||||
set => SetProperty(ref _responseModelClassName, value);
|
||||
}
|
||||
|
||||
private string _requestBodyModelClassName = string.Empty;
|
||||
public string RequestBodyModelClassName
|
||||
{
|
||||
get => _requestBodyModelClassName;
|
||||
set => SetProperty(ref _requestBodyModelClassName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Nodify.Calculator.Models
|
||||
// API node properties
|
||||
public string OPType { get; set; } = string.Empty;
|
||||
public string ResponseModelClassName { get; set; } = string.Empty;
|
||||
public string RequestBodyModelClassName { get; set; } = string.Empty;
|
||||
|
||||
// System node properties
|
||||
public string SystemOp { get; set; } = string.Empty;
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Nodify.Calculator.Models
|
||||
public List<string> InputNames { get; set; } = new List<string>();
|
||||
public string SwaggerFileName { get; set; } = string.Empty;
|
||||
public string ResponseModelClassName { get; set; } = string.Empty;
|
||||
public string RequestBodyModelClassName { get; set; } = string.Empty;
|
||||
public string SwaggerGroup { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,8 @@ namespace Nodify.Calculator.NodeHandlers
|
||||
{
|
||||
Title = info.Title,
|
||||
OperationType = (info.OPType ?? "GET").ToUpper(),
|
||||
ResponseModelClassName = info.ResponseModelClassName ?? string.Empty
|
||||
ResponseModelClassName = info.ResponseModelClassName ?? string.Empty,
|
||||
RequestBodyModelClassName = info.RequestBodyModelClassName ?? string.Empty
|
||||
};
|
||||
|
||||
// Flow connectors
|
||||
@@ -109,7 +110,35 @@ namespace Nodify.Calculator.NodeHandlers
|
||||
});
|
||||
}
|
||||
|
||||
// Data inputs
|
||||
// Request body input (for POST/PUT/PATCH)
|
||||
var httpMethod = (info.OPType ?? "").ToUpper();
|
||||
if (httpMethod == "POST" || httpMethod == "PUT" || httpMethod == "PATCH")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(info.RequestBodyModelClassName))
|
||||
{
|
||||
var bc = info.RequestBodyModelClassName;
|
||||
bool isList = bc.StartsWith("List<") && bc.EndsWith(">");
|
||||
op.Input.Add(new ConnectorViewModel
|
||||
{
|
||||
Title = $"Body ({bc})",
|
||||
Shape = isList ? ConnectorShape.Grid : ConnectorShape.Square,
|
||||
ConnectorColor = isList ? Color.MediumSpringGreen : Color.MediumPurple,
|
||||
DataType = bc
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
op.Input.Add(new ConnectorViewModel
|
||||
{
|
||||
Title = "Body",
|
||||
Shape = ConnectorShape.Circle,
|
||||
ConnectorColor = Color.LimeGreen,
|
||||
DataType = "object"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Other data inputs (query/path params)
|
||||
foreach (var label in info.Input)
|
||||
{
|
||||
op.Input.Add(new ConnectorViewModel { Title = label, ConnectorColor = Color.LimeGreen });
|
||||
@@ -124,11 +153,15 @@ namespace Nodify.Calculator.NodeHandlers
|
||||
Title = data.Title,
|
||||
OPType = data.OPType?.ToLower() ?? "get",
|
||||
Type = OperationType.API,
|
||||
ResponseModelClassName = data.ResponseModelClassName ?? string.Empty
|
||||
ResponseModelClassName = data.ResponseModelClassName ?? string.Empty,
|
||||
RequestBodyModelClassName = data.RequestBodyModelClassName ?? string.Empty
|
||||
};
|
||||
// Restore only query/path param inputs (skip flow triangles and body connectors)
|
||||
foreach (var ic in data.InputConnectors)
|
||||
{
|
||||
if (ic.Shape != "Triangle")
|
||||
if (ic.Shape == "Triangle") continue;
|
||||
if (ic.Shape == "Square" || ic.Shape == "Grid") continue; // body model connector
|
||||
if ((ic.Title ?? "").StartsWith("Body")) continue;
|
||||
info.Input.Add(ic.Title);
|
||||
}
|
||||
return Create(info);
|
||||
@@ -141,6 +174,7 @@ namespace Nodify.Calculator.NodeHandlers
|
||||
{
|
||||
data.OPType = api.OperationType;
|
||||
data.ResponseModelClassName = api.ResponseModelClassName;
|
||||
data.RequestBodyModelClassName = api.RequestBodyModelClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Nodify.Calculator
|
||||
public List<FunctionParameterInfo> FunctionInputs { get; set; } = new List<FunctionParameterInfo>();
|
||||
public List<FunctionParameterInfo> FunctionOutputs { get; set; } = new List<FunctionParameterInfo>();
|
||||
public string ResponseModelClassName { get; set; } = string.Empty;
|
||||
public string RequestBodyModelClassName { get; set; } = string.Empty;
|
||||
public string SwaggerGroup { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,12 +417,24 @@ namespace Nodify.Calculator
|
||||
var addedParams = new HashSet<string>();
|
||||
foreach (var parameter in method.Value.Parameters)
|
||||
{
|
||||
// Skip body parameters — they are handled by ExtractRequestBodyModel
|
||||
if (parameter.Kind == NSwag.OpenApiParameterKind.Body)
|
||||
continue;
|
||||
|
||||
if (addedParams.Add(parameter.Name))
|
||||
{
|
||||
ovmodel.Input.Add(parameter.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract request body model for POST/PUT/PATCH
|
||||
var httpMethodLower = method.Key.ToLower();
|
||||
if (httpMethodLower == "post" || httpMethodLower == "put" || httpMethodLower == "patch")
|
||||
{
|
||||
var bodyModelName = ExtractRequestBodyModel(method.Value, path.Key, method.Key, createdModels);
|
||||
ovmodel.RequestBodyModelClassName = bodyModelName;
|
||||
}
|
||||
|
||||
// Extract response model from 200/201 response schema
|
||||
var responseModelName = ExtractResponseModel(method.Value, path.Key, method.Key, createdModels);
|
||||
ovmodel.ResponseModelClassName = responseModelName;
|
||||
@@ -516,6 +528,85 @@ namespace Nodify.Calculator
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string ExtractRequestBodyModel(NSwag.OpenApiOperation operation, string path, string httpMethod, HashSet<string> createdModels)
|
||||
{
|
||||
try
|
||||
{
|
||||
NJsonSchema.JsonSchema bodySchema = null;
|
||||
|
||||
// OpenAPI 3.0: operation.RequestBody.Content
|
||||
if (operation.RequestBody?.Content != null && operation.RequestBody.Content.Count > 0)
|
||||
{
|
||||
if (operation.RequestBody.Content.TryGetValue("application/json", out var jsonContent))
|
||||
bodySchema = jsonContent.Schema;
|
||||
else
|
||||
bodySchema = operation.RequestBody.Content.Values.FirstOrDefault()?.Schema;
|
||||
}
|
||||
|
||||
// OpenAPI 2.0 (Swagger): body parameter with In == Body
|
||||
if (bodySchema == null)
|
||||
{
|
||||
var bodyParam = operation.Parameters.FirstOrDefault(
|
||||
p => p.Kind == NSwag.OpenApiParameterKind.Body);
|
||||
if (bodyParam != null)
|
||||
bodySchema = bodyParam.Schema ?? bodyParam.ActualSchema;
|
||||
}
|
||||
|
||||
if (bodySchema == null) return string.Empty;
|
||||
|
||||
var actualSchema = bodySchema.ActualSchema ?? bodySchema;
|
||||
|
||||
// Resolve arrays
|
||||
var targetSchema = actualSchema;
|
||||
bool isList = false;
|
||||
if (actualSchema.Type == NJsonSchema.JsonObjectType.Array && actualSchema.Item != null)
|
||||
{
|
||||
targetSchema = actualSchema.Item.ActualSchema ?? actualSchema.Item;
|
||||
isList = true;
|
||||
}
|
||||
targetSchema = targetSchema.ActualSchema ?? targetSchema;
|
||||
|
||||
// Derive class name
|
||||
var className = !string.IsNullOrEmpty(targetSchema.Title)
|
||||
? targetSchema.Title
|
||||
: DeriveRequestClassName(path, httpMethod);
|
||||
|
||||
className = SanitizeClassName(className);
|
||||
|
||||
var props = targetSchema.ActualProperties;
|
||||
if (string.IsNullOrEmpty(className) || props == null || props.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
// Generate model file if not already done
|
||||
if (createdModels.Add(className))
|
||||
{
|
||||
GenerateModelFromSchema(className, targetSchema);
|
||||
var modelInfo = new OperationInfoViewModel
|
||||
{
|
||||
Title = className,
|
||||
IsModelNode = true,
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.GET_SET,
|
||||
ClassName = className
|
||||
};
|
||||
AddNewModel(modelInfo);
|
||||
}
|
||||
|
||||
return isList ? $"List<{className}>" : className;
|
||||
}
|
||||
catch { /* Best-effort */ }
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string DeriveRequestClassName(string path, string httpMethod)
|
||||
{
|
||||
var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Where(s => !s.StartsWith("{"))
|
||||
.Select(s => Executor.ToPascalCase(s));
|
||||
return $"{Executor.ToPascalCase(httpMethod)}{string.Join("", segments)}Request";
|
||||
}
|
||||
|
||||
private void GenerateModelFromSchema(string className, NJsonSchema.JsonSchema schema)
|
||||
{
|
||||
var customModelDir = Path.Combine(ProjectManager.ProjectDirectory, "CustomModels");
|
||||
@@ -613,6 +704,7 @@ namespace Nodify.Calculator
|
||||
InputNames = new List<string>(node.Input),
|
||||
SwaggerFileName = swaggerFileName,
|
||||
ResponseModelClassName = node.ResponseModelClassName ?? string.Empty,
|
||||
RequestBodyModelClassName = node.RequestBodyModelClassName ?? string.Empty,
|
||||
SwaggerGroup = node.SwaggerGroup ?? string.Empty
|
||||
});
|
||||
}
|
||||
@@ -645,6 +737,7 @@ namespace Nodify.Calculator
|
||||
}
|
||||
|
||||
ovmodel.ResponseModelClassName = saved.ResponseModelClassName ?? string.Empty;
|
||||
ovmodel.RequestBodyModelClassName = saved.RequestBodyModelClassName ?? string.Empty;
|
||||
ovmodel.Output.Add("");
|
||||
SwaggerOperations.Add(ovmodel);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user