feat(contracts): openapi base, error codes, type generation
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: photo-live
|
||||
version: 0.1.0
|
||||
license:
|
||||
name: UNLICENSED
|
||||
identifier: UNLICENSED
|
||||
description: |
|
||||
photo-live 直播相册系统 API 契约(单一事实来源)。
|
||||
|
||||
- 类型经 `openapi-typescript` 生成并提交入库(`src/generated/openapi.d.ts`),
|
||||
三端(services/api、apps/admin、apps/viewer)直接消费生成类型,不自行跑 gen。
|
||||
- 错误响应使用稳定 `code`(见 `components.schemas.Error` 的枚举,与
|
||||
`src/errors.ts` 的 `ErrorCodes` 一一对应),客户端按 code 映射多语言文案,
|
||||
`message` 仅供诊断。
|
||||
- 列表接口统一游标分页,元信息见 `components.schemas.CursorPageMeta`。
|
||||
|
||||
servers:
|
||||
- url: /v1
|
||||
|
||||
tags:
|
||||
- name: auth
|
||||
description: 密码登录会话(签发、滑动续期、退出)
|
||||
|
||||
paths:
|
||||
/auth/password:
|
||||
post:
|
||||
operationId: loginWithPassword
|
||||
tags: [auth]
|
||||
summary: 密码登录
|
||||
description: 校验账号密码,签发会话令牌。
|
||||
security: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: 登录成功,返回会话令牌与过期时间。
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginResponse'
|
||||
'401':
|
||||
$ref: '#/components/responses/ErrorResponse'
|
||||
'500':
|
||||
$ref: '#/components/responses/ErrorResponse'
|
||||
|
||||
/auth/refresh:
|
||||
post:
|
||||
operationId: refreshSession
|
||||
tags: [auth]
|
||||
summary: 会话滑动续期
|
||||
description: 携带有效 Bearer 令牌滑动续期,返回新的过期时间。
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: 续期成功。
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RefreshResponse'
|
||||
'401':
|
||||
$ref: '#/components/responses/ErrorResponse'
|
||||
'500':
|
||||
$ref: '#/components/responses/ErrorResponse'
|
||||
|
||||
/auth/logout:
|
||||
post:
|
||||
operationId: logout
|
||||
tags: [auth]
|
||||
summary: 退出登录
|
||||
description: 使当前 Bearer 令牌失效。
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
'204':
|
||||
description: 已退出,无响应体。
|
||||
'401':
|
||||
$ref: '#/components/responses/ErrorResponse'
|
||||
'500':
|
||||
$ref: '#/components/responses/ErrorResponse'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
|
||||
responses:
|
||||
ErrorResponse:
|
||||
description: 错误响应(稳定 code;客户端按 code 映射文案,message 仅供诊断)。
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
schemas:
|
||||
Error:
|
||||
type: object
|
||||
required: [code, message, requestId]
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
readOnly: true
|
||||
description: 稳定错误码,与 src/errors.ts 的 ErrorCodes 一一对应。
|
||||
enum:
|
||||
- AUTH_INVALID_CREDENTIALS
|
||||
- AUTH_TOKEN_EXPIRED
|
||||
- AUTH_FORBIDDEN
|
||||
- ALBUM_NOT_FOUND
|
||||
- ALBUM_NOT_PUBLIC
|
||||
- ALBUM_UPLOAD_DISABLED
|
||||
- MEMBER_CONFLICT
|
||||
- UPLOAD_SESSION_CONFLICT
|
||||
- UPLOAD_VERIFY_FAILED
|
||||
- PHOTO_NOT_FOUND
|
||||
- PHOTO_NOT_PUBLIC
|
||||
- VALIDATION_FAILED
|
||||
- INTERNAL_ERROR
|
||||
message:
|
||||
type: string
|
||||
readOnly: true
|
||||
description: 服务器生成的可读消息(诊断用,不作为客户端展示文案依据)。
|
||||
requestId:
|
||||
type: string
|
||||
readOnly: true
|
||||
description: 请求追踪 ID。
|
||||
|
||||
CursorPageMeta:
|
||||
type: object
|
||||
required: [nextCursor, hasMore]
|
||||
description: 游标分页元信息;各列表响应以 allOf 内嵌本结构(条目 schema 在业务端点中定义)。
|
||||
properties:
|
||||
nextCursor:
|
||||
type: [string, 'null']
|
||||
readOnly: true
|
||||
description: 下一页游标;null 表示没有更多数据。
|
||||
hasMore:
|
||||
type: boolean
|
||||
readOnly: true
|
||||
description: 是否还有下一页。
|
||||
|
||||
LoginRequest:
|
||||
type: object
|
||||
required: [account, password]
|
||||
properties:
|
||||
account:
|
||||
type: string
|
||||
description: 账号(用户名或邮箱)。
|
||||
password:
|
||||
type: string
|
||||
description: 密码。
|
||||
LoginResponse:
|
||||
type: object
|
||||
required: [sessionToken, expiresAt]
|
||||
properties:
|
||||
sessionToken:
|
||||
type: string
|
||||
readOnly: true
|
||||
description: 会话令牌(Bearer)。
|
||||
expiresAt:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
description: 会话过期时间。
|
||||
RefreshResponse:
|
||||
type: object
|
||||
required: [expiresAt]
|
||||
properties:
|
||||
expiresAt:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
description: 续期后的过期时间。
|
||||
Reference in New Issue
Block a user