- 开发工具
- 代码生成
- API设计
【免费下载链接】swagger-codegen
swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
本篇技术指南以 swagger-codegen 仓库中 TypeScript Angular 集成测试的预期输出 README 为核心骨架,讲解由 OpenAPI/Swagger 定义自动生成的 TypeScript Angular(Angular 2)客户端 npm 包的完整生命周期:本地构建、发布到 npm、在业务项目中安装消费,以及如何在应用引导阶段覆盖服务的 base path。读完本文,你将掌握生成客户端包从构建到上线的完整操作流程,并能结合仓库源码理解数组与内嵌对象模型在 TypeScript 中的实际映射结果。
背景:这份 README 从何而来
array-and-object-expected/是 swagger-codegen 集成测试(integration test)目录integrationtests/typescript下的"期望输出"(expected output)资源之一。测试过程大致为:以 array-and-object-spec.json(一个模拟 Cupix API 的 Swagger 2.0 定义)为输入,运行 TypeScript Angular 客户端生成器(TypeScriptAngularClientCodegen,位于modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/),把生成结果与array-and-object-expected/目录逐一对比校验。
该测试资源的兄弟目录还包括petstore-expected/、additional-properties-expected/、node-es5-expected/,分别对应不同类型的生成验证场景。因此,这份 README 不只是普通说明文档,它本身也是测试断言体系的一部分,其中的构建、发布、消费命令与真实生成产物(package.json、api/、model/等)严格一致。
生成包的名称为arrayAndAnyTest,版本号为1.0.2,对应 npm 包标识arrayAndAnyTest@1.0.2。
生成产物的目录结构
在动手构建之前,先了解生成包内各文件的分工。以array-and-object-expected/目录为例:
| 路径 | 作用 |
|---|---|
| package.json | npm 包元数据,含名称、版本、构建脚本与 Angular 2 依赖 |
| tsconfig.json | TypeScript 编译配置(target es5、module commonjs、声明文件输出) |
| index.ts | 包入口,统一导出 api、model、配置与模块 |
| api/api.ts | API 汇总导出 |
| api/project.service.ts | 具体服务:封装 HTTP 调用(create/delete/get/update Project) |
| model/models.ts | 模型汇总导出 |
| model/projectEntity.ts | ProjectEntity接口(含枚举与内嵌对象) |
| model/projectEntityLocation.ts | 内嵌位置对象接口(lat/lon) |
| model/projectList.ts | ProjectList接口(数组字段 contents) |
| configuration.ts | 全局配置类(apiKey、用户名密码、token、basePath) |
| variables.ts | 定义BASE_PATH注入令牌 |
| api.module.ts | Angular NgModule,声明服务提供者与forConfig工厂 |
| rxjs-operators.ts | 引入 RxJS 操作符 |
| typings.json | typings 依赖声明 |
其中package.json的main指向dist/index.js,typings指向dist/index.d.ts,即构建产物统一输出到dist/目录。
构建:把 TypeScript 源码编译为 JavaScript
生成包的 README 给出了构建步骤,依次执行:
npm install npm run buildnpm install会安装devDependencies中声明的依赖,包括 TypeScript 编译器(typescript: ^2.0.0)、typings 工具(typings: ^1.3.2)以及 Angular 2 相关包(@angular/core、@angular/http、@angular/common、@angular/compiler、@angular/platform-browser,均为^2.0.0)和运行时依赖(core-js、reflect-metadata、rxjs: 5.0.0-beta.12、zone.js)。
构建脚本定义在 package.json 的scripts.build字段中:
"build": "typings install && tsc --outDir dist/"其执行链路为:
typings install:依据typings.json安装 TypeScript 类型定义文件;tsc --outDir dist/:调用 TypeScript 编译器,把tsconfig.json中filesGlob声明的./model/*.ts与./api/*.ts源文件编译为 ES5 JavaScript,输出到dist/目录。
tsconfig.json中值得注意的编译选项包括:target: "es5"(兼容旧浏览器)、module: "commonjs"(CommonJS 模块规范,便于 npm 包被 Node/打包器消费)、declaration: true(同时生成.d.ts类型声明,这正是package.json中typings字段能指向dist/index.d.ts的原因)、experimentalDecorators与emitDecoratorMetadata(Angular 2 依赖装饰器元数据)以及sourceMap: true(便于调试)。
发布:把包推送到 npm registry
构建完成且验证无误后,即可发布:
npm publish发布前请确认:
package.json中的name(arrayAndAnyTest)与version(1.0.2)正确且未被占用;- 已在 npm 完成登录认证(
npm login); - 需要发私有包时,可在生成阶段配置私有仓库地址或
private字段(本文档面向公开发布场景,未涉及该配置)。
消费:在你的 Angular 2 项目中安装依赖
发布后,在消费方项目的根目录执行以下命令即可安装:
npm install arrayAndAnyTest@1.0.2 --save其中--save会把该依赖写入消费方项目的package.json的dependencies中。
对于尚未发布(unPublished)的本地开发场景,README 明确标注了"不推荐(not recommended)"的方式——直接以本地路径安装:
npm install PATH_TO_GENERATED_PACKAGE --save这里的PATH_TO_GENERATED_PACKAGE指生成包的本地绝对或相对路径。不推荐的原因从工程实践看主要有两点:本地路径依赖无法被其他协作者或 CI 环境解析;路径移动即导致依赖失效。因此推荐始终走 registry 发布后按版本号安装。
安装完成后,在 Angular 2 项目中引入该服务。README 在该处保留了TODO: paste example.占位符(原文如此),示意在实际使用中需要粘贴服务注入示例。结合生成产物可补全这一示例:index.ts已统一导出api.module与各服务,因此在 AppModule 中引入ApiModule即可使用ProjectService:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { ApiModule } from 'arrayAndAnyTest'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, ApiModule.forConfig(new ApiModuleConfiguration({})) ], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { }设置服务 base path:覆盖生成时写入的默认地址
生成的ProjectService在构造器中写死了默认 base path(见 project.service.ts):
protected basePath = 'https://localhost/v1';该默认值由源 spec 的schemes(https)、host与basePath(/v1)组合而成。当你的后端服务地址与生成时不同(例如部署到https://your-web-service.com),就需要在应用引导阶段覆盖它。README 给出的做法是利用 Angular 2 的依赖注入令牌:
import { BASE_PATH } from './path-to-swagger-gen-service/index'; bootstrap(AppComponent, [ { provide: BASE_PATH, useValue: 'https://your-web-service.com' }, ]);其中BASE_PATH定义于生成包的 variables.ts:
import { OpaqueToken } from '@angular/core'; export const BASE_PATH = new OpaqueToken('basePath');而ProjectService的构造器通过@Inject(BASE_PATH)接收该令牌的值(project.service.ts#L48-L55):
constructor(protected http: Http, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) { if (basePath) { this.basePath = basePath; } if (configuration) { this.configuration = configuration; this.basePath = basePath || configuration.basePath || this.basePath; } }优先级从源码可以清晰看出:显式注入的basePath参数优先,其次才是configuration.basePath,最后回退到生成时写死的默认值。这解释了为什么在 bootstrap 中提供BASE_PATH即可全局覆盖所有生成服务(同目录下的其他服务构造器遵循同一模式)。
此外,configuration.ts 还提供了Configuration类,可在构造时一次性注入apiKey、username、password、accessToken、basePath等认证与连接参数,并通过 api.module.ts 的ApiModule.forConfig(configuration)提供给整个模块:
@NgModule({ imports: [ CommonModule, HttpModule ], declarations: [], exports: [], providers: [ ProjectService ] }) export class ApiModule { public static forConfig(configuration: Configuration): ModuleWithProviders { return { ngModule: ApiModule, providers: [ {provide: Configuration, useValue: configuration}] } } }源码级佐证:数组与内嵌对象的 TypeScript 映射
测试资源目录名为array-and-object-expected,其核心验证点正是"数组(array)与内嵌对象(object)"在 TypeScript 模型中的正确生成。对照源 spec 与生成产物可完整还原映射规则:
数组字段:源 spec 中ProjectList.contents声明为type: array,items引用#/definitions/ProjectEntity(array-and-object-spec.json#L478-L496)。生成的 projectList.ts 将其映射为Array<ProjectEntity>:
import { ProjectEntity } from './projectEntity'; export interface ProjectList { contents: Array<ProjectEntity>; }由于contents在 spec 的required列表中,因此该字段在接口中不是可选属性。这一映射行为也可由 TypeScriptFetchModelTest.java 等单元测试佐证:ArrayProperty生成的datatype为Array<string>这类形式,baseType为Array。
内嵌对象:源 spec 中ProjectEntity.location是匿名内嵌 object(含lat/lon两个 float 字段,array-and-object-spec.json#L535-L551)。生成器将其抽取为独立的顶层接口ProjectEntityLocation(projectEntityLocation.ts),并作为ProjectEntity.location的类型引用。
任意对象(any)与枚举:meta字段在 spec 中是type: object且无properties,生成器将其映射为any;kind字段带enum: ["project"],映射为命名空间内的KindEnum(见 projectEntity.ts):
export namespace ProjectEntity { export enum KindEnum { Project = <any> 'project' } }命名转换:spec 中的蛇形命名thumbnail_url、created_at等在生成产物中统一转换为驼峰thumbnailUrl、createdAt(projectEntity.ts),且date-time格式的字段映射为Date类型。
这些文件全部位于集成测试的期望输出目录,测试在每次构建时会对生成结果与期望结果做一致性校验,因此它们既是使用文档,也是"生成器行为契约"的一部分。
小结
围绕一份由 swagger-codegen 集成测试派生的 README,本文梳理了 TypeScript Angular 客户端 npm 包的完整交付链路:
- 构建:
npm install && npm run build,底层由typings install && tsc --outDir dist/完成类型定义安装与 ES5 编译; - 发布:
npm publish将arrayAndAnyTest@1.0.2推送到 npm registry; - 消费:
npm install arrayAndAnyTest@1.0.2 --save安装,未发布场景可用本地路径(不推荐); - base path 覆盖:通过
BASE_PATH注入令牌在 bootstrap 阶段提供实际服务地址,优先级为注入值 >Configuration.basePath> 生成默认值。
同时,通过array-and-object-expected/与array-and-object-spec.json的对照,可以直观看到数组字段、内嵌对象、任意对象、枚举与命名规范在 TypeScript 模型中的标准映射方式。若你的生成包结构与上述示例一致,可直接套用本文全部命令;若使用其他语言生成器,构建与发布环节请以对应生成产物中的package.json/构建配置为准。
- 开发工具
- 代码生成
- API设计
【免费下载链接】swagger-codegen
swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
相关推荐
LicenseFinder高级配置指南:自定义许可证规则与决策继承
LicenseFinder高级配置指南:自定义许可证规则与决策继承 LicenseFinder 是一款强大的开源许可证管理工具,它能自动扫描项目依赖并识别许可证
开发工具代码生成API设计终极指南:如何使用Swagger Codegen快速生成TypeScript客户端并集成到Angular与React项目
终极指南:如何使用Swagger Codegen快速生成TypeScript客户端并集成到Angular与React项目 Swagger Codegen是一个强
开发工具代码生成API设计FunClip:基于大语言模型的智能视频剪辑解决方案
FunClip:基于大语言模型的智能视频剪辑解决方案 在多媒体内容爆炸式增长的时代,视频剪辑已成为内容创作者、产品经理和技术开发者面临的核心挑战。传统视频剪辑工
音视频语音人工智能AI 应用本地部署
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考