From 019afd6b66de4b921c533685f347fb7ebe37620f Mon Sep 17 00:00:00 2001 From: Fellmonkey <90258055+Fellmonkey@users.noreply.github.com> Date: Wed, 30 Jul 2025 18:21:48 +0300 Subject: [PATCH 1/4] support c# --- src/SDK/Language/CLI.php | 5 + templates/cli/lib/commands/types.js.twig | 5 +- .../type-generation/languages/csharp.js.twig | 201 ++++++++++++++++++ 3 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 templates/cli/lib/type-generation/languages/csharp.js.twig diff --git a/src/SDK/Language/CLI.php b/src/SDK/Language/CLI.php index aa922619b..a072f3b56 100644 --- a/src/SDK/Language/CLI.php +++ b/src/SDK/Language/CLI.php @@ -231,6 +231,11 @@ public function getFiles(): array 'destination' => 'lib/type-generation/languages/dart.js', 'template' => 'cli/lib/type-generation/languages/dart.js.twig', ], + [ + 'scope' => 'default', + 'destination' => 'lib/type-generation/languages/csharp.js', + 'template' => 'cli/lib/type-generation/languages/csharp.js.twig', + ], [ 'scope' => 'default', 'destination' => 'lib/questions.js', diff --git a/templates/cli/lib/commands/types.js.twig b/templates/cli/lib/commands/types.js.twig index 16beecbbc..07a85a896 100644 --- a/templates/cli/lib/commands/types.js.twig +++ b/templates/cli/lib/commands/types.js.twig @@ -12,6 +12,7 @@ const { Swift } = require("../type-generation/languages/swift"); const { Java } = require("../type-generation/languages/java"); const { Dart } = require("../type-generation/languages/dart"); const { JavaScript } = require("../type-generation/languages/javascript"); +const { CSharp } = require("../type-generation/languages/csharp"); /** * @param {string} language @@ -33,6 +34,8 @@ function createLanguageMeta(language) { return new Java(); case "dart": return new Dart(); + case "cs": + return new CSharp(); default: throw new Error(`Language '${language}' is not supported`); } @@ -55,7 +58,7 @@ const typesLanguageOption = new Option( "-l, --language ", "The language of the types" ) - .choices(["auto", "ts", "js", "php", "kotlin", "swift", "java", "dart"]) + .choices(["auto", "ts", "js", "php", "kotlin", "swift", "java", "dart", "cs"]) .default("auto"); const typesStrictOption = new Option( diff --git a/templates/cli/lib/type-generation/languages/csharp.js.twig b/templates/cli/lib/type-generation/languages/csharp.js.twig new file mode 100644 index 000000000..953ec4b70 --- /dev/null +++ b/templates/cli/lib/type-generation/languages/csharp.js.twig @@ -0,0 +1,201 @@ +/** @typedef {import('../attribute').Attribute} Attribute */ +const { AttributeType } = require('../attribute'); +const { LanguageMeta } = require("./language"); + +class CSharp extends LanguageMeta { + getType(attribute, collections) { + let type = ""; + switch (attribute.type) { + case AttributeType.STRING: + case AttributeType.EMAIL: + case AttributeType.DATETIME: + type = "string"; + if (attribute.format === AttributeType.ENUM) { + type = LanguageMeta.toPascalCase(attribute.key); + } + break; + case AttributeType.INTEGER: + type = "int"; + break; + case AttributeType.FLOAT: + type = "double"; + break; + case AttributeType.BOOLEAN: + type = "bool"; + break; + case AttributeType.RELATIONSHIP: + const relatedCollection = collections.find(c => c.$id === attribute.relatedCollection); + if (!relatedCollection) { + throw new Error(`Related collection with ID '${attribute.relatedCollection}' not found.`); + } + type = LanguageMeta.toPascalCase(relatedCollection.name); + if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany') { + type = `List<${type}>`; + } + break; + default: + throw new Error(`Unknown attribute type: ${attribute.type}`); + } + if (attribute.array) { + type = `List<${type}>`; + } + if (!attribute.required) { + type += "?"; + } + return type; + } + + getTemplate() { + return `/// This file is auto-generated by the Appwrite CLI. +/// You can regenerate it by running \`appwrite ${process.argv.slice(2).join(' ')}\`. + +#nullable enable +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; +<% for (const attribute of collection.attributes) { -%> +<% if (attribute.type === 'relationship') { -%> +using Appwrite.Models; +<% } -%> +<% } %> +namespace Appwrite.Models +{ +<% for (const attribute of collection.attributes) { -%> +<% if (attribute.format === 'enum') { -%> + +public enum <%- toPascalCase(attribute.key) %> { +<% for (const [index, element] of Object.entries(attribute.elements) ) { -%> + [JsonPropertyName("<%- element %>")] + <%- toPascalCase(element) %><% if (index < attribute.elements.length - 1) { %>,<% } %> +<% } -%> +} +<% } -%> +<% } %> +public class <%= toPascalCase(collection.name) %> +{ +<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%> + [JsonPropertyName("<%- attribute.key %>")] + public <%- getType(attribute, collections) %> <%= toPascalCase(attribute.key) %> { get; private set; } + +<% } -%> + + public <%= toPascalCase(collection.name) %>( +<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%> + <%- getType(attribute, collections) %> <%= toCamelCase(attribute.key) %><% if (index < collection.attributes.length - 1) { %>,<% } %> +<% } -%> + ) + { +<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%> + <%= toPascalCase(attribute.key) %> = <%= toCamelCase(attribute.key) %>; +<% } -%> + } + + public static <%= toPascalCase(collection.name) %> From(Dictionary map) + { + return new <%= toPascalCase(collection.name) %>( +<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%> + <%- toCamelCase(attribute.key) %>:<% + // ENUM + if (attribute.format === 'enum') { + if (attribute.array) { + -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => (<%- toPascalCase(attribute.key) %>)Enum.Parse(typeof(<%- toPascalCase(attribute.key) %>), e.ToString())).ToList()<% + } else { + if (attribute.required) { + -%> (<%- toPascalCase(attribute.key) %>)Enum.Parse(typeof(<%- toPascalCase(attribute.key) %>), map["<%- attribute.key %>"].ToString())<% + } else { + -%> map["<%- attribute.key %>"] != null ? (<%- toPascalCase(attribute.key) %>)Enum.Parse(typeof(<%- toPascalCase(attribute.key) %>), map["<%- attribute.key %>"].ToString()) : null<% + } + } + // RELATIONSHIP + } else if (attribute.type === 'relationship') { + const relatedClass = toPascalCase(collections.find(c => c.$id === attribute.relatedCollection).name); + if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany' || attribute.array) { + -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Models.<%- relatedClass %>.From((Dictionary)e)).ToList()<% + } else { + if (attribute.required) { + -%> <%- relatedClass %>.From((Dictionary)map["<%- attribute.key %>"])<% + } else { + -%> map["<%- attribute.key %>"] != null ? <%- relatedClass %>.From((Dictionary)map["<%- attribute.key %>"]) : null<% + } + } + // INTEGER + } else if (attribute.type === 'integer') { + if (attribute.array) { + -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToInt32(e)).ToList()<% + } else { + -%> map["<%- attribute.key %>"] != null ? Convert.ToInt32(map["<%- attribute.key %>"]) : (<%- attribute.required ? '0' : 'null' %>)<% + } + // FLOAT + } else if (attribute.type === 'float') { + if (attribute.array) { + -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToDouble(e)).ToList()<% + } else { + -%> map["<%- attribute.key %>"] != null ? Convert.ToDouble(map["<%- attribute.key %>"]) : (<%- attribute.required ? '0.0' : 'null' %>)<% + } + // BOOLEAN + } else if (attribute.type === 'boolean') { + if (attribute.array) { + -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToBoolean(e)).ToList()<% + } else { + -%> map["<%- attribute.key %>"] != null ? Convert.ToBoolean(map["<%- attribute.key %>"]) : (<%- attribute.required ? 'false' : 'null' %>)<% + } + // STRING, DATETIME, EMAIL + } else if (attribute.type === 'string' || attribute.type === 'datetime' || attribute.type === 'email') { + if (attribute.array) { + -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => e.ToString()).ToList()<% + } else { + if (attribute.required) { + -%> map["<%- attribute.key %>"].ToString()<% + } else { + -%> map["<%- attribute.key %>"]?.ToString()<% + } + } + // UNKNOWN + } else { + -%> null <% + } + -%><% if (index < collection.attributes.length - 1) { %>,<% } %> +<% } -%> + ); + } + + public Dictionary ToMap() + { + return new Dictionary + { +<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%> + { "<%= attribute.key %>",<% + // ENUM + if (attribute.format === 'enum') { + if (attribute.array) { + -%> <%= toPascalCase(attribute.key) %>?.Select(e => e.ToString()).ToList()<% + } else { + -%> <%= toPascalCase(attribute.key) %>?.ToString()<% + } + // RELATIONSHIP + } else if (attribute.type === 'relationship') { + if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany' || attribute.array) { + -%> <%= toPascalCase(attribute.key) %>?.Select(e => e.ToMap()).ToList()<% + } else { + -%> <%= toPascalCase(attribute.key) %>?.ToMap()<% + } + // OTHER + } else { + -%> <%= toPascalCase(attribute.key) %><% + } + -%> }<% if (index < collection.attributes.length - 1) { %>,<% } %> +<% } -%> + }; + } +} +} +`; + } + + getFileName(collection) { + return LanguageMeta.toPascalCase(collection.name) + ".cs"; + } +} + +module.exports = { CSharp }; From 89882a22314b8d36099241aa3e0cc61689beaf03 Mon Sep 17 00:00:00 2001 From: Fellmonkey <90258055+Fellmonkey@users.noreply.github.com> Date: Thu, 31 Jul 2025 12:16:31 +0300 Subject: [PATCH 2/4] Remove redundant using directive in C# template --- templates/cli/lib/type-generation/languages/csharp.js.twig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/templates/cli/lib/type-generation/languages/csharp.js.twig b/templates/cli/lib/type-generation/languages/csharp.js.twig index 953ec4b70..2c27b8adb 100644 --- a/templates/cli/lib/type-generation/languages/csharp.js.twig +++ b/templates/cli/lib/type-generation/languages/csharp.js.twig @@ -54,11 +54,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; -<% for (const attribute of collection.attributes) { -%> -<% if (attribute.type === 'relationship') { -%> -using Appwrite.Models; -<% } -%> -<% } %> + namespace Appwrite.Models { <% for (const attribute of collection.attributes) { -%> From 99b4ba41250374ea02adcb1e63e102c90ea4fd44 Mon Sep 17 00:00:00 2001 From: Fellmonkey <90258055+Fellmonkey@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:08:02 +0300 Subject: [PATCH 3/4] Improve C# type generation for required attributes Update C# type generation template to throw ArgumentNullException for missing required int, double, and boolean attributes instead of using default values. Also, corrects the type check from 'float' to 'double' for consistency. --- .../cli/lib/type-generation/languages/csharp.js.twig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/cli/lib/type-generation/languages/csharp.js.twig b/templates/cli/lib/type-generation/languages/csharp.js.twig index 2c27b8adb..aef00bca5 100644 --- a/templates/cli/lib/type-generation/languages/csharp.js.twig +++ b/templates/cli/lib/type-generation/languages/csharp.js.twig @@ -120,21 +120,21 @@ public class <%= toPascalCase(collection.name) %> if (attribute.array) { -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToInt32(e)).ToList()<% } else { - -%> map["<%- attribute.key %>"] != null ? Convert.ToInt32(map["<%- attribute.key %>"]) : (<%- attribute.required ? '0' : 'null' %>)<% + -%> map["<%- attribute.key %>"] != null ? Convert.ToInt32(map["<%- attribute.key %>"]) : <% if (attribute.required) { %>throw new ArgumentNullException("<%- attribute.key %>", "Required attribute '<%- attribute.key %>' was null.")<% } else { %>null<% } %><% } // FLOAT - } else if (attribute.type === 'float') { + } else if (attribute.type === 'double') { if (attribute.array) { -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToDouble(e)).ToList()<% } else { - -%> map["<%- attribute.key %>"] != null ? Convert.ToDouble(map["<%- attribute.key %>"]) : (<%- attribute.required ? '0.0' : 'null' %>)<% + -%> map["<%- attribute.key %>"] != null ? Convert.ToDouble(map["<%- attribute.key %>"]) : <% if (attribute.required) { %>throw new ArgumentNullException("<%- attribute.key %>", "Required attribute '<%- attribute.key %>' was null.")<% } else { %>null<% } %><% } // BOOLEAN } else if (attribute.type === 'boolean') { if (attribute.array) { -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToBoolean(e)).ToList()<% } else { - -%> map["<%- attribute.key %>"] != null ? Convert.ToBoolean(map["<%- attribute.key %>"]) : (<%- attribute.required ? 'false' : 'null' %>)<% + -%> map["<%- attribute.key %>"] != null ? Convert.ToBoolean(map["<%- attribute.key %>"]) : <% if (attribute.required) { %>throw new ArgumentNullException("<%- attribute.key %>", "Required attribute '<%- attribute.key %>' was null.")<% } else { %>null<% } %><% } // STRING, DATETIME, EMAIL } else if (attribute.type === 'string' || attribute.type === 'datetime' || attribute.type === 'email') { From 0681707a0682c168ae01abd6abf9626cb81529d9 Mon Sep 17 00:00:00 2001 From: Fellmonkey <90258055+Fellmonkey@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:56:28 +0300 Subject: [PATCH 4/4] Refactor C# type generation for improved mapping Updated integer type mapping from int to long and refactored the From and ToMap methods for C# type generation. The changes improve handling of arrays, enums, relationships, and nullable types, resulting in more concise and robust code generation. --- .../type-generation/languages/csharp.js.twig | 117 +++++++----------- 1 file changed, 45 insertions(+), 72 deletions(-) diff --git a/templates/cli/lib/type-generation/languages/csharp.js.twig b/templates/cli/lib/type-generation/languages/csharp.js.twig index aef00bca5..1df7c7cdb 100644 --- a/templates/cli/lib/type-generation/languages/csharp.js.twig +++ b/templates/cli/lib/type-generation/languages/csharp.js.twig @@ -15,7 +15,7 @@ class CSharp extends LanguageMeta { } break; case AttributeType.INTEGER: - type = "int"; + type = "long"; break; case AttributeType.FLOAT: type = "double"; @@ -87,103 +87,76 @@ public class <%= toPascalCase(collection.name) %> <% } -%> } - public static <%= toPascalCase(collection.name) %> From(Dictionary map) - { - return new <%= toPascalCase(collection.name) %>( + public static <%= toPascalCase(collection.name) %> From(Dictionary map) => new <%= toPascalCase(collection.name) %>( <% for (const [index, attribute] of Object.entries(collection.attributes)) { -%> - <%- toCamelCase(attribute.key) %>:<% + <%- toCamelCase(attribute.key) %>: <% // ENUM if (attribute.format === 'enum') { if (attribute.array) { - -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => (<%- toPascalCase(attribute.key) %>)Enum.Parse(typeof(<%- toPascalCase(attribute.key) %>), e.ToString())).ToList()<% + -%>((IEnumerable)map["<%- attribute.key %>"]).Select(e => Enum.Parse>(e.ToString()!, true)).ToList()<% } else { - if (attribute.required) { - -%> (<%- toPascalCase(attribute.key) %>)Enum.Parse(typeof(<%- toPascalCase(attribute.key) %>), map["<%- attribute.key %>"].ToString())<% - } else { - -%> map["<%- attribute.key %>"] != null ? (<%- toPascalCase(attribute.key) %>)Enum.Parse(typeof(<%- toPascalCase(attribute.key) %>), map["<%- attribute.key %>"].ToString()) : null<% - } + -%>Enum.Parse>(map["<%- attribute.key %>"].ToString()!, true)<% } // RELATIONSHIP } else if (attribute.type === 'relationship') { const relatedClass = toPascalCase(collections.find(c => c.$id === attribute.relatedCollection).name); if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany' || attribute.array) { - -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Models.<%- relatedClass %>.From((Dictionary)e)).ToList()<% + -%>((IEnumerable)map["<%- attribute.key %>"]).Select(it => Models.<%- relatedClass %>.From((Dictionary)it)).ToList()<% } else { - if (attribute.required) { - -%> <%- relatedClass %>.From((Dictionary)map["<%- attribute.key %>"])<% - } else { - -%> map["<%- attribute.key %>"] != null ? <%- relatedClass %>.From((Dictionary)map["<%- attribute.key %>"]) : null<% - } + -%>Models.<%- relatedClass %>.From((Dictionary)map["<%- attribute.key %>"])<% } - // INTEGER - } else if (attribute.type === 'integer') { - if (attribute.array) { - -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToInt32(e)).ToList()<% - } else { - -%> map["<%- attribute.key %>"] != null ? Convert.ToInt32(map["<%- attribute.key %>"]) : <% if (attribute.required) { %>throw new ArgumentNullException("<%- attribute.key %>", "Required attribute '<%- attribute.key %>' was null.")<% } else { %>null<% } %><% + // ARRAY TYPES + } else if (attribute.array) { + if (attribute.type === 'string' || attribute.type === 'datetime' || attribute.type === 'email') { + -%>((IEnumerable)map["<%- attribute.key %>"]).Select(x => x?.ToString())<%- attribute.required ? '.Where(x => x != null)' : '' %>.ToList()!<% + } else if (attribute.type === 'integer') { + -%>((IEnumerable)map["<%- attribute.key %>"]).Select(x => <%- !attribute.required ? 'x == null ? (long?)null : ' : '' %>Convert.ToInt64(x)).ToList()<% + } else if (attribute.type === 'double') { + -%>((IEnumerable)map["<%- attribute.key %>"]).Select(x => <%- !attribute.required ? 'x == null ? (double?)null : ' : '' %>Convert.ToDouble(x)).ToList()<% + } else if (attribute.type === 'boolean') { + -%>((IEnumerable)map["<%- attribute.key %>"]).Select(x => <%- !attribute.required ? 'x == null ? (bool?)null : ' : '' %>(bool)x).ToList()<% } - // FLOAT + // SINGLE VALUE TYPES + } else if (attribute.type === 'integer') { + -%><%- !attribute.required ? 'map["' + attribute.key + '"] == null ? null : ' : '' %>Convert.ToInt64(map["<%- attribute.key %>"])<% } else if (attribute.type === 'double') { - if (attribute.array) { - -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToDouble(e)).ToList()<% - } else { - -%> map["<%- attribute.key %>"] != null ? Convert.ToDouble(map["<%- attribute.key %>"]) : <% if (attribute.required) { %>throw new ArgumentNullException("<%- attribute.key %>", "Required attribute '<%- attribute.key %>' was null.")<% } else { %>null<% } %><% - } - // BOOLEAN + -%><%- !attribute.required ? 'map["' + attribute.key + '"] == null ? null : ' : '' %>Convert.ToDouble(map["<%- attribute.key %>"])<% } else if (attribute.type === 'boolean') { - if (attribute.array) { - -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => Convert.ToBoolean(e)).ToList()<% - } else { - -%> map["<%- attribute.key %>"] != null ? Convert.ToBoolean(map["<%- attribute.key %>"]) : <% if (attribute.required) { %>throw new ArgumentNullException("<%- attribute.key %>", "Required attribute '<%- attribute.key %>' was null.")<% } else { %>null<% } %><% - } - // STRING, DATETIME, EMAIL + -%>(<%- getType(attribute, collections) %>)map["<%- attribute.key %>"]<% } else if (attribute.type === 'string' || attribute.type === 'datetime' || attribute.type === 'email') { - if (attribute.array) { - -%> (map["<%- attribute.key %>"] as IEnumerable)<%- !attribute.required ? '?' : '' %>.Select(e => e.ToString()).ToList()<% - } else { - if (attribute.required) { - -%> map["<%- attribute.key %>"].ToString()<% - } else { - -%> map["<%- attribute.key %>"]?.ToString()<% - } - } - // UNKNOWN + -%>map["<%- attribute.key %>"]<%- !attribute.required ? '?' : '' %>.ToString()<%- attribute.required ? '!' : ''%><% } else { - -%> null <% + -%>default<% } -%><% if (index < collection.attributes.length - 1) { %>,<% } %> <% } -%> - ); - } + ); - public Dictionary ToMap() + public Dictionary ToMap() => new Dictionary() { - return new Dictionary - { <% for (const [index, attribute] of Object.entries(collection.attributes)) { -%> - { "<%= attribute.key %>",<% - // ENUM - if (attribute.format === 'enum') { - if (attribute.array) { - -%> <%= toPascalCase(attribute.key) %>?.Select(e => e.ToString()).ToList()<% - } else { - -%> <%= toPascalCase(attribute.key) %>?.ToString()<% - } - // RELATIONSHIP - } else if (attribute.type === 'relationship') { - if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany' || attribute.array) { - -%> <%= toPascalCase(attribute.key) %>?.Select(e => e.ToMap()).ToList()<% - } else { - -%> <%= toPascalCase(attribute.key) %>?.ToMap()<% - } - // OTHER + { "<%- attribute.key %>", <% + // ENUM + if (attribute.format === 'enum') { + if (attribute.array) { + -%><%= toPascalCase(attribute.key) %>?.Select(e => e.ToString()).ToList()<% } else { - -%> <%= toPascalCase(attribute.key) %><% + -%><%= toPascalCase(attribute.key) %>?.ToString()<% } - -%> }<% if (index < collection.attributes.length - 1) { %>,<% } %> + // RELATIONSHIP + } else if (attribute.type === 'relationship') { + if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany' || attribute.array) { + -%><%= toPascalCase(attribute.key) %>?.Select(e => e.ToMap()).ToList()<% + } else { + -%><%= toPascalCase(attribute.key) %>?.ToMap()<% + } + // OTHER + } else { + -%><%= toPascalCase(attribute.key) %><% + } + -%> }<% if (index < collection.attributes.length - 1) { %>,<% } %> <% } -%> - }; - } + }; } } `;