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;
|
get => _responseModelClassName;
|
||||||
set => SetProperty(ref _responseModelClassName, value);
|
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
|
// API node properties
|
||||||
public string OPType { get; set; } = string.Empty;
|
public string OPType { get; set; } = string.Empty;
|
||||||
public string ResponseModelClassName { get; set; } = string.Empty;
|
public string ResponseModelClassName { get; set; } = string.Empty;
|
||||||
|
public string RequestBodyModelClassName { get; set; } = string.Empty;
|
||||||
|
|
||||||
// System node properties
|
// System node properties
|
||||||
public string SystemOp { get; set; } = string.Empty;
|
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 List<string> InputNames { get; set; } = new List<string>();
|
||||||
public string SwaggerFileName { get; set; } = string.Empty;
|
public string SwaggerFileName { get; set; } = string.Empty;
|
||||||
public string ResponseModelClassName { 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;
|
public string SwaggerGroup { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ namespace Nodify.Calculator.NodeHandlers
|
|||||||
{
|
{
|
||||||
Title = info.Title,
|
Title = info.Title,
|
||||||
OperationType = (info.OPType ?? "GET").ToUpper(),
|
OperationType = (info.OPType ?? "GET").ToUpper(),
|
||||||
ResponseModelClassName = info.ResponseModelClassName ?? string.Empty
|
ResponseModelClassName = info.ResponseModelClassName ?? string.Empty,
|
||||||
|
RequestBodyModelClassName = info.RequestBodyModelClassName ?? string.Empty
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flow connectors
|
// 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)
|
foreach (var label in info.Input)
|
||||||
{
|
{
|
||||||
op.Input.Add(new ConnectorViewModel { Title = label, ConnectorColor = Color.LimeGreen });
|
op.Input.Add(new ConnectorViewModel { Title = label, ConnectorColor = Color.LimeGreen });
|
||||||
@@ -124,12 +153,16 @@ namespace Nodify.Calculator.NodeHandlers
|
|||||||
Title = data.Title,
|
Title = data.Title,
|
||||||
OPType = data.OPType?.ToLower() ?? "get",
|
OPType = data.OPType?.ToLower() ?? "get",
|
||||||
Type = OperationType.API,
|
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)
|
foreach (var ic in data.InputConnectors)
|
||||||
{
|
{
|
||||||
if (ic.Shape != "Triangle")
|
if (ic.Shape == "Triangle") continue;
|
||||||
info.Input.Add(ic.Title);
|
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);
|
return Create(info);
|
||||||
}
|
}
|
||||||
@@ -141,6 +174,7 @@ namespace Nodify.Calculator.NodeHandlers
|
|||||||
{
|
{
|
||||||
data.OPType = api.OperationType;
|
data.OPType = api.OperationType;
|
||||||
data.ResponseModelClassName = api.ResponseModelClassName;
|
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> FunctionInputs { get; set; } = new List<FunctionParameterInfo>();
|
||||||
public List<FunctionParameterInfo> FunctionOutputs { get; set; } = new List<FunctionParameterInfo>();
|
public List<FunctionParameterInfo> FunctionOutputs { get; set; } = new List<FunctionParameterInfo>();
|
||||||
public string ResponseModelClassName { 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;
|
public string SwaggerGroup { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -417,12 +417,24 @@ namespace Nodify.Calculator
|
|||||||
var addedParams = new HashSet<string>();
|
var addedParams = new HashSet<string>();
|
||||||
foreach (var parameter in method.Value.Parameters)
|
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))
|
if (addedParams.Add(parameter.Name))
|
||||||
{
|
{
|
||||||
ovmodel.Input.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
|
// Extract response model from 200/201 response schema
|
||||||
var responseModelName = ExtractResponseModel(method.Value, path.Key, method.Key, createdModels);
|
var responseModelName = ExtractResponseModel(method.Value, path.Key, method.Key, createdModels);
|
||||||
ovmodel.ResponseModelClassName = responseModelName;
|
ovmodel.ResponseModelClassName = responseModelName;
|
||||||
@@ -516,6 +528,85 @@ namespace Nodify.Calculator
|
|||||||
return string.Empty;
|
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)
|
private void GenerateModelFromSchema(string className, NJsonSchema.JsonSchema schema)
|
||||||
{
|
{
|
||||||
var customModelDir = Path.Combine(ProjectManager.ProjectDirectory, "CustomModels");
|
var customModelDir = Path.Combine(ProjectManager.ProjectDirectory, "CustomModels");
|
||||||
@@ -613,6 +704,7 @@ namespace Nodify.Calculator
|
|||||||
InputNames = new List<string>(node.Input),
|
InputNames = new List<string>(node.Input),
|
||||||
SwaggerFileName = swaggerFileName,
|
SwaggerFileName = swaggerFileName,
|
||||||
ResponseModelClassName = node.ResponseModelClassName ?? string.Empty,
|
ResponseModelClassName = node.ResponseModelClassName ?? string.Empty,
|
||||||
|
RequestBodyModelClassName = node.RequestBodyModelClassName ?? string.Empty,
|
||||||
SwaggerGroup = node.SwaggerGroup ?? string.Empty
|
SwaggerGroup = node.SwaggerGroup ?? string.Empty
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -645,6 +737,7 @@ namespace Nodify.Calculator
|
|||||||
}
|
}
|
||||||
|
|
||||||
ovmodel.ResponseModelClassName = saved.ResponseModelClassName ?? string.Empty;
|
ovmodel.ResponseModelClassName = saved.ResponseModelClassName ?? string.Empty;
|
||||||
|
ovmodel.RequestBodyModelClassName = saved.RequestBodyModelClassName ?? string.Empty;
|
||||||
ovmodel.Output.Add("");
|
ovmodel.Output.Add("");
|
||||||
SwaggerOperations.Add(ovmodel);
|
SwaggerOperations.Add(ovmodel);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user