Skip to content

Adding C# to CLI type generation #1135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

Fellmonkey
Copy link
Contributor

@Fellmonkey Fellmonkey commented Jul 30, 2025

What does this PR do?

adding the C# language to CLI type generation

Supports generation for Unity, i.e. C# 9.0

Test Plan

config

    "collections": [
        {
            "$id": "6888d7fa000356c213fe",
            "$permissions": [],
            "databaseId": "6888d7dd001f35bf501b",
            "name": "Library",
            "enabled": true,
            "documentSecurity": false,
            "attributes": [
                {
                    "key": "book",
                    "type": "string",
                    "required": true,
                    "array": false,
                    "size": 128,
                    "default": null,
                    "encrypt": false
                },
                {
                    "key": "genre",
                    "type": "string",
                    "required": false,
                    "array": false,
                    "size": 56,
                    "default": null,
                    "encrypt": false
                },
                {
                    "key": "category",
                    "type": "string",
                    "required": false,
                    "array": false,
                    "size": 35,
                    "default": null,
                    "encrypt": false
                },
                {
                    "key": "size",
                    "type": "integer",
                    "required": false,
                    "array": false,
                    "min": -9223372036854775808,
                    "max": 9223372036854775807,
                    "default": null
                },
                {
                    "key": "badge",
                    "type": "string",
                    "required": false,
                    "array": true,
                    "size": 128,
                    "default": null,
                    "encrypt": false
                },
                {
                    "key": "last_upd",
                    "type": "datetime",
                    "required": false,
                    "array": false,
                    "format": "",
                    "default": null
                },
                {
                    "key": "state",
                    "type": "string",
                    "required": false,
                    "array": false,
                    "elements": [
                        "new",
                        "old",
                        "use"
                    ],
                    "format": "enum",
                    "default": "new"
                },
                {
                    "key": "gnom",
                    "type": "relationship",
                    "required": false,
                    "array": false,
                    "relatedCollection": "6888d8e00000019db392",
                    "relationType": "oneToMany",
                    "twoWay": false,
                    "twoWayKey": "6888d9140016fab32d21",
                    "onDelete": "cascade",
                    "side": "parent"
                }
            ],
            "indexes": []
        },
        {
            "$id": "6888d8e00000019db392",
            "$permissions": [],
            "databaseId": "6888d7dd001f35bf501b",
            "name": "gnom",
            "enabled": true,
            "documentSecurity": false,
            "attributes": [
                {
                    "key": "isStupid",
                    "type": "boolean",
                    "required": false,
                    "array": false,
                    "default": false
                }
            ],
            "indexes": []
        }
    ]

result:

Library

/// This file is auto-generated by the Appwrite CLI. 
/// You can regenerate it by running `appwrite types --language cs Test_server_appwrite/Models`.

#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Appwrite.Models;

namespace Appwrite.Models
{

public enum State {
    [JsonPropertyName("new")]
    New,
    [JsonPropertyName("old")]
    Old,
    [JsonPropertyName("use")]
    Use
}

public class Library
{
    [JsonPropertyName("book")]
    public string Book { get; private set; }

    [JsonPropertyName("genre")]
    public string? Genre { get; private set; }

    [JsonPropertyName("category")]
    public string? Category { get; private set; }

    [JsonPropertyName("size")]
    public int? Size { get; private set; }

    [JsonPropertyName("badge")]
    public List<string>? Badge { get; private set; }

    [JsonPropertyName("last_upd")]
    public string? LastUpd { get; private set; }

    [JsonPropertyName("state")]
    public State? State { get; private set; }

    [JsonPropertyName("gnom")]
    public List<Gnom>? Gnom { get; private set; }


    public Library(
        string book,
        string? genre,
        string? category,
        int? size,
        List<string>? badge,
        string? lastUpd,
        State? state,
        List<Gnom>? gnom
    )
    {
        Book = book;
        Genre = genre;
        Category = category;
        Size = size;
        Badge = badge;
        LastUpd = lastUpd;
        State = state;
        Gnom = gnom;
    }

    public static Library From(Dictionary<string, object> map)
    {
        return new Library(
            book: map["book"].ToString(),
            genre: map["genre"]?.ToString(),
            category: map["category"]?.ToString(),
            size: map["size"] != null ? Convert.ToInt32(map["size"]) : (null),
            badge: (map["badge"] as IEnumerable<object>)?.Select(e => e.ToString()).ToList(),
            lastUpd: map["last_upd"]?.ToString(),
            state: map["state"] != null ? (State)Enum.Parse(typeof(State), map["state"].ToString()) : null,
            gnom: (map["gnom"] as IEnumerable<object>)?.Select(e => Models.Gnom.From((Dictionary<string, object>)e)).ToList()
        );
    }

    public Dictionary<string, object?> ToMap()
    {
        return new Dictionary<string, object?>
        {
            { "book", Book },
            { "genre", Genre },
            { "category", Category },
            { "size", Size },
            { "badge", Badge },
            { "last_upd", LastUpd },
            { "state", State?.ToString() },
            { "gnom", Gnom?.Select(e => e.ToMap()).ToList() }
        };
    }
}
}

Gnom

/// This file is auto-generated by the Appwrite CLI. 
/// You can regenerate it by running `appwrite types --language cs Test_server_appwrite/Models`.

#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;

namespace Appwrite.Models
{

public class Gnom
{
    [JsonPropertyName("isStupid")]
    public bool? IsStupid { get; private set; }


    public Gnom(
        bool? isStupid
    )
    {
        IsStupid = isStupid;
    }

    public static Gnom From(Dictionary<string, object> map)
    {
        return new Gnom(
            isStupid: map["isStupid"] != null ? Convert.ToBoolean(map["isStupid"]) : (null)
        );
    }

    public Dictionary<string, object?> ToMap()
    {
        return new Dictionary<string, object?>
        {
            { "isStupid", IsStupid }
        };
    }
}
}

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

Yes

@Fellmonkey
Copy link
Contributor Author

Copilot answer:

This pull request introduces support for generating C# types in the Appwrite CLI. The changes include adding a new language option ("cs") for type generation, implementing the logic for handling C# attributes and collections, and updating related files to integrate C# into the CLI workflow.

Addition of C# Type Generation:

  • C# Language Support in Type Generation:
    • Added a new class CSharp in templates/cli/lib/type-generation/languages/csharp.js.twig to handle type generation logic for C#. This includes mapping attribute types to C# types, handling relationships, enums, arrays, and nullable types, and generating C# model files.

Integration with CLI Workflow:

  • CLI Language Options Update:

    • Updated templates/cli/lib/commands/types.js.twig to include "cs" as a valid language option for type generation. This includes adding "cs" to the list of choices for the typesLanguageOption and handling "cs" in the createLanguageMeta function. [1] [2]
  • C# Language Import:

    • Added an import statement for the CSharp class in templates/cli/lib/commands/types.js.twig.

File Configuration Updates:

  • File Mapping for C# Type Generation:
    • Updated src/SDK/Language/CLI.php to include the destination and template paths for C# type generation files.

@Fellmonkey Fellmonkey marked this pull request as ready for review July 30, 2025 15:36
@ChiragAgg5k ChiragAgg5k requested a review from Copilot July 31, 2025 06:29
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds C# language support to the Appwrite CLI type generation functionality, enabling developers to generate C# classes from Appwrite database collections. The implementation supports C# 9.0 features and is designed to work with Unity projects.

  • Adds complete C# type generation with support for all Appwrite attribute types including relationships, enums, and arrays
  • Integrates C# as a new language option ("cs") in the CLI command interface
  • Includes proper nullable reference types, JSON serialization attributes, and conversion methods

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
templates/cli/lib/type-generation/languages/csharp.js.twig Implements the core C# code generation logic with type mapping, template rendering, and file naming
templates/cli/lib/commands/types.js.twig Adds C# language support to the CLI command with import and language selection
src/SDK/Language/CLI.php Registers the C# template file in the SDK file generation configuration

@ChiragAgg5k ChiragAgg5k self-requested a review July 31, 2025 06:30
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.
@Fellmonkey
Copy link
Contributor Author

before:
{89E78171-C6C0-4EB8-BC7D-52AE80834E4C}

after:
{6E28F230-AFC9-478A-B940-C34F27D7AF9C}

There is also a bug in Dart (wrong type check).
{27301A9E-DAC0-41F1-A9D9-F91BC0B5DEE8}

@Fellmonkey Fellmonkey marked this pull request as draft July 31, 2025 13:03
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.
@Fellmonkey Fellmonkey marked this pull request as ready for review August 2, 2025 13:07
@Fellmonkey
Copy link
Contributor Author

Removed throwing exceptions, since the required parameters will be requested by the compiler anyway. And if you create a dictionary in a strange way and write down the necessary model, an appwrite exception will be thrown. So this is unnecessary.
{15E63DE3-23A6-4AE5-9938-D0E257E5E562}

@ChiragAgg5k
Copy link
Member

@Fellmonkey just out of curiosity, would you mind sharing your linkedin? i dont see one connected to your github account

@Fellmonkey
Copy link
Contributor Author

Hi, @ChiragAgg5k
Thanks to you, I created an account on LinkedIn.
I left the link in my GitHub profile. When I have time, I'll set up my profile there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants