Flynk.AutoGen.CS2TS 1.5.1

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global Flynk.AutoGen.CS2TS --version 1.5.1
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Flynk.AutoGen.CS2TS --version 1.5.1
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Flynk.AutoGen.CS2TS&version=1.5.1
                    
nuke :add-package Flynk.AutoGen.CS2TS --version 1.5.1
                    

Flynk.AutoGen.CS2TS

Automatic TypeScript code generation from C# using Roslyn

Generate clean, type-safe TypeScript interfaces, enums, and API clients directly from your C# codebase. Perfect for maintaining consistency between your backend and frontend without manual synchronization.

๐Ÿ†• What's New in v1.5.0

Nested Data Class Detection

Automatically generates all nested data classes! The generator now detects and generates nested classes used in DTOs and Requests, even if they don't follow standard naming conventions.

What's detected:

  • Classes ending with Data (e.g., ModelSpaceOrderData, LinkedObjectData)
  • Any public class in a .DTO namespace
  • Nested classes like AddObjectSchemaToSpaceSchema

Before (v1.4.x):

โŒ ERROR: Cannot resolve the following types:
  โ€ข ModelSpaceOrderData
  โ€ข LinkedObjectData
  โ€ข QueryOrderData
  โ€ข AddObjectSchemaToSpaceSchema

After (v1.5.0):

Found: 100 DTOs, 98 Requests, 47 Enums, 14 Controllers
โœ… TypeScript generation completed successfully!

All nested data classes are now automatically generated as DTOs - no manual definitions needed!

Hardcoded BaseAPI Import Path

Simpler configuration! The BaseAPI import path is now hardcoded to use relative paths ('../base-api'), eliminating unnecessary configuration complexity.

Other Improvements

  • Automatic Type Resolution: Scans TypeScript dependencies to auto-resolve imports
  • Assembly-Level Filtering: Only generates types from specified projects, excludes referenced DLLs
  • Better Error Messages: Clear warnings for duplicate method names with suggested fixes
  • Graceful Degradation: Continues generation even when individual controllers fail validation
  • Automatic Cleanup: Removes obsolete files automatically

โœจ Features

  • ๐Ÿš€ Roslyn-based Analysis - Direct C# source code analysis, no reflection needed
  • ๐Ÿ“ YAML Configuration - Simple, declarative configuration files
  • ๐Ÿ”„ Incremental Updates - Only regenerates changed files
  • ๐Ÿงน Automatic Cleanup - Removes obsolete generated files
  • ๐ŸŽฏ Nested Enum Support - Correctly handles nested types like Property.DataTypes โ†’ PropertyDataTypes
  • ๐Ÿ” Error Detection - Validates for duplicate method names and circular dependencies
  • ๐Ÿ“ฆ Repository-Specific - Each TypeScript repo maintains its own configuration
  • ๐ŸŽจ Clean Output - Generates readable, formatted TypeScript code
  • ๐Ÿ”— Automatic Type Resolution - Scans TypeScript dependencies to auto-resolve imports (no manual configuration!)
  • โœ… Compile-Safe Output - Ensures all types are resolved so generated TypeScript compiles without errors

๐Ÿ“ฆ Installation

Install as a local .NET tool in your TypeScript project:

# Navigate to your TypeScript repository
cd myproject.common.ts

# Create tool manifest (first time only)
dotnet new tool-manifest

# Install the tool
dotnet tool install Flynk.AutoGen.CS2TS

๐Ÿš€ Quick Start

1. Create Configuration File

Create codegen.config.yaml in your TypeScript repository:

# Project identification
projectName: "My Project"

# C# Source Configuration
source:
  # Path to .sln file (relative to this config file)
  solutionPath: "../MyProject.Server/MyProject.Server.sln"

  # C# projects to include
  includedProjects:
    - "MyProject.Common"
    - "MyProject.Utils"

  # Namespace prefixes to include
  includedNamespaces:
    - "MyProject"

# TypeScript Output Configuration
output:
  basePath: "."
  directories:
    dtos: "dtos"
    requests: "requests"
    enums: "enums"
    apis: "api"

# Type Mapping Configuration
typeMapping:
  # TypeScript dependency projects for automatic type resolution
  typeScriptDependencies:
    # Base shared types (Response, PagedList, IRequestConfig, etc.)
    - name: "Base Shared"
      path: "../Base/base.apps.web.shared"
      importPrefix: "@/base.apps.web.shared"
      includePatterns:
        - "**/*.ts"
      excludePatterns:
        - "node_modules/**"
        - "**/*.spec.ts"
        - "**/*.test.ts"

  # Types to skip GENERATION for (exist in dependencies)
  skipTypes:
    - "Response"
    - "PagedList"
    - "IRequestConfig"

  # Types to skip IMPORTS for (globally available/mapped to primitives)
  skipImports:
    - "Guid"
    - "JToken"

# Generation Options
generation:
  skipNavigationProperties: true
  skipControllers:
    - "BaseController"
  skipCleanup:
    - "base.ts"
    - "index.ts"

2. Run Code Generation

# Simple generation
dotnet cs2ts --config codegen.config.yaml

# With verbose output
dotnet cs2ts --config codegen.config.yaml --verbose

# Hard reset (delete all outputs first)
dotnet cs2ts --config codegen.config.yaml --hard-reset

# Generate only specific project
dotnet cs2ts --config codegen.config.yaml --project "MyProject.Common"

๐Ÿ“‹ What Gets Generated?

From your C# code:

namespace MyProject.Common.DTO
{
    public class UserDTO
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public UserStatus Status { get; set; }
        public DateTime CreatedAt { get; set; }
    }

    public enum UserStatus
    {
        Active = 1,
        Inactive = 2,
        Suspended = 3
    }
}

Generates TypeScript:

dtos/user-dto.ts:

// Auto-generated from UserDTO
import { UserStatus } from '../enums/user-status'

export interface UserDTO {
    id: string
    name: string
    email: string
    status: UserStatus
    createdAt: string
}

enums/user-status.ts:

// Auto-generated from UserStatus
export enum UserStatus {
    Active = 1,
    Inactive = 2,
    Suspended = 3,
}

๐Ÿ”ง CLI Options

Execution Scope (NOT Configuration)

All project configuration goes in YAML. CLI options control execution:

  • --config, -c <path> - Path to codegen.config.yaml
  • --hard-reset, -r - Delete all output directories before generation
  • --project, -p <name> - Generate only for specific project (overrides config)
  • --namespace, -n <name> - Generate only for specific namespace (overrides config)
  • --verbose, -v - Enable verbose logging
  • --help, -h - Show help message

๐Ÿ“ Type Conversion

C# Type TypeScript Type
int, long, decimal, double number
string, Guid, DateTime string
bool boolean
List<T>, T[] T[]
Dictionary<K,V> Record<K, V>
Task<Response<T>> Promise<Response<T>>
Custom DTO Imported interface
Enum Imported enum

๐ŸŽฏ Use Cases

Backend + Frontend Sync

Keep your TypeScript frontend in perfect sync with your C# backend API models.

Multiple Microservices

Generate TypeScript clients for multiple C# services, each with its own configuration.

Shared Libraries

Generate TypeScript definitions from shared C# libraries for consistent types across projects.

๐Ÿ”„ Workflow Integration

Development Script

Create generate-typescript.sh:

#!/bin/bash
set -e

cd "$(dirname "${BASH_SOURCE[0]}")"

echo "Generating TypeScript from C#..."
dotnet cs2ts --config codegen.config.yaml

echo "โœ… Generation complete!"

CI/CD Integration

# GitHub Actions example
- name: Install CS2TS
  run: dotnet tool restore

- name: Generate TypeScript
  run: dotnet cs2ts --config codegen.config.yaml

- name: Check for changes
  run: git diff --exit-code || echo "TypeScript definitions updated"

๐Ÿ“š Configuration Reference

Source Configuration

source:
  solutionPath: "../path/to/solution.sln"  # Required
  includedProjects:                        # Required
    - "Project1"
    - "Project2"
  includedNamespaces:                      # Required
    - "MyNamespace"
    - "MyOtherNamespace"

Output Configuration

output:
  basePath: "."                            # Default: current directory
  directories:
    dtos: "dtos"                          # Default: "dtos"
    requests: "requests"                  # Default: "requests"
    enums: "enums"                        # Default: "enums"
    apis: "api"                           # Default: "api"

Type Mapping & Automatic Import Resolution

๐ŸŽฏ New in v1.2.0: Automatic type resolution from TypeScript dependencies!

Instead of manually configuring imports for every type, the generator automatically scans your TypeScript dependency projects and resolves imports for you.

typeMapping:
  # TypeScript dependency projects for automatic type resolution
  typeScriptDependencies:
    # Example: Base shared types
    - name: "Base Shared"                    # Friendly name for logging
      path: "../Base/base.apps.web.shared"   # Path to TypeScript project
      importPrefix: "@/base.apps.web.shared" # Import path prefix
      includePatterns:                       # Files to scan (optional)
        - "**/*.ts"
      excludePatterns:                       # Files to ignore (optional)
        - "node_modules/**"
        - "**/*.spec.ts"
        - "**/*.test.ts"

    # Example: Project-specific manual types
    - name: "Manual Types"
      path: "./manual"                       # Relative to config file
      importPrefix: "../manual"
      includePatterns:
        - "**/*.ts"

  # Types to skip GENERATION for (don't create TypeScript files)
  # These types exist elsewhere (in dependencies or manually defined)
  # They WILL be imported if found in TypeScript dependencies
  skipTypes:
    - "Response"      # Exists in Base - will auto-import
    - "PagedList"     # Exists in Base - will auto-import
    - "IRequestConfig"  # Exists in Base - will auto-import

  # Types to skip IMPORTS for (don't add import statements)
  # Use this for globally available types that don't need imports
  skipImports:
    - "Guid"         # Mapped to string, no import needed
    - "JToken"       # Mapped to any, no import needed

How it works:

  1. Scanning Phase: At startup, the generator scans all configured TypeScript dependency projects
  2. Indexing: Extracts all exported types (interfaces, classes, enums, types) and their file paths
  3. Resolution: When generating code, automatically resolves import paths for any referenced types
  4. Validation: Warns if a type cannot be resolved, helping catch configuration issues

Example:

Your C# code returns Response<UserDTO> and PagedList<UserDTO>:

public Task<Response<UserDTO>> GetUser(Guid id);
public Task<Response<PagedList<UserDTO>>> GetUsers();

The generator:

  • Finds UserDTO in generated DTOs โ†’ imports from '../dtos/user-dto'
  • Finds Response in Base dependency โ†’ imports from '@/base.apps.web.shared/types/common-dtos/response'
  • Finds PagedList in Base dependency โ†’ imports from '@/base.apps.web.shared/types/common-dtos/paged-list'
  • Finds IRequestConfig in Base dependency โ†’ imports from '@/base.apps.web.shared/api/engyn-requests-refactored'

Result:

import { Response } from '@/base.apps.web.shared/types/common-dtos/response'
import { PagedList } from '@/base.apps.web.shared/types/common-dtos/paged-list'
import { IRequestConfig } from '@/base.apps.web.shared/api/engyn-requests-refactored'
import { UserDTO } from '../dtos/user-dto'

export default class UserAPI extends BaseAPI {
  public getUser = (id: string, config?: IRequestConfig): Promise<Response<UserDTO>> => {
    return this.request.get(`/user?id=${id}`, config)
  }

  public getUsers = (config?: IRequestConfig): Promise<Response<PagedList<UserDTO>>> => {
    return this.request.get(`/users`, config)
  }
}

All imports are resolved automatically - no manual configuration needed!

Generation Options

generation:
  skipNavigationProperties: true          # Avoid circular dependencies
  skipControllers:
    - "BaseController"                   # Controllers to skip
  skipCleanup:
    - "base.ts"                          # Files to preserve during cleanup
    - "index.ts"

Git Integration (Optional)

git:
  autoCommit: false                       # Auto-commit generated changes
  autoPush: false                         # Auto-push after commit
  commitMessage: "Update TypeScript definitions from C# code"

๐Ÿ› ๏ธ Advanced Usage

Multiple Repositories

Each TypeScript repository should have its own configuration:

MyProject/
โ”œโ”€โ”€ backend/
โ”‚   โ””โ”€โ”€ MyProject.sln
โ”œโ”€โ”€ frontend-web/
โ”‚   โ”œโ”€โ”€ codegen.config.yaml      # Config for web frontend
โ”‚   โ””โ”€โ”€ .config/
โ”‚       โ””โ”€โ”€ dotnet-tools.json
โ””โ”€โ”€ frontend-mobile/
    โ”œโ”€โ”€ codegen.config.yaml      # Config for mobile frontend
    โ””โ”€โ”€ .config/
        โ””โ”€โ”€ dotnet-tools.json

Filtering During Execution

Override configuration temporarily:

# Generate only Core project
dotnet cs2ts -c codegen.config.yaml -p "MyProject.Core"

# Generate only specific namespace
dotnet cs2ts -c codegen.config.yaml -n "MyProject.Admin"

๐Ÿค Contributing

Issues and pull requests are welcome. Just reach out @ Flynk Support.

๐Ÿ“„ License

See LICENSE.txt for details.


Made with โค๏ธ by Flynk

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.6.3 209 10/25/2025
1.6.2 209 10/24/2025
1.6.1 217 10/23/2025
1.6.0 218 10/22/2025
1.5.1 211 10/22/2025
1.5.0 217 10/22/2025
1.4.0 216 10/21/2025
1.2.0 223 10/20/2025
1.0.1 206 10/20/2025
1.0.0 226 10/20/2025