SwaggerToTypeScript 1.8.1

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global SwaggerToTypeScript --version 1.8.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 SwaggerToTypeScript --version 1.8.1
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=SwaggerToTypeScript&version=1.8.1
                    
nuke :add-package SwaggerToTypeScript --version 1.8.1
                    

Swagger To TypeScript

这是一个从 Swagger 生成 TypeScript 模型和请求的简单工具。

  • 支持控制器生成 TypeScript 模型
  • 支持控制器生成 TypeScript 请求
  • 支持生成 TypeScript 枚举,当描述为 name = value 时,自动转换为 TS 枚举 → export enum EName { name = value }
  • 支持自定义上传请求,例如:-upload uploadRequest
  • 自动忽略匿名 AnonymousType 类型
  • 自动忽略无控制器的路由,例如:/health/

安装

dotnet tool install -g SwaggerToTypeScript

升级

dotnet tool update -g SwaggerToTypeScript

使用

# 快速使用
SwaggerToTypeScript -url http://localhost:5007/swagger/v1/swagger.json

# 自定义输出目录、名称和命名空间
SwaggerToTypeScript -url http://localhost:5007/swagger/v1/swagger.json -output ./src/api/ -filename model.ts -namespace '@/utils/request'

# 自定义上传请求
SwaggerToTypeScript -url http://localhost:5007/swagger/v1/swagger.json -upload uploadRequest

前端项目 package.json 中添加脚本,方便调用,例如:npm cun api

{
  "scripts": {
    "dev": "vite",
    "api": "SwaggerToTypeScript -url http://192.168.18.100:2601/swagger/v1/swagger.json -output ./src/api/ -filename index.ts -namespace '@/utils/request'"
  },
}

参数

-url                      Swagger Url
-filename                 文件名,默认:model.ts
-output                   保存路径,默认:当前执行目录
-namespace                request 命名空间,默认:@/utils/request
-upload                   upload 自定义上传请求,默认:无,示例:-upload uploadRequest

发布

发布到 newget.org

发布后,将 Release 目录下的 newgut.1.1.0.nupkg 上传到 newget.org

dotnet pack -c Release
dotnet nuget push ./bin/Release/SwaggerToTypeScript.1.1.0.nupkg -k xxx -s https://api.nuget.org/v3/index.json

dotnet pack --configuration Release
dotnet nuget push bin/Release/newgut.1.1.0.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json

注意

EnumSchemaFilter Swagger 枚举类型转换为字符串

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc(name, new OpenApiInfo { Title = title, Version = version });

    // 添加 Swagger EnumSchemaFilter 过滤器
    c.SchemaFilter<EnumSchemaFilter>();
});

/// <summary>
/// Swagger 枚举类型转换为字符串
/// </summary>
public class EnumSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            schema.Type = "string";

            schema.Enum = new List<IOpenApiAny>();

            foreach (Enum enumValue in Enum.GetValues(context.Type))
            {
                var description = enumValue.GetDescription();

                var v = new OpenApiString($"/** {description?.Replace("\r\n", "\r\n * ")} */\r\n{enumValue} = {Convert.ToInt32(enumValue)}");
                schema.Enum.Add(v);
            }
        }
    }
}

requst.ts 需要自行实现。

示例

import type { AxiosError, InternalAxiosRequestConfig } from 'axios'
import axios from 'axios'
import { showFailToast, showNotify } from 'vant'
import { localStorage } from '@/utils/local-storage'
import { STORAGE_TOKEN_KEY } from '@/stores/mutation-type'

// 这里是用于设定请求后端时,所用的 Token KEY
// 可以根据自己的需要修改,常见的如 Access-Token,Authorization
// 需要注意的是,请尽量保证使用中横线`-` 来作为分隔符,
// 避免被 nginx 等负载均衡器丢弃了自定义的请求头
export const REQUEST_TOKEN_KEY = 'Authorization'

const getApi = () => {
  const host = process.env.VUE_APP_API_BASE_URL;
  return host;
}

// 创建 axios 实例
const request = axios.create({
  // API 请求的默认前缀
  baseURL: getApi(),
  timeout: 6000 * 10, // 请求超时时间
})

// 创建上传 axios 实例
const uploadRequest = axios.create({
  baseURL: getUploadApiURL(),
  timeout: 6000 * 100, // 请求超时时间
})

export type RequestError = AxiosError<{
  message?: string
  result?: any
  errorMessage?: string
  code?: number;
  success?: boolean;
}>

// 异常拦截处理器
const errorHandler = (error: RequestError): Promise<any> => {
  if (error.response) {
    const { data = {}, status, statusText } = error.response

    // 异常错误提示
    const { code, success, message } = data;
    if (success === false && code !== 0) {
      showFailToast(message);
    }

    // 403 无权限
    if (status === 403) {
      showNotify({
        type: 'danger',
        message: (data && data.message) || statusText,
      })
    }
    // 401 未登录/未授权
    if (status === 401 && data.result && data.result.isLogin) {
      showNotify({
        type: 'danger',
        message: 'Authorization verification failed',
      })
      // 如果你需要直接跳转登录页面
      // location.replace(loginRoutePath)
    }
  }
  return Promise.reject(error)
}

// 请求拦截器
const requestHandler = (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig> => {
  const savedToken = localStorage.get(STORAGE_TOKEN_KEY)
  // 如果 token 存在
  // 让每个请求携带自定义 token, 请根据实际情况修改
  if (savedToken)
    config.headers[REQUEST_TOKEN_KEY] = 'Bearer ' + savedToken

  return config
}

// Add a request interceptor
request.interceptors.request.use(requestHandler, errorHandler)

// 响应拦截器
const responseHandler = (response: { data: any }) => {

  // 错误的时候返回
  const { data } = response;
  if (!data) {
    // return '[HTTP] Request has no return value';
    throw new Error('请求失败');
  }
  //  这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
  const { code, result, data: resultData, message } = data;

  // 判断 data 是不是对象,如果不是则返回
  if (typeof data !== 'object' || data === null || Array.isArray(data)) {
    return data;
  }

  // 这里进行特殊拦截,用于判断是否存在 code 和 data 如果不存在,则直接返回所有值,目前用于接口上传
  if (data && !Reflect.has(data, 'code') && !Reflect.has(data, 'data')) {
    return data;
  }

  // 这里逻辑可以根据项目进行修改
  const hasSuccess = data && Reflect.has(data, 'code') && code === 0;
  if (hasSuccess) {
    return result ?? resultData;
  }
  else if (message) {
    showFailToast(message);
    throw new Error('请求失败');
  }

  // 自定义错误编码处理
  if (code == 401) {
    // const userStore = useUserStoreWithOut();
    // userStore.logout(true);
  }

  return response.data
}

// Add a response interceptor
request.interceptors.response.use(responseHandler, errorHandler)

uploadRequest.interceptors.request.use(requestHandler, errorHandler)
uploadRequest.interceptors.response.use(responseHandler, errorHandler)

export default request
export { uploadRequest }

输出结果示例

/* tslint:disable */
/* eslint-disable */

//----------------------
// <auto-generated>
//     自动生成 Swagger To TypeScript v1.0.0
// </auto-generated>
//----------------------

import request from '@/utils/request';

/**
 * 网页设计器 2.0(platform:91xuanxiao、91goodschool,默认:91xuanxiao)
 */
namespace DesignerApi {

    /**
     * 组件 - 列表
     */
    export const components = (platform: string): Promise<WebDesignerComponentInfo[]> => {
        return request.get(`/api/designer/${platform}/components`);
    };

    /**
     * 组件 - 属性
     */
    export const componentProperties = (platform: string): Promise<ComponentPropertiesResponse> => {
        return request.get(`/api/designer/${platform}/component-properties`);
    };

    /**
     * 机构 - 详情
     */
    export const agencyGet = (platform: string): Promise<WebDesignerAgencyInfo> => {
        return request.get(`/api/designer/${platform}/agency`);
    };

    /**
     * 机构 - 更新
     * @returns OK
     */
    export const agencyPost = (platform: string) => {
        return request.post(`/api/designer/${platform}/agency`);
    };

    /**
     * 上传 - 快速上传
     * @returns OK
     */
    export const upload = (platform: string, file: String) => {
        return request.post(`/api/designer/${platform}/upload`, { file });
    };

    /**
     * 获取机构跳转数据
     */
    export const agencyData = (platform: string, agencyId: string): Promise<XuanXiaoHomeIndex> => {
        return request.get(`/api/designer/${platform}/agency-data/${agencyId}`);
    };

}

export { DesignerApi, EntryApi, HomeApi, OpenApi, SchoolApi, TestApi, TokenApi, UploadApi };

/**
 * 资讯
 */
export interface XuanXiaoNews {
    /**
     * 资讯ID
     */
    id?: number | undefined;
    /**
     * 标题
     */
    title?: string | undefined;
    /**
     * 发布时间
     */
    time?: string | undefined;
    /**
     * 配图
     */
    pic?: string | undefined;
    /**
     * 描述
     */
    desc?: string | undefined;
    /**
     * 地址
     */
    url?: string | undefined;
}

/**
 * 简介组件 01 - 配图方式
 */
export enum EIntroduction01MediaType {
    /** 图片 */
    图片 = 0,
    /** 视频 */
    视频 = 1,
    /** 轮播 */
    轮播 = 2,
}

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.9.1 109 7/17/2025
1.9.0 180 4/10/2025
1.8.1 174 4/8/2025
1.8.0 166 4/8/2025
1.7.1 172 4/8/2025
1.7.0 119 2/27/2025
1.6.0 117 2/9/2025
1.5.0 118 2/9/2025
1.3.0 119 2/9/2025
1.2.0 116 2/5/2025
1.1.5 123 2/5/2025
1.1.4 114 2/5/2025
1.1.3 115 2/5/2025