Flynk.AutoGen.CS2TS
1.6.2
Prefix Reserved
See the version list below for details.
dotnet tool install --global Flynk.AutoGen.CS2TS --version 1.6.2
dotnet new tool-manifest
dotnet tool install --local Flynk.AutoGen.CS2TS --version 1.6.2
#tool dotnet:?package=Flynk.AutoGen.CS2TS&version=1.6.2
nuke :add-package Flynk.AutoGen.CS2TS --version 1.6.2
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.6.2
Fixed Nested Enum Flattening
Bug fix: Ensured consistent name flattening for nested enums from external assemblies.
Examples:
Status.PublishโStatusPublishโCurrency.CodesโCurrencyCodesโPlatform.TypesโPlatformTypesโ
What was fixed:
- Enhanced enum handling to properly flatten nested enum names from referenced assemblies
- Added fallback metadata name parsing for edge cases where Roslyn's
ContainingTypemight be null - Improved consistency between import collection and type conversion
This ensures that nested enums from external projects (like Core utils) are properly flattened to match TypeScript dependency definitions.
Previous Features (v1.6.0)
Optional BaseAPI Inheritance: BaseAPI is now completely optional and configurable. Specify your own base class or omit it entirely for standalone API classes.
Fixed skipImports for Generic Types: skipImports now properly works for generic return types like Response<T> and PagedList<T>.
Previous Features (v1.5.0)
- Nested Data Class Detection: Automatically generates all nested data classes
- Automatic Type Resolution: Scans TypeScript dependencies to auto-resolve imports
- Assembly-Level Filtering: Only generates types from specified projects
- Better Error Messages: Clear warnings for duplicate method names
- Graceful Degradation: Continues generation even when controllers fail validation
โจ 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:
- Scanning Phase: At startup, the generator scans all configured TypeScript dependency projects
- Indexing: Extracts all exported types (interfaces, classes, enums, types) and their file paths
- Resolution: When generating code, automatically resolves import paths for any referenced types
- 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
UserDTOin generated DTOs โ imports from'../dtos/user-dto' - Finds
Responsein Base dependency โ imports from'@/base.apps.web.shared/types/common-dtos/response' - Finds
PagedListin Base dependency โ imports from'@/base.apps.web.shared/types/common-dtos/paged-list' - Finds
IRequestConfigin 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"
# Optional: API base class configuration (new in v1.6.0)
apiBaseClass: "BaseAPI" # Base class name (omit for no inheritance)
apiBaseClassImportPath: "../base-api" # Import path (only used if apiBaseClass is set)
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.
๐ Links
Made with โค๏ธ by Flynk
| Product | Versions 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. |
This package has no dependencies.