@ api- ts/ openapi- 生成器
亚庇Ts openapi 生成器 是一个用于转换 io- ts- http 的命令行工具 API 规格为 OpenAPI 规格.
目录
1. 安装
npm install --save-dev @api-ts/openapi-generator
2. 用途
这个 openapi 生成器 假设io-ts-http apiSpec 在顶层导出
作为输入参数通过的 Typescript 文件。 OpenAPI 规格将
写给stdout.
ARGUMENTS:
<file> - API route definition file
OPTIONS:
--name, -n <str> - API name [optional]
--version, -v <str> - API version [optional]
--codec-file, -c <str> - Custom codec definition file [optional]
FLAGS:
--internal, -i - include routes marked private
--help, -h - show help
例如:
npx openapi-generator src/index.ts
3. 为可再使用的编码器准备一个类型包
为了使用外部类型 io-ts 类型软件包,您必须确保两样东西
结束了.
- 包源代码必须包含在捆绑中, 因为生成器是建到
生成基于 Typescript AST 的光谱。 它不是用来与
转接的js代码。 你可以通过修改你的
package.json包含您的 捆绑中的源代码 。 例如,如果源代码存在于src/目录,然后添加src/中的文件数组package.json你的项目. - 步骤一之后,更改
source区域package.json作为切入点 的类别。 例如,如果进入点是src/index.ts, (中文(简体) ), 然后设定"source": "src/index.ts"输入package.json
4. 定义自定义编码
合作时 openapi-generator,您可能会遇到处理自定义的挑战
需要 JavaScript 解释或本地支持的代码
发电机 这些问题通常与编码器如: new t.Type(...) 其他项目
不直接支持的原始人. 不过,有两个解决办法需要解决:
这些挑战是有效的。 点击 这里 页:1
支持原始人列表.
解决方案1:在类型包中定义自定义代码Schemas(建议)
openapi-generator 现在提供了定义自定义编码器的策略的能力
直接在定义它们的类型包内,而不是下游包内
用他们。 这种方法对于许多文书中使用的解码器特别有用
不同类型包。 以下是您如何定义您的自定义编码器的策略
上游仓库 :
-
创建名为的文件
openapi-gen.config.js在您的仓库的根部. -
添加以下一行到
package.json类型包:"customCodecFile": "openapi-gen.config.js"您还必须添加
"openapi-gen.config.js"到软件包中的文件字段, 以便包含在最后的捆绑中. -
在那个
openapi-gen.config.js文件,定义自定义解码器 :module.exports = (E) => { return { SampleCodecDefinition: () => E.right({ type: 'string', default: 'defaultString', minLength: 1, }), // ... rest of your custom codec definitions }; };
通过这些步骤,您的自定义解码器的策略将包含在
生成了 API 文档,用于使用相应编码器的任何端点。 输入参数
E 是名称空间导入 fp-ts/Either,返回类型应为: Record
包含外部库的 AST 定义。 详情见
已知的进口。 。 。 .
解决方案2: 使用自定义代码配置文件
openapi-generator 支持从其他软件包导入编码器 node_modules不过
它与挣扎 io-ts 需要 JavaScript 解释的原始人, 如
new t.Type(...)。要围绕这个问题开展工作,您可以在一个
下游类型包中的配置文件(其中生成 API)
(中文(简体) ). 这使得生成器能够理解和在必要时使用这些计划.
遵循这些步骤创建和使用自定义代码配置文件 :
-
创建 JavaScript 文件,格式如下 :
module.exports = (E) => { return { 'io-ts-bigint': { BigIntFromString: () => E.right({ type: 'string' }), NonZeroBigInt: () => E.right({ type: 'number' }), NonZeroBigIntFromString: () => E.right({ type: 'string' }), NegativeBigIntFromString: () => E.right({ type: 'string' }), NonNegativeBigIntFromString: () => E.right({ type: 'string' }), PositiveBigIntFromString: () => E.right({ type: 'string' }), }, // ... and so on for other packages }; }; -
输入参数
E是名称空间导入fp-ts/Either,从而避免 问题require。返回类型应为:Record包含 AST 的 外部图书馆的定义。 有关该结构的更多信息,请参阅: 已知的进口。 。 。 .
5. 被支持的io-ts原始人名单
stringnumberbigintbooleannullnullTypeundefinedunknownanyarrayreadonlyArrayobjecttypepartialexactstrictrecordunionintersectionliteralkeyofbrandUnknownRecordvoid
6. 发电机参考
本节将突出此生成器支持的所有特性, 并举例 帮助您在您的代码中添加有意义的文档,允许客户端使用我们 APIs与轻松.
6.1. 端点文件
鉴于使用定义的终点 h.httpRoute,可以添加文档和元数据到
通过使用JS Docs,这个终点. 以下是以下属性列表:
被支持.
6.1.1 总结
摘要为"JSDoc"第一行. 这将添加到 OpenAPI 作为终点摘要的规格
/**
* This is the summary
*/
const route = h.httpRoute({ ... })
6.1.2 说明
说明是下一个 x jSDoc的未标记行. 这将添加到
OpenAPI 规格作为终点描述
/**
* This is the summary
* This is description line 1
* This is description line 2
*/
const route = h.httpRoute({ ... })
6.1.3 行动身份证
所有终点必须有一个 operationId 被识别。 您可以添加操作ID
改为使用 @operationId 在JSDocs的标签。 这会增加它
此路由的 OpenAPI 规格 .
/**
* This is the summary
* This is description line 1
* This is description line 2
*
* @operationId v2.sample.route
*/
const route = h.httpRoute({ ... })
6.1.4 标记
标记是我们如何将终点组织成不同的组 dev-portal。有许多
不同的标记和标记组,例如 Wallet, (中文(简体) ), Address等 (中文(简体) ).
点击这里
为完整的标签列表。 您可以使用 @tag JSDoc标签.
/**
* This is the summary
* This is description line 1
* This is description line 2
*
* @operationId v2.sample.route
* @tag Wallet
*/
const route = h.httpRoute({ ... })
6.1.5 私人路线
在很多情况下,你会希望一个终点是私人的,例如: admin 或者说
internal 路线。 在文档中,您只需添加一个
@private 标记为 JSDoc 。 在规格中,将增加 x-internal: true
字段,表示在预处理中要剥去的字段
步骤 打开
dev-portal. (原始内容存档于2018-09-27).
/**
* This is the summary
* This is description line 1
* This is description line 2
*
* @private
* @operationId v2.sample.route
* @tag Wallet
*/
const route = h.httpRoute({ ... })
6.1.5.1 公共路线
明确标明一条路线为公共路线(制作) x-internal: false),使用 @public
标签。 当您的 CI 管道强制所有端点明确声明时, 这样做是有用的
他们的能见度.
/**
* This is the summary
* This is description line 1
* This is description line 2
*
* @public
* @operationId v2.sample.route
* @tag Wallet
*/
const route = h.httpRoute({ ... })
说明: 使用两者
@public财务报告和审定财务报表@private在同一路径或字段上将产生 错误.
6.1.6 不稳定路线
如果你正在研究一个不稳定或尚未完全执行的终点,
您可以添加 @unstable 标签以确保消费者知道它仍在开发中
并且可能无法如预期的那样工作.
/**
* This is the summary
* This is description line 1
* This is description line 2
*
* @unstable
* @operationId v2.sample.route
* @tag Wallet
*/
const route = h.httpRoute({ ... })
6.1.7 实例
您也可以在您的端点的顶级JS Docs中添加实例响应, 但作为 你会看到以后的章节, 还有其他方法做到这一点.
/**
* This is the summary
* This is description line 1
* This is description line 2
*
* @unstable
* @operationId v2.sample.route
* @tag Wallet
* @example { example: { object: { key: value }}}
*/
const route = h.httpRoute({ ... })
6.1.8 未知标记
在此顶级添加的任何其他标记都将归类为无名标记,以及
将放在 x-unknown-tags openAPI 规格中的字段。 你们可以
使用此功能为您全部写入自定义工作流程和过滤逻辑
规格。 例如,您可以添加一个 @version 标签和工作流程
过滤基于版本字段的端点 x-unknown-tags 字段.
/**
* This is the summary
* This is description line 1
* This is description line 2
*
* @unstable
* @operationId v2.sample.route
* @tag Wallet
* @example { example: { object: { key: value }}}
* @version 3
*/
const route = h.httpRoute({ ... })
6.1.9 抽样产出
这就是OpenAPI的规格 对我们建造的路线来说是什么样的.
{
"openapi": 3.03,
"paths": {
"/api/v2/sample/route": {
"get": {
"summary": "This is the summary",
"description": "This is description line 1\nThis is description line 2",
"operationId": "v2.sample.route",
"example": {
"object": {
"key": "value"
}
},
"tag": "Wallet",
"x-internal": true, // @private
"x-unstable": true, // @unstable
"x-unknown-tags": {
"version": 3
}
...parameters,
...requestBody,
...responses
}
}
}
}
6.2. Schema 文档
除了为顶级线路添加JSDocs之外,您还可以为以下线路添加JSDocs: 平分仪、请求体和反应体计划.
6.2.1 说明
只要在上方添加一个JSDoc,并加上一个 说明.
import * as t from 'io-ts';
/**
* This is a description that will be included in the OpenAPI specification.
*/
const schema = t.type({
field: t.number,
});
6.2.2 支持的 OpenAPI 标记
这些是您可以在 JS Doc 中设置的 OpenAPI 标签列表,并将包含其中 在生成的 OpenAPI spec 中.
@default[value: any]@example [example: any]@minLength [length: number]@maxLength [length: number]@pattern [pattern: regex]@minimum [min: number]@maximum [max: number]@minItems [minItems: number]@maxItems [maxItems: number]@minProperties [min: number]@maxProperties [max: number]@exclusiveMinimum@exclusiveMaximum@multipleOf [num: number]@uniqueItems@readOnly@writeOnly@format [format: format]@title [title: string]
以下是所有这些标记在使用的示例计划。 不要担心田地,只是 注意每个领域的不同联合来文和联合来文标记。 您还可以添加多少 标记为您想要的一个字段(条件是标记不冲突)。 您还可以添加 说明
include * as t from 'io-ts';
/** @title Sample Schema Title */
const SampleSchema = t.type({
/** @default defaultValueForField1 */
field1: t.string,
/** @example exampleForField2 */
field2: t.string,
/** @minLength 4 */
field3: t.string,
/** @maxLength 6 */
field4: t.string,
/** @pattern ^[0-9a-f]{32}$ */
fieldWithId: t.string,
/** @minimum 10 */
minField: t.number,
/** @maximum 40 */
maxField: t.number,
/** @minItems 10 */
minItemsArray: t.array(t.string),
/** @maxItems 50 */
maxItemsArray: t.array(t.string),
/** @minProperties 3 */,
minPropRecord: t.record(t.string, t.string),
/** @maxProperties 10 */
maxPropRecord: t.record(t.string, t.string),
nestedObject: t.partial({
/**
* @minimum 2
* @exclusiveMinimum
*/
exclMin: t.number,
/**
* @maximum 50
* @exclusiveMaximum
*/
exclMax: t.number,
/** @multipleOf 5*/
multOf: t.number,
/** @uniqueItems */
arr: t.array(t.string),
/** @readOnly */
readOnlyField: t.unknown,
/** @writeOnly */
writeOnlyField: t.unknown,
/** @format uuid */
uuidField: t.string,
/** @title Hello */
titleField: t.string
})
})
6.2.3 自定义标记
这些都是一些标签,你可以使用 在你的计划JSDocs是定制 这个生成器.
@private允许您将任何计划中的字段标为私有。 最终会 有过x-internal: true与计划@private标签.@public允许您明确标记任何计划中的任何字段为公开字段。 最终 spec 会有x-internal: false与计划@public标签。 使用两者@public财务报告和审定财务报表@private在同一字段上会出现错误.@deprecated允许将任何计划中的字段标记为已贬值。 最后的轮廓 将包括deprecated: true在最后的特莱克顿.
import * as t from 'io-ts';
const Schema = t.type({
/** @private */
privateField: t.string,
/** @public */
publicField: t.string,
/** @deprecated */
deprecatedField: t.string,
untaggedField: t.string,
});
6.2.3.1 联盟请求机构
当请求机构被定义为 t.union 联 合 国 httpRequest 计划(接受其中之一)
多个相互排斥的形状),描述必须放在 联合编码c
本身,而不是单个变体:
import * as t from 'io-ts';
import * as h from '@api-ts/io-ts-http';
/**
* The member to add — supply either a userId or an email address.
*/
const AddMemberRequest = t.union([
h.httpRequest({ body: { userId: t.string } }),
h.httpRequest({ body: { email: t.string } }),
]);
const route = h.httpRoute({
path: '/enterprise/{enterpriseId}/members',
method: 'POST',
request: AddMemberRequest,
response: { 200: t.string },
});
这能产生 description 打开 requestBody.content['application/json'].schema,哪个
满足 missing-request-body-description 质量检查.
说明: 把联合来文文件放在个人身上
httpRequest(...)页:1 工会包装 没有 向人体图案传播描述 说明必须在工会编码器上.
6.2.4 Enum文档
使用时 t.keyof 以定义 enums,您可以添加描述和折旧通知
到单个素值。 这些将输出为 x-enumDescriptions 财务报告和审定财务报表
x-enumsDeprecated 在 OpenAPI 规格中.
@description- 添加一个特定激发值的描述。 所有符号值 说明被收集到x-enumDescriptionsopenAPI 规格中的对象.@deprecated- 标出已贬值的具体enum值。 所有已贬值的语句 将数值收集到x-enumsDeprecatedopenAPI 光谱中的数组.
import * as t from 'io-ts';
/**
* Transaction status values
*/
export const TransactionStatus = t.keyof(
{
/**
* @description Transaction is waiting for approval from authorized users
*/
pendingApproval: 1,
/**
* @description Transaction was canceled by the user
* @deprecated
*/
canceled: 1,
/**
* @description Transaction was rejected by approvers
* @deprecated
*/
rejected: 1,
/**
* @description Transaction has been successfully completed
*/
completed: 1,
},
'TransactionStatus',
);
这将生成以下 OpenAPI 计划 :
{
"TransactionStatus": {
"type": "string",
"enum": ["pendingApproval", "canceled", "rejected", "completed"],
"x-enumDescriptions": {
"pendingApproval": "Transaction is waiting for approval from authorized users",
"canceled": "Transaction was canceled by the user",
"rejected": "Transaction was rejected by approvers",
"completed": "Transaction has been successfully completed"
},
"x-enumsDeprecated": ["canceled", "rejected"]
}
}