From 9f66f5d0fda651e6957c3acc10f8c544a4b473ea Mon Sep 17 00:00:00 2001
From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com>
Date: Wed, 22 Oct 2025 21:14:03 +1100
Subject: [PATCH 1/4] fix thing
---
.../CodeGenerationHelpers.cs | 25 ++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs b/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs
index 7172d4d6..1fdc115d 100644
--- a/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs
+++ b/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs
@@ -15,10 +15,33 @@ public static string ToPascalCase(string text)
return text;
}
- var parts = text.Split(['-', '_', ' '], StringSplitOptions.RemoveEmptyEntries);
+ var sanitized = SanitizeIdentifier(text);
+ var parts = sanitized.Split(['-', '_', ' '], StringSplitOptions.RemoveEmptyEntries);
return string.Join(string.Empty, parts.Select(p => char.ToUpperInvariant(p[0]) + p[1..]));
}
+ /// Removes invalid C# identifier characters from a string.
+ /// The text to sanitize.
+ /// The sanitized text with invalid characters removed.
+ private static string SanitizeIdentifier(string text)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return text;
+ }
+
+ var result = new System.Text.StringBuilder(text.Length);
+ foreach (var c in text)
+ {
+ if (char.IsLetterOrDigit(c) || c == '_' || c == '-' || c == ' ')
+ {
+ _ = result.Append(c);
+ }
+ }
+
+ return result.ToString();
+ }
+
/// Converts a string to camelCase.
/// The text to convert.
/// The camelCase version of the text.
From c85f54c01d3e6ad2cd086b2a571768ccbe5fc68a Mon Sep 17 00:00:00 2001
From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com>
Date: Wed, 22 Oct 2025 21:15:50 +1100
Subject: [PATCH 2/4] Fix test coverage
---
.../MSTestSettings.cs | 1 -
.../OpenApiCodeGeneratorTests.cs | 1459 +++++++++++++++++
...stClient.Net.OpenApiGenerator.Tests.csproj | 1 +
.../ModelGenerator.cs | 20 +
.../Generated/NucliaDBApiExtensions.g.cs | 96 +-
.../Generated/NucliaDBApiModels.g.cs | 321 ++--
.../Generated/NucliaDbMcpTools.g.cs | 24 +-
.../Generated/JSONPlaceholderApiModels.g.cs | 1 +
8 files changed, 1702 insertions(+), 221 deletions(-)
delete mode 100644 RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs
diff --git a/RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs b/RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs
deleted file mode 100644
index aaf278c8..00000000
--- a/RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs
+++ /dev/null
@@ -1 +0,0 @@
-[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
diff --git a/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs b/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs
index e33d7e9d..6860d51e 100644
--- a/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs
+++ b/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs
@@ -519,4 +519,1463 @@ public void Generate_CreatesPrivateStaticFuncFields()
&& result.ExtensionMethodsCode.Contains(", cancellationToken)")
);
}
+
+ [TestMethod]
+ public void Generate_HandlesAnyOfSchemasInProperties()
+ {
+ var specWithAnyOf = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/kb": {
+ "get": {
+ "operationId": "getKb",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/KnowledgeBoxObj"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "KnowledgeBoxObj": {
+ "type": "object",
+ "required": ["uuid"],
+ "properties": {
+ "slug": {
+ "anyOf": [
+ { "type": "string", "maxLength": 250 },
+ { "type": "null" }
+ ]
+ },
+ "uuid": {
+ "type": "string"
+ },
+ "config": {
+ "anyOf": [
+ { "$ref": "#/components/schemas/KnowledgeBoxConfig" },
+ { "type": "null" }
+ ]
+ },
+ "model": {
+ "anyOf": [
+ { "$ref": "#/components/schemas/SemanticModelMetadata" },
+ { "type": "null" }
+ ]
+ }
+ }
+ },
+ "KnowledgeBoxConfig": {
+ "type": "object",
+ "properties": {
+ "title": { "type": "string" }
+ }
+ },
+ "SemanticModelMetadata": {
+ "type": "object",
+ "properties": {
+ "similarity_function": { "type": "string" }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(
+ specWithAnyOf,
+ "TestApi",
+ "TestApiExtensions",
+ Path.GetTempPath()
+ )
+ );
+
+ // Verify anyOf properties are correctly typed - THIS PROVES BUG #142 IS FIXED
+ Assert.IsTrue(result.ModelsCode.Contains("public record KnowledgeBoxObj("));
+ Assert.IsTrue(result.ModelsCode.Contains("string? Slug"), $"Expected 'string? Slug' but got: {result.ModelsCode}");
+ Assert.IsTrue(result.ModelsCode.Contains("string Uuid"), $"Expected 'string Uuid' but got: {result.ModelsCode}");
+ Assert.IsTrue(result.ModelsCode.Contains("KnowledgeBoxConfig? Config"), $"Expected 'KnowledgeBoxConfig? Config' but got: {result.ModelsCode}");
+ Assert.IsTrue(result.ModelsCode.Contains("SemanticModelMetadata? Model"), $"Expected 'SemanticModelMetadata? Model' but got: {result.ModelsCode}");
+ Assert.IsFalse(result.ModelsCode.Contains("object Slug"), "Should not have 'object Slug'");
+ Assert.IsFalse(result.ModelsCode.Contains("object Config"), "Should not have 'object Config'");
+ Assert.IsFalse(result.ModelsCode.Contains("object Model"), "Should not have 'object Model'");
+ }
+
+ [TestMethod]
+ public void Generate_HandlesAnyOfWithInteger()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/resource": {
+ "get": {
+ "operationId": "getResource",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "anyOf": [
+ { "type": "integer" },
+ { "type": "null" }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ModelsCode.Contains("int? Count"));
+ Assert.IsFalse(result.ModelsCode.Contains("object Count"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesArrayOfIntegers()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/numbers": {
+ "get": {
+ "operationId": "getNumbers",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("Result,"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesInt64Format()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/resource/{id}": {
+ "get": {
+ "operationId": "getResource",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ModelsCode.Contains("long Id"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("long id"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesDoubleFormat()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/resource": {
+ "get": {
+ "operationId": "getResource",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "price": {
+ "type": "number",
+ "format": "double"
+ },
+ "rating": {
+ "type": "number"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ModelsCode.Contains("double Price"));
+ Assert.IsTrue(result.ModelsCode.Contains("float Rating"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesBooleanType()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/resource": {
+ "get": {
+ "operationId": "getResource",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "isActive": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ModelsCode.Contains("bool IsActive"));
+ }
+
+ [TestMethod]
+ public void Generate_SkipsStringEnums()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/resource": {
+ "get": {
+ "operationId": "getResource",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Status": {
+ "type": "string",
+ "enum": ["active", "inactive", "pending"]
+ },
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "$ref": "#/components/schemas/Status"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ // String enums should not generate records, and references should map to string
+ Assert.IsFalse(result.ModelsCode.Contains("public record Status"));
+ Assert.IsTrue(result.ModelsCode.Contains("string Status"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesArrayOfReferences()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/items": {
+ "get": {
+ "operationId": "getItems",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Item"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Item": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("Result,"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesComplexNestedStructures()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/order": {
+ "get": {
+ "operationId": "getOrder",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Order"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Order": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "customer": {
+ "$ref": "#/components/schemas/Customer"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/OrderItem"
+ }
+ },
+ "total": {
+ "type": "number",
+ "format": "double"
+ }
+ }
+ },
+ "Customer": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "email": {
+ "type": "string"
+ }
+ }
+ },
+ "OrderItem": {
+ "type": "object",
+ "properties": {
+ "productId": {
+ "type": "integer"
+ },
+ "quantity": {
+ "type": "integer"
+ },
+ "price": {
+ "type": "number"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ // Verify Order model
+ Assert.IsTrue(result.ModelsCode.Contains("public record Order("));
+ Assert.IsTrue(result.ModelsCode.Contains("long Id"));
+ Assert.IsTrue(result.ModelsCode.Contains("Customer Customer"));
+ Assert.IsTrue(result.ModelsCode.Contains("List Items"));
+ Assert.IsTrue(result.ModelsCode.Contains("double Total"));
+
+ // Verify Customer model
+ Assert.IsTrue(result.ModelsCode.Contains("public record Customer("));
+ Assert.IsTrue(result.ModelsCode.Contains("string Name"));
+ Assert.IsTrue(result.ModelsCode.Contains("string Email"));
+
+ // Verify OrderItem model
+ Assert.IsTrue(result.ModelsCode.Contains("public record OrderItem("));
+ Assert.IsTrue(result.ModelsCode.Contains("int ProductId"));
+ Assert.IsTrue(result.ModelsCode.Contains("int Quantity"));
+ Assert.IsTrue(result.ModelsCode.Contains("float Price"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesPutMethod()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets/{petId}": {
+ "put": {
+ "operationId": "updatePet",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Pet": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("UpdatePet"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreatePut"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesPatchMethod()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets/{petId}": {
+ "patch": {
+ "operationId": "patchPet",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/PetUpdate"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Pet": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ "PetUpdate": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("PatchPet"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreatePatch"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesOptionalQueryParameters()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets": {
+ "get": {
+ "operationId": "listPets",
+ "parameters": [
+ {
+ "name": "limit",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "offset",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("int? limit"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("int? offset"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("BuildQueryString"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesHeaderParameters()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets": {
+ "get": {
+ "operationId": "listPets",
+ "parameters": [
+ {
+ "name": "X-API-Key",
+ "in": "header",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ // Just verify it compiled and generated - the actual parameter handling is implementation detail
+ Assert.IsFalse(string.IsNullOrEmpty(result.ExtensionMethodsCode));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("ListPets"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesPathAndQueryParametersCombined()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets/{petId}/friends": {
+ "get": {
+ "operationId": "getPetFriends",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("petId"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("limit"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesMultilineDescriptions()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets": {
+ "get": {
+ "operationId": "listPets",
+ "description": "List all pets\n\n---\n\nReturns a paginated list of pets",
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ // Should only include the summary before the --- separator
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("/// List all pets"));
+ Assert.IsFalse(result.ExtensionMethodsCode.Contains("Returns a paginated list"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesNoPathParameters()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/health": {
+ "get": {
+ "operationId": "getHealth",
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("GetHealth"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("Unit.Value"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesDefaultParameterValues()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets": {
+ "get": {
+ "operationId": "listPets",
+ "parameters": [
+ {
+ "name": "limit",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "default": 10
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("limit = 10"));
+ }
+
+ [TestMethod]
+ public void Generate_SanitizesParameterNames()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets/{pet_id}": {
+ "get": {
+ "operationId": "getPet",
+ "parameters": [
+ {
+ "name": "pet_id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ // Parameter name should be converted to camelCase
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("int petId"));
+ // But path template should preserve original name
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("{petId}"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesOperationWithoutOperationId()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ // Should generate method name from path and HTTP method
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("GetPets"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesMultipleResponseTypes()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets": {
+ "get": {
+ "operationId": "listPets",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Not Found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Pet": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" }
+ }
+ },
+ "Error": {
+ "type": "object",
+ "properties": {
+ "message": { "type": "string" }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("Result"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesEmptyResponseContent()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets/{petId}": {
+ "delete": {
+ "operationId": "deletePet",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "Deleted"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("DeletePet"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreateDelete"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesRequiredHeaderParameters()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets": {
+ "get": {
+ "operationId": "listPets",
+ "parameters": [
+ {
+ "name": "Authorization",
+ "in": "header",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "X-Request-ID",
+ "in": "header",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("authorization"), "Should contain 'authorization'");
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("xRequestID"), "Should contain 'xRequestID'");
+ }
+
+ [TestMethod]
+ public void Generate_HandlesStringDefaultValues()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/search": {
+ "get": {
+ "operationId": "search",
+ "parameters": [
+ {
+ "name": "query",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "default": "test"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("query = \"test\""));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesOperationWithOnlyErrorResponse()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/test": {
+ "get": {
+ "operationId": "testOp",
+ "responses": {
+ "400": {
+ "description": "Bad Request",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Error": {
+ "type": "object",
+ "properties": {
+ "message": { "type": "string" }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("TestOp"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesRequiredQueryParameters()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/search": {
+ "get": {
+ "operationId": "search",
+ "parameters": [
+ {
+ "name": "query",
+ "in": "query",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ // Required query params should not be nullable
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("string query"));
+ Assert.IsFalse(result.ExtensionMethodsCode.Contains("string? query"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesPostWithoutRequestBody()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/action": {
+ "post": {
+ "operationId": "performAction",
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("PerformAction"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreatePost"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesBooleanDefaultValue()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/items": {
+ "get": {
+ "operationId": "listItems",
+ "parameters": [
+ {
+ "name": "includeDeleted",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Success"
+ }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("includeDeleted = false"));
+ }
+
+ [TestMethod]
+ public void Generate_HandlesPathWithMultipleOperations()
+ {
+ var spec = """
+ {
+ "openapi": "3.0.0",
+ "info": { "title": "Test API", "version": "1.0.0" },
+ "servers": [{ "url": "https://api.test.com" }],
+ "paths": {
+ "/pets/{petId}": {
+ "get": {
+ "operationId": "getPet",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "required": true,
+ "schema": { "type": "integer" }
+ }
+ ],
+ "responses": {
+ "200": { "description": "Success" }
+ }
+ },
+ "put": {
+ "operationId": "updatePet",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "required": true,
+ "schema": { "type": "integer" }
+ }
+ ],
+ "responses": {
+ "200": { "description": "Success" }
+ }
+ },
+ "delete": {
+ "operationId": "deletePet",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "required": true,
+ "schema": { "type": "integer" }
+ }
+ ],
+ "responses": {
+ "204": { "description": "Deleted" }
+ }
+ }
+ }
+ }
+ }
+ """;
+
+ var result = GetSuccessResult(
+ OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath())
+ );
+
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("GetPet"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("UpdatePet"));
+ Assert.IsTrue(result.ExtensionMethodsCode.Contains("DeletePet"));
+ }
}
diff --git a/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj b/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj
index 4a963d6d..1d62fbc5 100644
--- a/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj
+++ b/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj
@@ -9,6 +9,7 @@
+
diff --git a/RestClient.Net.OpenApiGenerator/ModelGenerator.cs b/RestClient.Net.OpenApiGenerator/ModelGenerator.cs
index 16c91c1d..64533ee8 100644
--- a/RestClient.Net.OpenApiGenerator/ModelGenerator.cs
+++ b/RestClient.Net.OpenApiGenerator/ModelGenerator.cs
@@ -33,6 +33,7 @@ public static string GenerateModels(OpenApiDocument document, string @namespace)
var modelsCode = string.Join("\n\n", models);
return $$"""
+ #nullable enable
namespace {{@namespace}};
{{modelsCode}}
@@ -131,6 +132,25 @@ public static string MapOpenApiType(
return "object";
}
+ // Handle anyOf schemas
+ if (schemaObj.AnyOf != null && schemaObj.AnyOf.Count > 0)
+ {
+ // Filter out null types and get the first non-null type
+ // Handle both OpenApiSchema with Type != Null and OpenApiSchemaReference
+ var nonNullSchema = schemaObj.AnyOf.FirstOrDefault(s =>
+ s is OpenApiSchemaReference
+ || (s is OpenApiSchema os && os.Type != JsonSchemaType.Null)
+ );
+
+ if (nonNullSchema != null)
+ {
+ // Recursively resolve the type
+ var baseType = MapOpenApiType(nonNullSchema, schemas);
+ // Make it nullable since it's in an anyOf with null
+ return baseType.EndsWith('?') ? baseType : $"{baseType}?";
+ }
+ }
+
// Handle arrays
if (schemaObj.Type == JsonSchemaType.Array)
{
diff --git a/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs b/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs
index 5f761e89..b82b8c2d 100644
--- a/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs
+++ b/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs
@@ -57,7 +57,7 @@ public static Task>> AskK
/// List resources of a Knowledge Box
public static Task>> CatalogGetKbKbidCatalogAsync(
this HttpClient httpClient,
- string kbid, string query = "", object? filterExpression = null, List? filters = null, List? faceted = null, string sortField = "", object? sortLimit = null, string sortOrder = "desc", int pageNumber = 0, int pageSize = 20, object? withStatus = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, object? hidden = null, List? show = null,
+ string kbid, string query = "", string? filterExpression = null, List? filters = null, List? faceted = null, string sortField = "", int? sortLimit = null, string sortOrder = "desc", int pageNumber = 0, int pageSize = 20, string? withStatus = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, bool? hidden = null, List? show = null,
CancellationToken cancellationToken = default
) => _catalogGetKbKbidCatalogAsync(httpClient, (kbid, query, filterExpression, filters, faceted, sortField, sortLimit, sortOrder, pageNumber, pageSize, withStatus, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, hidden, show), cancellationToken);
@@ -211,7 +211,7 @@ public static Task>> SendFeedbackE
/// Find on a Knowledge Box
public static Task>> FindKnowledgeboxKbKbidFindAsync(
this HttpClient httpClient,
- string kbid, string query = "", object? filterExpression = null, List? fields = null, List? filters = null, object? topK = null, object? minScore = null, object? minScoreSemantic = null, float minScoreBm25 = 0, object? vectorset = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string rankFusion = "rrf", object? reranker = null, object? searchConfiguration = null, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null,
+ string kbid, string query = "", string? filterExpression = null, List? fields = null, List? filters = null, int? topK = null, float? minScore = null, float? minScoreSemantic = null, float minScoreBm25 = 0, string? vectorset = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string rankFusion = "rrf", string? reranker = null, string? searchConfiguration = null, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null,
CancellationToken cancellationToken = default
) => _findKnowledgeboxKbKbidFindAsync(httpClient, (kbid, query, filterExpression, fields, filters, topK, minScore, minScoreSemantic, minScoreBm25, vectorset, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, rankFusion, reranker, searchConfiguration, xNdbClient, xNucliadbUser, xForwardedFor), cancellationToken);
@@ -330,14 +330,14 @@ public static Task>> PredictProxyE
/// Provides the status of the processing of the given Knowledge Box.
public static Task>> ProcessingStatusKbKbidProcessingStatusAsync(
this HttpClient httpClient,
- string kbid, object? cursor = null, object? scheduled = null, int limit = 20,
+ string kbid, string? cursor = null, bool? scheduled = null, int limit = 20,
CancellationToken cancellationToken = default
) => _processingStatusKbKbidProcessingStatusAsync(httpClient, (kbid, cursor, scheduled, limit), cancellationToken);
/// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER`
public static Task>> TusPostRidPrefixKbKbidResourcePathRidFileFieldTusuploadAsync(
this HttpClient httpClient,
- string kbid, string pathRid, string field, object body, object? xExtractStrategy = null, object? xSplitStrategy = null,
+ string kbid, string pathRid, string field, object body, string? xExtractStrategy = null, string? xSplitStrategy = null,
CancellationToken cancellationToken = default
) => _tusPostRidPrefixKbKbidResourcePathRidFileFieldTusuploadAsync(httpClient, (kbid, pathRid, field, xExtractStrategy, xSplitStrategy, body), cancellationToken);
@@ -351,7 +351,7 @@ public static Task>> UploadInforma
/// Upload a file as a field on an existing resource, if the field exists will return a conflict (419)
public static Task>> UploadRidPrefixKbKbidResourcePathRidFileFieldUploadAsync(
this HttpClient httpClient,
- string kbid, string pathRid, string field, object body, object? xFilename = null, object? xPassword = null, object? xLanguage = null, object? xMd5 = null, object? xExtractStrategy = null, object? xSplitStrategy = null,
+ string kbid, string pathRid, string field, object body, string? xFilename = null, string? xPassword = null, string? xLanguage = null, string? xMd5 = null, string? xExtractStrategy = null, string? xSplitStrategy = null,
CancellationToken cancellationToken = default
) => _uploadRidPrefixKbKbidResourcePathRidFileFieldUploadAsync(httpClient, (kbid, pathRid, field, xFilename, xPassword, xLanguage, xMd5, xExtractStrategy, xSplitStrategy, body), cancellationToken);
@@ -421,7 +421,7 @@ public static Task>> DownloadField
/// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER`
public static Task>> ReprocessFileFieldKbKbidResourceRidFileFieldIdReprocessAsync(
this HttpClient httpClient,
- string kbid, string rid, string fieldId, object body, bool resetTitle = false, string? xNucliadbUser = null, object? xFilePassword = null,
+ string kbid, string rid, string fieldId, object body, bool resetTitle = false, string? xNucliadbUser = null, string? xFilePassword = null,
CancellationToken cancellationToken = default
) => _reprocessFileFieldKbKbidResourceRidFileFieldIdReprocessAsync(httpClient, (kbid, rid, fieldId, resetTitle, xNucliadbUser, xFilePassword, body), cancellationToken);
@@ -463,7 +463,7 @@ public static Task
/// Search on a single resource
public static Task>> ResourceSearchKbKbidResourceRidSearchAsync(
this HttpClient httpClient,
- string kbid, string rid, string query, object? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, object? sortField = null, string sortOrder = "desc", object? topK = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, bool highlight = false, bool debug = false, string xNdbClient = "api",
+ string kbid, string rid, string query, string? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string? sortField = null, string sortOrder = "desc", int? topK = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, bool highlight = false, bool debug = false, string xNdbClient = "api",
CancellationToken cancellationToken = default
) => _resourceSearchKbKbidResourceRidSearchAsync(httpClient, (kbid, rid, query, filterExpression, fields, filters, faceted, sortField, sortOrder, topK, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, highlight, debug, xNdbClient), cancellationToken);
@@ -484,7 +484,7 @@ public static Task>> ResourceFieldRi
/// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER`
public static Task>> ResourceFieldRidPrefixKbKbidResourceRidFieldTypeFieldIdGetAsync(
this HttpClient httpClient,
- string kbid, string rid, string fieldType, string fieldId, List? show = null, List? extracted = null, object? page = null,
+ string kbid, string rid, string fieldType, string fieldId, List? show = null, List? extracted = null, string? page = null,
CancellationToken cancellationToken = default
) => _resourceFieldRidPrefixKbKbidResourceRidFieldTypeFieldIdGetAsync(httpClient, (kbid, rid, fieldType, fieldId, show, extracted, page), cancellationToken);
@@ -519,7 +519,7 @@ public static Task>> SchemaForConf
/// Search on a Knowledge Box and retrieve separate results for documents, paragraphs, and sentences. Usually, it is better to use `find`
public static Task>> SearchKnowledgeboxKbKbidSearchAsync(
this HttpClient httpClient,
- string kbid, string query = "", object? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string sortField = "", object? sortLimit = null, string sortOrder = "desc", int topK = 20, object? minScore = null, object? minScoreSemantic = null, float minScoreBm25 = 0, object? vectorset = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null,
+ string kbid, string query = "", string? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string sortField = "", int? sortLimit = null, string sortOrder = "desc", int topK = 20, float? minScore = null, float? minScoreSemantic = null, float minScoreBm25 = 0, string? vectorset = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null,
CancellationToken cancellationToken = default
) => _searchKnowledgeboxKbKbidSearchAsync(httpClient, (kbid, query, filterExpression, fields, filters, faceted, sortField, sortLimit, sortOrder, topK, minScore, minScoreSemantic, minScoreBm25, vectorset, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, xNdbClient, xNucliadbUser, xForwardedFor), cancellationToken);
@@ -624,7 +624,7 @@ public static Task>> DownloadField
/// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER`
public static Task>> TusPostRslugPrefixKbKbidSlugRslugFileFieldTusuploadAsync(
this HttpClient httpClient,
- string kbid, string rslug, string field, object body, object? xExtractStrategy = null, object? xSplitStrategy = null,
+ string kbid, string rslug, string field, object body, string? xExtractStrategy = null, string? xSplitStrategy = null,
CancellationToken cancellationToken = default
) => _tusPostRslugPrefixKbKbidSlugRslugFileFieldTusuploadAsync(httpClient, (kbid, rslug, field, xExtractStrategy, xSplitStrategy, body), cancellationToken);
@@ -645,7 +645,7 @@ public static Task>> UploadInforma
/// Upload a file as a field on an existing resource, if the field exists will return a conflict (419)
public static Task>> UploadRslugPrefixKbKbidSlugRslugFileFieldUploadAsync(
this HttpClient httpClient,
- string kbid, string rslug, string field, object body, object? xFilename = null, object? xPassword = null, object? xLanguage = null, object? xMd5 = null, object? xExtractStrategy = null, object? xSplitStrategy = null,
+ string kbid, string rslug, string field, object body, string? xFilename = null, string? xPassword = null, string? xLanguage = null, string? xMd5 = null, string? xExtractStrategy = null, string? xSplitStrategy = null,
CancellationToken cancellationToken = default
) => _uploadRslugPrefixKbKbidSlugRslugFileFieldUploadAsync(httpClient, (kbid, rslug, field, xFilename, xPassword, xLanguage, xMd5, xExtractStrategy, xSplitStrategy, body), cancellationToken);
@@ -687,7 +687,7 @@ public static Task>> ResourceFieldRs
/// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER`
public static Task>> ResourceFieldRslugPrefixKbKbidSlugRslugFieldTypeFieldIdGetAsync(
this HttpClient httpClient,
- string kbid, string rslug, string fieldType, string fieldId, List? show = null, List? extracted = null, object? page = null,
+ string kbid, string rslug, string fieldType, string fieldId, List? show = null, List? extracted = null, string? page = null,
CancellationToken cancellationToken = default
) => _resourceFieldRslugPrefixKbKbidSlugRslugFieldTypeFieldIdGetAsync(httpClient, (kbid, rslug, fieldType, fieldId, show, extracted, page), cancellationToken);
@@ -743,7 +743,7 @@ public static Task>> SplitStrategy
/// Suggestions on a knowledge box
public static Task>> SuggestKnowledgeboxKbKbidSuggestAsync(
this HttpClient httpClient,
- string kbid, string query, List? fields = null, List? filters = null, List? faceted = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, List? show = null, List? fieldType = null, bool debug = false, bool highlight = false, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null,
+ string kbid, string query, List? fields = null, List? filters = null, List? faceted = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, List? show = null, List? fieldType = null, bool debug = false, bool highlight = false, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null,
CancellationToken cancellationToken = default
) => _suggestKnowledgeboxKbKbidSuggestAsync(httpClient, (kbid, query, fields, filters, faceted, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, show, fieldType, debug, highlight, showHidden, xNdbClient, xNucliadbUser, xForwardedFor), cancellationToken);
@@ -757,14 +757,14 @@ public static Task>> S
/// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER`
public static Task>> TusPostKbKbidTusuploadAsync(
this HttpClient httpClient,
- string kbid, object body, object? xExtractStrategy = null, object? xSplitStrategy = null,
+ string kbid, object body, string? xExtractStrategy = null, string? xSplitStrategy = null,
CancellationToken cancellationToken = default
) => _tusPostKbKbidTusuploadAsync(httpClient, (kbid, xExtractStrategy, xSplitStrategy, body), cancellationToken);
/// TUS Server information
public static Task>> TusOptionsKbKbidTusuploadAsync(
this HttpClient httpClient,
- string kbid, object? rid = null, object? rslug = null, object? uploadId = null, object? field = null,
+ string kbid, string? rid = null, string? rslug = null, string? uploadId = null, string? field = null,
CancellationToken cancellationToken = default
) => _tusOptionsKbKbidTusuploadAsync(httpClient, (kbid, rid, rslug, uploadId, field), cancellationToken);
@@ -785,7 +785,7 @@ public static Task>> UploadInforma
/// Upload a file onto a Knowledge Box, field id will be file and rid will be autogenerated.
public static Task>> UploadKbKbidUploadAsync(
this HttpClient httpClient,
- string kbid, object body, object? xFilename = null, object? xPassword = null, object? xLanguage = null, object? xMd5 = null, object? xExtractStrategy = null, object? xSplitStrategy = null,
+ string kbid, object body, string? xFilename = null, string? xPassword = null, string? xLanguage = null, string? xMd5 = null, string? xExtractStrategy = null, string? xSplitStrategy = null,
CancellationToken cancellationToken = default
) => _uploadKbKbidUploadAsync(httpClient, (kbid, xFilename, xPassword, xLanguage, xMd5, xExtractStrategy, xSplitStrategy, body), cancellationToken);
@@ -837,8 +837,8 @@ public static Task>> LearningConfi
deserializeError: DeserializeJson
);
- private static GetAsync? filters, List? faceted, string sortField, object? sortLimit, string sortOrder, int pageNumber, int pageSize, object? withStatus, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, object? hidden, List? show)> _catalogGetKbKbidCatalogAsync { get; } =
- RestClient.Net.HttpClientFactoryExtensions.CreateGet? filters, List? faceted, string sortField, object? sortLimit, string sortOrder, int pageNumber, int pageSize, object? withStatus, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, object? hidden, List? show)>(
+ private static GetAsync? filters, List? faceted, string sortField, int? sortLimit, string sortOrder, int pageNumber, int pageSize, string? withStatus, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, bool? hidden, List? show)> _catalogGetKbKbidCatalogAsync { get; } =
+ RestClient.Net.HttpClientFactoryExtensions.CreateGet? filters, List? faceted, string sortField, int? sortLimit, string sortOrder, int pageNumber, int pageSize, string? withStatus, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, bool? hidden, List? show)>(
url: BaseUrl,
buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/catalog{BuildQueryString(("query", param.query), ("filter_expression", param.filterExpression), ("filters", param.filters), ("faceted", param.faceted), ("sort_field", param.sortField), ("sort_limit", param.sortLimit), ("sort_order", param.sortOrder), ("page_number", param.pageNumber), ("page_size", param.pageSize), ("with_status", param.withStatus), ("range_creation_start", param.rangeCreationStart), ("range_creation_end", param.rangeCreationEnd), ("range_modification_start", param.rangeModificationStart), ("range_modification_end", param.rangeModificationEnd), ("hidden", param.hidden), ("show", param.show))}"), null, null),
deserializeSuccess: DeserializeJson,
@@ -1013,8 +1013,8 @@ public static Task>> LearningConfi
deserializeError: DeserializeJson
);
- private static GetAsync? fields, List? filters, object? topK, object? minScore, object? minScoreSemantic, float minScoreBm25, object? vectorset, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, object? reranker, object? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _findKnowledgeboxKbKbidFindAsync { get; } =
- RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, object? topK, object? minScore, object? minScoreSemantic, float minScoreBm25, object? vectorset, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, object? reranker, object? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>(
+ private static GetAsync? fields, List? filters, int? topK, float? minScore, float? minScoreSemantic, float minScoreBm25, string? vectorset, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, string? reranker, string? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _findKnowledgeboxKbKbidFindAsync { get; } =
+ RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, int? topK, float? minScore, float? minScoreSemantic, float minScoreBm25, string? vectorset, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, string? reranker, string? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>(
url: BaseUrl,
buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/find{BuildQueryString(("query", param.query), ("filter_expression", param.filterExpression), ("fields", param.fields), ("filters", param.filters), ("top_k", param.topK), ("min_score", param.minScore), ("min_score_semantic", param.minScoreSemantic), ("min_score_bm25", param.minScoreBm25), ("vectorset", param.vectorset), ("range_creation_start", param.rangeCreationStart), ("range_creation_end", param.rangeCreationEnd), ("range_modification_start", param.rangeModificationStart), ("range_modification_end", param.rangeModificationEnd), ("features", param.features), ("debug", param.debug), ("highlight", param.highlight), ("show", param.show), ("field_type", param.fieldType), ("extracted", param.extracted), ("with_duplicates", param.withDuplicates), ("with_synonyms", param.withSynonyms), ("autofilter", param.autofilter), ("security_groups", param.securityGroups), ("show_hidden", param.showHidden), ("rank_fusion", param.rankFusion), ("reranker", param.reranker), ("search_configuration", param.searchConfiguration))}"), null, new Dictionary { ["x-ndb-client"] = param.xNdbClient.ToString(), ["x-nucliadb-user"] = param.xNucliadbUser?.ToString() ?? string.Empty, ["x-forwarded-for"] = param.xForwardedFor?.ToString() ?? string.Empty }),
deserializeSuccess: DeserializeJson,
@@ -1149,16 +1149,16 @@ public static Task>> LearningConfi
deserializeError: DeserializeJson
);
- private static GetAsync _processingStatusKbKbidProcessingStatusAsync { get; } =
- RestClient.Net.HttpClientFactoryExtensions.CreateGet(
+ private static GetAsync _processingStatusKbKbidProcessingStatusAsync { get; } =
+ RestClient.Net.HttpClientFactoryExtensions.CreateGet(
url: BaseUrl,
buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/processing-status{BuildQueryString(("cursor", param.cursor), ("scheduled", param.scheduled), ("limit", param.limit))}"), null, null),
deserializeSuccess: DeserializeJson,
deserializeError: DeserializeError
);
- private static PostAsync