Skip to content
Clone

feat: add new exports for various modules in index.ts

ZhenYi committed
parent 8923bc0 commit 927a8b2 Browse files

300 files changed

+17588 −2464

This change is very large, so some diffs are not shown. Clone the repository to see the full change.

File tree 300
Modified app/src/cli.rs View app/src/cli.rs
@@ -12,7 +12,6 @@
1212 Serve,
1313 Mail,
1414 Migrate,
15 IdentityOpenapi,
1615 Openapi {
1716 #[arg(long)]
1817 check: bool,
Modified app/src/main.rs View app/src/main.rs
@@ -16,15 +16,6 @@
1616 Command::Mail => mail(),
1717 Command::Migrate => migrate(),
1818 Command::Openapi { check } => openapi(check),
19 Command::IdentityOpenapi => {
20 use utoipa::OpenApi;
21 let doc = auth::openapi::ApiDoc::openapi();
22 let path =
23 PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../lib/auth/OpenApi.Auth.json");
24 std::fs::write(&path, doc.to_pretty_json()?).context("writing identity OpenAPI")?;
25 println!("wrote {}", path.display());
26 Ok(())
27 }
2819 }
2920}
3021
Deleted lib/auth/OpenApi.Auth.json
@@ -1,2434 +0,0 @@
1{
2 "openapi": "3.1.0",
3 "info": {
4 "title": "auth",
5 "description": "认证与账号服务:工作量证明、口令与验证码登录、二次验证、注册、口令重置与 SSH 公钥。",
6 "license": {
7 "name": "MIT",
8 "identifier": "MIT"
9 },
10 "version": "1.0.0"
11 },
12 "paths": {
13 "/api/v1/auth/challenge": {
14 "post": {
15 "tags": [
16 "auth"
17 ],
18 "summary": "签发工作量证明挑战",
19 "description": "把挑战写进当前会话并返回。客户端需要为 `context` 找出一枚满足 `difficulty`(前导零比特数)的 nonce;`pow.v1` 算法与前端求解器一致。",
20 "operationId": "auth_challenge",
21 "responses": {
22 "200": {
23 "description": "挑战已签发并写入会话",
24 "content": {
25 "application/json": {
26 "schema": {
27 "$ref": "#/components/schemas/Envelope_ChallengeResponse"
28 },
29 "example": {
30 "code": 200,
31 "data": {
32 "context": "3xJk9Qp2mV7sLbT1rZa8nHc4wDf6YgU0",
33 "difficulty": 16,
34 "expires_at": 1767139500,
35 "issued_at": 1767139200
36 },
37 "message": "success"
38 }
39 }
40 }
41 },
42 "500": {
43 "description": "`internal`(挑战无法写入会话)/ `cache` / `session` / `serialization`",
44 "content": {
45 "application/json": {
46 "schema": {
47 "$ref": "#/components/schemas/Envelope_NoData"
48 },
49 "example": {
50 "code": "internal",
51 "message": "internal server error"
52 }
53 }
54 }
55 }
56 }
57 }
58 },
59 "/api/v1/auth/login": {
60 "post": {
61 "tags": [
62 "auth"
63 ],
64 "summary": "口令登录",
65 "description": "用口令登录。`identity` 可以是用户名、邮箱(大小写不敏感)或用户编号,`password_hash` 是客户端先算好的口令摘要,工作量证明的载荷必须是 `identity`。账号启用了多因子时返回 `mfa_required: true` 与 `challenge`,此时会话尚未绑定,需再调 `/api/v1/auth/login/verify`。",
66 "operationId": "auth_login",
67 "requestBody": {
68 "content": {
69 "application/json": {
70 "schema": {
71 "$ref": "#/components/schemas/UserLoginRequest"
72 }
73 }
74 },
75 "required": true
76 },
77 "responses": {
78 "200": {
79 "description": "登录成功;`mfa_required` 为真时还需二次验证",
80 "content": {
81 "application/json": {
82 "schema": {
83 "$ref": "#/components/schemas/Envelope_UserLoginResponse"
84 },
85 "example": {
86 "code": 200,
87 "data": {
88 "challenge": null,
89 "displayname": "Ada",
90 "mfa_required": false,
91 "user_id": 1024,
92 "username": "ada"
93 },
94 "message": "success"
95 }
96 }
97 }
98 },
99 "400": {
100 "description": "工作量证明过期、载荷不匹配或请求不合法(`expired`、`invalid_proof`、`invalid_payload`、`malformed_request`)",
101 "content": {
102 "application/json": {
103 "schema": {
104 "$ref": "#/components/schemas/Envelope_NoData"
105 },
106 "example": {
107 "code": "expired",
108 "message": "challenge expired"
109 }
110 }
111 }
112 },
113 "401": {
114 "description": "身份或口令不正确(`invalid_credentials`)",
115 "content": {
116 "application/json": {
117 "schema": {
118 "$ref": "#/components/schemas/Envelope_NoData"
119 },
120 "example": {
121 "code": "invalid_credentials",
122 "message": "invalid credentials"
123 }
124 }
125 }
126 },
127 "403": {
128 "description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
129 "content": {
130 "application/json": {
131 "schema": {
132 "$ref": "#/components/schemas/Envelope_NoData"
133 },
134 "example": {
135 "code": "login_forbidden",
136 "message": "account is banned"
137 }
138 }
139 }
140 },
141 "429": {
142 "description": "失败次数超出配额(`rate_limited`)",
143 "content": {
144 "application/json": {
145 "schema": {
146 "$ref": "#/components/schemas/Envelope_NoData"
147 },
148 "example": {
149 "code": "rate_limited",
150 "message": "too many attempts"
151 }
152 }
153 }
154 },
155 "500": {
156 "description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
157 "content": {
158 "application/json": {
159 "schema": {
160 "$ref": "#/components/schemas/Envelope_NoData"
161 },
162 "example": {
163 "code": "internal",
164 "message": "internal server error"
165 }
166 }
167 }
168 }
169 }
170 }
171 },
172 "/api/v1/auth/login/code": {
173 "post": {
174 "tags": [
175 "auth"
176 ],
177 "summary": "发送邮箱登录验证码",
178 "description": "向账号邮箱发送 6 位登录验证码,`expires_in_secs` 为有效期。工作量证明的载荷必须是 `email`。同一账号的发码间隔受 `email_code_rate_limit_secs` 限制。",
179 "operationId": "auth_login_code",
180 "requestBody": {
181 "content": {
182 "application/json": {
183 "schema": {
184 "$ref": "#/components/schemas/LoginCodeRequest"
185 }
186 }
187 },
188 "required": true
189 },
190 "responses": {
191 "200": {
192 "description": "验证码已发送",
193 "content": {
194 "application/json": {
195 "schema": {
196 "$ref": "#/components/schemas/Envelope_LoginCodeResponse"
197 },
198 "example": {
199 "code": 200,
200 "data": {
201 "expires_in_secs": 600
202 },
203 "message": "success"
204 }
205 }
206 }
207 },
208 "400": {
209 "description": "邮箱格式不合法或工作量证明过期、载荷不匹配(`invalid_email`、`expired`、`invalid_proof`、`invalid_payload`、`malformed_request`)",
210 "content": {
211 "application/json": {
212 "schema": {
213 "$ref": "#/components/schemas/Envelope_NoData"
214 },
215 "example": {
216 "code": "invalid_email",
217 "message": "invalid email address"
218 }
219 }
220 }
221 },
222 "401": {
223 "description": "邮箱未注册或账号不可用(`invalid_credentials`)",
224 "content": {
225 "application/json": {
226 "schema": {
227 "$ref": "#/components/schemas/Envelope_NoData"
228 },
229 "example": {
230 "code": "invalid_credentials",
231 "message": "invalid credentials"
232 }
233 }
234 }
235 },
236 "403": {
237 "description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
238 "content": {
239 "application/json": {
240 "schema": {
241 "$ref": "#/components/schemas/Envelope_NoData"
242 },
243 "example": {
244 "code": "login_forbidden",
245 "message": "account is banned"
246 }
247 }
248 }
249 },
250 "429": {
251 "description": "发码过于频繁(`rate_limited`)",
252 "content": {
253 "application/json": {
254 "schema": {
255 "$ref": "#/components/schemas/Envelope_NoData"
256 },
257 "example": {
258 "code": "rate_limited",
259 "message": "too many requests"
260 }
261 }
262 }
263 },
264 "500": {
265 "description": "服务端故障,含邮件发送失败(`internal`、`database`、`cache`、`session`、`email`、`serialization`)",
266 "content": {
267 "application/json": {
268 "schema": {
269 "$ref": "#/components/schemas/Envelope_NoData"
270 },
271 "example": {
272 "code": "internal",
273 "message": "internal server error"
274 }
275 }
276 }
277 }
278 }
279 }
280 },
281 "/api/v1/auth/login/code/verify": {
282 "post": {
283 "tags": [
284 "auth"
285 ],
286 "summary": "邮箱验证码换会话",
287 "description": "用邮箱登录验证码换会话。工作量证明的载荷必须是 `email`。验证码一旦核对通过即作废,连续输错 `max_verify_attempts` 次后需重新申请。账号启用了多因子时返回 `mfa_required: true` 与 `challenge`。",
288 "operationId": "auth_login_code_verify",
289 "requestBody": {
290 "content": {
291 "application/json": {
292 "schema": {
293 "$ref": "#/components/schemas/LoginCodeVerifyRequest"
294 }
295 }
296 },
297 "required": true
298 },
299 "responses": {
300 "200": {
301 "description": "登录成功;`mfa_required` 为真时还需二次验证",
302 "content": {
303 "application/json": {
304 "schema": {
305 "$ref": "#/components/schemas/Envelope_UserLoginResponse"
306 },
307 "example": {
308 "code": 200,
309 "data": {
310 "challenge": null,
311 "displayname": "Ada",
312 "mfa_required": false,
313 "user_id": 1024,
314 "username": "ada"
315 },
316 "message": "success"
317 }
318 }
319 }
320 },
321 "400": {
322 "description": "验证码不正确或已过期,或邮箱格式、工作量证明不合法(`invalid_email_code`、`invalid_email`、`expired`、`invalid_proof`、`invalid_payload`、`malformed_request`)",
323 "content": {
324 "application/json": {
325 "schema": {
326 "$ref": "#/components/schemas/Envelope_NoData"
327 },
328 "example": {
329 "code": "invalid_email_code",
330 "message": "invalid email code"
331 }
332 }
333 }
334 },
335 "401": {
336 "description": "邮箱未注册或账号不可用(`invalid_credentials`)",
337 "content": {
338 "application/json": {
339 "schema": {
340 "$ref": "#/components/schemas/Envelope_NoData"
341 },
342 "example": {
343 "code": "invalid_credentials",
344 "message": "invalid credentials"
345 }
346 }
347 }
348 },
349 "403": {
350 "description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
351 "content": {
352 "application/json": {
353 "schema": {
354 "$ref": "#/components/schemas/Envelope_NoData"
355 },
356 "example": {
357 "code": "login_forbidden",
358 "message": "account is banned"
359 }
360 }
361 }
362 },
363 "429": {
364 "description": "验证码尝试次数超限或请求过频(`email_code_attempts_exceeded`、`rate_limited`)",
365 "content": {
366 "application/json": {
367 "schema": {
368 "$ref": "#/components/schemas/Envelope_NoData"
369 },
370 "example": {
371 "code": "email_code_attempts_exceeded",
372 "message": "too many attempts"
373 }
374 }
375 }
376 },
377 "500": {
378 "description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
379 "content": {
380 "application/json": {
381 "schema": {
382 "$ref": "#/components/schemas/Envelope_NoData"
383 },
384 "example": {
385 "code": "internal",
386 "message": "internal server error"
387 }
388 }
389 }
390 }
391 }
392 }
393 },
394 "/api/v1/auth/login/verify": {
395 "post": {
396 "tags": [
397 "auth"
398 ],
399 "summary": "二次验证换会话",
400 "description": "用 6 位 TOTP 动态码或一枚未使用的恢复码完成二次验证并绑定会话。`challenge` 必须与 `/api/v1/auth/login` 或 `/api/v1/auth/login/code/verify` 返回的一致,挑战有效期 300 秒,同一动态码时间步不能重复使用,恢复码用掉即作废。",
401 "operationId": "auth_login_verify",
402 "requestBody": {
403 "content": {
404 "application/json": {
405 "schema": {
406 "$ref": "#/components/schemas/LoginVerifyRequest"
407 }
408 }
409 },
410 "required": true
411 },
412 "responses": {
413 "200": {
414 "description": "登录成功,会话已绑定",
415 "content": {
416 "application/json": {
417 "schema": {
418 "$ref": "#/components/schemas/Envelope_UserLoginResponse"
419 },
420 "example": {
421 "code": 200,
422 "data": {
423 "challenge": null,
424 "displayname": "Ada",
425 "mfa_required": false,
426 "user_id": 1024,
427 "username": "ada"
428 },
429 "message": "success"
430 }
431 }
432 }
433 },
434 "400": {
435 "description": "挑战过期或对不上、动态码错误、动态码时间步已用过、恢复码无效(`expired`、`malformed_request`、`totp_code_invalid`、`totp_step_reused`、`recovery_code_invalid`)",
436 "content": {
437 "application/json": {
438 "schema": {
439 "$ref": "#/components/schemas/Envelope_NoData"
440 },
441 "example": {
442 "code": "totp_code_invalid",
443 "message": "invalid totp code"
444 }
445 }
446 }
447 },
448 "401": {
449 "description": "会话里没有待验证挑战、账号不可用或多因子记录已被撤销(`unauthenticated`、`invalid_credentials`、`mfa_required`)",
450 "content": {
451 "application/json": {
452 "schema": {
453 "$ref": "#/components/schemas/Envelope_NoData"
454 },
455 "example": {
456 "code": "mfa_required",
457 "message": "multi-factor authentication required"
458 }
459 }
460 }
461 },
462 "403": {
463 "description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
464 "content": {
465 "application/json": {
466 "schema": {
467 "$ref": "#/components/schemas/Envelope_NoData"
468 },
469 "example": {
470 "code": "login_forbidden",
471 "message": "account is banned"
472 }
473 }
474 }
475 },
476 "429": {
477 "description": "尝试次数超限或恢复码已用尽(`rate_limited`、`recovery_codes_exhausted`)",
478 "content": {
479 "application/json": {
480 "schema": {
481 "$ref": "#/components/schemas/Envelope_NoData"
482 },
483 "example": {
484 "code": "rate_limited",
485 "message": "too many attempts"
486 }
487 }
488 }
489 },
490 "500": {
491 "description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
492 "content": {
493 "application/json": {
494 "schema": {
495 "$ref": "#/components/schemas/Envelope_NoData"
496 },
497 "example": {
498 "code": "internal",
499 "message": "internal server error"
500 }
501 }
502 }
503 }
504 }
505 }
506 },
507 "/api/v1/auth/me": {
508 "get": {
509 "tags": [
510 "auth"
511 ],
512 "summary": "当前登录用户",
513 "description": "通过会话 Cookie 返回用户自述信息。结果在服务端缓存 300 秒,每第 5 次访问回源刷新;登出与改密会主动失效该缓存。",
514 "operationId": "auth_me",
515 "responses": {
516 "200": {
517 "description": "当前登录用户",
518 "content": {
519 "application/json": {
520 "schema": {
521 "$ref": "#/components/schemas/Envelope_MeResponse"
522 },
523 "example": {
524 "code": 200,
525 "data": {
526 "avatar_url": "https://cdn.example.com/avatar/ada.png",
527 "created_at": "2025-11-20T02:15:00Z",
528 "displayname": "Ada",
529 "email": "ada@example.com",
530 "email_verified_at": "2026-01-05T08:30:00Z",
531 "is_admin": false,
532 "user_id": 1024,
533 "username": "ada",
534 "version": 3
535 },
536 "message": "success"
537 }
538 }
539 }
540 },
541 "401": {
542 "description": "会话未绑定用户,或账号已被删除(`unauthenticated`)",
543 "content": {
544 "application/json": {
545 "schema": {
546 "$ref": "#/components/schemas/Envelope_NoData"
547 },
548 "example": {
549 "code": "unauthenticated",
550 "message": "authentication required"
551 }
552 }
553 }
554 },
555 "500": {
556 "description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
557 "content": {
558 "application/json": {
559 "schema": {
560 "$ref": "#/components/schemas/Envelope_NoData"
561 },
562 "example": {
563 "code": "internal",
564 "message": "internal server error"
565 }
566 }
567 }
568 }
569 }
570 }
571 },
572 "/api/v1/auth/password/reset": {
573 "post": {
574 "tags": [
575 "auth"
576 ],
577 "summary": "申请密码重置",
578 "description": "校验工作量证明(payload = 邮箱的 UTF-8 字节)后,作废该用户其余未消费的重置令牌,签发新令牌(长度 `reset_token_bytes`,有效期 `reset_token_ttl_secs`),库内只存 `sha256_hex(token)` 且 `hash_key_id = \"sha256-v1\"`,同时把摘要写入缓存键 `auth:code:reset:{email}`,发信限流键 `auth:rate:reset:{email}`。",
579 "operationId": "auth_password_reset_request",
580 "requestBody": {
581 "content": {
582 "application/json": {
583 "schema": {
584 "$ref": "#/components/schemas/PasswordResetRequest"
585 }
586 }
587 },
588 "required": true
589 },
590 "responses": {
591 "200": {
592 "description": "申请已受理;是否真的发信不对外披露",
593 "content": {
594 "application/json": {
595 "schema": {
596 "$ref": "#/components/schemas/Envelope_PasswordResetResponse"
597 },
598 "example": {
599 "code": 200,
600 "data": {
601 "expires_in_secs": 1800
602 },
603 "message": "success"
604 }
605 }
606 }
607 },
608 "400": {
609 "description": "`invalid_email` / `expired` / `invalid_payload`(payload 与邮箱不一致)/ `invalid_proof`",
610 "content": {
611 "application/json": {
612 "schema": {
613 "$ref": "#/components/schemas/Envelope_NoData"
614 },
615 "example": {
616 "code": "invalid_email",
617 "message": "email is invalid"
618 }
619 }
620 }
621 },
622 "429": {
623 "description": "`rate_limited`(同一邮箱申请过于频繁)",
624 "content": {
625 "application/json": {
626 "schema": {
627 "$ref": "#/components/schemas/Envelope_NoData"
628 },
629 "example": {
630 "code": "rate_limited",
631 "message": "too many requests, retry after 60s"
632 }
633 }
634 }
635 },
636 "500": {
637 "description": "`email`(投递失败)/ `database` / `cache` / `session` / `serialization` / `internal`",
638 "content": {
639 "application/json": {
640 "schema": {
641 "$ref": "#/components/schemas/Envelope_NoData"
642 },
643 "example": {
644 "code": "internal",
645 "message": "internal server error"
646 }
647 }
648 }
649 }
650 }
651 }
652 },
653 "/api/v1/auth/password/reset/confirm": {
654 "post": {
655 "tags": [
656 "auth"
657 ],
658 "summary": "确认密码重置",
659 "description": "校验工作量证明(payload = `token` 的 UTF-8 字节)与缓存键 `auth:code:reset:{email}`(尝试上限 `max_verify_attempts`,错误计入 `invalid_email_code`)后,条件消费数据库令牌行(`consumed_at` 单次占用),Argon2 重哈希新口令,更新 `password_hash`/`password_updated_at`/`password_must_change`/`security_version + 1`,作废其余令牌并记 `PasswordChange` 审计事件。",
660 "operationId": "auth_password_reset",
661 "requestBody": {
662 "content": {
663 "application/json": {
664 "schema": {
665 "$ref": "#/components/schemas/PasswordResetConfirmRequest"
666 }
667 }
668 },
669 "required": true
670 },
671 "responses": {
672 "200": {
673 "description": "口令已改写;旧口令与其余重置令牌失效",
674 "content": {
675 "application/json": {
676 "schema": {
677 "$ref": "#/components/schemas/Envelope_PasswordResetConfirmResponse"
678 },
679 "example": {
680 "code": 200,
681 "data": {
682 "user_id": 1234567
683 },
684 "message": "success"
685 }
686 }
687 }
688 },
689 "400": {
690 "description": "`invalid_reset_token`(令牌不存在/已消费/已作废/已过期/账号不可用或凭据代数不匹配)/ `invalid_email_code`(缓存内摘要不匹配或已过期)/ `invalid_password` / `expired` / `invalid_payload` / `invalid_proof`",
691 "content": {
692 "application/json": {
693 "schema": {
694 "$ref": "#/components/schemas/Envelope_NoData"
695 },
696 "example": {
697 "code": "invalid_reset_token",
698 "message": "password reset token is invalid"
699 }
700 }
701 }
702 },
703 "429": {
704 "description": "`email_code_attempts_exceeded`(令牌尝试次数用尽)",
705 "content": {
706 "application/json": {
707 "schema": {
708 "$ref": "#/components/schemas/Envelope_NoData"
709 },
710 "example": {
711 "code": "email_code_attempts_exceeded",
712 "message": "too many invalid email verification attempts"
713 }
714 }
715 }
716 },
717 "500": {
718 "description": "`password_hash`(口令重哈希失败)/ `database` / `cache` / `session` / `serialization` / `internal`",
719 "content": {
720 "application/json": {
721 "schema": {
722 "$ref": "#/components/schemas/Envelope_NoData"
723 },
724 "example": {
725 "code": "internal",
726 "message": "internal server error"
727 }
728 }
729 }
730 }
731 }
732 }
733 },
734 "/api/v1/auth/register": {
735 "post": {
736 "tags": [
737 "auth"
738 ],
739 "summary": "提交注册",
740 "description": "校验工作量证明(payload = 用户名的 UTF-8 字节)、用户名/展示名/出生日期/邮箱、邮箱验证码(键 `auth:code:register:{email}`,尝试上限 `max_verify_attempts`)后,Argon2 重哈希口令并创建用户与初始档案。成功后写会话(user_id、security_version、renew)并记审计事件。",
741 "operationId": "auth_register",
742 "requestBody": {
743 "content": {
744 "application/json": {
745 "schema": {
746 "$ref": "#/components/schemas/UserRegisterRequest"
747 }
748 }
749 },
750 "required": true
751 },
752 "responses": {
753 "200": {
754 "description": "注册成功且已登录",
755 "content": {
756 "application/json": {
757 "schema": {
758 "$ref": "#/components/schemas/Envelope_UserRegisterResponse"
759 },
760 "example": {
761 "code": 200,
762 "data": {
763 "displayname": "Alice",
764 "user_id": 1234567,
765 "username": "alice"
766 },
767 "message": "success"
768 }
769 }
770 }
771 },
772 "400": {
773 "description": "`invalid_username` / `invalid_displayname` / `invalid_email` / `invalid_birth_date` / `invalid_password` / `invalid_email_code`(验证码错误或已过期)/ `expired` / `invalid_payload` / `invalid_proof`",
774 "content": {
775 "application/json": {
776 "schema": {
777 "$ref": "#/components/schemas/Envelope_NoData"
778 },
779 "example": {
780 "code": "invalid_email_code",
781 "message": "email verification code is invalid"
782 }
783 }
784 }
785 },
786 "403": {
787 "description": "`under_minimum_age`(未满最小年龄)",
788 "content": {
789 "application/json": {
790 "schema": {
791 "$ref": "#/components/schemas/Envelope_NoData"
792 },
793 "example": {
794 "code": "under_minimum_age",
795 "message": "you must be at least 13 years old"
796 }
797 }
798 }
799 },
800 "409": {
801 "description": "`username_taken` / `email_taken`",
802 "content": {
803 "application/json": {
804 "schema": {
805 "$ref": "#/components/schemas/Envelope_NoData"
806 },
807 "example": {
808 "code": "username_taken",
809 "message": "username is already taken"
810 }
811 }
812 }
813 },
814 "429": {
815 "description": "`email_code_attempts_exceeded`(验证码尝试次数用尽)",
816 "content": {
817 "application/json": {
818 "schema": {
819 "$ref": "#/components/schemas/Envelope_NoData"
820 },
821 "example": {
822 "code": "email_code_attempts_exceeded",
823 "message": "too many invalid email verification attempts"
824 }
825 }
826 }
827 },
828 "500": {
829 "description": "`password_hash`(口令重哈希失败)/ `database` / `cache` / `session` / `serialization` / `internal`",
830 "content": {
831 "application/json": {
832 "schema": {
833 "$ref": "#/components/schemas/Envelope_NoData"
834 },
835 "example": {
836 "code": "internal",
837 "message": "internal server error"
838 }
839 }
840 }
841 }
842 }
843 }
844 },
845 "/api/v1/auth/register/code": {
846 "post": {
847 "tags": [
848 "auth"
849 ],
850 "summary": "发送注册验证码",
851 "description": "校验工作量证明(payload = 邮箱的 UTF-8 字节)与邮箱格式后,把 6 位验证码写入缓存并寄出。缓存键 `auth:code:register:{email}`,有效期由 `verify_code_ttl_secs` 决定,发码限流键 `auth:rate:register:{email}`。",
852 "operationId": "auth_register_code",
853 "requestBody": {
854 "content": {
855 "application/json": {
856 "schema": {
857 "$ref": "#/components/schemas/RegisterCodeRequest"
858 }
859 }
860 },
861 "required": true
862 },
863 "responses": {
864 "200": {
865 "description": "验证码已写入缓存并寄出",
866 "content": {
867 "application/json": {
868 "schema": {
869 "$ref": "#/components/schemas/Envelope_RegisterCodeResponse"
870 },
871 "example": {
872 "code": 200,
873 "data": {
874 "expires_in_secs": 600
875 },
876 "message": "success"
877 }
878 }
879 }
880 },
881 "400": {
882 "description": "`invalid_email`(邮箱格式)/ `expired`(挑战过期)/ `invalid_payload`(payload 与邮箱不一致)/ `invalid_proof`(未满足难度)",
883 "content": {
884 "application/json": {
885 "schema": {
886 "$ref": "#/components/schemas/Envelope_NoData"
887 },
888 "example": {
889 "code": "invalid_email",
890 "message": "email is invalid"
891 }
892 }
893 }
894 },
895 "409": {
896 "description": "`email_taken`(邮箱已注册)",
897 "content": {
898 "application/json": {
899 "schema": {
900 "$ref": "#/components/schemas/Envelope_NoData"
901 },
902 "example": {
903 "code": "email_taken",
904 "message": "email is already taken"
905 }
906 }
907 }
908 },
909 "429": {
910 "description": "`rate_limited`(同一邮箱发码过于频繁)",
911 "content": {
912 "application/json": {
913 "schema": {
914 "$ref": "#/components/schemas/Envelope_NoData"
915 },
916 "example": {
917 "code": "rate_limited",
918 "message": "too many requests, retry after 60s"
919 }
920 }
921 }
922 },
923 "500": {
924 "description": "`email`(投递失败)/ `cache` / `session` / `serialization` / `internal`",
925 "content": {
926 "application/json": {
927 "schema": {
928 "$ref": "#/components/schemas/Envelope_NoData"
929 },
930 "example": {
931 "code": "internal",
932 "message": "internal server error"
933 }
934 }
935 }
936 }
937 }
938 }
939 },
940 "/api/v1/auth/session/logout": {
941 "post": {
942 "tags": [
943 "auth"
944 ],
945 "summary": "登出",
946 "description": "销毁当前会话,并清掉该用户的 `/api/v1/auth/me` 缓存。匿名调用同样成功,此时 `user_id` 为 `null`。",
947 "operationId": "auth_logout",
948 "responses": {
949 "200": {
950 "description": "会话已销毁",
951 "content": {
952 "application/json": {
953 "schema": {
954 "$ref": "#/components/schemas/Envelope_LogoutResponse"
955 },
956 "example": {
957 "code": 200,
958 "data": {
959 "user_id": 1024
960 },
961 "message": "success"
962 }
963 }
964 }
965 },
966 "500": {
967 "description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
968 "content": {
969 "application/json": {
970 "schema": {
971 "$ref": "#/components/schemas/Envelope_NoData"
972 },
973 "example": {
974 "code": "internal",
975 "message": "internal server error"
976 }
977 }
978 }
979 }
980 }
981 }
982 },
983 "/api/v1/auth/ssh-keys": {
984 "get": {
985 "tags": [
986 "auth"
987 ],
988 "summary": "列示 SSH 公钥",
989 "description": "按创建时间倒序返回当前账号的公钥,含已吊销与已过期的记录。分页参数由 `page` / `page_size` 控制。查询串不是合法分页参数时由 actix-web 直接返回 400。",
990 "operationId": "auth_ssh_key_list",
991 "parameters": [
992 {
993 "name": "page",
994 "in": "query",
995 "description": "页码,从 1 开始;默认 1",
996 "required": false,
997 "schema": {
998 "type": "integer",
999 "format": "int64",
1000 "minimum": 0
1001 }
1002 },
1003 {
1004 "name": "page_size",
1005 "in": "query",
1006 "description": "每页条数,默认 20,最多 100",
1007 "required": false,
1008 "schema": {
1009 "type": "integer",
1010 "format": "int64",
1011 "minimum": 0
1012 }
1013 }
1014 ],
1015 "responses": {
1016 "200": {
1017 "description": "公钥列表",
1018 "content": {
1019 "application/json": {
1020 "schema": {
1021 "$ref": "#/components/schemas/Envelope_Vec_SshKeySummary"
1022 },
1023 "example": {
1024 "code": 200,
1025 "data": [
1026 {
1027 "algorithm": "ed25519",
1028 "created_at": "2026-01-02T03:04:05Z",
1029 "description": "笔记本",
1030 "expires_at": null,
1031 "fingerprint": "SHA256:9pQ2mLk1v3sT6yZx8cV0bN4mR7wQ2eH5jK9aD1sF3gU",
1032 "id": "018f2b1c-4d5e-7f80-9a1b-2c3d4e5f6072",
1033 "last_used_at": null,
1034 "name": "thinkpad",
1035 "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL9kQ2mXv7Tb1sYz8cV0bN4mR7wQ2eH5jK9aD1sF3gU thinkpad",
1036 "revoked_at": null
1037 }
1038 ],
1039 "message": "success"
1040 }
1041 }
1042 }
1043 },
1044 "401": {
1045 "description": "会话未绑定账号(`unauthenticated`)",
1046 "content": {
1047 "application/json": {
1048 "schema": {
1049 "$ref": "#/components/schemas/Envelope_NoData"
1050 },
1051 "example": {
1052 "code": "unauthenticated",
1053 "message": "authentication required"
1054 }
1055 }
1056 }
1057 },
1058 "500": {
1059 "description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
1060 "content": {
1061 "application/json": {
1062 "schema": {
1063 "$ref": "#/components/schemas/Envelope_NoData"
1064 },
1065 "example": {
1066 "code": "internal",
1067 "message": "internal server error"
1068 }
1069 }
1070 }
1071 }
1072 }
1073 },
1074 "post": {
1075 "tags": [
1076 "auth"
1077 ],
1078 "summary": "添加 SSH 公钥",
1079 "description": "名称 1~64 字符、备注最长 255 字符,公钥 32~8192 字节且必须是受支持的单行 OpenSSH 公钥,`expires_at` 必须晚于当前时间。重复公钥(指纹唯一)返回 `ssh_key_taken`。添加成功记 `PublicKeyAdded` 审计事件。",
1080 "operationId": "auth_ssh_key_add",
1081 "requestBody": {
1082 "content": {
1083 "application/json": {
1084 "schema": {
1085 "$ref": "#/components/schemas/SshKeyAddRequest"
1086 }
1087 }
1088 },
1089 "required": true
1090 },
1091 "responses": {
1092 "200": {
1093 "description": "公钥已登记",
1094 "content": {
1095 "application/json": {
1096 "schema": {
1097 "$ref": "#/components/schemas/Envelope_SshKeySummary"
1098 },
1099 "example": {
1100 "code": 200,
1101 "data": {
1102 "algorithm": "ed25519",
1103 "created_at": "2026-01-02T03:04:05Z",
1104 "description": "笔记本",
1105 "expires_at": null,
1106 "fingerprint": "SHA256:9pQ2mLk1v3sT6yZx8cV0bN4mR7wQ2eH5jK9aD1sF3gU",
1107 "id": "018f2b1c-4d5e-7f80-9a1b-2c3d4e5f6072",
1108 "last_used_at": null,
1109 "name": "thinkpad",
1110 "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL9kQ2mXv7Tb1sYz8cV0bN4mR7wQ2eH5jK9aD1sF3gU thinkpad",
1111 "revoked_at": null
1112 },
1113 "message": "success"
1114 }
1115 }
1116 }
1117 },
1118 "400": {
1119 "description": "名称、备注、公钥或过期时间不合法(`ssh_key_name_invalid`、`malformed_request`、`ssh_key_invalid`、`invalid_expiry`)",
1120 "content": {
1121 "application/json": {
1122 "schema": {
1123 "$ref": "#/components/schemas/Envelope_NoData"
1124 },
1125 "example": {
1126 "code": "ssh_key_invalid",
1127 "message": "public key is invalid"
1128 }
1129 }
1130 }
1131 },
1132 "401": {
1133 "description": "会话未绑定账号,或账号已删除 / 不允许使用(`unauthenticated`)",
1134 "content": {
1135 "application/json": {
1136 "schema": {
1137 "$ref": "#/components/schemas/Envelope_NoData"
1138 },
1139 "example": {
1140 "code": "unauthenticated",
1141 "message": "authentication required"
1142 }
1143 }
1144 }
1145 },
1146 "409": {
1147 "description": "同一把公钥已经登记过(`ssh_key_taken`)",
1148 "content": {
1149 "application/json": {
1150 "schema": {
1151 "$ref": "#/components/schemas/Envelope_NoData"
1152 },
1153 "example": {
1154 "code": "ssh_key_taken",
1155 "message": "public key is already registered"
1156 }
1157 }
1158 }
1159 },
1160 "500": {
1161 "description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
1162 "content": {
1163 "application/json": {
1164 "schema": {
1165 "$ref": "#/components/schemas/Envelope_NoData"
1166 },
1167 "example": {
1168 "code": "internal",
1169 "message": "internal server error"
1170 }
1171 }
1172 }
1173 }
1174 }
1175 }
1176 },
1177 "/api/v1/auth/ssh-keys/{key_id}": {
1178 "delete": {
1179 "tags": [
1180 "auth"
1181 ],
1182 "summary": "吊销 SSH 公钥",
1183 "description": "把公钥标记为已吊销,记录保留不硬删;重复调用幂等。公钥不存在或不属于当前账号返回 `ssh_key_not_found`。吊销成功记 `PublicKeyRemoved` 审计事件,并递增 `security_version` 让该账号既有的访问令牌一并失效。`key_id` 不是合法 UUID 时由 actix-web 的路径提取器直接返回 400。",
1184 "operationId": "auth_ssh_key_delete",
1185 "parameters": [
1186 {
1187 "name": "key_id",
1188 "in": "path",
1189 "description": "公钥编号",
1190 "required": true,
1191 "schema": {
1192 "type": "string",
1193 "format": "uuid"
1194 }
1195 }
1196 ],
1197 "responses": {
1198 "200": {
1199 "description": "已吊销;重复调用同样返回成功",
1200 "content": {
1201 "application/json": {
1202 "schema": {
1203 "$ref": "#/components/schemas/Envelope_NoData"
1204 },
1205 "example": {
1206 "code": 200,
1207 "data": null,
1208 "message": "success"
1209 }
1210 }
1211 }
1212 },
1213 "401": {
1214 "description": "会话未绑定账号(`unauthenticated`)",
1215 "content": {
1216 "application/json": {
1217 "schema": {
1218 "$ref": "#/components/schemas/Envelope_NoData"
1219 },
1220 "example": {
1221 "code": "unauthenticated",
1222 "message": "authentication required"
1223 }
1224 }
1225 }
1226 },
1227 "404": {
1228 "description": "公钥不存在或不属于当前账号(`ssh_key_not_found`)",
1229 "content": {
1230 "application/json": {
1231 "schema": {
1232 "$ref": "#/components/schemas/Envelope_NoData"
1233 },
1234 "example": {
1235 "code": "ssh_key_not_found",
1236 "message": "ssh key does not exist"
1237 }
1238 }
1239 }
1240 },
1241 "500": {
1242 "description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
1243 "content": {
1244 "application/json": {
1245 "schema": {
1246 "$ref": "#/components/schemas/Envelope_NoData"
1247 },
1248 "example": {
1249 "code": "internal",
1250 "message": "internal server error"
1251 }
1252 }
1253 }
1254 }
1255 }
1256 }
1257 }
1258 },
1259 "components": {
1260 "schemas": {
1261 "ChallengeResponse": {
1262 "type": "object",
1263 "required": [
1264 "context",
1265 "difficulty",
1266 "issued_at",
1267 "expires_at"
1268 ],
1269 "properties": {
1270 "context": {
1271 "type": "string"
1272 },
1273 "difficulty": {
1274 "type": "integer",
1275 "format": "int32",
1276 "minimum": 0
1277 },
1278 "expires_at": {
1279 "type": "integer",
1280 "format": "int64",
1281 "minimum": 0
1282 },
1283 "issued_at": {
1284 "type": "integer",
1285 "format": "int64",
1286 "minimum": 0
1287 }
1288 }
1289 },
1290 "Envelope_ChallengeResponse": {
1291 "type": "object",
1292 "required": [
1293 "code",
1294 "message"
1295 ],
1296 "properties": {
1297 "code": {
1298 "type": "integer",
1299 "format": "int32"
1300 },
1301 "data": {
1302 "type": "object",
1303 "required": [
1304 "context",
1305 "difficulty",
1306 "issued_at",
1307 "expires_at"
1308 ],
1309 "properties": {
1310 "context": {
1311 "type": "string"
1312 },
1313 "difficulty": {
1314 "type": "integer",
1315 "format": "int32",
1316 "minimum": 0
1317 },
1318 "expires_at": {
1319 "type": "integer",
1320 "format": "int64",
1321 "minimum": 0
1322 },
1323 "issued_at": {
1324 "type": "integer",
1325 "format": "int64",
1326 "minimum": 0
1327 }
1328 }
1329 },
1330 "error": {
1331 "type": [
1332 "string",
1333 "null"
1334 ]
1335 },
1336 "error_code": {
1337 "type": [
1338 "string",
1339 "null"
1340 ]
1341 },
1342 "message": {
1343 "type": "string"
1344 },
1345 "request_id": {
1346 "type": "string"
1347 }
1348 }
1349 },
1350 "Envelope_LoginCodeResponse": {
1351 "type": "object",
1352 "required": [
1353 "code",
1354 "message"
1355 ],
1356 "properties": {
1357 "code": {
1358 "type": "integer",
1359 "format": "int32"
1360 },
1361 "data": {
1362 "type": "object",
1363 "required": [
1364 "expires_in_secs"
1365 ],
1366 "properties": {
1367 "expires_in_secs": {
1368 "type": "integer",
1369 "format": "int64",
1370 "minimum": 0
1371 }
1372 }
1373 },
1374 "error": {
1375 "type": [
1376 "string",
1377 "null"
1378 ]
1379 },
1380 "error_code": {
1381 "type": [
1382 "string",
1383 "null"
1384 ]
1385 },
1386 "message": {
1387 "type": "string"
1388 },
1389 "request_id": {
1390 "type": "string"
1391 }
1392 }
1393 },
1394 "Envelope_LogoutResponse": {
1395 "type": "object",
1396 "required": [
1397 "code",
1398 "message"
1399 ],
1400 "properties": {
1401 "code": {
1402 "type": "integer",
1403 "format": "int32"
1404 },
1405 "data": {
1406 "type": "object",
1407 "properties": {
1408 "user_id": {
1409 "type": [
1410 "integer",
1411 "null"
1412 ],
1413 "format": "int64"
1414 }
1415 }
1416 },
1417 "error": {
1418 "type": [
1419 "string",
1420 "null"
1421 ]
1422 },
1423 "error_code": {
1424 "type": [
1425 "string",
1426 "null"
1427 ]
1428 },
1429 "message": {
1430 "type": "string"
1431 },
1432 "request_id": {
1433 "type": "string"
1434 }
1435 }
1436 },
1437 "Envelope_MeResponse": {
1438 "type": "object",
1439 "required": [
1440 "code",
1441 "message"
1442 ],
1443 "properties": {
1444 "code": {
1445 "type": "integer",
1446 "format": "int32"
1447 },
1448 "data": {
1449 "type": "object",
1450 "required": [
1451 "user_id",
1452 "username",
1453 "email",
1454 "is_admin",
1455 "created_at",
1456 "version"
1457 ],
1458 "properties": {
1459 "avatar_url": {
1460 "type": [
1461 "string",
1462 "null"
1463 ]
1464 },
1465 "created_at": {
1466 "type": "string",
1467 "format": "date-time"
1468 },
1469 "displayname": {
1470 "type": [
1471 "string",
1472 "null"
1473 ]
1474 },
1475 "email": {
1476 "type": "string"
1477 },
1478 "email_verified_at": {
1479 "type": [
1480 "string",
1481 "null"
1482 ],
1483 "format": "date-time"
1484 },
1485 "is_admin": {
1486 "type": "boolean"
1487 },
1488 "user_id": {
1489 "type": "integer",
1490 "format": "int64"
1491 },
1492 "username": {
1493 "type": "string"
1494 },
1495 "version": {
1496 "type": "integer",
1497 "format": "int32"
1498 }
1499 }
1500 },
1501 "error": {
1502 "type": [
1503 "string",
1504 "null"
1505 ]
1506 },
1507 "error_code": {
1508 "type": [
1509 "string",
1510 "null"
1511 ]
1512 },
1513 "message": {
1514 "type": "string"
1515 },
1516 "request_id": {
1517 "type": "string"
1518 }
1519 }
1520 },
1521 "Envelope_NoData": {
1522 "type": "object",
1523 "required": [
1524 "code",
1525 "message"
1526 ],
1527 "properties": {
1528 "code": {
1529 "type": "integer",
1530 "format": "int32"
1531 },
1532 "data": {
1533 "default": null
1534 },
1535 "error": {
1536 "type": [
1537 "string",
1538 "null"
1539 ]
1540 },
1541 "error_code": {
1542 "type": [
1543 "string",
1544 "null"
1545 ]
1546 },
1547 "message": {
1548 "type": "string"
1549 },
1550 "request_id": {
1551 "type": "string"
1552 }
1553 }
1554 },
1555 "Envelope_PasswordResetConfirmResponse": {
1556 "type": "object",
1557 "required": [
1558 "code",
1559 "message"
1560 ],
1561 "properties": {
1562 "code": {
1563 "type": "integer",
1564 "format": "int32"
1565 },
1566 "data": {
1567 "type": "object",
1568 "required": [
1569 "user_id"
1570 ],
1571 "properties": {
1572 "user_id": {
1573 "type": "integer",
1574 "format": "int64"
1575 }
1576 }
1577 },
1578 "error": {
1579 "type": [
1580 "string",
1581 "null"
1582 ]
1583 },
1584 "error_code": {
1585 "type": [
1586 "string",
1587 "null"
1588 ]
1589 },
1590 "message": {
1591 "type": "string"
1592 },
1593 "request_id": {
1594 "type": "string"
1595 }
1596 }
1597 },
1598 "Envelope_PasswordResetResponse": {
1599 "type": "object",
1600 "required": [
1601 "code",
1602 "message"
1603 ],
1604 "properties": {
1605 "code": {
1606 "type": "integer",
1607 "format": "int32"
1608 },
1609 "data": {
1610 "type": "object",
1611 "required": [
1612 "expires_in_secs"
1613 ],
1614 "properties": {
1615 "expires_in_secs": {
1616 "type": "integer",
1617 "format": "int64",
1618 "minimum": 0
1619 }
1620 }
1621 },
1622 "error": {
1623 "type": [
1624 "string",
1625 "null"
1626 ]
1627 },
1628 "error_code": {
1629 "type": [
1630 "string",
1631 "null"
1632 ]
1633 },
1634 "message": {
1635 "type": "string"
1636 },
1637 "request_id": {
1638 "type": "string"
1639 }
1640 }
1641 },
1642 "Envelope_RegisterCodeResponse": {
1643 "type": "object",
1644 "required": [
1645 "code",
1646 "message"
1647 ],
1648 "properties": {
1649 "code": {
1650 "type": "integer",
1651 "format": "int32"
1652 },
1653 "data": {
1654 "type": "object",
1655 "required": [
1656 "expires_in_secs"
1657 ],
1658 "properties": {
1659 "expires_in_secs": {
1660 "type": "integer",
1661 "format": "int64",
1662 "minimum": 0
1663 }
1664 }
1665 },
1666 "error": {
1667 "type": [
1668 "string",
1669 "null"
1670 ]
1671 },
1672 "error_code": {
1673 "type": [
1674 "string",
1675 "null"
1676 ]
1677 },
1678 "message": {
1679 "type": "string"
1680 },
1681 "request_id": {
1682 "type": "string"
1683 }
1684 }
1685 },
1686 "Envelope_SshKeySummary": {
1687 "type": "object",
1688 "required": [
1689 "code",
1690 "message"
1691 ],
1692 "properties": {
1693 "code": {
1694 "type": "integer",
1695 "format": "int32"
1696 },
1697 "data": {
1698 "type": "object",
1699 "required": [
1700 "id",
1701 "name",
1702 "algorithm",
1703 "fingerprint",
1704 "public_key",
1705 "created_at"
1706 ],
1707 "properties": {
1708 "algorithm": {
1709 "$ref": "#/components/schemas/SshKeyAlgorithm"
1710 },
1711 "created_at": {
1712 "type": "string",
1713 "format": "date-time"
1714 },
1715 "description": {
1716 "type": [
1717 "string",
1718 "null"
1719 ]
1720 },
1721 "expires_at": {
1722 "type": [
1723 "string",
1724 "null"
1725 ],
1726 "format": "date-time"
1727 },
1728 "fingerprint": {
1729 "type": "string"
1730 },
1731 "id": {
1732 "type": "string",
1733 "format": "uuid"
1734 },
1735 "last_used_at": {
1736 "type": [
1737 "string",
1738 "null"
1739 ],
1740 "format": "date-time"
1741 },
1742 "name": {
1743 "type": "string"
1744 },
1745 "public_key": {
1746 "type": "string"
1747 },
1748 "revoked_at": {
1749 "type": [
1750 "string",
1751 "null"
1752 ],
1753 "format": "date-time"
1754 }
1755 }
1756 },
1757 "error": {
1758 "type": [
1759 "string",
1760 "null"
1761 ]
1762 },
1763 "error_code": {
1764 "type": [
1765 "string",
1766 "null"
1767 ]
1768 },
1769 "message": {
1770 "type": "string"
1771 },
1772 "request_id": {
1773 "type": "string"
1774 }
1775 }
1776 },
1777 "Envelope_UserLoginResponse": {
1778 "type": "object",
1779 "required": [
1780 "code",
1781 "message"
1782 ],
1783 "properties": {
1784 "code": {
1785 "type": "integer",
1786 "format": "int32"
1787 },
1788 "data": {
1789 "type": "object",
1790 "required": [
1791 "user_id",
1792 "username",
1793 "mfa_required"
1794 ],
1795 "properties": {
1796 "challenge": {
1797 "type": [
1798 "string",
1799 "null"
1800 ]
1801 },
1802 "displayname": {
1803 "type": [
1804 "string",
1805 "null"
1806 ]
1807 },
1808 "mfa_required": {
1809 "type": "boolean"
1810 },
1811 "user_id": {
1812 "type": "integer",
1813 "format": "int64"
1814 },
1815 "username": {
1816 "type": "string"
1817 }
1818 }
1819 },
1820 "error": {
1821 "type": [
1822 "string",
1823 "null"
1824 ]
1825 },
1826 "error_code": {
1827 "type": [
1828 "string",
1829 "null"
1830 ]
1831 },
1832 "message": {
1833 "type": "string"
1834 },
1835 "request_id": {
1836 "type": "string"
1837 }
1838 }
1839 },
1840 "Envelope_UserRegisterResponse": {
1841 "type": "object",
1842 "required": [
1843 "code",
1844 "message"
1845 ],
1846 "properties": {
1847 "code": {
1848 "type": "integer",
1849 "format": "int32"
1850 },
1851 "data": {
1852 "type": "object",
1853 "required": [
1854 "user_id",
1855 "username"
1856 ],
1857 "properties": {
1858 "displayname": {
1859 "type": [
1860 "string",
1861 "null"
1862 ]
1863 },
1864 "user_id": {
1865 "type": "integer",
1866 "format": "int64"
1867 },
1868 "username": {
1869 "type": "string"
1870 }
1871 }
1872 },
1873 "error": {
1874 "type": [
1875 "string",
1876 "null"
1877 ]
1878 },
1879 "error_code": {
1880 "type": [
1881 "string",
1882 "null"
1883 ]
1884 },
1885 "message": {
1886 "type": "string"
1887 },
1888 "request_id": {
1889 "type": "string"
1890 }
1891 }
1892 },
1893 "Envelope_Vec_SshKeySummary": {
1894 "type": "object",
1895 "required": [
1896 "code",
1897 "message"
1898 ],
1899 "properties": {
1900 "code": {
1901 "type": "integer",
1902 "format": "int32"
1903 },
1904 "data": {
1905 "type": "array",
1906 "items": {
1907 "type": "object",
1908 "required": [
1909 "id",
1910 "name",
1911 "algorithm",
1912 "fingerprint",
1913 "public_key",
1914 "created_at"
1915 ],
1916 "properties": {
1917 "algorithm": {
1918 "$ref": "#/components/schemas/SshKeyAlgorithm"
1919 },
1920 "created_at": {
1921 "type": "string",
1922 "format": "date-time"
1923 },
1924 "description": {
1925 "type": [
1926 "string",
1927 "null"
1928 ]
1929 },
1930 "expires_at": {
1931 "type": [
1932 "string",
1933 "null"
1934 ],
1935 "format": "date-time"
1936 },
1937 "fingerprint": {
1938 "type": "string"
1939 },
1940 "id": {
1941 "type": "string",
1942 "format": "uuid"
1943 },
1944 "last_used_at": {
1945 "type": [
1946 "string",
1947 "null"
1948 ],
1949 "format": "date-time"
1950 },
1951 "name": {
1952 "type": "string"
1953 },
1954 "public_key": {
1955 "type": "string"
1956 },
1957 "revoked_at": {
1958 "type": [
1959 "string",
1960 "null"
1961 ],
1962 "format": "date-time"
1963 }
1964 }
1965 }
1966 },
1967 "error": {
1968 "type": [
1969 "string",
1970 "null"
1971 ]
1972 },
1973 "error_code": {
1974 "type": [
1975 "string",
1976 "null"
1977 ]
1978 },
1979 "message": {
1980 "type": "string"
1981 },
1982 "request_id": {
1983 "type": "string"
1984 }
1985 }
1986 },
1987 "LoginCodeRequest": {
1988 "type": "object",
1989 "required": [
1990 "email",
1991 "pow_payload"
1992 ],
1993 "properties": {
1994 "email": {
1995 "type": "string"
1996 },
1997 "pow_payload": {
1998 "$ref": "#/components/schemas/PowProofRequest"
1999 }
2000 }
2001 },
2002 "LoginCodeResponse": {
2003 "type": "object",
2004 "required": [
2005 "expires_in_secs"
2006 ],
2007 "properties": {
2008 "expires_in_secs": {
2009 "type": "integer",
2010 "format": "int64",
2011 "minimum": 0
2012 }
2013 }
2014 },
2015 "LoginCodeVerifyRequest": {
2016 "type": "object",
2017 "required": [
2018 "email",
2019 "email_code",
2020 "pow_payload"
2021 ],
2022 "properties": {
2023 "email": {
2024 "type": "string"
2025 },
2026 "email_code": {
2027 "type": "string"
2028 },
2029 "pow_payload": {
2030 "$ref": "#/components/schemas/PowProofRequest"
2031 }
2032 }
2033 },
2034 "LoginVerifyRequest": {
2035 "type": "object",
2036 "required": [
2037 "challenge",
2038 "code"
2039 ],
2040 "properties": {
2041 "challenge": {
2042 "type": "string"
2043 },
2044 "code": {
2045 "type": "string"
2046 }
2047 }
2048 },
2049 "LogoutResponse": {
2050 "type": "object",
2051 "properties": {
2052 "user_id": {
2053 "type": [
2054 "integer",
2055 "null"
2056 ],
2057 "format": "int64"
2058 }
2059 }
2060 },
2061 "MeResponse": {
2062 "type": "object",
2063 "required": [
2064 "user_id",
2065 "username",
2066 "email",
2067 "is_admin",
2068 "created_at",
2069 "version"
2070 ],
2071 "properties": {
2072 "avatar_url": {
2073 "type": [
2074 "string",
2075 "null"
2076 ]
2077 },
2078 "created_at": {
2079 "type": "string",
2080 "format": "date-time"
2081 },
2082 "displayname": {
2083 "type": [
2084 "string",
2085 "null"
2086 ]
2087 },
2088 "email": {
2089 "type": "string"
2090 },
2091 "email_verified_at": {
2092 "type": [
2093 "string",
2094 "null"
2095 ],
2096 "format": "date-time"
2097 },
2098 "is_admin": {
2099 "type": "boolean"
2100 },
2101 "user_id": {
2102 "type": "integer",
2103 "format": "int64"
2104 },
2105 "username": {
2106 "type": "string"
2107 },
2108 "version": {
2109 "type": "integer",
2110 "format": "int32"
2111 }
2112 }
2113 },
2114 "NoData": {
2115 "default": null
2116 },
2117 "PasswordResetConfirmRequest": {
2118 "type": "object",
2119 "required": [
2120 "token",
2121 "password_hash",
2122 "pow_payload"
2123 ],
2124 "properties": {
2125 "password_hash": {
2126 "type": "string"
2127 },
2128 "pow_payload": {
2129 "$ref": "#/components/schemas/PowProofRequest"
2130 },
2131 "token": {
2132 "type": "string"
2133 }
2134 }
2135 },
2136 "PasswordResetConfirmResponse": {
2137 "type": "object",
2138 "required": [
2139 "user_id"
2140 ],
2141 "properties": {
2142 "user_id": {
2143 "type": "integer",
2144 "format": "int64"
2145 }
2146 }
2147 },
2148 "PasswordResetRequest": {
2149 "type": "object",
2150 "required": [
2151 "email",
2152 "pow_payload"
2153 ],
2154 "properties": {
2155 "email": {
2156 "type": "string"
2157 },
2158 "pow_payload": {
2159 "$ref": "#/components/schemas/PowProofRequest"
2160 }
2161 }
2162 },
2163 "PasswordResetResponse": {
2164 "type": "object",
2165 "required": [
2166 "expires_in_secs"
2167 ],
2168 "properties": {
2169 "expires_in_secs": {
2170 "type": "integer",
2171 "format": "int64",
2172 "minimum": 0
2173 }
2174 }
2175 },
2176 "PowProofRequest": {
2177 "type": "object",
2178 "required": [
2179 "nonce",
2180 "payload"
2181 ],
2182 "properties": {
2183 "nonce": {
2184 "type": "integer",
2185 "format": "int64",
2186 "minimum": 0
2187 },
2188 "payload": {
2189 "type": "array",
2190 "items": {
2191 "type": "integer",
2192 "format": "int32",
2193 "minimum": 0
2194 }
2195 }
2196 }
2197 },
2198 "RegisterCodeRequest": {
2199 "type": "object",
2200 "required": [
2201 "email",
2202 "pow_payload"
2203 ],
2204 "properties": {
2205 "email": {
2206 "type": "string"
2207 },
2208 "pow_payload": {
2209 "$ref": "#/components/schemas/PowProofRequest"
2210 }
2211 }
2212 },
2213 "RegisterCodeResponse": {
2214 "type": "object",
2215 "required": [
2216 "expires_in_secs"
2217 ],
2218 "properties": {
2219 "expires_in_secs": {
2220 "type": "integer",
2221 "format": "int64",
2222 "minimum": 0
2223 }
2224 }
2225 },
2226 "SshKeyAddRequest": {
2227 "type": "object",
2228 "required": [
2229 "name",
2230 "public_key"
2231 ],
2232 "properties": {
2233 "description": {
2234 "type": [
2235 "string",
2236 "null"
2237 ]
2238 },
2239 "expires_at": {
2240 "type": [
2241 "string",
2242 "null"
2243 ],
2244 "format": "date-time"
2245 },
2246 "name": {
2247 "type": "string"
2248 },
2249 "public_key": {
2250 "type": "string"
2251 }
2252 }
2253 },
2254 "SshKeyAlgorithm": {
2255 "type": "string",
2256 "enum": [
2257 "rsa",
2258 "ed25519",
2259 "ecdsa"
2260 ]
2261 },
2262 "SshKeySummary": {
2263 "type": "object",
2264 "required": [
2265 "id",
2266 "name",
2267 "algorithm",
2268 "fingerprint",
2269 "public_key",
2270 "created_at"
2271 ],
2272 "properties": {
2273 "algorithm": {
2274 "$ref": "#/components/schemas/SshKeyAlgorithm"
2275 },
2276 "created_at": {
2277 "type": "string",
2278 "format": "date-time"
2279 },
2280 "description": {
2281 "type": [
2282 "string",
2283 "null"
2284 ]
2285 },
2286 "expires_at": {
2287 "type": [
2288 "string",
2289 "null"
2290 ],
2291 "format": "date-time"
2292 },
2293 "fingerprint": {
2294 "type": "string"
2295 },
2296 "id": {
2297 "type": "string",
2298 "format": "uuid"
2299 },
2300 "last_used_at": {
2301 "type": [
2302 "string",
2303 "null"
2304 ],
2305 "format": "date-time"
2306 },
2307 "name": {
2308 "type": "string"
2309 },
2310 "public_key": {
2311 "type": "string"
2312 },
2313 "revoked_at": {
2314 "type": [
2315 "string",
2316 "null"
2317 ],
2318 "format": "date-time"
2319 }
2320 }
2321 },
2322 "UserLoginRequest": {
2323 "type": "object",
2324 "required": [
2325 "identity",
2326 "password_hash",
2327 "pow_payload"
2328 ],
2329 "properties": {
2330 "identity": {
2331 "type": "string"
2332 },
2333 "password_hash": {
2334 "type": "string"
2335 },
2336 "pow_payload": {
2337 "$ref": "#/components/schemas/PowProofRequest"
2338 }
2339 }
2340 },
2341 "UserLoginResponse": {
2342 "type": "object",
2343 "required": [
2344 "user_id",
2345 "username",
2346 "mfa_required"
2347 ],
2348 "properties": {
2349 "challenge": {
2350 "type": [
2351 "string",
2352 "null"
2353 ]
2354 },
2355 "displayname": {
2356 "type": [
2357 "string",
2358 "null"
2359 ]
2360 },
2361 "mfa_required": {
2362 "type": "boolean"
2363 },
2364 "user_id": {
2365 "type": "integer",
2366 "format": "int64"
2367 },
2368 "username": {
2369 "type": "string"
2370 }
2371 }
2372 },
2373 "UserRegisterRequest": {
2374 "type": "object",
2375 "required": [
2376 "username",
2377 "birth_date",
2378 "email",
2379 "password_hash",
2380 "email_code",
2381 "pow_payload"
2382 ],
2383 "properties": {
2384 "birth_date": {
2385 "type": "string"
2386 },
2387 "displayname": {
2388 "type": [
2389 "string",
2390 "null"
2391 ]
2392 },
2393 "email": {
2394 "type": "string"
2395 },
2396 "email_code": {
2397 "type": "string"
2398 },
2399 "password_hash": {
2400 "type": "string"
2401 },
2402 "pow_payload": {
2403 "$ref": "#/components/schemas/PowProofRequest"
2404 },
2405 "username": {
2406 "type": "string"
2407 }
2408 }
2409 },
2410 "UserRegisterResponse": {
2411 "type": "object",
2412 "required": [
2413 "user_id",
2414 "username"
2415 ],
2416 "properties": {
2417 "displayname": {
2418 "type": [
2419 "string",
2420 "null"
2421 ]
2422 },
2423 "user_id": {
2424 "type": "integer",
2425 "format": "int64"
2426 },
2427 "username": {
2428 "type": "string"
2429 }
2430 }
2431 }
2432 }
2433 }
2434}
No newline at end of file
Modified lib/chat/src/handlers/dms.rs View lib/chat/src/handlers/dms.rs
@@ -13,7 +13,6 @@
1313 path = "/chat/dms",
1414 tag = "chat",
1515 description = "打开与指定用户的私聊会话;已有会话则恢复,新会话则创建。",
16 params(export::pagination::PageQuery),
1716 request_body = OpenDmCmd,
1817 responses(
1918 (status = 200, description = "dm opened", body = AppResponseData<DmDto>),
Modified lib/git/src/handler/remotes/fetch.rs View lib/git/src/handler/remotes/fetch.rs
@@ -18,6 +18,7 @@
1818 post,
1919 path = "/repos/{space_name}/{repo_name}/remotes/fetch",
2020 tag = "remotes",
21 operation_id = "fetch_remote",
2122 description = "从指定远程抓取引用并修剪已删除的远端分支。",
2223 params(RepoPath),
2324 request_body = RemoteFetchBody,
Added packages/apiclient/account/accept-agreement.schemas.ts View packages/apiclient/account/accept-agreement.schemas.ts
@@ -0,0 +1,117 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface AcceptAgreementCmd {
90 version: string;
91}
92
93export type EnvelopeAcceptAgreementRespData = {
94 recorded: boolean;
95};
96
97export interface EnvelopeAcceptAgreementResp {
98 code: number;
99 data?: EnvelopeAcceptAgreementRespData;
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
107
108export interface EnvelopeNoData {
109 code: number;
110 data?: unknown;
111 /** @nullable */
112 error?: string | null;
113 /** @nullable */
114 error_code?: string | null;
115 message: string;
116 request_id?: string;
117}
Added packages/apiclient/account/accept-agreement.ts View packages/apiclient/account/accept-agreement.ts
@@ -0,0 +1,173 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 AcceptAgreementCmd,
91 EnvelopeAcceptAgreementResp,
92 EnvelopeNoData,
93} from "./accept-agreement.schemas";
94
95export type acceptAgreementResponse200 = {
96 data: EnvelopeAcceptAgreementResp;
97 status: 200;
98};
99
100export type acceptAgreementResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type acceptAgreementResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type acceptAgreementResponseSuccess = acceptAgreementResponse200 & {
111 headers: Headers;
112};
113export type acceptAgreementResponseError = (
114 acceptAgreementResponse400 | acceptAgreementResponse401
115) & {
116 headers: Headers;
117};
118
119export type acceptAgreementResponse =
120 acceptAgreementResponseSuccess | acceptAgreementResponseError;
121
122export const getAcceptAgreementUrl = (key: string) => {
123 return `/api/v1/me/agreements/${key}`;
124};
125
126/**
127 * 记录当前用户已同意指定版本的协议文本。
128 */
129export const acceptAgreement = async (
130 key: string,
131 acceptAgreementCmd: AcceptAgreementCmd,
132 options?: RequestInit,
133): Promise<acceptAgreementResponse> => {
134 const getHeaders = (
135 h?: NonNullable<RequestInit["headers"]>,
136 ): Record<string, string | readonly string[]> => {
137 if (!h) return {};
138 if (h instanceof Headers) return Object.fromEntries(h.entries());
139 if (Symbol.iterator in h) {
140 return Object.fromEntries(
141 Array.from(
142 h as Iterable<Iterable<string>>,
143 (entry) => Array.from(entry) as [string, string],
144 ),
145 );
146 }
147 const headers: Record<string, string | readonly string[]> = {};
148 for (const [name, value] of Object.entries<
149 string | readonly string[] | undefined
150 >(h)) {
151 if (value !== undefined) headers[name] = value;
152 }
153 return headers;
154 };
155 const res = await fetch(getAcceptAgreementUrl(key), {
156 ...options,
157 method: "PUT",
158 headers: {
159 "Content-Type": "application/json",
160 ...getHeaders(options?.headers),
161 },
162 body: JSON.stringify(acceptAgreementCmd),
163 });
164
165 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
166
167 const data: acceptAgreementResponse["data"] = body ? JSON.parse(body) : {};
168 return {
169 data,
170 status: res.status,
171 headers: res.headers,
172 } as acceptAgreementResponse;
173};
Added packages/apiclient/account/account-deletion-status.schemas.ts View packages/apiclient/account/account-deletion-status.schemas.ts
@@ -0,0 +1,117 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeAccountDeletionDtoData = {
90 /** @nullable */
91 last_error?: string | null;
92 purge_after: string;
93 requested_at: string;
94 status: string;
95};
96
97export interface EnvelopeAccountDeletionDto {
98 code: number;
99 data?: EnvelopeAccountDeletionDtoData;
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
107
108export interface EnvelopeNoData {
109 code: number;
110 data?: unknown;
111 /** @nullable */
112 error?: string | null;
113 /** @nullable */
114 error_code?: string | null;
115 message: string;
116 request_id?: string;
117}
Added packages/apiclient/account/account-deletion-status.ts View packages/apiclient/account/account-deletion-status.ts
@@ -0,0 +1,141 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeAccountDeletionDto,
91 EnvelopeNoData,
92} from "./account-deletion-status.schemas";
93
94export type accountDeletionStatusResponse200 = {
95 data: EnvelopeAccountDeletionDto;
96 status: 200;
97};
98
99export type accountDeletionStatusResponse401 = {
100 data: EnvelopeNoData;
101 status: 401;
102};
103
104export type accountDeletionStatusResponseSuccess =
105 accountDeletionStatusResponse200 & {
106 headers: Headers;
107 };
108export type accountDeletionStatusResponseError =
109 accountDeletionStatusResponse401 & {
110 headers: Headers;
111 };
112
113export type accountDeletionStatusResponse =
114 accountDeletionStatusResponseSuccess | accountDeletionStatusResponseError;
115
116export const getAccountDeletionStatusUrl = () => {
117 return `/api/v1/me/deletion`;
118};
119
120/**
121 * 读取当前账号的删除计划;没有计划时 data 为 null。
122 */
123export const accountDeletionStatus = async (
124 options?: RequestInit,
125): Promise<accountDeletionStatusResponse> => {
126 const res = await fetch(getAccountDeletionStatusUrl(), {
127 ...options,
128 method: "GET",
129 });
130
131 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
132
133 const data: accountDeletionStatusResponse["data"] = body
134 ? JSON.parse(body)
135 : {};
136 return {
137 data,
138 status: res.status,
139 headers: res.headers,
140 } as accountDeletionStatusResponse;
141};
Added packages/apiclient/account/cancel-account-deletion.schemas.ts View packages/apiclient/account/cancel-account-deletion.schemas.ts
@@ -0,0 +1,98 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
Added packages/apiclient/account/cancel-account-deletion.ts View packages/apiclient/account/cancel-account-deletion.ts
@@ -0,0 +1,144 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeNoData } from "./cancel-account-deletion.schemas";
90
91export type cancelAccountDeletionResponse200 = {
92 data: EnvelopeNoData;
93 status: 200;
94};
95
96export type cancelAccountDeletionResponse401 = {
97 data: EnvelopeNoData;
98 status: 401;
99};
100
101export type cancelAccountDeletionResponse404 = {
102 data: EnvelopeNoData;
103 status: 404;
104};
105
106export type cancelAccountDeletionResponseSuccess =
107 cancelAccountDeletionResponse200 & {
108 headers: Headers;
109 };
110export type cancelAccountDeletionResponseError = (
111 cancelAccountDeletionResponse401 | cancelAccountDeletionResponse404
112) & {
113 headers: Headers;
114};
115
116export type cancelAccountDeletionResponse =
117 cancelAccountDeletionResponseSuccess | cancelAccountDeletionResponseError;
118
119export const getCancelAccountDeletionUrl = () => {
120 return `/api/v1/me/deletion`;
121};
122
123/**
124 * 撤销尚未执行的账号删除计划;已撤销的会话与令牌不会恢复,需重新登录。
125 */
126export const cancelAccountDeletion = async (
127 options?: RequestInit,
128): Promise<cancelAccountDeletionResponse> => {
129 const res = await fetch(getCancelAccountDeletionUrl(), {
130 ...options,
131 method: "DELETE",
132 });
133
134 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
135
136 const data: cancelAccountDeletionResponse["data"] = body
137 ? JSON.parse(body)
138 : {};
139 return {
140 data,
141 status: res.status,
142 headers: res.headers,
143 } as cancelAccountDeletionResponse;
144};
Added packages/apiclient/account/get-preferences.schemas.ts View packages/apiclient/account/get-preferences.schemas.ts
@@ -0,0 +1,127 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type Audience = "Everyone" | "FollowingOnly" | "Nobody";
90export interface EnvelopeNoData {
91 code: number;
92 data?: unknown;
93 /** @nullable */
94 error?: string | null;
95 /** @nullable */
96 error_code?: string | null;
97 message: string;
98 request_id?: string;
99}
100
101export type EnvelopeUserPreferencesDtoData = {
102 allow_dms_from: Audience;
103 allow_mentions_from: Audience;
104 /** Default view for the 问题集 page: `board` or `list`. */
105 board_view_mode: string;
106 /** @nullable */
107 diff_view_style?: string | null;
108 email_digest: boolean;
109 email_flags: number;
110 in_app_flags: number;
111 /** @nullable */
112 mute_until?: string | null;
113 push_flags: number;
114 show_online_status: boolean;
115 theme_mode: string;
116};
117
118export interface EnvelopeUserPreferencesDto {
119 code: number;
120 data?: EnvelopeUserPreferencesDtoData;
121 /** @nullable */
122 error?: string | null;
123 /** @nullable */
124 error_code?: string | null;
125 message: string;
126 request_id?: string;
127}
Added packages/apiclient/account/get-preferences.ts View packages/apiclient/account/get-preferences.ts
@@ -0,0 +1,144 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeUserPreferencesDto,
92} from "./get-preferences.schemas";
93
94export type getPreferencesResponse200 = {
95 data: EnvelopeUserPreferencesDto;
96 status: 200;
97};
98
99export type getPreferencesResponse401 = {
100 data: EnvelopeNoData;
101 status: 401;
102};
103
104export type getPreferencesResponse404 = {
105 data: EnvelopeNoData;
106 status: 404;
107};
108
109export type getPreferencesResponseSuccess = getPreferencesResponse200 & {
110 headers: Headers;
111};
112export type getPreferencesResponseError = (
113 getPreferencesResponse401 | getPreferencesResponse404
114) & {
115 headers: Headers;
116};
117
118export type getPreferencesResponse =
119 getPreferencesResponseSuccess | getPreferencesResponseError;
120
121export const getGetPreferencesUrl = () => {
122 return `/api/v1/me/preferences`;
123};
124
125/**
126 * 读取当前用户的通知与界面偏好,未配置时返回默认值。
127 */
128export const getPreferences = async (
129 options?: RequestInit,
130): Promise<getPreferencesResponse> => {
131 const res = await fetch(getGetPreferencesUrl(), {
132 ...options,
133 method: "GET",
134 });
135
136 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
137
138 const data: getPreferencesResponse["data"] = body ? JSON.parse(body) : {};
139 return {
140 data,
141 status: res.status,
142 headers: res.headers,
143 } as getPreferencesResponse;
144};
Added packages/apiclient/account/index.ts View packages/apiclient/account/index.ts
@@ -0,0 +1,12 @@
1export * from "./list-agreements";
2export * from "./me";
3export * from "./update-profile";
4export * from "./accept-agreement";
5export * from "./account-deletion-status";
6export * from "./request-account-deletion";
7export * from "./cancel-account-deletion";
8export * from "./list-devices";
9export * from "./mark-notifications-read";
10export * from "./get-preferences";
11export * from "./update-preferences";
12export * from "./update-username";
Added packages/apiclient/account/list-agreements.schemas.ts View packages/apiclient/account/list-agreements.schemas.ts
@@ -0,0 +1,116 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeVecAgreementDocDataItem = {
101 content_md: string;
102 key: string;
103 title: string;
104 version: string;
105};
106
107export interface EnvelopeVecAgreementDoc {
108 code: number;
109 data?: EnvelopeVecAgreementDocDataItem[];
110 /** @nullable */
111 error?: string | null;
112 /** @nullable */
113 error_code?: string | null;
114 message: string;
115 request_id?: string;
116}
Added packages/apiclient/account/list-agreements.ts View packages/apiclient/account/list-agreements.ts
@@ -0,0 +1,137 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeVecAgreementDoc,
92} from "./list-agreements.schemas";
93
94export type listAgreementsResponse200 = {
95 data: EnvelopeVecAgreementDoc;
96 status: 200;
97};
98
99export type listAgreementsResponse404 = {
100 data: EnvelopeNoData;
101 status: 404;
102};
103
104export type listAgreementsResponseSuccess = listAgreementsResponse200 & {
105 headers: Headers;
106};
107export type listAgreementsResponseError = listAgreementsResponse404 & {
108 headers: Headers;
109};
110
111export type listAgreementsResponse =
112 listAgreementsResponseSuccess | listAgreementsResponseError;
113
114export const getListAgreementsUrl = () => {
115 return `/api/v1/auth/agreements`;
116};
117
118/**
119 * 返回服务端配置中的协议列表及其当前版本与正文。
120 */
121export const listAgreements = async (
122 options?: RequestInit,
123): Promise<listAgreementsResponse> => {
124 const res = await fetch(getListAgreementsUrl(), {
125 ...options,
126 method: "GET",
127 });
128
129 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
130
131 const data: listAgreementsResponse["data"] = body ? JSON.parse(body) : {};
132 return {
133 data,
134 status: res.status,
135 headers: res.headers,
136 } as listAgreementsResponse;
137};
Added packages/apiclient/account/list-devices.schemas.ts View packages/apiclient/account/list-devices.schemas.ts
@@ -0,0 +1,128 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeVecDeviceDtoDataItem = {
90 /** @nullable */
91 device_name?: string | null;
92 /** @nullable */
93 device_type?: string | null;
94 first_seen_at: string;
95 id: string;
96 is_trusted: boolean;
97 last_seen_at: string;
98 /** @nullable */
99 os?: string | null;
100};
101
102export interface EnvelopeVecDeviceDto {
103 code: number;
104 data?: EnvelopeVecDeviceDtoDataItem[];
105 /** @nullable */
106 error?: string | null;
107 /** @nullable */
108 error_code?: string | null;
109 message: string;
110 request_id?: string;
111}
112
113export type ListDevicesParams = {
114 /**
115 * @minimum 0
116 * @nullable
117 */
118 limit?: number | null;
119 /**
120 * @minimum 0
121 * @nullable
122 */
123 offset?: number | null;
124 /**
125 * @nullable
126 */
127 sort?: string | null;
128};
Added packages/apiclient/account/list-devices.ts View packages/apiclient/account/list-devices.ts
@@ -0,0 +1,150 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeVecDeviceDto,
91 ListDevicesParams,
92} from "./list-devices.schemas";
93
94export type listDevicesResponse200 = {
95 data: EnvelopeVecDeviceDto;
96 status: 200;
97};
98
99export type listDevicesResponse401 = {
100 data: EnvelopeVecDeviceDto;
101 status: 401;
102};
103
104export type listDevicesResponseSuccess = listDevicesResponse200 & {
105 headers: Headers;
106};
107export type listDevicesResponseError = listDevicesResponse401 & {
108 headers: Headers;
109};
110
111export type listDevicesResponse =
112 listDevicesResponseSuccess | listDevicesResponseError;
113
114export const getListDevicesUrl = (params?: ListDevicesParams) => {
115 const normalizedParams = new URLSearchParams();
116
117 Object.entries(params || {}).forEach(([key, value]) => {
118 if (value !== undefined) {
119 normalizedParams.append(key, value === null ? "null" : String(value));
120 }
121 });
122
123 const stringifiedParams = normalizedParams.toString();
124
125 return stringifiedParams.length > 0
126 ? `/api/v1/me/devices?${stringifiedParams}`
127 : `/api/v1/me/devices`;
128};
129
130/**
131 * 按会话的用户代理归并出当前账号出现过的设备及其最近活跃时间。
132 */
133export const listDevices = async (
134 params?: ListDevicesParams,
135 options?: RequestInit,
136): Promise<listDevicesResponse> => {
137 const res = await fetch(getListDevicesUrl(params), {
138 ...options,
139 method: "GET",
140 });
141
142 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
143
144 const data: listDevicesResponse["data"] = body ? JSON.parse(body) : {};
145 return {
146 data,
147 status: res.status,
148 headers: res.headers,
149 } as listDevicesResponse;
150};
Added packages/apiclient/account/mark-notifications-read.schemas.ts View packages/apiclient/account/mark-notifications-read.schemas.ts
@@ -0,0 +1,120 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeMarkedCountRespData = {
90 /** @minimum 0 */
91 marked: number;
92};
93
94export interface EnvelopeMarkedCountResp {
95 code: number;
96 data?: EnvelopeMarkedCountRespData;
97 /** @nullable */
98 error?: string | null;
99 /** @nullable */
100 error_code?: string | null;
101 message: string;
102 request_id?: string;
103}
104
105export interface EnvelopeNoData {
106 code: number;
107 data?: unknown;
108 /** @nullable */
109 error?: string | null;
110 /** @nullable */
111 error_code?: string | null;
112 message: string;
113 request_id?: string;
114}
115
116export interface MarkNotificationsReadCmd {
117 all?: boolean;
118 /** @nullable */
119 ids?: string[] | null;
120}
Added packages/apiclient/account/mark-notifications-read.ts View packages/apiclient/account/mark-notifications-read.ts
@@ -0,0 +1,175 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMarkedCountResp,
91 EnvelopeNoData,
92 MarkNotificationsReadCmd,
93} from "./mark-notifications-read.schemas";
94
95export type markNotificationsReadResponse200 = {
96 data: EnvelopeMarkedCountResp;
97 status: 200;
98};
99
100export type markNotificationsReadResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type markNotificationsReadResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type markNotificationsReadResponseSuccess =
111 markNotificationsReadResponse200 & {
112 headers: Headers;
113 };
114export type markNotificationsReadResponseError = (
115 markNotificationsReadResponse400 | markNotificationsReadResponse401
116) & {
117 headers: Headers;
118};
119
120export type markNotificationsReadResponse =
121 markNotificationsReadResponseSuccess | markNotificationsReadResponseError;
122
123export const getMarkNotificationsReadUrl = () => {
124 return `/api/v1/me/notifications/read`;
125};
126
127/**
128 * 按通知 ID 集合或 all=true 将当前用户的通知标记为已读。
129 */
130export const markNotificationsRead = async (
131 markNotificationsReadCmd: MarkNotificationsReadCmd,
132 options?: RequestInit,
133): Promise<markNotificationsReadResponse> => {
134 const getHeaders = (
135 h?: NonNullable<RequestInit["headers"]>,
136 ): Record<string, string | readonly string[]> => {
137 if (!h) return {};
138 if (h instanceof Headers) return Object.fromEntries(h.entries());
139 if (Symbol.iterator in h) {
140 return Object.fromEntries(
141 Array.from(
142 h as Iterable<Iterable<string>>,
143 (entry) => Array.from(entry) as [string, string],
144 ),
145 );
146 }
147 const headers: Record<string, string | readonly string[]> = {};
148 for (const [name, value] of Object.entries<
149 string | readonly string[] | undefined
150 >(h)) {
151 if (value !== undefined) headers[name] = value;
152 }
153 return headers;
154 };
155 const res = await fetch(getMarkNotificationsReadUrl(), {
156 ...options,
157 method: "PUT",
158 headers: {
159 "Content-Type": "application/json",
160 ...getHeaders(options?.headers),
161 },
162 body: JSON.stringify(markNotificationsReadCmd),
163 });
164
165 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
166
167 const data: markNotificationsReadResponse["data"] = body
168 ? JSON.parse(body)
169 : {};
170 return {
171 data,
172 status: res.status,
173 headers: res.headers,
174 } as markNotificationsReadResponse;
175};
Added packages/apiclient/account/me.schemas.ts View packages/apiclient/account/me.schemas.ts
@@ -0,0 +1,159 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface ProfileDto {
90 /** @nullable */
91 bio?: string | null;
92 /** @nullable */
93 company?: string | null;
94 /** @nullable */
95 date_of_birth?: string | null;
96 /** @nullable */
97 location?: string | null;
98 /** @nullable */
99 privacy_agreed_at?: string | null;
100 /** @nullable */
101 pronouns?: string | null;
102 /** @nullable */
103 real_name?: string | null;
104 show_activity: boolean;
105 show_email: boolean;
106 show_location: boolean;
107 show_real_name: boolean;
108 /** @nullable */
109 website?: string | null;
110}
111
112export type ProfileVisibility =
113 "Public" | "RegisteredOnly" | "MembersOnly" | "Private";
114export interface UserMeDto {
115 avatar_url: string;
116 bot: boolean;
117 created_at: string;
118 display_name: string;
119 is_active: boolean;
120 is_restricted: boolean;
121 /** @nullable */
122 language?: string | null;
123 /** @nullable */
124 locale?: string | null;
125 prohibit_login: boolean;
126 system: boolean;
127 /** @nullable */
128 timezone?: string | null;
129 user_id: number;
130 username: string;
131 visibility: ProfileVisibility;
132}
133
134export type EnvelopeMeRespData = {
135 profile?: null | ProfileDto;
136 user: UserMeDto;
137};
138
139export interface EnvelopeMeResp {
140 code: number;
141 data?: EnvelopeMeRespData;
142 /** @nullable */
143 error?: string | null;
144 /** @nullable */
145 error_code?: string | null;
146 message: string;
147 request_id?: string;
148}
149
150export interface EnvelopeNoData {
151 code: number;
152 data?: unknown;
153 /** @nullable */
154 error?: string | null;
155 /** @nullable */
156 error_code?: string | null;
157 message: string;
158 request_id?: string;
159}
Added packages/apiclient/account/me.ts View packages/apiclient/account/me.ts
@@ -0,0 +1,132 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeMeResp, EnvelopeNoData } from "./me.schemas";
90
91export type meResponse200 = {
92 data: EnvelopeMeResp;
93 status: 200;
94};
95
96export type meResponse401 = {
97 data: EnvelopeNoData;
98 status: 401;
99};
100
101export type meResponse404 = {
102 data: EnvelopeNoData;
103 status: 404;
104};
105
106export type meResponseSuccess = meResponse200 & {
107 headers: Headers;
108};
109export type meResponseError = (meResponse401 | meResponse404) & {
110 headers: Headers;
111};
112
113export type meResponse = meResponseSuccess | meResponseError;
114
115export const getMeUrl = () => {
116 return `/api/v1/me`;
117};
118
119/**
120 * 返回当前登录用户的身份、账号状态与资料。
121 */
122export const me = async (options?: RequestInit): Promise<meResponse> => {
123 const res = await fetch(getMeUrl(), {
124 ...options,
125 method: "GET",
126 });
127
128 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
129
130 const data: meResponse["data"] = body ? JSON.parse(body) : {};
131 return { data, status: res.status, headers: res.headers } as meResponse;
132};
Added packages/apiclient/account/request-account-deletion.schemas.ts View packages/apiclient/account/request-account-deletion.schemas.ts
@@ -0,0 +1,117 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeAccountDeletionDtoData = {
90 /** @nullable */
91 last_error?: string | null;
92 purge_after: string;
93 requested_at: string;
94 status: string;
95};
96
97export interface EnvelopeAccountDeletionDto {
98 code: number;
99 data?: EnvelopeAccountDeletionDtoData;
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
107
108export interface EnvelopeNoData {
109 code: number;
110 data?: unknown;
111 /** @nullable */
112 error?: string | null;
113 /** @nullable */
114 error_code?: string | null;
115 message: string;
116 request_id?: string;
117}
Added packages/apiclient/account/request-account-deletion.ts View packages/apiclient/account/request-account-deletion.ts
@@ -0,0 +1,147 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeAccountDeletionDto,
91 EnvelopeNoData,
92} from "./request-account-deletion.schemas";
93
94export type requestAccountDeletionResponse200 = {
95 data: EnvelopeAccountDeletionDto;
96 status: 200;
97};
98
99export type requestAccountDeletionResponse401 = {
100 data: EnvelopeNoData;
101 status: 401;
102};
103
104export type requestAccountDeletionResponse409 = {
105 data: EnvelopeNoData;
106 status: 409;
107};
108
109export type requestAccountDeletionResponseSuccess =
110 requestAccountDeletionResponse200 & {
111 headers: Headers;
112 };
113export type requestAccountDeletionResponseError = (
114 requestAccountDeletionResponse401 | requestAccountDeletionResponse409
115) & {
116 headers: Headers;
117};
118
119export type requestAccountDeletionResponse =
120 requestAccountDeletionResponseSuccess | requestAccountDeletionResponseError;
121
122export const getRequestAccountDeletionUrl = () => {
123 return `/api/v1/me/deletion`;
124};
125
126/**
127 * 申请删除当前账号:立即软删并撤销全部会话/令牌/SSH 公钥,宽限期后匿名化。仍有活跃组织 OWNER 身份时返回 409。
128 */
129export const requestAccountDeletion = async (
130 options?: RequestInit,
131): Promise<requestAccountDeletionResponse> => {
132 const res = await fetch(getRequestAccountDeletionUrl(), {
133 ...options,
134 method: "POST",
135 });
136
137 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
138
139 const data: requestAccountDeletionResponse["data"] = body
140 ? JSON.parse(body)
141 : {};
142 return {
143 data,
144 status: res.status,
145 headers: res.headers,
146 } as requestAccountDeletionResponse;
147};
Added packages/apiclient/account/update-preferences.schemas.ts View packages/apiclient/account/update-preferences.schemas.ts
@@ -0,0 +1,154 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type Audience = "Everyone" | "FollowingOnly" | "Nobody";
90export interface EnvelopeNoData {
91 code: number;
92 data?: unknown;
93 /** @nullable */
94 error?: string | null;
95 /** @nullable */
96 error_code?: string | null;
97 message: string;
98 request_id?: string;
99}
100
101export type EnvelopeUserPreferencesDtoData = {
102 allow_dms_from: Audience;
103 allow_mentions_from: Audience;
104 /** Default view for the 问题集 page: `board` or `list`. */
105 board_view_mode: string;
106 /** @nullable */
107 diff_view_style?: string | null;
108 email_digest: boolean;
109 email_flags: number;
110 in_app_flags: number;
111 /** @nullable */
112 mute_until?: string | null;
113 push_flags: number;
114 show_online_status: boolean;
115 theme_mode: string;
116};
117
118export interface EnvelopeUserPreferencesDto {
119 code: number;
120 data?: EnvelopeUserPreferencesDtoData;
121 /** @nullable */
122 error?: string | null;
123 /** @nullable */
124 error_code?: string | null;
125 message: string;
126 request_id?: string;
127}
128
129export interface UpdatePreferencesCmd {
130 allow_dms_from?: null | Audience;
131 allow_mentions_from?: null | Audience;
132 /** @nullable */
133 board_view_mode?: string | null;
134 /** @nullable */
135 diff_view_style?: string | null;
136 /** @nullable */
137 email_digest?: boolean | null;
138 /** @nullable */
139 email_flags?: number | null;
140 /** @nullable */
141 in_app_flags?: number | null;
142 /**
143 * 三态:缺省不动、`null` 清除、给值设置(与 `lib/webapi/src/openapi.rs`
144 * 声明的 PATCH 语义一致)。
145 * @nullable
146 */
147 mute_until?: string | null;
148 /** @nullable */
149 push_flags?: number | null;
150 /** @nullable */
151 show_online_status?: boolean | null;
152 /** @nullable */
153 theme_mode?: string | null;
154}
Added packages/apiclient/account/update-preferences.ts View packages/apiclient/account/update-preferences.ts
@@ -0,0 +1,172 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeUserPreferencesDto,
92 UpdatePreferencesCmd,
93} from "./update-preferences.schemas";
94
95export type updatePreferencesResponse200 = {
96 data: EnvelopeUserPreferencesDto;
97 status: 200;
98};
99
100export type updatePreferencesResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type updatePreferencesResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type updatePreferencesResponseSuccess = updatePreferencesResponse200 & {
111 headers: Headers;
112};
113export type updatePreferencesResponseError = (
114 updatePreferencesResponse400 | updatePreferencesResponse401
115) & {
116 headers: Headers;
117};
118
119export type updatePreferencesResponse =
120 updatePreferencesResponseSuccess | updatePreferencesResponseError;
121
122export const getUpdatePreferencesUrl = () => {
123 return `/api/v1/me/preferences`;
124};
125
126/**
127 * 增量更新当前用户的通知、界面和静音等偏好设置。
128 */
129export const updatePreferences = async (
130 updatePreferencesCmd: UpdatePreferencesCmd,
131 options?: RequestInit,
132): Promise<updatePreferencesResponse> => {
133 const getHeaders = (
134 h?: NonNullable<RequestInit["headers"]>,
135 ): Record<string, string | readonly string[]> => {
136 if (!h) return {};
137 if (h instanceof Headers) return Object.fromEntries(h.entries());
138 if (Symbol.iterator in h) {
139 return Object.fromEntries(
140 Array.from(
141 h as Iterable<Iterable<string>>,
142 (entry) => Array.from(entry) as [string, string],
143 ),
144 );
145 }
146 const headers: Record<string, string | readonly string[]> = {};
147 for (const [name, value] of Object.entries<
148 string | readonly string[] | undefined
149 >(h)) {
150 if (value !== undefined) headers[name] = value;
151 }
152 return headers;
153 };
154 const res = await fetch(getUpdatePreferencesUrl(), {
155 ...options,
156 method: "PATCH",
157 headers: {
158 "Content-Type": "application/json",
159 ...getHeaders(options?.headers),
160 },
161 body: JSON.stringify(updatePreferencesCmd),
162 });
163
164 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
165
166 const data: updatePreferencesResponse["data"] = body ? JSON.parse(body) : {};
167 return {
168 data,
169 status: res.status,
170 headers: res.headers,
171 } as updatePreferencesResponse;
172};
Added packages/apiclient/account/update-profile.schemas.ts View packages/apiclient/account/update-profile.schemas.ts
@@ -0,0 +1,134 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type ProfileVisibility =
90 "Public" | "RegisteredOnly" | "MembersOnly" | "Private";
91export interface EnvelopeNoData {
92 code: number;
93 data?: unknown;
94 /** @nullable */
95 error?: string | null;
96 /** @nullable */
97 error_code?: string | null;
98 message: string;
99 request_id?: string;
100}
101
102export interface UpdateProfileCmd {
103 /** @nullable */
104 bio?: string | null;
105 /** @nullable */
106 company?: string | null;
107 /** @nullable */
108 date_of_birth?: string | null;
109 /** @nullable */
110 display_name?: string | null;
111 /** @nullable */
112 language?: string | null;
113 /** @nullable */
114 locale?: string | null;
115 /** @nullable */
116 location?: string | null;
117 /** @nullable */
118 pronouns?: string | null;
119 /** @nullable */
120 real_name?: string | null;
121 /** @nullable */
122 show_activity?: boolean | null;
123 /** @nullable */
124 show_email?: boolean | null;
125 /** @nullable */
126 show_location?: boolean | null;
127 /** @nullable */
128 show_real_name?: boolean | null;
129 /** @nullable */
130 timezone?: string | null;
131 visibility?: null | ProfileVisibility;
132 /** @nullable */
133 website?: string | null;
134}
Added packages/apiclient/account/update-profile.ts View packages/apiclient/account/update-profile.ts
@@ -0,0 +1,171 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 UpdateProfileCmd,
92} from "./update-profile.schemas";
93
94export type updateProfileResponse200 = {
95 data: EnvelopeNoData;
96 status: 200;
97};
98
99export type updateProfileResponse400 = {
100 data: EnvelopeNoData;
101 status: 400;
102};
103
104export type updateProfileResponse401 = {
105 data: EnvelopeNoData;
106 status: 401;
107};
108
109export type updateProfileResponseSuccess = updateProfileResponse200 & {
110 headers: Headers;
111};
112export type updateProfileResponseError = (
113 updateProfileResponse400 | updateProfileResponse401
114) & {
115 headers: Headers;
116};
117
118export type updateProfileResponse =
119 updateProfileResponseSuccess | updateProfileResponseError;
120
121export const getUpdateProfileUrl = () => {
122 return `/api/v1/me`;
123};
124
125/**
126 * 增量更新当前用户的显示资料、时区语言、可见性和资料开关。
127 */
128export const updateProfile = async (
129 updateProfileCmd: UpdateProfileCmd,
130 options?: RequestInit,
131): Promise<updateProfileResponse> => {
132 const getHeaders = (
133 h?: NonNullable<RequestInit["headers"]>,
134 ): Record<string, string | readonly string[]> => {
135 if (!h) return {};
136 if (h instanceof Headers) return Object.fromEntries(h.entries());
137 if (Symbol.iterator in h) {
138 return Object.fromEntries(
139 Array.from(
140 h as Iterable<Iterable<string>>,
141 (entry) => Array.from(entry) as [string, string],
142 ),
143 );
144 }
145 const headers: Record<string, string | readonly string[]> = {};
146 for (const [name, value] of Object.entries<
147 string | readonly string[] | undefined
148 >(h)) {
149 if (value !== undefined) headers[name] = value;
150 }
151 return headers;
152 };
153 const res = await fetch(getUpdateProfileUrl(), {
154 ...options,
155 method: "PATCH",
156 headers: {
157 "Content-Type": "application/json",
158 ...getHeaders(options?.headers),
159 },
160 body: JSON.stringify(updateProfileCmd),
161 });
162
163 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
164
165 const data: updateProfileResponse["data"] = body ? JSON.parse(body) : {};
166 return {
167 data,
168 status: res.status,
169 headers: res.headers,
170 } as updateProfileResponse;
171};
Added packages/apiclient/account/update-username.schemas.ts View packages/apiclient/account/update-username.schemas.ts
@@ -0,0 +1,120 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeUserPublicData = {
101 avatar_url: string;
102 display_name: string;
103 user_id: number;
104 username: string;
105};
106
107export interface EnvelopeUserPublic {
108 code: number;
109 data?: EnvelopeUserPublicData;
110 /** @nullable */
111 error?: string | null;
112 /** @nullable */
113 error_code?: string | null;
114 message: string;
115 request_id?: string;
116}
117
118export interface UpdateUsernameCmd {
119 username: string;
120}
Added packages/apiclient/account/update-username.ts View packages/apiclient/account/update-username.ts
@@ -0,0 +1,172 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeUserPublic,
92 UpdateUsernameCmd,
93} from "./update-username.schemas";
94
95export type updateUsernameResponse200 = {
96 data: EnvelopeUserPublic;
97 status: 200;
98};
99
100export type updateUsernameResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type updateUsernameResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type updateUsernameResponseSuccess = updateUsernameResponse200 & {
111 headers: Headers;
112};
113export type updateUsernameResponseError = (
114 updateUsernameResponse400 | updateUsernameResponse401
115) & {
116 headers: Headers;
117};
118
119export type updateUsernameResponse =
120 updateUsernameResponseSuccess | updateUsernameResponseError;
121
122export const getUpdateUsernameUrl = () => {
123 return `/api/v1/me/username`;
124};
125
126/**
127 * 校验格式和全局唯一性后修改当前用户用户名。
128 */
129export const updateUsername = async (
130 updateUsernameCmd: UpdateUsernameCmd,
131 options?: RequestInit,
132): Promise<updateUsernameResponse> => {
133 const getHeaders = (
134 h?: NonNullable<RequestInit["headers"]>,
135 ): Record<string, string | readonly string[]> => {
136 if (!h) return {};
137 if (h instanceof Headers) return Object.fromEntries(h.entries());
138 if (Symbol.iterator in h) {
139 return Object.fromEntries(
140 Array.from(
141 h as Iterable<Iterable<string>>,
142 (entry) => Array.from(entry) as [string, string],
143 ),
144 );
145 }
146 const headers: Record<string, string | readonly string[]> = {};
147 for (const [name, value] of Object.entries<
148 string | readonly string[] | undefined
149 >(h)) {
150 if (value !== undefined) headers[name] = value;
151 }
152 return headers;
153 };
154 const res = await fetch(getUpdateUsernameUrl(), {
155 ...options,
156 method: "PUT",
157 headers: {
158 "Content-Type": "application/json",
159 ...getHeaders(options?.headers),
160 },
161 body: JSON.stringify(updateUsernameCmd),
162 });
163
164 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
165
166 const data: updateUsernameResponse["data"] = body ? JSON.parse(body) : {};
167 return {
168 data,
169 status: res.status,
170 headers: res.headers,
171 } as updateUsernameResponse;
172};
Added packages/apiclient/analysis/code-activity.schemas.ts View packages/apiclient/analysis/code-activity.schemas.ts
@@ -0,0 +1,120 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface CodeActivityAuthorDto {
90 additions: number;
91 commits: number;
92 deletions: number;
93 email: string;
94 name: string;
95}
96
97export type EnvelopeCodeActivityDtoData = {
98 authors: CodeActivityAuthorDto[];
99 total_additions: number;
100 total_commits: number;
101 total_deletions: number;
102};
103
104export interface EnvelopeCodeActivityDto {
105 code: number;
106 data?: EnvelopeCodeActivityDtoData;
107 /** @nullable */
108 error?: string | null;
109 /** @nullable */
110 error_code?: string | null;
111 message: string;
112 request_id?: string;
113}
114
115export type CodeActivityParams = {
116 /**
117 * @nullable
118 */
119 branch?: string | null;
120};
Added packages/apiclient/analysis/code-activity.ts View packages/apiclient/analysis/code-activity.ts
@@ -0,0 +1,146 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 CodeActivityParams,
91 EnvelopeCodeActivityDto,
92} from "./code-activity.schemas";
93
94export type codeActivityResponse200 = {
95 data: EnvelopeCodeActivityDto;
96 status: 200;
97};
98
99export type codeActivityResponseSuccess = codeActivityResponse200 & {
100 headers: Headers;
101};
102export type codeActivityResponse = codeActivityResponseSuccess;
103
104export const getCodeActivityUrl = (
105 spaceName: string,
106 repoName: string,
107 params?: CodeActivityParams,
108) => {
109 const normalizedParams = new URLSearchParams();
110
111 Object.entries(params || {}).forEach(([key, value]) => {
112 if (value !== undefined) {
113 normalizedParams.append(key, value === null ? "null" : String(value));
114 }
115 });
116
117 const stringifiedParams = normalizedParams.toString();
118
119 return stringifiedParams.length > 0
120 ? `/api/v1/repos/${spaceName}/${repoName}/analysis/code-activity?${stringifiedParams}`
121 : `/api/v1/repos/${spaceName}/${repoName}/analysis/code-activity`;
122};
123
124/**
125 * 按作者汇总指定分支的提交、新增和删除活动。
126 */
127export const codeActivity = async (
128 spaceName: string,
129 repoName: string,
130 params?: CodeActivityParams,
131 options?: RequestInit,
132): Promise<codeActivityResponse> => {
133 const res = await fetch(getCodeActivityUrl(spaceName, repoName, params), {
134 ...options,
135 method: "GET",
136 });
137
138 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
139
140 const data: codeActivityResponse["data"] = body ? JSON.parse(body) : {};
141 return {
142 data,
143 status: res.status,
144 headers: res.headers,
145 } as codeActivityResponse;
146};
Added packages/apiclient/analysis/contributors.schemas.ts View packages/apiclient/analysis/contributors.schemas.ts
@@ -0,0 +1,106 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeVecContributorStatDtoDataItem = {
90 additions: number;
91 commits: number;
92 deletions: number;
93 email: string;
94 name: string;
95};
96
97export interface EnvelopeVecContributorStatDto {
98 code: number;
99 data?: EnvelopeVecContributorStatDtoDataItem[];
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
Added packages/apiclient/analysis/contributors.ts View packages/apiclient/analysis/contributors.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeVecContributorStatDto } from "./contributors.schemas";
90
91export type contributorsResponse200 = {
92 data: EnvelopeVecContributorStatDto;
93 status: 200;
94};
95
96export type contributorsResponseSuccess = contributorsResponse200 & {
97 headers: Headers;
98};
99export type contributorsResponse = contributorsResponseSuccess;
100
101export const getContributorsUrl = (spaceName: string, repoName: string) => {
102 return `/api/v1/repos/${spaceName}/${repoName}/analysis/contributors`;
103};
104
105/**
106 * 按提交数返回指定修订历史的贡献者及代码量统计。
107 */
108export const contributors = async (
109 spaceName: string,
110 repoName: string,
111 options?: RequestInit,
112): Promise<contributorsResponse> => {
113 const res = await fetch(getContributorsUrl(spaceName, repoName), {
114 ...options,
115 method: "GET",
116 });
117
118 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
119
120 const data: contributorsResponse["data"] = body ? JSON.parse(body) : {};
121 return {
122 data,
123 status: res.status,
124 headers: res.headers,
125 } as contributorsResponse;
126};
Added packages/apiclient/analysis/index.ts View packages/apiclient/analysis/index.ts
@@ -0,0 +1,4 @@
1export * from "./code-activity";
2export * from "./contributors";
3export * from "./languages-read";
4export * from "./languages";
Added packages/apiclient/analysis/languages-read.schemas.ts View packages/apiclient/analysis/languages-read.schemas.ts
@@ -0,0 +1,105 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeVecLanguageStatDtoDataItem = {
90 is_primary: boolean;
91 language: string;
92 percentage_bp: number;
93 size: number;
94};
95
96export interface EnvelopeVecLanguageStatDto {
97 code: number;
98 data?: EnvelopeVecLanguageStatDtoDataItem[];
99 /** @nullable */
100 error?: string | null;
101 /** @nullable */
102 error_code?: string | null;
103 message: string;
104 request_id?: string;
105}
Added packages/apiclient/analysis/languages-read.ts View packages/apiclient/analysis/languages-read.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeVecLanguageStatDto } from "./languages-read.schemas";
90
91export type languagesReadResponse200 = {
92 data: EnvelopeVecLanguageStatDto;
93 status: 200;
94};
95
96export type languagesReadResponseSuccess = languagesReadResponse200 & {
97 headers: Headers;
98};
99export type languagesReadResponse = languagesReadResponseSuccess;
100
101export const getLanguagesReadUrl = (spaceName: string, repoName: string) => {
102 return `/api/v1/repos/${spaceName}/${repoName}/analysis/languages`;
103};
104
105/**
106 * 读取最近一次已计算的仓库语言统计。
107 */
108export const languagesRead = async (
109 spaceName: string,
110 repoName: string,
111 options?: RequestInit,
112): Promise<languagesReadResponse> => {
113 const res = await fetch(getLanguagesReadUrl(spaceName, repoName), {
114 ...options,
115 method: "GET",
116 });
117
118 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
119
120 const data: languagesReadResponse["data"] = body ? JSON.parse(body) : {};
121 return {
122 data,
123 status: res.status,
124 headers: res.headers,
125 } as languagesReadResponse;
126};
Added packages/apiclient/analysis/languages.schemas.ts View packages/apiclient/analysis/languages.schemas.ts
@@ -0,0 +1,105 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeVecLanguageStatDtoDataItem = {
90 is_primary: boolean;
91 language: string;
92 percentage_bp: number;
93 size: number;
94};
95
96export interface EnvelopeVecLanguageStatDto {
97 code: number;
98 data?: EnvelopeVecLanguageStatDtoDataItem[];
99 /** @nullable */
100 error?: string | null;
101 /** @nullable */
102 error_code?: string | null;
103 message: string;
104 request_id?: string;
105}
Added packages/apiclient/analysis/languages.ts View packages/apiclient/analysis/languages.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeVecLanguageStatDto } from "./languages.schemas";
90
91export type languagesResponse200 = {
92 data: EnvelopeVecLanguageStatDto;
93 status: 200;
94};
95
96export type languagesResponseSuccess = languagesResponse200 & {
97 headers: Headers;
98};
99export type languagesResponse = languagesResponseSuccess;
100
101export const getLanguagesUrl = (spaceName: string, repoName: string) => {
102 return `/api/v1/repos/${spaceName}/${repoName}/analysis/languages`;
103};
104
105/**
106 * 重新扫描仓库树并持久化语言构成与主语言统计。
107 */
108export const languages = async (
109 spaceName: string,
110 repoName: string,
111 options?: RequestInit,
112): Promise<languagesResponse> => {
113 const res = await fetch(getLanguagesUrl(spaceName, repoName), {
114 ...options,
115 method: "POST",
116 });
117
118 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
119
120 const data: languagesResponse["data"] = body ? JSON.parse(body) : {};
121 return {
122 data,
123 status: res.status,
124 headers: res.headers,
125 } as languagesResponse;
126};
Added packages/apiclient/archives/create-archive.schemas.ts View packages/apiclient/archives/create-archive.schemas.ts
@@ -0,0 +1,114 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type ArchiveFormatDto = "tar" | "tar_gz" | "tar_bz2" | "zip";
90export interface ArchiveCreateCmd {
91 format: ArchiveFormatDto;
92 /** @nullable */
93 path_filter?: string | null;
94 revision: string;
95}
96
97export type EnvelopeArchiveResultDtoData = {
98 cache_key: string;
99 /** @nullable */
100 download_url?: string | null;
101 format: string;
102 size: number;
103};
104
105export interface EnvelopeArchiveResultDto {
106 code: number;
107 data?: EnvelopeArchiveResultDtoData;
108 /** @nullable */
109 error?: string | null;
110 /** @nullable */
111 error_code?: string | null;
112 message: string;
113 request_id?: string;
114}
Added packages/apiclient/archives/create-archive.ts View packages/apiclient/archives/create-archive.ts
@@ -0,0 +1,156 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 ArchiveCreateCmd,
91 EnvelopeArchiveResultDto,
92} from "./create-archive.schemas";
93
94export type createArchiveResponse200 = {
95 data: EnvelopeArchiveResultDto;
96 status: 200;
97};
98
99export type createArchiveResponseSuccess = createArchiveResponse200 & {
100 headers: Headers;
101};
102export type createArchiveResponse = createArchiveResponseSuccess;
103
104export const getCreateArchiveUrl = (spaceName: string, repoName: string) => {
105 return `/api/v1/repos/${spaceName}/${repoName}/archives`;
106};
107
108/**
109 * 为指定修订生成归档并上传存储,返回下载地址。
110 */
111export const createArchive = async (
112 spaceName: string,
113 repoName: string,
114 archiveCreateCmd: ArchiveCreateCmd,
115 options?: RequestInit,
116): Promise<createArchiveResponse> => {
117 const getHeaders = (
118 h?: NonNullable<RequestInit["headers"]>,
119 ): Record<string, string | readonly string[]> => {
120 if (!h) return {};
121 if (h instanceof Headers) return Object.fromEntries(h.entries());
122 if (Symbol.iterator in h) {
123 return Object.fromEntries(
124 Array.from(
125 h as Iterable<Iterable<string>>,
126 (entry) => Array.from(entry) as [string, string],
127 ),
128 );
129 }
130 const headers: Record<string, string | readonly string[]> = {};
131 for (const [name, value] of Object.entries<
132 string | readonly string[] | undefined
133 >(h)) {
134 if (value !== undefined) headers[name] = value;
135 }
136 return headers;
137 };
138 const res = await fetch(getCreateArchiveUrl(spaceName, repoName), {
139 ...options,
140 method: "POST",
141 headers: {
142 "Content-Type": "application/json",
143 ...getHeaders(options?.headers),
144 },
145 body: JSON.stringify(archiveCreateCmd),
146 });
147
148 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
149
150 const data: createArchiveResponse["data"] = body ? JSON.parse(body) : {};
151 return {
152 data,
153 status: res.status,
154 headers: res.headers,
155 } as createArchiveResponse;
156};
Added packages/apiclient/archives/create-bundle.schemas.ts View packages/apiclient/archives/create-bundle.schemas.ts
@@ -0,0 +1,106 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeArchiveResultDtoData = {
90 cache_key: string;
91 /** @nullable */
92 download_url?: string | null;
93 format: string;
94 size: number;
95};
96
97export interface EnvelopeArchiveResultDto {
98 code: number;
99 data?: EnvelopeArchiveResultDtoData;
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
Added packages/apiclient/archives/create-bundle.ts View packages/apiclient/archives/create-bundle.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeArchiveResultDto } from "./create-bundle.schemas";
90
91export type createBundleResponse200 = {
92 data: EnvelopeArchiveResultDto;
93 status: 200;
94};
95
96export type createBundleResponseSuccess = createBundleResponse200 & {
97 headers: Headers;
98};
99export type createBundleResponse = createBundleResponseSuccess;
100
101export const getCreateBundleUrl = (spaceName: string, repoName: string) => {
102 return `/api/v1/repos/${spaceName}/${repoName}/archives/bundle`;
103};
104
105/**
106 * 将仓库全部引用打包为 Git bundle 并上传存储。
107 */
108export const createBundle = async (
109 spaceName: string,
110 repoName: string,
111 options?: RequestInit,
112): Promise<createBundleResponse> => {
113 const res = await fetch(getCreateBundleUrl(spaceName, repoName), {
114 ...options,
115 method: "POST",
116 });
117
118 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
119
120 const data: createBundleResponse["data"] = body ? JSON.parse(body) : {};
121 return {
122 data,
123 status: res.status,
124 headers: res.headers,
125 } as createBundleResponse;
126};
Added packages/apiclient/archives/get-archive.schemas.ts View packages/apiclient/archives/get-archive.schemas.ts
@@ -0,0 +1,117 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeArchiveResultDtoData = {
90 cache_key: string;
91 /** @nullable */
92 download_url?: string | null;
93 format: string;
94 size: number;
95};
96
97export interface EnvelopeArchiveResultDto {
98 code: number;
99 data?: EnvelopeArchiveResultDtoData;
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
107
108export type GetArchiveParams = {
109 /**
110 * archive format
111 */
112 format: string;
113 /**
114 * path filter
115 */
116 path_filter?: string;
117};
Added packages/apiclient/archives/get-archive.ts View packages/apiclient/archives/get-archive.ts
@@ -0,0 +1,151 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeArchiveResultDto,
91 GetArchiveParams,
92} from "./get-archive.schemas";
93
94export type getArchiveResponse200 = {
95 data: EnvelopeArchiveResultDto;
96 status: 200;
97};
98
99export type getArchiveResponseSuccess = getArchiveResponse200 & {
100 headers: Headers;
101};
102export type getArchiveResponse = getArchiveResponseSuccess;
103
104export const getGetArchiveUrl = (
105 spaceName: string,
106 repoName: string,
107 revision: string,
108 params: GetArchiveParams,
109) => {
110 const normalizedParams = new URLSearchParams();
111
112 Object.entries(params || {}).forEach(([key, value]) => {
113 if (value !== undefined) {
114 normalizedParams.append(key, value === null ? "null" : String(value));
115 }
116 });
117
118 const stringifiedParams = normalizedParams.toString();
119
120 return stringifiedParams.length > 0
121 ? `/api/v1/repos/${spaceName}/${repoName}/archives/${revision}?${stringifiedParams}`
122 : `/api/v1/repos/${spaceName}/${repoName}/archives/${revision}`;
123};
124
125/**
126 * 查询已生成归档的元数据并换取短期下载地址。
127 */
128export const getArchive = async (
129 spaceName: string,
130 repoName: string,
131 revision: string,
132 params: GetArchiveParams,
133 options?: RequestInit,
134): Promise<getArchiveResponse> => {
135 const res = await fetch(
136 getGetArchiveUrl(spaceName, repoName, revision, params),
137 {
138 ...options,
139 method: "GET",
140 },
141 );
142
143 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
144
145 const data: getArchiveResponse["data"] = body ? JSON.parse(body) : {};
146 return {
147 data,
148 status: res.status,
149 headers: res.headers,
150 } as getArchiveResponse;
151};
Added packages/apiclient/archives/index.ts View packages/apiclient/archives/index.ts
@@ -0,0 +1,3 @@
1export * from "./create-archive";
2export * from "./create-bundle";
3export * from "./get-archive";
Added packages/apiclient/auth/auth-challenge.schemas.ts View packages/apiclient/auth/auth-challenge.schemas.ts
@@ -0,0 +1,119 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeChallengeResponseData = {
90 context: string;
91 /** @minimum 0 */
92 difficulty: number;
93 /** @minimum 0 */
94 expires_at: number;
95 /** @minimum 0 */
96 issued_at: number;
97};
98
99export interface EnvelopeChallengeResponse {
100 code: number;
101 data?: EnvelopeChallengeResponseData;
102 /** @nullable */
103 error?: string | null;
104 /** @nullable */
105 error_code?: string | null;
106 message: string;
107 request_id?: string;
108}
109
110export interface EnvelopeNoData {
111 code: number;
112 data?: unknown;
113 /** @nullable */
114 error?: string | null;
115 /** @nullable */
116 error_code?: string | null;
117 message: string;
118 request_id?: string;
119}
Added packages/apiclient/auth/auth-challenge.ts View packages/apiclient/auth/auth-challenge.ts
@@ -0,0 +1,138 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeChallengeResponse,
91 EnvelopeNoData,
92} from "./auth-challenge.schemas";
93
94export type authChallengeResponse200 = {
95 data: EnvelopeChallengeResponse;
96 status: 200;
97};
98
99export type authChallengeResponse500 = {
100 data: EnvelopeNoData;
101 status: 500;
102};
103
104export type authChallengeResponseSuccess = authChallengeResponse200 & {
105 headers: Headers;
106};
107export type authChallengeResponseError = authChallengeResponse500 & {
108 headers: Headers;
109};
110
111export type authChallengeResponse =
112 authChallengeResponseSuccess | authChallengeResponseError;
113
114export const getAuthChallengeUrl = () => {
115 return `/api/v1/auth/challenge`;
116};
117
118/**
119 * 把挑战写进当前会话并返回。客户端需要为 `context` 找出一枚满足 `difficulty`(前导零比特数)的 nonce;`pow.v1` 算法与前端求解器一致。
120 * @summary 签发工作量证明挑战
121 */
122export const authChallenge = async (
123 options?: RequestInit,
124): Promise<authChallengeResponse> => {
125 const res = await fetch(getAuthChallengeUrl(), {
126 ...options,
127 method: "POST",
128 });
129
130 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
131
132 const data: authChallengeResponse["data"] = body ? JSON.parse(body) : {};
133 return {
134 data,
135 status: res.status,
136 headers: res.headers,
137 } as authChallengeResponse;
138};
Added packages/apiclient/auth/auth-login-code-verify.schemas.ts View packages/apiclient/auth/auth-login-code-verify.schemas.ts
@@ -0,0 +1,132 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeUserLoginResponseData = {
101 /** @nullable */
102 challenge?: string | null;
103 /** @nullable */
104 displayname?: string | null;
105 mfa_required: boolean;
106 user_id: number;
107 username: string;
108};
109
110export interface EnvelopeUserLoginResponse {
111 code: number;
112 data?: EnvelopeUserLoginResponseData;
113 /** @nullable */
114 error?: string | null;
115 /** @nullable */
116 error_code?: string | null;
117 message: string;
118 request_id?: string;
119}
120
121export interface PowProofRequest {
122 /** @minimum 0 */
123 nonce: number;
124 /** @items.minimum 0 */
125 payload: number[];
126}
127
128export interface LoginCodeVerifyRequest {
129 email: string;
130 email_code: string;
131 pow_payload: PowProofRequest;
132}
Added packages/apiclient/auth/auth-login-code-verify.ts View packages/apiclient/auth/auth-login-code-verify.ts
@@ -0,0 +1,195 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeUserLoginResponse,
92 LoginCodeVerifyRequest,
93} from "./auth-login-code-verify.schemas";
94
95export type authLoginCodeVerifyResponse200 = {
96 data: EnvelopeUserLoginResponse;
97 status: 200;
98};
99
100export type authLoginCodeVerifyResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authLoginCodeVerifyResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type authLoginCodeVerifyResponse403 = {
111 data: EnvelopeNoData;
112 status: 403;
113};
114
115export type authLoginCodeVerifyResponse429 = {
116 data: EnvelopeNoData;
117 status: 429;
118};
119
120export type authLoginCodeVerifyResponse500 = {
121 data: EnvelopeNoData;
122 status: 500;
123};
124
125export type authLoginCodeVerifyResponseSuccess =
126 authLoginCodeVerifyResponse200 & {
127 headers: Headers;
128 };
129export type authLoginCodeVerifyResponseError = (
130 | authLoginCodeVerifyResponse400
131 | authLoginCodeVerifyResponse401
132 | authLoginCodeVerifyResponse403
133 | authLoginCodeVerifyResponse429
134 | authLoginCodeVerifyResponse500
135) & {
136 headers: Headers;
137};
138
139export type authLoginCodeVerifyResponse =
140 authLoginCodeVerifyResponseSuccess | authLoginCodeVerifyResponseError;
141
142export const getAuthLoginCodeVerifyUrl = () => {
143 return `/api/v1/auth/login/code/verify`;
144};
145
146/**
147 * 用邮箱登录验证码换会话。工作量证明的载荷必须是 `email`。验证码一旦核对通过即作废,连续输错 `max_verify_attempts` 次后需重新申请。账号启用了多因子时返回 `mfa_required: true` 与 `challenge`。
148 * @summary 邮箱验证码换会话
149 */
150export const authLoginCodeVerify = async (
151 loginCodeVerifyRequest: LoginCodeVerifyRequest,
152 options?: RequestInit,
153): Promise<authLoginCodeVerifyResponse> => {
154 const getHeaders = (
155 h?: NonNullable<RequestInit["headers"]>,
156 ): Record<string, string | readonly string[]> => {
157 if (!h) return {};
158 if (h instanceof Headers) return Object.fromEntries(h.entries());
159 if (Symbol.iterator in h) {
160 return Object.fromEntries(
161 Array.from(
162 h as Iterable<Iterable<string>>,
163 (entry) => Array.from(entry) as [string, string],
164 ),
165 );
166 }
167 const headers: Record<string, string | readonly string[]> = {};
168 for (const [name, value] of Object.entries<
169 string | readonly string[] | undefined
170 >(h)) {
171 if (value !== undefined) headers[name] = value;
172 }
173 return headers;
174 };
175 const res = await fetch(getAuthLoginCodeVerifyUrl(), {
176 ...options,
177 method: "POST",
178 headers: {
179 "Content-Type": "application/json",
180 ...getHeaders(options?.headers),
181 },
182 body: JSON.stringify(loginCodeVerifyRequest),
183 });
184
185 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
186
187 const data: authLoginCodeVerifyResponse["data"] = body
188 ? JSON.parse(body)
189 : {};
190 return {
191 data,
192 status: res.status,
193 headers: res.headers,
194 } as authLoginCodeVerifyResponse;
195};
Added packages/apiclient/auth/auth-login-code.schemas.ts View packages/apiclient/auth/auth-login-code.schemas.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeLoginCodeResponseData = {
90 /** @minimum 0 */
91 expires_in_secs: number;
92};
93
94export interface EnvelopeLoginCodeResponse {
95 code: number;
96 data?: EnvelopeLoginCodeResponseData;
97 /** @nullable */
98 error?: string | null;
99 /** @nullable */
100 error_code?: string | null;
101 message: string;
102 request_id?: string;
103}
104
105export interface EnvelopeNoData {
106 code: number;
107 data?: unknown;
108 /** @nullable */
109 error?: string | null;
110 /** @nullable */
111 error_code?: string | null;
112 message: string;
113 request_id?: string;
114}
115
116export interface PowProofRequest {
117 /** @minimum 0 */
118 nonce: number;
119 /** @items.minimum 0 */
120 payload: number[];
121}
122
123export interface LoginCodeRequest {
124 email: string;
125 pow_payload: PowProofRequest;
126}
Added packages/apiclient/auth/auth-login-code.ts View packages/apiclient/auth/auth-login-code.ts
@@ -0,0 +1,192 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeLoginCodeResponse,
91 EnvelopeNoData,
92 LoginCodeRequest,
93} from "./auth-login-code.schemas";
94
95export type authLoginCodeResponse200 = {
96 data: EnvelopeLoginCodeResponse;
97 status: 200;
98};
99
100export type authLoginCodeResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authLoginCodeResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type authLoginCodeResponse403 = {
111 data: EnvelopeNoData;
112 status: 403;
113};
114
115export type authLoginCodeResponse429 = {
116 data: EnvelopeNoData;
117 status: 429;
118};
119
120export type authLoginCodeResponse500 = {
121 data: EnvelopeNoData;
122 status: 500;
123};
124
125export type authLoginCodeResponseSuccess = authLoginCodeResponse200 & {
126 headers: Headers;
127};
128export type authLoginCodeResponseError = (
129 | authLoginCodeResponse400
130 | authLoginCodeResponse401
131 | authLoginCodeResponse403
132 | authLoginCodeResponse429
133 | authLoginCodeResponse500
134) & {
135 headers: Headers;
136};
137
138export type authLoginCodeResponse =
139 authLoginCodeResponseSuccess | authLoginCodeResponseError;
140
141export const getAuthLoginCodeUrl = () => {
142 return `/api/v1/auth/login/code`;
143};
144
145/**
146 * 向账号邮箱发送 6 位登录验证码,`expires_in_secs` 为有效期。工作量证明的载荷必须是 `email`。同一账号的发码间隔受 `email_code_rate_limit_secs` 限制。
147 * @summary 发送邮箱登录验证码
148 */
149export const authLoginCode = async (
150 loginCodeRequest: LoginCodeRequest,
151 options?: RequestInit,
152): Promise<authLoginCodeResponse> => {
153 const getHeaders = (
154 h?: NonNullable<RequestInit["headers"]>,
155 ): Record<string, string | readonly string[]> => {
156 if (!h) return {};
157 if (h instanceof Headers) return Object.fromEntries(h.entries());
158 if (Symbol.iterator in h) {
159 return Object.fromEntries(
160 Array.from(
161 h as Iterable<Iterable<string>>,
162 (entry) => Array.from(entry) as [string, string],
163 ),
164 );
165 }
166 const headers: Record<string, string | readonly string[]> = {};
167 for (const [name, value] of Object.entries<
168 string | readonly string[] | undefined
169 >(h)) {
170 if (value !== undefined) headers[name] = value;
171 }
172 return headers;
173 };
174 const res = await fetch(getAuthLoginCodeUrl(), {
175 ...options,
176 method: "POST",
177 headers: {
178 "Content-Type": "application/json",
179 ...getHeaders(options?.headers),
180 },
181 body: JSON.stringify(loginCodeRequest),
182 });
183
184 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
185
186 const data: authLoginCodeResponse["data"] = body ? JSON.parse(body) : {};
187 return {
188 data,
189 status: res.status,
190 headers: res.headers,
191 } as authLoginCodeResponse;
192};
Added packages/apiclient/auth/auth-login-verify.schemas.ts View packages/apiclient/auth/auth-login-verify.schemas.ts
@@ -0,0 +1,124 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeUserLoginResponseData = {
101 /** @nullable */
102 challenge?: string | null;
103 /** @nullable */
104 displayname?: string | null;
105 mfa_required: boolean;
106 user_id: number;
107 username: string;
108};
109
110export interface EnvelopeUserLoginResponse {
111 code: number;
112 data?: EnvelopeUserLoginResponseData;
113 /** @nullable */
114 error?: string | null;
115 /** @nullable */
116 error_code?: string | null;
117 message: string;
118 request_id?: string;
119}
120
121export interface LoginVerifyRequest {
122 challenge: string;
123 code: string;
124}
Added packages/apiclient/auth/auth-login-verify.ts View packages/apiclient/auth/auth-login-verify.ts
@@ -0,0 +1,192 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeUserLoginResponse,
92 LoginVerifyRequest,
93} from "./auth-login-verify.schemas";
94
95export type authLoginVerifyResponse200 = {
96 data: EnvelopeUserLoginResponse;
97 status: 200;
98};
99
100export type authLoginVerifyResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authLoginVerifyResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type authLoginVerifyResponse403 = {
111 data: EnvelopeNoData;
112 status: 403;
113};
114
115export type authLoginVerifyResponse429 = {
116 data: EnvelopeNoData;
117 status: 429;
118};
119
120export type authLoginVerifyResponse500 = {
121 data: EnvelopeNoData;
122 status: 500;
123};
124
125export type authLoginVerifyResponseSuccess = authLoginVerifyResponse200 & {
126 headers: Headers;
127};
128export type authLoginVerifyResponseError = (
129 | authLoginVerifyResponse400
130 | authLoginVerifyResponse401
131 | authLoginVerifyResponse403
132 | authLoginVerifyResponse429
133 | authLoginVerifyResponse500
134) & {
135 headers: Headers;
136};
137
138export type authLoginVerifyResponse =
139 authLoginVerifyResponseSuccess | authLoginVerifyResponseError;
140
141export const getAuthLoginVerifyUrl = () => {
142 return `/api/v1/auth/login/verify`;
143};
144
145/**
146 * 用 6 位 TOTP 动态码或一枚未使用的恢复码完成二次验证并绑定会话。`challenge` 必须与 `/api/v1/auth/login` 或 `/api/v1/auth/login/code/verify` 返回的一致,挑战有效期 300 秒,同一动态码时间步不能重复使用,恢复码用掉即作废。
147 * @summary 二次验证换会话
148 */
149export const authLoginVerify = async (
150 loginVerifyRequest: LoginVerifyRequest,
151 options?: RequestInit,
152): Promise<authLoginVerifyResponse> => {
153 const getHeaders = (
154 h?: NonNullable<RequestInit["headers"]>,
155 ): Record<string, string | readonly string[]> => {
156 if (!h) return {};
157 if (h instanceof Headers) return Object.fromEntries(h.entries());
158 if (Symbol.iterator in h) {
159 return Object.fromEntries(
160 Array.from(
161 h as Iterable<Iterable<string>>,
162 (entry) => Array.from(entry) as [string, string],
163 ),
164 );
165 }
166 const headers: Record<string, string | readonly string[]> = {};
167 for (const [name, value] of Object.entries<
168 string | readonly string[] | undefined
169 >(h)) {
170 if (value !== undefined) headers[name] = value;
171 }
172 return headers;
173 };
174 const res = await fetch(getAuthLoginVerifyUrl(), {
175 ...options,
176 method: "POST",
177 headers: {
178 "Content-Type": "application/json",
179 ...getHeaders(options?.headers),
180 },
181 body: JSON.stringify(loginVerifyRequest),
182 });
183
184 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
185
186 const data: authLoginVerifyResponse["data"] = body ? JSON.parse(body) : {};
187 return {
188 data,
189 status: res.status,
190 headers: res.headers,
191 } as authLoginVerifyResponse;
192};
Added packages/apiclient/auth/auth-login.schemas.ts View packages/apiclient/auth/auth-login.schemas.ts
@@ -0,0 +1,132 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeUserLoginResponseData = {
101 /** @nullable */
102 challenge?: string | null;
103 /** @nullable */
104 displayname?: string | null;
105 mfa_required: boolean;
106 user_id: number;
107 username: string;
108};
109
110export interface EnvelopeUserLoginResponse {
111 code: number;
112 data?: EnvelopeUserLoginResponseData;
113 /** @nullable */
114 error?: string | null;
115 /** @nullable */
116 error_code?: string | null;
117 message: string;
118 request_id?: string;
119}
120
121export interface PowProofRequest {
122 /** @minimum 0 */
123 nonce: number;
124 /** @items.minimum 0 */
125 payload: number[];
126}
127
128export interface UserLoginRequest {
129 identity: string;
130 password_hash: string;
131 pow_payload: PowProofRequest;
132}
Added packages/apiclient/auth/auth-login.ts View packages/apiclient/auth/auth-login.ts
@@ -0,0 +1,192 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeUserLoginResponse,
92 UserLoginRequest,
93} from "./auth-login.schemas";
94
95export type authLoginResponse200 = {
96 data: EnvelopeUserLoginResponse;
97 status: 200;
98};
99
100export type authLoginResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authLoginResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type authLoginResponse403 = {
111 data: EnvelopeNoData;
112 status: 403;
113};
114
115export type authLoginResponse429 = {
116 data: EnvelopeNoData;
117 status: 429;
118};
119
120export type authLoginResponse500 = {
121 data: EnvelopeNoData;
122 status: 500;
123};
124
125export type authLoginResponseSuccess = authLoginResponse200 & {
126 headers: Headers;
127};
128export type authLoginResponseError = (
129 | authLoginResponse400
130 | authLoginResponse401
131 | authLoginResponse403
132 | authLoginResponse429
133 | authLoginResponse500
134) & {
135 headers: Headers;
136};
137
138export type authLoginResponse =
139 authLoginResponseSuccess | authLoginResponseError;
140
141export const getAuthLoginUrl = () => {
142 return `/api/v1/auth/login`;
143};
144
145/**
146 * 用口令登录。`identity` 可以是用户名、邮箱(大小写不敏感)或用户编号,`password_hash` 是客户端先算好的口令摘要,工作量证明的载荷必须是 `identity`。账号启用了多因子时返回 `mfa_required: true` 与 `challenge`,此时会话尚未绑定,需再调 `/api/v1/auth/login/verify`。
147 * @summary 口令登录
148 */
149export const authLogin = async (
150 userLoginRequest: UserLoginRequest,
151 options?: RequestInit,
152): Promise<authLoginResponse> => {
153 const getHeaders = (
154 h?: NonNullable<RequestInit["headers"]>,
155 ): Record<string, string | readonly string[]> => {
156 if (!h) return {};
157 if (h instanceof Headers) return Object.fromEntries(h.entries());
158 if (Symbol.iterator in h) {
159 return Object.fromEntries(
160 Array.from(
161 h as Iterable<Iterable<string>>,
162 (entry) => Array.from(entry) as [string, string],
163 ),
164 );
165 }
166 const headers: Record<string, string | readonly string[]> = {};
167 for (const [name, value] of Object.entries<
168 string | readonly string[] | undefined
169 >(h)) {
170 if (value !== undefined) headers[name] = value;
171 }
172 return headers;
173 };
174 const res = await fetch(getAuthLoginUrl(), {
175 ...options,
176 method: "POST",
177 headers: {
178 "Content-Type": "application/json",
179 ...getHeaders(options?.headers),
180 },
181 body: JSON.stringify(userLoginRequest),
182 });
183
184 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
185
186 const data: authLoginResponse["data"] = body ? JSON.parse(body) : {};
187 return {
188 data,
189 status: res.status,
190 headers: res.headers,
191 } as authLoginResponse;
192};
Added packages/apiclient/auth/auth-logout.schemas.ts View packages/apiclient/auth/auth-logout.schemas.ts
@@ -0,0 +1,114 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeLogoutResponseData = {
90 /** @nullable */
91 user_id?: number | null;
92};
93
94export interface EnvelopeLogoutResponse {
95 code: number;
96 data?: EnvelopeLogoutResponseData;
97 /** @nullable */
98 error?: string | null;
99 /** @nullable */
100 error_code?: string | null;
101 message: string;
102 request_id?: string;
103}
104
105export interface EnvelopeNoData {
106 code: number;
107 data?: unknown;
108 /** @nullable */
109 error?: string | null;
110 /** @nullable */
111 error_code?: string | null;
112 message: string;
113 request_id?: string;
114}
Added packages/apiclient/auth/auth-logout.ts View packages/apiclient/auth/auth-logout.ts
@@ -0,0 +1,138 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeLogoutResponse,
91 EnvelopeNoData,
92} from "./auth-logout.schemas";
93
94export type authLogoutResponse200 = {
95 data: EnvelopeLogoutResponse;
96 status: 200;
97};
98
99export type authLogoutResponse500 = {
100 data: EnvelopeNoData;
101 status: 500;
102};
103
104export type authLogoutResponseSuccess = authLogoutResponse200 & {
105 headers: Headers;
106};
107export type authLogoutResponseError = authLogoutResponse500 & {
108 headers: Headers;
109};
110
111export type authLogoutResponse =
112 authLogoutResponseSuccess | authLogoutResponseError;
113
114export const getAuthLogoutUrl = () => {
115 return `/api/v1/auth/session/logout`;
116};
117
118/**
119 * 销毁当前会话,并清掉该用户的 `/api/v1/auth/me` 缓存。匿名调用同样成功,此时 `user_id` 为 `null`。
120 * @summary 登出
121 */
122export const authLogout = async (
123 options?: RequestInit,
124): Promise<authLogoutResponse> => {
125 const res = await fetch(getAuthLogoutUrl(), {
126 ...options,
127 method: "POST",
128 });
129
130 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
131
132 const data: authLogoutResponse["data"] = body ? JSON.parse(body) : {};
133 return {
134 data,
135 status: res.status,
136 headers: res.headers,
137 } as authLogoutResponse;
138};
Added packages/apiclient/auth/auth-me.schemas.ts View packages/apiclient/auth/auth-me.schemas.ts
@@ -0,0 +1,124 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type EnvelopeMeResponseData = {
90 /** @nullable */
91 avatar_url?: string | null;
92 created_at: string;
93 /** @nullable */
94 displayname?: string | null;
95 email: string;
96 /** @nullable */
97 email_verified_at?: string | null;
98 is_admin: boolean;
99 user_id: number;
100 username: string;
101 version: number;
102};
103
104export interface EnvelopeMeResponse {
105 code: number;
106 data?: EnvelopeMeResponseData;
107 /** @nullable */
108 error?: string | null;
109 /** @nullable */
110 error_code?: string | null;
111 message: string;
112 request_id?: string;
113}
114
115export interface EnvelopeNoData {
116 code: number;
117 data?: unknown;
118 /** @nullable */
119 error?: string | null;
120 /** @nullable */
121 error_code?: string | null;
122 message: string;
123 request_id?: string;
124}
Added packages/apiclient/auth/auth-me.ts View packages/apiclient/auth/auth-me.ts
@@ -0,0 +1,135 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeMeResponse, EnvelopeNoData } from "./auth-me.schemas";
90
91export type authMeResponse200 = {
92 data: EnvelopeMeResponse;
93 status: 200;
94};
95
96export type authMeResponse401 = {
97 data: EnvelopeNoData;
98 status: 401;
99};
100
101export type authMeResponse500 = {
102 data: EnvelopeNoData;
103 status: 500;
104};
105
106export type authMeResponseSuccess = authMeResponse200 & {
107 headers: Headers;
108};
109export type authMeResponseError = (authMeResponse401 | authMeResponse500) & {
110 headers: Headers;
111};
112
113export type authMeResponse = authMeResponseSuccess | authMeResponseError;
114
115export const getAuthMeUrl = () => {
116 return `/api/v1/auth/me`;
117};
118
119/**
120 * 通过会话 Cookie 返回用户自述信息。结果在服务端缓存 300 秒,每第 5 次访问回源刷新;登出与改密会主动失效该缓存。
121 * @summary 当前登录用户
122 */
123export const authMe = async (
124 options?: RequestInit,
125): Promise<authMeResponse> => {
126 const res = await fetch(getAuthMeUrl(), {
127 ...options,
128 method: "GET",
129 });
130
131 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
132
133 const data: authMeResponse["data"] = body ? JSON.parse(body) : {};
134 return { data, status: res.status, headers: res.headers } as authMeResponse;
135};
Added packages/apiclient/auth/auth-password-reset-request.schemas.ts View packages/apiclient/auth/auth-password-reset-request.schemas.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopePasswordResetResponseData = {
101 /** @minimum 0 */
102 expires_in_secs: number;
103};
104
105export interface EnvelopePasswordResetResponse {
106 code: number;
107 data?: EnvelopePasswordResetResponseData;
108 /** @nullable */
109 error?: string | null;
110 /** @nullable */
111 error_code?: string | null;
112 message: string;
113 request_id?: string;
114}
115
116export interface PowProofRequest {
117 /** @minimum 0 */
118 nonce: number;
119 /** @items.minimum 0 */
120 payload: number[];
121}
122
123export interface PasswordResetRequest {
124 email: string;
125 pow_payload: PowProofRequest;
126}
Added packages/apiclient/auth/auth-password-reset-request.ts View packages/apiclient/auth/auth-password-reset-request.ts
@@ -0,0 +1,184 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopePasswordResetResponse,
92 PasswordResetRequest,
93} from "./auth-password-reset-request.schemas";
94
95export type authPasswordResetRequestResponse200 = {
96 data: EnvelopePasswordResetResponse;
97 status: 200;
98};
99
100export type authPasswordResetRequestResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authPasswordResetRequestResponse429 = {
106 data: EnvelopeNoData;
107 status: 429;
108};
109
110export type authPasswordResetRequestResponse500 = {
111 data: EnvelopeNoData;
112 status: 500;
113};
114
115export type authPasswordResetRequestResponseSuccess =
116 authPasswordResetRequestResponse200 & {
117 headers: Headers;
118 };
119export type authPasswordResetRequestResponseError = (
120 | authPasswordResetRequestResponse400
121 | authPasswordResetRequestResponse429
122 | authPasswordResetRequestResponse500
123) & {
124 headers: Headers;
125};
126
127export type authPasswordResetRequestResponse =
128 | authPasswordResetRequestResponseSuccess
129 | authPasswordResetRequestResponseError;
130
131export const getAuthPasswordResetRequestUrl = () => {
132 return `/api/v1/auth/password/reset`;
133};
134
135/**
136 * 校验工作量证明(payload = 邮箱的 UTF-8 字节)后,作废该用户其余未消费的重置令牌,签发新令牌(长度 `reset_token_bytes`,有效期 `reset_token_ttl_secs`),库内只存 `sha256_hex(token)` 且 `hash_key_id = "sha256-v1"`,同时把摘要写入缓存键 `auth:code:reset:{email}`,发信限流键 `auth:rate:reset:{email}`。
137 * @summary 申请密码重置
138 */
139export const authPasswordResetRequest = async (
140 passwordResetRequest: PasswordResetRequest,
141 options?: RequestInit,
142): Promise<authPasswordResetRequestResponse> => {
143 const getHeaders = (
144 h?: NonNullable<RequestInit["headers"]>,
145 ): Record<string, string | readonly string[]> => {
146 if (!h) return {};
147 if (h instanceof Headers) return Object.fromEntries(h.entries());
148 if (Symbol.iterator in h) {
149 return Object.fromEntries(
150 Array.from(
151 h as Iterable<Iterable<string>>,
152 (entry) => Array.from(entry) as [string, string],
153 ),
154 );
155 }
156 const headers: Record<string, string | readonly string[]> = {};
157 for (const [name, value] of Object.entries<
158 string | readonly string[] | undefined
159 >(h)) {
160 if (value !== undefined) headers[name] = value;
161 }
162 return headers;
163 };
164 const res = await fetch(getAuthPasswordResetRequestUrl(), {
165 ...options,
166 method: "POST",
167 headers: {
168 "Content-Type": "application/json",
169 ...getHeaders(options?.headers),
170 },
171 body: JSON.stringify(passwordResetRequest),
172 });
173
174 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
175
176 const data: authPasswordResetRequestResponse["data"] = body
177 ? JSON.parse(body)
178 : {};
179 return {
180 data,
181 status: res.status,
182 headers: res.headers,
183 } as authPasswordResetRequestResponse;
184};
Added packages/apiclient/auth/auth-password-reset.schemas.ts View packages/apiclient/auth/auth-password-reset.schemas.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopePasswordResetConfirmResponseData = {
101 user_id: number;
102};
103
104export interface EnvelopePasswordResetConfirmResponse {
105 code: number;
106 data?: EnvelopePasswordResetConfirmResponseData;
107 /** @nullable */
108 error?: string | null;
109 /** @nullable */
110 error_code?: string | null;
111 message: string;
112 request_id?: string;
113}
114
115export interface PowProofRequest {
116 /** @minimum 0 */
117 nonce: number;
118 /** @items.minimum 0 */
119 payload: number[];
120}
121
122export interface PasswordResetConfirmRequest {
123 password_hash: string;
124 pow_payload: PowProofRequest;
125 token: string;
126}
Added packages/apiclient/auth/auth-password-reset.ts View packages/apiclient/auth/auth-password-reset.ts
@@ -0,0 +1,180 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopePasswordResetConfirmResponse,
92 PasswordResetConfirmRequest,
93} from "./auth-password-reset.schemas";
94
95export type authPasswordResetResponse200 = {
96 data: EnvelopePasswordResetConfirmResponse;
97 status: 200;
98};
99
100export type authPasswordResetResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authPasswordResetResponse429 = {
106 data: EnvelopeNoData;
107 status: 429;
108};
109
110export type authPasswordResetResponse500 = {
111 data: EnvelopeNoData;
112 status: 500;
113};
114
115export type authPasswordResetResponseSuccess = authPasswordResetResponse200 & {
116 headers: Headers;
117};
118export type authPasswordResetResponseError = (
119 | authPasswordResetResponse400
120 | authPasswordResetResponse429
121 | authPasswordResetResponse500
122) & {
123 headers: Headers;
124};
125
126export type authPasswordResetResponse =
127 authPasswordResetResponseSuccess | authPasswordResetResponseError;
128
129export const getAuthPasswordResetUrl = () => {
130 return `/api/v1/auth/password/reset/confirm`;
131};
132
133/**
134 * 校验工作量证明(payload = `token` 的 UTF-8 字节)与缓存键 `auth:code:reset:{email}`(尝试上限 `max_verify_attempts`,错误计入 `invalid_email_code`)后,条件消费数据库令牌行(`consumed_at` 单次占用),Argon2 重哈希新口令,更新 `password_hash`/`password_updated_at`/`password_must_change`/`security_version + 1`,作废其余令牌并记 `PasswordChange` 审计事件。
135 * @summary 确认密码重置
136 */
137export const authPasswordReset = async (
138 passwordResetConfirmRequest: PasswordResetConfirmRequest,
139 options?: RequestInit,
140): Promise<authPasswordResetResponse> => {
141 const getHeaders = (
142 h?: NonNullable<RequestInit["headers"]>,
143 ): Record<string, string | readonly string[]> => {
144 if (!h) return {};
145 if (h instanceof Headers) return Object.fromEntries(h.entries());
146 if (Symbol.iterator in h) {
147 return Object.fromEntries(
148 Array.from(
149 h as Iterable<Iterable<string>>,
150 (entry) => Array.from(entry) as [string, string],
151 ),
152 );
153 }
154 const headers: Record<string, string | readonly string[]> = {};
155 for (const [name, value] of Object.entries<
156 string | readonly string[] | undefined
157 >(h)) {
158 if (value !== undefined) headers[name] = value;
159 }
160 return headers;
161 };
162 const res = await fetch(getAuthPasswordResetUrl(), {
163 ...options,
164 method: "POST",
165 headers: {
166 "Content-Type": "application/json",
167 ...getHeaders(options?.headers),
168 },
169 body: JSON.stringify(passwordResetConfirmRequest),
170 });
171
172 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
173
174 const data: authPasswordResetResponse["data"] = body ? JSON.parse(body) : {};
175 return {
176 data,
177 status: res.status,
178 headers: res.headers,
179 } as authPasswordResetResponse;
180};
Added packages/apiclient/auth/auth-register-code.schemas.ts View packages/apiclient/auth/auth-register-code.schemas.ts
@@ -0,0 +1,126 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeRegisterCodeResponseData = {
101 /** @minimum 0 */
102 expires_in_secs: number;
103};
104
105export interface EnvelopeRegisterCodeResponse {
106 code: number;
107 data?: EnvelopeRegisterCodeResponseData;
108 /** @nullable */
109 error?: string | null;
110 /** @nullable */
111 error_code?: string | null;
112 message: string;
113 request_id?: string;
114}
115
116export interface PowProofRequest {
117 /** @minimum 0 */
118 nonce: number;
119 /** @items.minimum 0 */
120 payload: number[];
121}
122
123export interface RegisterCodeRequest {
124 email: string;
125 pow_payload: PowProofRequest;
126}
Added packages/apiclient/auth/auth-register-code.ts View packages/apiclient/auth/auth-register-code.ts
@@ -0,0 +1,186 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeRegisterCodeResponse,
92 RegisterCodeRequest,
93} from "./auth-register-code.schemas";
94
95export type authRegisterCodeResponse200 = {
96 data: EnvelopeRegisterCodeResponse;
97 status: 200;
98};
99
100export type authRegisterCodeResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authRegisterCodeResponse409 = {
106 data: EnvelopeNoData;
107 status: 409;
108};
109
110export type authRegisterCodeResponse429 = {
111 data: EnvelopeNoData;
112 status: 429;
113};
114
115export type authRegisterCodeResponse500 = {
116 data: EnvelopeNoData;
117 status: 500;
118};
119
120export type authRegisterCodeResponseSuccess = authRegisterCodeResponse200 & {
121 headers: Headers;
122};
123export type authRegisterCodeResponseError = (
124 | authRegisterCodeResponse400
125 | authRegisterCodeResponse409
126 | authRegisterCodeResponse429
127 | authRegisterCodeResponse500
128) & {
129 headers: Headers;
130};
131
132export type authRegisterCodeResponse =
133 authRegisterCodeResponseSuccess | authRegisterCodeResponseError;
134
135export const getAuthRegisterCodeUrl = () => {
136 return `/api/v1/auth/register/code`;
137};
138
139/**
140 * 校验工作量证明(payload = 邮箱的 UTF-8 字节)与邮箱格式后,把 6 位验证码写入缓存并寄出。缓存键 `auth:code:register:{email}`,有效期由 `verify_code_ttl_secs` 决定,发码限流键 `auth:rate:register:{email}`。
141 * @summary 发送注册验证码
142 */
143export const authRegisterCode = async (
144 registerCodeRequest: RegisterCodeRequest,
145 options?: RequestInit,
146): Promise<authRegisterCodeResponse> => {
147 const getHeaders = (
148 h?: NonNullable<RequestInit["headers"]>,
149 ): Record<string, string | readonly string[]> => {
150 if (!h) return {};
151 if (h instanceof Headers) return Object.fromEntries(h.entries());
152 if (Symbol.iterator in h) {
153 return Object.fromEntries(
154 Array.from(
155 h as Iterable<Iterable<string>>,
156 (entry) => Array.from(entry) as [string, string],
157 ),
158 );
159 }
160 const headers: Record<string, string | readonly string[]> = {};
161 for (const [name, value] of Object.entries<
162 string | readonly string[] | undefined
163 >(h)) {
164 if (value !== undefined) headers[name] = value;
165 }
166 return headers;
167 };
168 const res = await fetch(getAuthRegisterCodeUrl(), {
169 ...options,
170 method: "POST",
171 headers: {
172 "Content-Type": "application/json",
173 ...getHeaders(options?.headers),
174 },
175 body: JSON.stringify(registerCodeRequest),
176 });
177
178 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
179
180 const data: authRegisterCodeResponse["data"] = body ? JSON.parse(body) : {};
181 return {
182 data,
183 status: res.status,
184 headers: res.headers,
185 } as authRegisterCodeResponse;
186};
Added packages/apiclient/auth/auth-register.schemas.ts View packages/apiclient/auth/auth-register.schemas.ts
@@ -0,0 +1,134 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeUserRegisterResponseData = {
101 /** @nullable */
102 displayname?: string | null;
103 user_id: number;
104 username: string;
105};
106
107export interface EnvelopeUserRegisterResponse {
108 code: number;
109 data?: EnvelopeUserRegisterResponseData;
110 /** @nullable */
111 error?: string | null;
112 /** @nullable */
113 error_code?: string | null;
114 message: string;
115 request_id?: string;
116}
117
118export interface PowProofRequest {
119 /** @minimum 0 */
120 nonce: number;
121 /** @items.minimum 0 */
122 payload: number[];
123}
124
125export interface UserRegisterRequest {
126 birth_date: string;
127 /** @nullable */
128 displayname?: string | null;
129 email: string;
130 email_code: string;
131 password_hash: string;
132 pow_payload: PowProofRequest;
133 username: string;
134}
Added packages/apiclient/auth/auth-register.ts View packages/apiclient/auth/auth-register.ts
@@ -0,0 +1,192 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeUserRegisterResponse,
92 UserRegisterRequest,
93} from "./auth-register.schemas";
94
95export type authRegisterResponse200 = {
96 data: EnvelopeUserRegisterResponse;
97 status: 200;
98};
99
100export type authRegisterResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authRegisterResponse403 = {
106 data: EnvelopeNoData;
107 status: 403;
108};
109
110export type authRegisterResponse409 = {
111 data: EnvelopeNoData;
112 status: 409;
113};
114
115export type authRegisterResponse429 = {
116 data: EnvelopeNoData;
117 status: 429;
118};
119
120export type authRegisterResponse500 = {
121 data: EnvelopeNoData;
122 status: 500;
123};
124
125export type authRegisterResponseSuccess = authRegisterResponse200 & {
126 headers: Headers;
127};
128export type authRegisterResponseError = (
129 | authRegisterResponse400
130 | authRegisterResponse403
131 | authRegisterResponse409
132 | authRegisterResponse429
133 | authRegisterResponse500
134) & {
135 headers: Headers;
136};
137
138export type authRegisterResponse =
139 authRegisterResponseSuccess | authRegisterResponseError;
140
141export const getAuthRegisterUrl = () => {
142 return `/api/v1/auth/register`;
143};
144
145/**
146 * 校验工作量证明(payload = 用户名的 UTF-8 字节)、用户名/展示名/出生日期/邮箱、邮箱验证码(键 `auth:code:register:{email}`,尝试上限 `max_verify_attempts`)后,Argon2 重哈希口令并创建用户与初始档案。成功后写会话(user_id、security_version、renew)并记审计事件。
147 * @summary 提交注册
148 */
149export const authRegister = async (
150 userRegisterRequest: UserRegisterRequest,
151 options?: RequestInit,
152): Promise<authRegisterResponse> => {
153 const getHeaders = (
154 h?: NonNullable<RequestInit["headers"]>,
155 ): Record<string, string | readonly string[]> => {
156 if (!h) return {};
157 if (h instanceof Headers) return Object.fromEntries(h.entries());
158 if (Symbol.iterator in h) {
159 return Object.fromEntries(
160 Array.from(
161 h as Iterable<Iterable<string>>,
162 (entry) => Array.from(entry) as [string, string],
163 ),
164 );
165 }
166 const headers: Record<string, string | readonly string[]> = {};
167 for (const [name, value] of Object.entries<
168 string | readonly string[] | undefined
169 >(h)) {
170 if (value !== undefined) headers[name] = value;
171 }
172 return headers;
173 };
174 const res = await fetch(getAuthRegisterUrl(), {
175 ...options,
176 method: "POST",
177 headers: {
178 "Content-Type": "application/json",
179 ...getHeaders(options?.headers),
180 },
181 body: JSON.stringify(userRegisterRequest),
182 });
183
184 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
185
186 const data: authRegisterResponse["data"] = body ? JSON.parse(body) : {};
187 return {
188 data,
189 status: res.status,
190 headers: res.headers,
191 } as authRegisterResponse;
192};
Added packages/apiclient/auth/auth-ssh-key-add.schemas.ts View packages/apiclient/auth/auth-ssh-key-add.schemas.ts
@@ -0,0 +1,136 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type SshKeyAlgorithm = "rsa" | "ed25519" | "ecdsa";
101export type EnvelopeSshKeySummaryData = {
102 algorithm: SshKeyAlgorithm;
103 created_at: string;
104 /** @nullable */
105 description?: string | null;
106 /** @nullable */
107 expires_at?: string | null;
108 fingerprint: string;
109 id: string;
110 /** @nullable */
111 last_used_at?: string | null;
112 name: string;
113 public_key: string;
114 /** @nullable */
115 revoked_at?: string | null;
116};
117
118export interface EnvelopeSshKeySummary {
119 code: number;
120 data?: EnvelopeSshKeySummaryData;
121 /** @nullable */
122 error?: string | null;
123 /** @nullable */
124 error_code?: string | null;
125 message: string;
126 request_id?: string;
127}
128
129export interface SshKeyAddRequest {
130 /** @nullable */
131 description?: string | null;
132 /** @nullable */
133 expires_at?: string | null;
134 name: string;
135 public_key: string;
136}
Added packages/apiclient/auth/auth-ssh-key-add.ts View packages/apiclient/auth/auth-ssh-key-add.ts
@@ -0,0 +1,186 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeSshKeySummary,
92 SshKeyAddRequest,
93} from "./auth-ssh-key-add.schemas";
94
95export type authSshKeyAddResponse200 = {
96 data: EnvelopeSshKeySummary;
97 status: 200;
98};
99
100export type authSshKeyAddResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type authSshKeyAddResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type authSshKeyAddResponse409 = {
111 data: EnvelopeNoData;
112 status: 409;
113};
114
115export type authSshKeyAddResponse500 = {
116 data: EnvelopeNoData;
117 status: 500;
118};
119
120export type authSshKeyAddResponseSuccess = authSshKeyAddResponse200 & {
121 headers: Headers;
122};
123export type authSshKeyAddResponseError = (
124 | authSshKeyAddResponse400
125 | authSshKeyAddResponse401
126 | authSshKeyAddResponse409
127 | authSshKeyAddResponse500
128) & {
129 headers: Headers;
130};
131
132export type authSshKeyAddResponse =
133 authSshKeyAddResponseSuccess | authSshKeyAddResponseError;
134
135export const getAuthSshKeyAddUrl = () => {
136 return `/api/v1/auth/ssh-keys`;
137};
138
139/**
140 * 名称 1~64 字符、备注最长 255 字符,公钥 32~8192 字节且必须是受支持的单行 OpenSSH 公钥,`expires_at` 必须晚于当前时间。重复公钥(指纹唯一)返回 `ssh_key_taken`。添加成功记 `PublicKeyAdded` 审计事件。
141 * @summary 添加 SSH 公钥
142 */
143export const authSshKeyAdd = async (
144 sshKeyAddRequest: SshKeyAddRequest,
145 options?: RequestInit,
146): Promise<authSshKeyAddResponse> => {
147 const getHeaders = (
148 h?: NonNullable<RequestInit["headers"]>,
149 ): Record<string, string | readonly string[]> => {
150 if (!h) return {};
151 if (h instanceof Headers) return Object.fromEntries(h.entries());
152 if (Symbol.iterator in h) {
153 return Object.fromEntries(
154 Array.from(
155 h as Iterable<Iterable<string>>,
156 (entry) => Array.from(entry) as [string, string],
157 ),
158 );
159 }
160 const headers: Record<string, string | readonly string[]> = {};
161 for (const [name, value] of Object.entries<
162 string | readonly string[] | undefined
163 >(h)) {
164 if (value !== undefined) headers[name] = value;
165 }
166 return headers;
167 };
168 const res = await fetch(getAuthSshKeyAddUrl(), {
169 ...options,
170 method: "POST",
171 headers: {
172 "Content-Type": "application/json",
173 ...getHeaders(options?.headers),
174 },
175 body: JSON.stringify(sshKeyAddRequest),
176 });
177
178 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
179
180 const data: authSshKeyAddResponse["data"] = body ? JSON.parse(body) : {};
181 return {
182 data,
183 status: res.status,
184 headers: res.headers,
185 } as authSshKeyAddResponse;
186};
Added packages/apiclient/auth/auth-ssh-key-delete.schemas.ts View packages/apiclient/auth/auth-ssh-key-delete.schemas.ts
@@ -0,0 +1,98 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
Added packages/apiclient/auth/auth-ssh-key-delete.ts View packages/apiclient/auth/auth-ssh-key-delete.ts
@@ -0,0 +1,150 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeNoData } from "./auth-ssh-key-delete.schemas";
90
91export type authSshKeyDeleteResponse200 = {
92 data: EnvelopeNoData;
93 status: 200;
94};
95
96export type authSshKeyDeleteResponse401 = {
97 data: EnvelopeNoData;
98 status: 401;
99};
100
101export type authSshKeyDeleteResponse404 = {
102 data: EnvelopeNoData;
103 status: 404;
104};
105
106export type authSshKeyDeleteResponse500 = {
107 data: EnvelopeNoData;
108 status: 500;
109};
110
111export type authSshKeyDeleteResponseSuccess = authSshKeyDeleteResponse200 & {
112 headers: Headers;
113};
114export type authSshKeyDeleteResponseError = (
115 | authSshKeyDeleteResponse401
116 | authSshKeyDeleteResponse404
117 | authSshKeyDeleteResponse500
118) & {
119 headers: Headers;
120};
121
122export type authSshKeyDeleteResponse =
123 authSshKeyDeleteResponseSuccess | authSshKeyDeleteResponseError;
124
125export const getAuthSshKeyDeleteUrl = (keyId: string) => {
126 return `/api/v1/auth/ssh-keys/${keyId}`;
127};
128
129/**
130 * 把公钥标记为已吊销,记录保留不硬删;重复调用幂等。公钥不存在或不属于当前账号返回 `ssh_key_not_found`。吊销成功记 `PublicKeyRemoved` 审计事件,并递增 `security_version` 让该账号既有的访问令牌一并失效。`key_id` 不是合法 UUID 时由 actix-web 的路径提取器直接返回 400。
131 * @summary 吊销 SSH 公钥
132 */
133export const authSshKeyDelete = async (
134 keyId: string,
135 options?: RequestInit,
136): Promise<authSshKeyDeleteResponse> => {
137 const res = await fetch(getAuthSshKeyDeleteUrl(keyId), {
138 ...options,
139 method: "DELETE",
140 });
141
142 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
143
144 const data: authSshKeyDeleteResponse["data"] = body ? JSON.parse(body) : {};
145 return {
146 data,
147 status: res.status,
148 headers: res.headers,
149 } as authSshKeyDeleteResponse;
150};
Added packages/apiclient/auth/auth-ssh-key-list.schemas.ts View packages/apiclient/auth/auth-ssh-key-list.schemas.ts
@@ -0,0 +1,140 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type SshKeyAlgorithm = "rsa" | "ed25519" | "ecdsa";
101export type EnvelopeVecSshKeySummaryDataItem = {
102 algorithm: SshKeyAlgorithm;
103 created_at: string;
104 /** @nullable */
105 description?: string | null;
106 /** @nullable */
107 expires_at?: string | null;
108 fingerprint: string;
109 id: string;
110 /** @nullable */
111 last_used_at?: string | null;
112 name: string;
113 public_key: string;
114 /** @nullable */
115 revoked_at?: string | null;
116};
117
118export interface EnvelopeVecSshKeySummary {
119 code: number;
120 data?: EnvelopeVecSshKeySummaryDataItem[];
121 /** @nullable */
122 error?: string | null;
123 /** @nullable */
124 error_code?: string | null;
125 message: string;
126 request_id?: string;
127}
128
129export type AuthSshKeyListParams = {
130 /**
131 * 页码,从 1 开始;默认 1
132 * @minimum 0
133 */
134 page?: number;
135 /**
136 * 每页条数,默认 20,最多 100
137 * @minimum 0
138 */
139 page_size?: number;
140};
Added packages/apiclient/auth/auth-ssh-key-list.ts View packages/apiclient/auth/auth-ssh-key-list.ts
@@ -0,0 +1,159 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 AuthSshKeyListParams,
91 EnvelopeNoData,
92 EnvelopeVecSshKeySummary,
93} from "./auth-ssh-key-list.schemas";
94
95export type authSshKeyListResponse200 = {
96 data: EnvelopeVecSshKeySummary;
97 status: 200;
98};
99
100export type authSshKeyListResponse401 = {
101 data: EnvelopeNoData;
102 status: 401;
103};
104
105export type authSshKeyListResponse500 = {
106 data: EnvelopeNoData;
107 status: 500;
108};
109
110export type authSshKeyListResponseSuccess = authSshKeyListResponse200 & {
111 headers: Headers;
112};
113export type authSshKeyListResponseError = (
114 authSshKeyListResponse401 | authSshKeyListResponse500
115) & {
116 headers: Headers;
117};
118
119export type authSshKeyListResponse =
120 authSshKeyListResponseSuccess | authSshKeyListResponseError;
121
122export const getAuthSshKeyListUrl = (params?: AuthSshKeyListParams) => {
123 const normalizedParams = new URLSearchParams();
124
125 Object.entries(params || {}).forEach(([key, value]) => {
126 if (value !== undefined) {
127 normalizedParams.append(key, value === null ? "null" : String(value));
128 }
129 });
130
131 const stringifiedParams = normalizedParams.toString();
132
133 return stringifiedParams.length > 0
134 ? `/api/v1/auth/ssh-keys?${stringifiedParams}`
135 : `/api/v1/auth/ssh-keys`;
136};
137
138/**
139 * 按创建时间倒序返回当前账号的公钥,含已吊销与已过期的记录。分页参数由 `page` / `page_size` 控制。查询串不是合法分页参数时由 actix-web 直接返回 400。
140 * @summary 列示 SSH 公钥
141 */
142export const authSshKeyList = async (
143 params?: AuthSshKeyListParams,
144 options?: RequestInit,
145): Promise<authSshKeyListResponse> => {
146 const res = await fetch(getAuthSshKeyListUrl(params), {
147 ...options,
148 method: "GET",
149 });
150
151 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
152
153 const data: authSshKeyListResponse["data"] = body ? JSON.parse(body) : {};
154 return {
155 data,
156 status: res.status,
157 headers: res.headers,
158 } as authSshKeyListResponse;
159};
Added packages/apiclient/auth/change-password.schemas.ts View packages/apiclient/auth/change-password.schemas.ts
@@ -0,0 +1,103 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface ChangePasswordCmd {
90 new_password: string;
91 old_password: string;
92}
93
94export interface EnvelopeNoData {
95 code: number;
96 data?: unknown;
97 /** @nullable */
98 error?: string | null;
99 /** @nullable */
100 error_code?: string | null;
101 message: string;
102 request_id?: string;
103}
Added packages/apiclient/auth/change-password.ts View packages/apiclient/auth/change-password.ts
@@ -0,0 +1,171 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 ChangePasswordCmd,
91 EnvelopeNoData,
92} from "./change-password.schemas";
93
94export type changePasswordResponse200 = {
95 data: EnvelopeNoData;
96 status: 200;
97};
98
99export type changePasswordResponse400 = {
100 data: EnvelopeNoData;
101 status: 400;
102};
103
104export type changePasswordResponse401 = {
105 data: EnvelopeNoData;
106 status: 401;
107};
108
109export type changePasswordResponseSuccess = changePasswordResponse200 & {
110 headers: Headers;
111};
112export type changePasswordResponseError = (
113 changePasswordResponse400 | changePasswordResponse401
114) & {
115 headers: Headers;
116};
117
118export type changePasswordResponse =
119 changePasswordResponseSuccess | changePasswordResponseError;
120
121export const getChangePasswordUrl = () => {
122 return `/api/v1/auth/password/change`;
123};
124
125/**
126 * 修改当前账号口令,成功后吊销除当前会话以外的全部会话。
127 */
128export const changePassword = async (
129 changePasswordCmd: ChangePasswordCmd,
130 options?: RequestInit,
131): Promise<changePasswordResponse> => {
132 const getHeaders = (
133 h?: NonNullable<RequestInit["headers"]>,
134 ): Record<string, string | readonly string[]> => {
135 if (!h) return {};
136 if (h instanceof Headers) return Object.fromEntries(h.entries());
137 if (Symbol.iterator in h) {
138 return Object.fromEntries(
139 Array.from(
140 h as Iterable<Iterable<string>>,
141 (entry) => Array.from(entry) as [string, string],
142 ),
143 );
144 }
145 const headers: Record<string, string | readonly string[]> = {};
146 for (const [name, value] of Object.entries<
147 string | readonly string[] | undefined
148 >(h)) {
149 if (value !== undefined) headers[name] = value;
150 }
151 return headers;
152 };
153 const res = await fetch(getChangePasswordUrl(), {
154 ...options,
155 method: "POST",
156 headers: {
157 "Content-Type": "application/json",
158 ...getHeaders(options?.headers),
159 },
160 body: JSON.stringify(changePasswordCmd),
161 });
162
163 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
164
165 const data: changePasswordResponse["data"] = body ? JSON.parse(body) : {};
166 return {
167 data,
168 status: res.status,
169 headers: res.headers,
170 } as changePasswordResponse;
171};
Added packages/apiclient/auth/index.ts View packages/apiclient/auth/index.ts
@@ -0,0 +1,59 @@
1export * from "./totp-disable";
2export * from "./totp-enable";
3export * from "./recovery-codes";
4export * from "./regenerate-recovery-codes";
5export * from "./totp-setup";
6export * from "./totp-status";
7export * from "./auth-challenge";
8export * from "./auth-login";
9export * from "./auth-login-code";
10export * from "./auth-login-code-verify";
11export * from "./auth-login-verify";
12export * from "./auth-me";
13export * from "./change-password";
14export * from "./auth-password-reset-request";
15export * from "./auth-password-reset";
16export * from "./auth-register";
17export * from "./auth-register-code";
18export * from "./auth-logout";
19export * from "./auth-ssh-key-list";
20export * from "./auth-ssh-key-add";
21export * from "./auth-ssh-key-delete";
22export * from "./space-list";
23export * from "./space-create";
24export * from "./space-invite-redeem";
25export * from "./space-get";
26export * from "./space-delete";
27export * from "./space-update";
28export * from "./space-archive";
29export * from "./space-ban-list";
30export * from "./space-ban-get";
31export * from "./space-ban-delete";
32export * from "./space-ban-update";
33export * from "./space-invite-list";
34export * from "./space-invite-create";
35export * from "./space-invite-revoke";
36export * from "./space-leave";
37export * from "./space-member-list";
38export * from "./space-member-add";
39export * from "./space-member-update-self";
40export * from "./space-member-get";
41export * from "./space-member-remove";
42export * from "./space-member-update";
43export * from "./space-member-ban";
44export * from "./space-member-permissions";
45export * from "./space-member-role";
46export * from "./space-member-unban";
47export * from "./space-permission-check";
48export * from "./space-restore";
49export * from "./space-role-list";
50export * from "./space-role-create";
51export * from "./space-role-assign";
52export * from "./space-role-unassign";
53export * from "./space-role-get";
54export * from "./space-role-delete";
55export * from "./space-role-update";
56export * from "./space-role-join";
57export * from "./space-role-leave";
58export * from "./space-role-permissions";
59export * from "./space-transfer";
Added packages/apiclient/auth/recovery-codes.schemas.ts View packages/apiclient/auth/recovery-codes.schemas.ts
@@ -0,0 +1,117 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeRecoveryCodesRespData = {
101 codes: string[];
102 /** @minimum 0 */
103 total: number;
104 /** @minimum 0 */
105 used: number;
106};
107
108export interface EnvelopeRecoveryCodesResp {
109 code: number;
110 data?: EnvelopeRecoveryCodesRespData;
111 /** @nullable */
112 error?: string | null;
113 /** @nullable */
114 error_code?: string | null;
115 message: string;
116 request_id?: string;
117}
Added packages/apiclient/auth/recovery-codes.ts View packages/apiclient/auth/recovery-codes.ts
@@ -0,0 +1,137 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeRecoveryCodesResp,
92} from "./recovery-codes.schemas";
93
94export type recoveryCodesResponse200 = {
95 data: EnvelopeRecoveryCodesResp;
96 status: 200;
97};
98
99export type recoveryCodesResponse401 = {
100 data: EnvelopeNoData;
101 status: 401;
102};
103
104export type recoveryCodesResponseSuccess = recoveryCodesResponse200 & {
105 headers: Headers;
106};
107export type recoveryCodesResponseError = recoveryCodesResponse401 & {
108 headers: Headers;
109};
110
111export type recoveryCodesResponse =
112 recoveryCodesResponseSuccess | recoveryCodesResponseError;
113
114export const getRecoveryCodesUrl = () => {
115 return `/api/v1/auth/2fa/recovery-codes`;
116};
117
118/**
119 * 查看恢复码批次用量。明文只在生成时返回一次,这里不会回显。
120 */
121export const recoveryCodes = async (
122 options?: RequestInit,
123): Promise<recoveryCodesResponse> => {
124 const res = await fetch(getRecoveryCodesUrl(), {
125 ...options,
126 method: "GET",
127 });
128
129 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
130
131 const data: recoveryCodesResponse["data"] = body ? JSON.parse(body) : {};
132 return {
133 data,
134 status: res.status,
135 headers: res.headers,
136 } as recoveryCodesResponse;
137};
Added packages/apiclient/auth/regenerate-recovery-codes.schemas.ts View packages/apiclient/auth/regenerate-recovery-codes.schemas.ts
@@ -0,0 +1,121 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeRecoveryCodesRespData = {
101 codes: string[];
102 /** @minimum 0 */
103 total: number;
104 /** @minimum 0 */
105 used: number;
106};
107
108export interface EnvelopeRecoveryCodesResp {
109 code: number;
110 data?: EnvelopeRecoveryCodesRespData;
111 /** @nullable */
112 error?: string | null;
113 /** @nullable */
114 error_code?: string | null;
115 message: string;
116 request_id?: string;
117}
118
119export interface RegenerateRecoveryCodesCmd {
120 password: string;
121}
Added packages/apiclient/auth/regenerate-recovery-codes.ts View packages/apiclient/auth/regenerate-recovery-codes.ts
@@ -0,0 +1,175 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeRecoveryCodesResp,
92 RegenerateRecoveryCodesCmd,
93} from "./regenerate-recovery-codes.schemas";
94
95export type regenerateRecoveryCodesResponse200 = {
96 data: EnvelopeRecoveryCodesResp;
97 status: 200;
98};
99
100export type regenerateRecoveryCodesResponse400 = {
101 data: EnvelopeNoData;
102 status: 400;
103};
104
105export type regenerateRecoveryCodesResponse401 = {
106 data: EnvelopeNoData;
107 status: 401;
108};
109
110export type regenerateRecoveryCodesResponseSuccess =
111 regenerateRecoveryCodesResponse200 & {
112 headers: Headers;
113 };
114export type regenerateRecoveryCodesResponseError = (
115 regenerateRecoveryCodesResponse400 | regenerateRecoveryCodesResponse401
116) & {
117 headers: Headers;
118};
119
120export type regenerateRecoveryCodesResponse =
121 regenerateRecoveryCodesResponseSuccess | regenerateRecoveryCodesResponseError;
122
123export const getRegenerateRecoveryCodesUrl = () => {
124 return `/api/v1/auth/2fa/recovery-codes`;
125};
126
127/**
128 * 校验账号口令后重建恢复码批次,返回新的一批明文。
129 */
130export const regenerateRecoveryCodes = async (
131 regenerateRecoveryCodesCmd: RegenerateRecoveryCodesCmd,
132 options?: RequestInit,
133): Promise<regenerateRecoveryCodesResponse> => {
134 const getHeaders = (
135 h?: NonNullable<RequestInit["headers"]>,
136 ): Record<string, string | readonly string[]> => {
137 if (!h) return {};
138 if (h instanceof Headers) return Object.fromEntries(h.entries());
139 if (Symbol.iterator in h) {
140 return Object.fromEntries(
141 Array.from(
142 h as Iterable<Iterable<string>>,
143 (entry) => Array.from(entry) as [string, string],
144 ),
145 );
146 }
147 const headers: Record<string, string | readonly string[]> = {};
148 for (const [name, value] of Object.entries<
149 string | readonly string[] | undefined
150 >(h)) {
151 if (value !== undefined) headers[name] = value;
152 }
153 return headers;
154 };
155 const res = await fetch(getRegenerateRecoveryCodesUrl(), {
156 ...options,
157 method: "PUT",
158 headers: {
159 "Content-Type": "application/json",
160 ...getHeaders(options?.headers),
161 },
162 body: JSON.stringify(regenerateRecoveryCodesCmd),
163 });
164
165 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
166
167 const data: regenerateRecoveryCodesResponse["data"] = body
168 ? JSON.parse(body)
169 : {};
170 return {
171 data,
172 status: res.status,
173 headers: res.headers,
174 } as regenerateRecoveryCodesResponse;
175};
Added packages/apiclient/auth/space-archive.schemas.ts View packages/apiclient/auth/space-archive.schemas.ts
@@ -0,0 +1,145 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinPolicy = "open" | "approval" | "invite_only" | "private";
91export interface EnvelopeNoData {
92 code: number;
93 data?: unknown;
94 /** @nullable */
95 error?: string | null;
96 /** @nullable */
97 error_code?: string | null;
98 message: string;
99 request_id?: string;
100}
101
102export type SpaceStatus = "active" | "suspended" | "archived";
103export type EnvelopeOrganizationSummaryData = {
104 allow_invite: boolean;
105 allow_join: boolean;
106 allow_join_level: number;
107 /** @nullable */
108 archived_at?: string | null;
109 /** @nullable */
110 avatar_url?: string | null;
111 created_at: string;
112 /** @nullable */
113 description?: string | null;
114 id: string;
115 join_policy: SpaceJoinPolicy;
116 member_count: number;
117 member_must_enable_2fa: boolean;
118 my_role?: null | SpaceMemberRole;
119 name: string;
120 owner_user_id: number;
121 require_email_verified: boolean;
122 require_mfa: boolean;
123 slug: string;
124 status: SpaceStatus;
125 updated_at: string;
126 version: number;
127 /** @nullable */
128 welcome_message?: string | null;
129};
130
131export interface EnvelopeOrganizationSummary {
132 code: number;
133 data?: EnvelopeOrganizationSummaryData;
134 /** @nullable */
135 error?: string | null;
136 /** @nullable */
137 error_code?: string | null;
138 message: string;
139 request_id?: string;
140}
141
142export interface ReasonBody {
143 /** @nullable */
144 reason?: string | null;
145}
Added packages/apiclient/auth/space-archive.ts View packages/apiclient/auth/space-archive.ts
@@ -0,0 +1,167 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeOrganizationSummary,
92 ReasonBody,
93} from "./space-archive.schemas";
94
95export type spaceArchiveResponse200 = {
96 data: EnvelopeOrganizationSummary;
97 status: 200;
98};
99
100export type spaceArchiveResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceArchiveResponseSuccess = spaceArchiveResponse200 & {
106 headers: Headers;
107};
108export type spaceArchiveResponseError = spaceArchiveResponse403 & {
109 headers: Headers;
110};
111
112export type spaceArchiveResponse =
113 spaceArchiveResponseSuccess | spaceArchiveResponseError;
114
115export const getSpaceArchiveUrl = (spaceName: string) => {
116 return `/api/v1/spaces/${spaceName}/archive`;
117};
118
119/**
120 * 需要 `org.archive`。归档后全部权限判定返回 false,可恢复。
121 * @summary 归档组织
122 */
123export const spaceArchive = async (
124 spaceName: string,
125 reasonBody: ReasonBody,
126 options?: RequestInit,
127): Promise<spaceArchiveResponse> => {
128 const getHeaders = (
129 h?: NonNullable<RequestInit["headers"]>,
130 ): Record<string, string | readonly string[]> => {
131 if (!h) return {};
132 if (h instanceof Headers) return Object.fromEntries(h.entries());
133 if (Symbol.iterator in h) {
134 return Object.fromEntries(
135 Array.from(
136 h as Iterable<Iterable<string>>,
137 (entry) => Array.from(entry) as [string, string],
138 ),
139 );
140 }
141 const headers: Record<string, string | readonly string[]> = {};
142 for (const [name, value] of Object.entries<
143 string | readonly string[] | undefined
144 >(h)) {
145 if (value !== undefined) headers[name] = value;
146 }
147 return headers;
148 };
149 const res = await fetch(getSpaceArchiveUrl(spaceName), {
150 ...options,
151 method: "POST",
152 headers: {
153 "Content-Type": "application/json",
154 ...getHeaders(options?.headers),
155 },
156 body: JSON.stringify(reasonBody),
157 });
158
159 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
160
161 const data: spaceArchiveResponse["data"] = body ? JSON.parse(body) : {};
162 return {
163 data,
164 status: res.status,
165 headers: res.headers,
166 } as spaceArchiveResponse;
167};
Added packages/apiclient/auth/space-ban-delete.schemas.ts View packages/apiclient/auth/space-ban-delete.schemas.ts
@@ -0,0 +1,160 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
Added packages/apiclient/auth/space-ban-delete.ts View packages/apiclient/auth/space-ban-delete.ts
@@ -0,0 +1,140 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMemberSummary,
91 EnvelopeNoData,
92} from "./space-ban-delete.schemas";
93
94export type spaceBanDeleteResponse200 = {
95 data: EnvelopeMemberSummary;
96 status: 200;
97};
98
99export type spaceBanDeleteResponse404 = {
100 data: EnvelopeNoData;
101 status: 404;
102};
103
104export type spaceBanDeleteResponseSuccess = spaceBanDeleteResponse200 & {
105 headers: Headers;
106};
107export type spaceBanDeleteResponseError = spaceBanDeleteResponse404 & {
108 headers: Headers;
109};
110
111export type spaceBanDeleteResponse =
112 spaceBanDeleteResponseSuccess | spaceBanDeleteResponseError;
113
114export const getSpaceBanDeleteUrl = (spaceName: string, userId: number) => {
115 return `/api/v1/spaces/${spaceName}/bans/${userId}`;
116};
117
118/**
119 * 需要 `member.ban`。等价于按会籍 id 解封,便于按用户维度操作。
120 * @summary 按用户解封
121 */
122export const spaceBanDelete = async (
123 spaceName: string,
124 userId: number,
125 options?: RequestInit,
126): Promise<spaceBanDeleteResponse> => {
127 const res = await fetch(getSpaceBanDeleteUrl(spaceName, userId), {
128 ...options,
129 method: "DELETE",
130 });
131
132 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
133
134 const data: spaceBanDeleteResponse["data"] = body ? JSON.parse(body) : {};
135 return {
136 data,
137 status: res.status,
138 headers: res.headers,
139 } as spaceBanDeleteResponse;
140};
Added packages/apiclient/auth/space-ban-get.schemas.ts View packages/apiclient/auth/space-ban-get.schemas.ts
@@ -0,0 +1,160 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
Added packages/apiclient/auth/space-ban-get.ts View packages/apiclient/auth/space-ban-get.ts
@@ -0,0 +1,140 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMemberSummary,
91 EnvelopeNoData,
92} from "./space-ban-get.schemas";
93
94export type spaceBanGetResponse200 = {
95 data: EnvelopeMemberSummary;
96 status: 200;
97};
98
99export type spaceBanGetResponse404 = {
100 data: EnvelopeNoData;
101 status: 404;
102};
103
104export type spaceBanGetResponseSuccess = spaceBanGetResponse200 & {
105 headers: Headers;
106};
107export type spaceBanGetResponseError = spaceBanGetResponse404 & {
108 headers: Headers;
109};
110
111export type spaceBanGetResponse =
112 spaceBanGetResponseSuccess | spaceBanGetResponseError;
113
114export const getSpaceBanGetUrl = (spaceName: string, userId: number) => {
115 return `/api/v1/spaces/${spaceName}/bans/${userId}`;
116};
117
118/**
119 * 需要 `member.ban`。未封禁返回 404。
120 * @summary 封禁详情
121 */
122export const spaceBanGet = async (
123 spaceName: string,
124 userId: number,
125 options?: RequestInit,
126): Promise<spaceBanGetResponse> => {
127 const res = await fetch(getSpaceBanGetUrl(spaceName, userId), {
128 ...options,
129 method: "GET",
130 });
131
132 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
133
134 const data: spaceBanGetResponse["data"] = body ? JSON.parse(body) : {};
135 return {
136 data,
137 status: res.status,
138 headers: res.headers,
139 } as spaceBanGetResponse;
140};
Added packages/apiclient/auth/space-ban-list.schemas.ts View packages/apiclient/auth/space-ban-list.schemas.ts
@@ -0,0 +1,173 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export interface EnvelopeNoData {
98 code: number;
99 data?: unknown;
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
107
108export type EnvelopeVecMemberSummaryDataItem = {
109 /** @nullable */
110 alias_avatar_url?: string | null;
111 /** @nullable */
112 alias_name?: string | null;
113 ban_allow_agent_join: boolean;
114 ban_allow_comment_any: boolean;
115 ban_allow_push_repo: boolean;
116 ban_allow_speak: boolean;
117 /** @nullable */
118 ban_expires_at?: string | null;
119 /** @nullable */
120 ban_reason?: string | null;
121 /** @nullable */
122 banned_at?: string | null;
123 /** @nullable */
124 displayname?: string | null;
125 hide_muted_channels: boolean;
126 id: string;
127 /** @nullable */
128 invited_by?: number | null;
129 join_method: SpaceJoinMethod;
130 joined_at: string;
131 /** @nullable */
132 last_active_at?: string | null;
133 /** @nullable */
134 left_at?: string | null;
135 message_notifications: MessageNotifications;
136 mobile_push: boolean;
137 /** @nullable */
138 mute_until?: string | null;
139 muted: boolean;
140 organization_id: string;
141 permissions: string[];
142 role: SpaceMemberRole;
143 role_keys: string[];
144 suppress_everyone: boolean;
145 suppress_roles: boolean;
146 user_id: number;
147 username: string;
148 version: number;
149};
150
151export interface EnvelopeVecMemberSummary {
152 code: number;
153 data?: EnvelopeVecMemberSummaryDataItem[];
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
161
162export type SpaceBanListParams = {
163 /**
164 * 页码,从 1 开始
165 * @minimum 0
166 */
167 page?: number;
168 /**
169 * 每页条数
170 * @minimum 0
171 */
172 page_size?: number;
173};
Added packages/apiclient/auth/space-ban-list.ts View packages/apiclient/auth/space-ban-list.ts
@@ -0,0 +1,156 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeVecMemberSummary,
92 SpaceBanListParams,
93} from "./space-ban-list.schemas";
94
95export type spaceBanListResponse200 = {
96 data: EnvelopeVecMemberSummary;
97 status: 200;
98};
99
100export type spaceBanListResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceBanListResponseSuccess = spaceBanListResponse200 & {
106 headers: Headers;
107};
108export type spaceBanListResponseError = spaceBanListResponse403 & {
109 headers: Headers;
110};
111
112export type spaceBanListResponse =
113 spaceBanListResponseSuccess | spaceBanListResponseError;
114
115export const getSpaceBanListUrl = (
116 spaceName: string,
117 params?: SpaceBanListParams,
118) => {
119 const normalizedParams = new URLSearchParams();
120
121 Object.entries(params || {}).forEach(([key, value]) => {
122 if (value !== undefined) {
123 normalizedParams.append(key, value === null ? "null" : String(value));
124 }
125 });
126
127 const stringifiedParams = normalizedParams.toString();
128
129 return stringifiedParams.length > 0
130 ? `/api/v1/spaces/${spaceName}/bans?${stringifiedParams}`
131 : `/api/v1/spaces/${spaceName}/bans`;
132};
133
134/**
135 * 需要 `member.ban`。按封禁时间倒序。
136 * @summary 封禁列表
137 */
138export const spaceBanList = async (
139 spaceName: string,
140 params?: SpaceBanListParams,
141 options?: RequestInit,
142): Promise<spaceBanListResponse> => {
143 const res = await fetch(getSpaceBanListUrl(spaceName, params), {
144 ...options,
145 method: "GET",
146 });
147
148 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
149
150 const data: spaceBanListResponse["data"] = body ? JSON.parse(body) : {};
151 return {
152 data,
153 status: res.status,
154 headers: res.headers,
155 } as spaceBanListResponse;
156};
Added packages/apiclient/auth/space-ban-update.schemas.ts View packages/apiclient/auth/space-ban-update.schemas.ts
@@ -0,0 +1,178 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
161
162/**
163 * 封禁更新:原因、到期时间与四个放行位。缺失表示不变,null 表示清空。
164 */
165export interface UpdateBanBody {
166 /** @nullable */
167 allow_agent_join?: boolean | null;
168 /** @nullable */
169 allow_comment_any?: boolean | null;
170 /** @nullable */
171 allow_push_repo?: boolean | null;
172 /** @nullable */
173 allow_speak?: boolean | null;
174 /** @nullable */
175 expires_at?: string | null;
176 /** @nullable */
177 reason?: string | null;
178}
Added packages/apiclient/auth/space-ban-update.ts View packages/apiclient/auth/space-ban-update.ts
@@ -0,0 +1,168 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMemberSummary,
91 EnvelopeNoData,
92 UpdateBanBody,
93} from "./space-ban-update.schemas";
94
95export type spaceBanUpdateResponse200 = {
96 data: EnvelopeMemberSummary;
97 status: 200;
98};
99
100export type spaceBanUpdateResponse404 = {
101 data: EnvelopeNoData;
102 status: 404;
103};
104
105export type spaceBanUpdateResponseSuccess = spaceBanUpdateResponse200 & {
106 headers: Headers;
107};
108export type spaceBanUpdateResponseError = spaceBanUpdateResponse404 & {
109 headers: Headers;
110};
111
112export type spaceBanUpdateResponse =
113 spaceBanUpdateResponseSuccess | spaceBanUpdateResponseError;
114
115export const getSpaceBanUpdateUrl = (spaceName: string, userId: number) => {
116 return `/api/v1/spaces/${spaceName}/bans/${userId}`;
117};
118
119/**
120 * 需要 `member.ban`。改原因、到期时间与四个放行位;未封禁返回 404。
121 * @summary 更新封禁
122 */
123export const spaceBanUpdate = async (
124 spaceName: string,
125 userId: number,
126 updateBanBody: UpdateBanBody,
127 options?: RequestInit,
128): Promise<spaceBanUpdateResponse> => {
129 const getHeaders = (
130 h?: NonNullable<RequestInit["headers"]>,
131 ): Record<string, string | readonly string[]> => {
132 if (!h) return {};
133 if (h instanceof Headers) return Object.fromEntries(h.entries());
134 if (Symbol.iterator in h) {
135 return Object.fromEntries(
136 Array.from(
137 h as Iterable<Iterable<string>>,
138 (entry) => Array.from(entry) as [string, string],
139 ),
140 );
141 }
142 const headers: Record<string, string | readonly string[]> = {};
143 for (const [name, value] of Object.entries<
144 string | readonly string[] | undefined
145 >(h)) {
146 if (value !== undefined) headers[name] = value;
147 }
148 return headers;
149 };
150 const res = await fetch(getSpaceBanUpdateUrl(spaceName, userId), {
151 ...options,
152 method: "PATCH",
153 headers: {
154 "Content-Type": "application/json",
155 ...getHeaders(options?.headers),
156 },
157 body: JSON.stringify(updateBanBody),
158 });
159
160 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
161
162 const data: spaceBanUpdateResponse["data"] = body ? JSON.parse(body) : {};
163 return {
164 data,
165 status: res.status,
166 headers: res.headers,
167 } as spaceBanUpdateResponse;
168};
Added packages/apiclient/auth/space-create.schemas.ts View packages/apiclient/auth/space-create.schemas.ts
@@ -0,0 +1,164 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinPolicy = "open" | "approval" | "invite_only" | "private";
91export interface CreateOrganizationBody {
92 /** @nullable */
93 allow_invite?: boolean | null;
94 /** @nullable */
95 allow_join?: boolean | null;
96 /** @nullable */
97 allow_join_level?: number | null;
98 /** @nullable */
99 avatar_url?: string | null;
100 /** @nullable */
101 description?: string | null;
102 join_policy?: null | SpaceJoinPolicy;
103 /** @nullable */
104 member_must_enable_2fa?: boolean | null;
105 name: string;
106 /** @nullable */
107 require_email_verified?: boolean | null;
108 /** @nullable */
109 require_mfa?: boolean | null;
110 slug: string;
111 /** @nullable */
112 welcome_message?: string | null;
113}
114
115export interface EnvelopeNoData {
116 code: number;
117 data?: unknown;
118 /** @nullable */
119 error?: string | null;
120 /** @nullable */
121 error_code?: string | null;
122 message: string;
123 request_id?: string;
124}
125
126export type SpaceStatus = "active" | "suspended" | "archived";
127export type EnvelopeOrganizationSummaryData = {
128 allow_invite: boolean;
129 allow_join: boolean;
130 allow_join_level: number;
131 /** @nullable */
132 archived_at?: string | null;
133 /** @nullable */
134 avatar_url?: string | null;
135 created_at: string;
136 /** @nullable */
137 description?: string | null;
138 id: string;
139 join_policy: SpaceJoinPolicy;
140 member_count: number;
141 member_must_enable_2fa: boolean;
142 my_role?: null | SpaceMemberRole;
143 name: string;
144 owner_user_id: number;
145 require_email_verified: boolean;
146 require_mfa: boolean;
147 slug: string;
148 status: SpaceStatus;
149 updated_at: string;
150 version: number;
151 /** @nullable */
152 welcome_message?: string | null;
153};
154
155export interface EnvelopeOrganizationSummary {
156 code: number;
157 data?: EnvelopeOrganizationSummaryData;
158 /** @nullable */
159 error?: string | null;
160 /** @nullable */
161 error_code?: string | null;
162 message: string;
163 request_id?: string;
164}
Added packages/apiclient/auth/space-create.ts View packages/apiclient/auth/space-create.ts
@@ -0,0 +1,173 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 CreateOrganizationBody,
91 EnvelopeNoData,
92 EnvelopeOrganizationSummary,
93} from "./space-create.schemas";
94
95export type spaceCreateResponse200 = {
96 data: EnvelopeOrganizationSummary;
97 status: 200;
98};
99
100export type spaceCreateResponse401 = {
101 data: EnvelopeNoData;
102 status: 401;
103};
104
105export type spaceCreateResponse409 = {
106 data: EnvelopeNoData;
107 status: 409;
108};
109
110export type spaceCreateResponseSuccess = spaceCreateResponse200 & {
111 headers: Headers;
112};
113export type spaceCreateResponseError = (
114 spaceCreateResponse401 | spaceCreateResponse409
115) & {
116 headers: Headers;
117};
118
119export type spaceCreateResponse =
120 spaceCreateResponseSuccess | spaceCreateResponseError;
121
122export const getSpaceCreateUrl = () => {
123 return `/api/v1/spaces`;
124};
125
126/**
127 * 创建者自动成为 OWNER 并写入 owner/admin/member 三个内置角色。slug 全局唯一且只允许小写字母、数字与连字符。
128 * @summary 新建组织
129 */
130export const spaceCreate = async (
131 createOrganizationBody: CreateOrganizationBody,
132 options?: RequestInit,
133): Promise<spaceCreateResponse> => {
134 const getHeaders = (
135 h?: NonNullable<RequestInit["headers"]>,
136 ): Record<string, string | readonly string[]> => {
137 if (!h) return {};
138 if (h instanceof Headers) return Object.fromEntries(h.entries());
139 if (Symbol.iterator in h) {
140 return Object.fromEntries(
141 Array.from(
142 h as Iterable<Iterable<string>>,
143 (entry) => Array.from(entry) as [string, string],
144 ),
145 );
146 }
147 const headers: Record<string, string | readonly string[]> = {};
148 for (const [name, value] of Object.entries<
149 string | readonly string[] | undefined
150 >(h)) {
151 if (value !== undefined) headers[name] = value;
152 }
153 return headers;
154 };
155 const res = await fetch(getSpaceCreateUrl(), {
156 ...options,
157 method: "POST",
158 headers: {
159 "Content-Type": "application/json",
160 ...getHeaders(options?.headers),
161 },
162 body: JSON.stringify(createOrganizationBody),
163 });
164
165 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
166
167 const data: spaceCreateResponse["data"] = body ? JSON.parse(body) : {};
168 return {
169 data,
170 status: res.status,
171 headers: res.headers,
172 } as spaceCreateResponse;
173};
Added packages/apiclient/auth/space-delete.schemas.ts View packages/apiclient/auth/space-delete.schemas.ts
@@ -0,0 +1,120 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export interface EnvelopeBool {
101 code: number;
102 data?: boolean;
103 /** @nullable */
104 error?: string | null;
105 /** @nullable */
106 error_code?: string | null;
107 message: string;
108 request_id?: string;
109}
110
111export type SpaceDeleteParams = {
112 /**
113 * 是否连成员一并清理
114 */
115 force?: boolean;
116 /**
117 * 删除原因,最长 512 字符
118 */
119 reason?: string;
120};
Added packages/apiclient/auth/space-delete.ts View packages/apiclient/auth/space-delete.ts
@@ -0,0 +1,163 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeBool,
91 EnvelopeNoData,
92 SpaceDeleteParams,
93} from "./space-delete.schemas";
94
95export type spaceDeleteResponse200 = {
96 data: EnvelopeBool;
97 status: 200;
98};
99
100export type spaceDeleteResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceDeleteResponse409 = {
106 data: EnvelopeNoData;
107 status: 409;
108};
109
110export type spaceDeleteResponseSuccess = spaceDeleteResponse200 & {
111 headers: Headers;
112};
113export type spaceDeleteResponseError = (
114 spaceDeleteResponse403 | spaceDeleteResponse409
115) & {
116 headers: Headers;
117};
118
119export type spaceDeleteResponse =
120 spaceDeleteResponseSuccess | spaceDeleteResponseError;
121
122export const getSpaceDeleteUrl = (
123 spaceName: string,
124 params?: SpaceDeleteParams,
125) => {
126 const normalizedParams = new URLSearchParams();
127
128 Object.entries(params || {}).forEach(([key, value]) => {
129 if (value !== undefined) {
130 normalizedParams.append(key, value === null ? "null" : String(value));
131 }
132 });
133
134 const stringifiedParams = normalizedParams.toString();
135
136 return stringifiedParams.length > 0
137 ? `/api/v1/spaces/${spaceName}?${stringifiedParams}`
138 : `/api/v1/spaces/${spaceName}`;
139};
140
141/**
142 * 仍存在活跃成员且未指定 `force=true` 时返回 409。删除会清理成员、角色与邀请。
143 * @summary 删除组织
144 */
145export const spaceDelete = async (
146 spaceName: string,
147 params?: SpaceDeleteParams,
148 options?: RequestInit,
149): Promise<spaceDeleteResponse> => {
150 const res = await fetch(getSpaceDeleteUrl(spaceName, params), {
151 ...options,
152 method: "DELETE",
153 });
154
155 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
156
157 const data: spaceDeleteResponse["data"] = body ? JSON.parse(body) : {};
158 return {
159 data,
160 status: res.status,
161 headers: res.headers,
162 } as spaceDeleteResponse;
163};
Added packages/apiclient/auth/space-get.schemas.ts View packages/apiclient/auth/space-get.schemas.ts
@@ -0,0 +1,140 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinPolicy = "open" | "approval" | "invite_only" | "private";
91export interface EnvelopeNoData {
92 code: number;
93 data?: unknown;
94 /** @nullable */
95 error?: string | null;
96 /** @nullable */
97 error_code?: string | null;
98 message: string;
99 request_id?: string;
100}
101
102export type SpaceStatus = "active" | "suspended" | "archived";
103export type EnvelopeOrganizationSummaryData = {
104 allow_invite: boolean;
105 allow_join: boolean;
106 allow_join_level: number;
107 /** @nullable */
108 archived_at?: string | null;
109 /** @nullable */
110 avatar_url?: string | null;
111 created_at: string;
112 /** @nullable */
113 description?: string | null;
114 id: string;
115 join_policy: SpaceJoinPolicy;
116 member_count: number;
117 member_must_enable_2fa: boolean;
118 my_role?: null | SpaceMemberRole;
119 name: string;
120 owner_user_id: number;
121 require_email_verified: boolean;
122 require_mfa: boolean;
123 slug: string;
124 status: SpaceStatus;
125 updated_at: string;
126 version: number;
127 /** @nullable */
128 welcome_message?: string | null;
129};
130
131export interface EnvelopeOrganizationSummary {
132 code: number;
133 data?: EnvelopeOrganizationSummaryData;
134 /** @nullable */
135 error?: string | null;
136 /** @nullable */
137 error_code?: string | null;
138 message: string;
139 request_id?: string;
140}
Added packages/apiclient/auth/space-get.ts View packages/apiclient/auth/space-get.ts
@@ -0,0 +1,133 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeOrganizationSummary,
92} from "./space-get.schemas";
93
94export type spaceGetResponse200 = {
95 data: EnvelopeOrganizationSummary;
96 status: 200;
97};
98
99export type spaceGetResponse404 = {
100 data: EnvelopeNoData;
101 status: 404;
102};
103
104export type spaceGetResponseSuccess = spaceGetResponse200 & {
105 headers: Headers;
106};
107export type spaceGetResponseError = spaceGetResponse404 & {
108 headers: Headers;
109};
110
111export type spaceGetResponse = spaceGetResponseSuccess | spaceGetResponseError;
112
113export const getSpaceGetUrl = (spaceName: string) => {
114 return `/api/v1/spaces/${spaceName}`;
115};
116
117/**
118 * @summary 组织详情
119 */
120export const spaceGet = async (
121 spaceName: string,
122 options?: RequestInit,
123): Promise<spaceGetResponse> => {
124 const res = await fetch(getSpaceGetUrl(spaceName), {
125 ...options,
126 method: "GET",
127 });
128
129 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
130
131 const data: spaceGetResponse["data"] = body ? JSON.parse(body) : {};
132 return { data, status: res.status, headers: res.headers } as spaceGetResponse;
133};
Added packages/apiclient/auth/space-invite-create.schemas.ts View packages/apiclient/auth/space-invite-create.schemas.ts
@@ -0,0 +1,149 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface CreateInviteBody {
90 max_uses?: number;
91 /** @nullable */
92 role_id?: string | null;
93 /** @nullable */
94 target_user_id?: number | null;
95 /**
96 * @minimum 0
97 * @nullable
98 */
99 ttl_secs?: number | null;
100}
101
102export type SpaceJoinMethod =
103 "direct" | "invite_link" | "invite_targeted" | "invite_email";
104export interface InviteSummary {
105 created_at: string;
106 created_by: number;
107 /** @nullable */
108 email?: string | null;
109 /** @nullable */
110 expires_at?: string | null;
111 id: string;
112 max_uses: number;
113 method: SpaceJoinMethod;
114 organization_id: string;
115 /** @nullable */
116 revoked_at?: string | null;
117 /** @nullable */
118 role_id?: string | null;
119 /** @nullable */
120 target_user_id?: number | null;
121 uses: number;
122}
123
124export type EnvelopeCreateInviteResponseData = {
125 invite: InviteSummary;
126 token: string;
127};
128
129export interface EnvelopeCreateInviteResponse {
130 code: number;
131 data?: EnvelopeCreateInviteResponseData;
132 /** @nullable */
133 error?: string | null;
134 /** @nullable */
135 error_code?: string | null;
136 message: string;
137 request_id?: string;
138}
139
140export interface EnvelopeNoData {
141 code: number;
142 data?: unknown;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
Added packages/apiclient/auth/space-invite-create.ts View packages/apiclient/auth/space-invite-create.ts
@@ -0,0 +1,167 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 CreateInviteBody,
91 EnvelopeCreateInviteResponse,
92 EnvelopeNoData,
93} from "./space-invite-create.schemas";
94
95export type spaceInviteCreateResponse200 = {
96 data: EnvelopeCreateInviteResponse;
97 status: 200;
98};
99
100export type spaceInviteCreateResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceInviteCreateResponseSuccess = spaceInviteCreateResponse200 & {
106 headers: Headers;
107};
108export type spaceInviteCreateResponseError = spaceInviteCreateResponse403 & {
109 headers: Headers;
110};
111
112export type spaceInviteCreateResponse =
113 spaceInviteCreateResponseSuccess | spaceInviteCreateResponseError;
114
115export const getSpaceInviteCreateUrl = (spaceName: string) => {
116 return `/api/v1/spaces/${spaceName}/invites`;
117};
118
119/**
120 * 需要 `invite.create`。明文 token 只在创建响应里返回一次,之后只存 sha256。
121 * @summary 创建邀请
122 */
123export const spaceInviteCreate = async (
124 spaceName: string,
125 createInviteBody: CreateInviteBody,
126 options?: RequestInit,
127): Promise<spaceInviteCreateResponse> => {
128 const getHeaders = (
129 h?: NonNullable<RequestInit["headers"]>,
130 ): Record<string, string | readonly string[]> => {
131 if (!h) return {};
132 if (h instanceof Headers) return Object.fromEntries(h.entries());
133 if (Symbol.iterator in h) {
134 return Object.fromEntries(
135 Array.from(
136 h as Iterable<Iterable<string>>,
137 (entry) => Array.from(entry) as [string, string],
138 ),
139 );
140 }
141 const headers: Record<string, string | readonly string[]> = {};
142 for (const [name, value] of Object.entries<
143 string | readonly string[] | undefined
144 >(h)) {
145 if (value !== undefined) headers[name] = value;
146 }
147 return headers;
148 };
149 const res = await fetch(getSpaceInviteCreateUrl(spaceName), {
150 ...options,
151 method: "POST",
152 headers: {
153 "Content-Type": "application/json",
154 ...getHeaders(options?.headers),
155 },
156 body: JSON.stringify(createInviteBody),
157 });
158
159 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
160
161 const data: spaceInviteCreateResponse["data"] = body ? JSON.parse(body) : {};
162 return {
163 data,
164 status: res.status,
165 headers: res.headers,
166 } as spaceInviteCreateResponse;
167};
Added packages/apiclient/auth/space-invite-list.schemas.ts View packages/apiclient/auth/space-invite-list.schemas.ts
@@ -0,0 +1,138 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceJoinMethod =
90 "direct" | "invite_link" | "invite_targeted" | "invite_email";
91export interface EnvelopeNoData {
92 code: number;
93 data?: unknown;
94 /** @nullable */
95 error?: string | null;
96 /** @nullable */
97 error_code?: string | null;
98 message: string;
99 request_id?: string;
100}
101
102export type EnvelopeVecInviteSummaryDataItem = {
103 created_at: string;
104 created_by: number;
105 /** @nullable */
106 email?: string | null;
107 /** @nullable */
108 expires_at?: string | null;
109 id: string;
110 max_uses: number;
111 method: SpaceJoinMethod;
112 organization_id: string;
113 /** @nullable */
114 revoked_at?: string | null;
115 /** @nullable */
116 role_id?: string | null;
117 /** @nullable */
118 target_user_id?: number | null;
119 uses: number;
120};
121
122export interface EnvelopeVecInviteSummary {
123 code: number;
124 data?: EnvelopeVecInviteSummaryDataItem[];
125 /** @nullable */
126 error?: string | null;
127 /** @nullable */
128 error_code?: string | null;
129 message: string;
130 request_id?: string;
131}
132
133export type SpaceInviteListParams = {
134 /**
135 * 包含已撤销邀请
136 */
137 include_revoked?: boolean;
138};
Added packages/apiclient/auth/space-invite-list.ts View packages/apiclient/auth/space-invite-list.ts
@@ -0,0 +1,156 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeVecInviteSummary,
92 SpaceInviteListParams,
93} from "./space-invite-list.schemas";
94
95export type spaceInviteListResponse200 = {
96 data: EnvelopeVecInviteSummary;
97 status: 200;
98};
99
100export type spaceInviteListResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceInviteListResponseSuccess = spaceInviteListResponse200 & {
106 headers: Headers;
107};
108export type spaceInviteListResponseError = spaceInviteListResponse403 & {
109 headers: Headers;
110};
111
112export type spaceInviteListResponse =
113 spaceInviteListResponseSuccess | spaceInviteListResponseError;
114
115export const getSpaceInviteListUrl = (
116 spaceName: string,
117 params?: SpaceInviteListParams,
118) => {
119 const normalizedParams = new URLSearchParams();
120
121 Object.entries(params || {}).forEach(([key, value]) => {
122 if (value !== undefined) {
123 normalizedParams.append(key, value === null ? "null" : String(value));
124 }
125 });
126
127 const stringifiedParams = normalizedParams.toString();
128
129 return stringifiedParams.length > 0
130 ? `/api/v1/spaces/${spaceName}/invites?${stringifiedParams}`
131 : `/api/v1/spaces/${spaceName}/invites`;
132};
133
134/**
135 * 需要 `invite.view`。不含 token 明文。
136 * @summary 列示邀请
137 */
138export const spaceInviteList = async (
139 spaceName: string,
140 params?: SpaceInviteListParams,
141 options?: RequestInit,
142): Promise<spaceInviteListResponse> => {
143 const res = await fetch(getSpaceInviteListUrl(spaceName, params), {
144 ...options,
145 method: "GET",
146 });
147
148 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
149
150 const data: spaceInviteListResponse["data"] = body ? JSON.parse(body) : {};
151 return {
152 data,
153 status: res.status,
154 headers: res.headers,
155 } as spaceInviteListResponse;
156};
Added packages/apiclient/auth/space-invite-redeem.schemas.ts View packages/apiclient/auth/space-invite-redeem.schemas.ts
@@ -0,0 +1,119 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export type EnvelopeRedeemInviteResponseData = {
101 joined: boolean;
102 member_id: string;
103 organization_id: string;
104};
105
106export interface EnvelopeRedeemInviteResponse {
107 code: number;
108 data?: EnvelopeRedeemInviteResponseData;
109 /** @nullable */
110 error?: string | null;
111 /** @nullable */
112 error_code?: string | null;
113 message: string;
114 request_id?: string;
115}
116
117export interface RedeemInviteBody {
118 token: string;
119}
Added packages/apiclient/auth/space-invite-redeem.ts View packages/apiclient/auth/space-invite-redeem.ts
@@ -0,0 +1,173 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeRedeemInviteResponse,
92 RedeemInviteBody,
93} from "./space-invite-redeem.schemas";
94
95export type spaceInviteRedeemResponse200 = {
96 data: EnvelopeRedeemInviteResponse;
97 status: 200;
98};
99
100export type spaceInviteRedeemResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceInviteRedeemResponse409 = {
106 data: EnvelopeNoData;
107 status: 409;
108};
109
110export type spaceInviteRedeemResponseSuccess = spaceInviteRedeemResponse200 & {
111 headers: Headers;
112};
113export type spaceInviteRedeemResponseError = (
114 spaceInviteRedeemResponse403 | spaceInviteRedeemResponse409
115) & {
116 headers: Headers;
117};
118
119export type spaceInviteRedeemResponse =
120 spaceInviteRedeemResponseSuccess | spaceInviteRedeemResponseError;
121
122export const getSpaceInviteRedeemUrl = () => {
123 return `/api/v1/spaces/invites/redeem`;
124};
125
126/**
127 * uses 递增与兑换记录写入同事务。定向邀请只能由目标用户兑换。
128 * @summary 兑换邀请
129 */
130export const spaceInviteRedeem = async (
131 redeemInviteBody: RedeemInviteBody,
132 options?: RequestInit,
133): Promise<spaceInviteRedeemResponse> => {
134 const getHeaders = (
135 h?: NonNullable<RequestInit["headers"]>,
136 ): Record<string, string | readonly string[]> => {
137 if (!h) return {};
138 if (h instanceof Headers) return Object.fromEntries(h.entries());
139 if (Symbol.iterator in h) {
140 return Object.fromEntries(
141 Array.from(
142 h as Iterable<Iterable<string>>,
143 (entry) => Array.from(entry) as [string, string],
144 ),
145 );
146 }
147 const headers: Record<string, string | readonly string[]> = {};
148 for (const [name, value] of Object.entries<
149 string | readonly string[] | undefined
150 >(h)) {
151 if (value !== undefined) headers[name] = value;
152 }
153 return headers;
154 };
155 const res = await fetch(getSpaceInviteRedeemUrl(), {
156 ...options,
157 method: "POST",
158 headers: {
159 "Content-Type": "application/json",
160 ...getHeaders(options?.headers),
161 },
162 body: JSON.stringify(redeemInviteBody),
163 });
164
165 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
166
167 const data: spaceInviteRedeemResponse["data"] = body ? JSON.parse(body) : {};
168 return {
169 data,
170 status: res.status,
171 headers: res.headers,
172 } as spaceInviteRedeemResponse;
173};
Added packages/apiclient/auth/space-invite-revoke.schemas.ts View packages/apiclient/auth/space-invite-revoke.schemas.ts
@@ -0,0 +1,109 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export interface EnvelopeBool {
101 code: number;
102 data?: boolean;
103 /** @nullable */
104 error?: string | null;
105 /** @nullable */
106 error_code?: string | null;
107 message: string;
108 request_id?: string;
109}
Added packages/apiclient/auth/space-invite-revoke.ts View packages/apiclient/auth/space-invite-revoke.ts
@@ -0,0 +1,143 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeBool,
91 EnvelopeNoData,
92} from "./space-invite-revoke.schemas";
93
94export type spaceInviteRevokeResponse200 = {
95 data: EnvelopeBool;
96 status: 200;
97};
98
99export type spaceInviteRevokeResponse404 = {
100 data: EnvelopeNoData;
101 status: 404;
102};
103
104export type spaceInviteRevokeResponseSuccess = spaceInviteRevokeResponse200 & {
105 headers: Headers;
106};
107export type spaceInviteRevokeResponseError = spaceInviteRevokeResponse404 & {
108 headers: Headers;
109};
110
111export type spaceInviteRevokeResponse =
112 spaceInviteRevokeResponseSuccess | spaceInviteRevokeResponseError;
113
114export const getSpaceInviteRevokeUrl = (
115 spaceName: string,
116 inviteId: string,
117) => {
118 return `/api/v1/spaces/${spaceName}/invites/${inviteId}`;
119};
120
121/**
122 * 需要 `invite.revoke`。已撤销的邀请再次撤销返回 false。
123 * @summary 撤销邀请
124 */
125export const spaceInviteRevoke = async (
126 spaceName: string,
127 inviteId: string,
128 options?: RequestInit,
129): Promise<spaceInviteRevokeResponse> => {
130 const res = await fetch(getSpaceInviteRevokeUrl(spaceName, inviteId), {
131 ...options,
132 method: "DELETE",
133 });
134
135 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
136
137 const data: spaceInviteRevokeResponse["data"] = body ? JSON.parse(body) : {};
138 return {
139 data,
140 status: res.status,
141 headers: res.headers,
142 } as spaceInviteRevokeResponse;
143};
Added packages/apiclient/auth/space-leave.schemas.ts View packages/apiclient/auth/space-leave.schemas.ts
@@ -0,0 +1,109 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export interface EnvelopeBool {
101 code: number;
102 data?: boolean;
103 /** @nullable */
104 error?: string | null;
105 /** @nullable */
106 error_code?: string | null;
107 message: string;
108 request_id?: string;
109}
Added packages/apiclient/auth/space-leave.ts View packages/apiclient/auth/space-leave.ts
@@ -0,0 +1,136 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type { EnvelopeBool, EnvelopeNoData } from "./space-leave.schemas";
90
91export type spaceLeaveResponse200 = {
92 data: EnvelopeBool;
93 status: 200;
94};
95
96export type spaceLeaveResponse409 = {
97 data: EnvelopeNoData;
98 status: 409;
99};
100
101export type spaceLeaveResponseSuccess = spaceLeaveResponse200 & {
102 headers: Headers;
103};
104export type spaceLeaveResponseError = spaceLeaveResponse409 & {
105 headers: Headers;
106};
107
108export type spaceLeaveResponse =
109 spaceLeaveResponseSuccess | spaceLeaveResponseError;
110
111export const getSpaceLeaveUrl = (spaceName: string) => {
112 return `/api/v1/spaces/${spaceName}/leave`;
113};
114
115/**
116 * OWNER 必须先转移所有权,否则返回 409。
117 * @summary 退出组织
118 */
119export const spaceLeave = async (
120 spaceName: string,
121 options?: RequestInit,
122): Promise<spaceLeaveResponse> => {
123 const res = await fetch(getSpaceLeaveUrl(spaceName), {
124 ...options,
125 method: "POST",
126 });
127
128 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
129
130 const data: spaceLeaveResponse["data"] = body ? JSON.parse(body) : {};
131 return {
132 data,
133 status: res.status,
134 headers: res.headers,
135 } as spaceLeaveResponse;
136};
Added packages/apiclient/auth/space-list.schemas.ts View packages/apiclient/auth/space-list.schemas.ts
@@ -0,0 +1,140 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinPolicy = "open" | "approval" | "invite_only" | "private";
91export interface EnvelopeNoData {
92 code: number;
93 data?: unknown;
94 /** @nullable */
95 error?: string | null;
96 /** @nullable */
97 error_code?: string | null;
98 message: string;
99 request_id?: string;
100}
101
102export type SpaceStatus = "active" | "suspended" | "archived";
103export type EnvelopeVecOrganizationSummaryDataItem = {
104 allow_invite: boolean;
105 allow_join: boolean;
106 allow_join_level: number;
107 /** @nullable */
108 archived_at?: string | null;
109 /** @nullable */
110 avatar_url?: string | null;
111 created_at: string;
112 /** @nullable */
113 description?: string | null;
114 id: string;
115 join_policy: SpaceJoinPolicy;
116 member_count: number;
117 member_must_enable_2fa: boolean;
118 my_role?: null | SpaceMemberRole;
119 name: string;
120 owner_user_id: number;
121 require_email_verified: boolean;
122 require_mfa: boolean;
123 slug: string;
124 status: SpaceStatus;
125 updated_at: string;
126 version: number;
127 /** @nullable */
128 welcome_message?: string | null;
129};
130
131export interface EnvelopeVecOrganizationSummary {
132 code: number;
133 data?: EnvelopeVecOrganizationSummaryDataItem[];
134 /** @nullable */
135 error?: string | null;
136 /** @nullable */
137 error_code?: string | null;
138 message: string;
139 request_id?: string;
140}
Added packages/apiclient/auth/space-list.ts View packages/apiclient/auth/space-list.ts
@@ -0,0 +1,138 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeVecOrganizationSummary,
92} from "./space-list.schemas";
93
94export type spaceListResponse200 = {
95 data: EnvelopeVecOrganizationSummary;
96 status: 200;
97};
98
99export type spaceListResponse401 = {
100 data: EnvelopeNoData;
101 status: 401;
102};
103
104export type spaceListResponseSuccess = spaceListResponse200 & {
105 headers: Headers;
106};
107export type spaceListResponseError = spaceListResponse401 & {
108 headers: Headers;
109};
110
111export type spaceListResponse =
112 spaceListResponseSuccess | spaceListResponseError;
113
114export const getSpaceListUrl = () => {
115 return `/api/v1/spaces`;
116};
117
118/**
119 * 默认只返回 ACTIVE 组织;`include_archived=true` 时一并返回已归档组织。
120 * @summary 列示我加入的组织
121 */
122export const spaceList = async (
123 options?: RequestInit,
124): Promise<spaceListResponse> => {
125 const res = await fetch(getSpaceListUrl(), {
126 ...options,
127 method: "GET",
128 });
129
130 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
131
132 const data: spaceListResponse["data"] = body ? JSON.parse(body) : {};
133 return {
134 data,
135 status: res.status,
136 headers: res.headers,
137 } as spaceListResponse;
138};
Added packages/apiclient/auth/space-member-add.schemas.ts View packages/apiclient/auth/space-member-add.schemas.ts
@@ -0,0 +1,166 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export interface AddMemberBody {
91 role?: null | SpaceMemberRole;
92 role_keys?: string[];
93 user_id: number;
94}
95
96export type SpaceJoinMethod =
97 "direct" | "invite_link" | "invite_targeted" | "invite_email";
98/**
99 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
100 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
101 */
102export type MessageNotifications = "all" | "mentions" | "nothing";
103export type EnvelopeMemberSummaryData = {
104 /** @nullable */
105 alias_avatar_url?: string | null;
106 /** @nullable */
107 alias_name?: string | null;
108 ban_allow_agent_join: boolean;
109 ban_allow_comment_any: boolean;
110 ban_allow_push_repo: boolean;
111 ban_allow_speak: boolean;
112 /** @nullable */
113 ban_expires_at?: string | null;
114 /** @nullable */
115 ban_reason?: string | null;
116 /** @nullable */
117 banned_at?: string | null;
118 /** @nullable */
119 displayname?: string | null;
120 hide_muted_channels: boolean;
121 id: string;
122 /** @nullable */
123 invited_by?: number | null;
124 join_method: SpaceJoinMethod;
125 joined_at: string;
126 /** @nullable */
127 last_active_at?: string | null;
128 /** @nullable */
129 left_at?: string | null;
130 message_notifications: MessageNotifications;
131 mobile_push: boolean;
132 /** @nullable */
133 mute_until?: string | null;
134 muted: boolean;
135 organization_id: string;
136 permissions: string[];
137 role: SpaceMemberRole;
138 role_keys: string[];
139 suppress_everyone: boolean;
140 suppress_roles: boolean;
141 user_id: number;
142 username: string;
143 version: number;
144};
145
146export interface EnvelopeMemberSummary {
147 code: number;
148 data?: EnvelopeMemberSummaryData;
149 /** @nullable */
150 error?: string | null;
151 /** @nullable */
152 error_code?: string | null;
153 message: string;
154 request_id?: string;
155}
156
157export interface EnvelopeNoData {
158 code: number;
159 data?: unknown;
160 /** @nullable */
161 error?: string | null;
162 /** @nullable */
163 error_code?: string | null;
164 message: string;
165 request_id?: string;
166}
Added packages/apiclient/auth/space-member-add.ts View packages/apiclient/auth/space-member-add.ts
@@ -0,0 +1,174 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 AddMemberBody,
91 EnvelopeMemberSummary,
92 EnvelopeNoData,
93} from "./space-member-add.schemas";
94
95export type spaceMemberAddResponse200 = {
96 data: EnvelopeMemberSummary;
97 status: 200;
98};
99
100export type spaceMemberAddResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceMemberAddResponse404 = {
106 data: EnvelopeNoData;
107 status: 404;
108};
109
110export type spaceMemberAddResponseSuccess = spaceMemberAddResponse200 & {
111 headers: Headers;
112};
113export type spaceMemberAddResponseError = (
114 spaceMemberAddResponse403 | spaceMemberAddResponse404
115) & {
116 headers: Headers;
117};
118
119export type spaceMemberAddResponse =
120 spaceMemberAddResponseSuccess | spaceMemberAddResponseError;
121
122export const getSpaceMemberAddUrl = (spaceName: string) => {
123 return `/api/v1/spaces/${spaceName}/members`;
124};
125
126/**
127 * 需要 `member.add`。已退出的会籍按复活处理,已封禁的返回 403。
128 * @summary 直接添加成员
129 */
130export const spaceMemberAdd = async (
131 spaceName: string,
132 addMemberBody: AddMemberBody,
133 options?: RequestInit,
134): Promise<spaceMemberAddResponse> => {
135 const getHeaders = (
136 h?: NonNullable<RequestInit["headers"]>,
137 ): Record<string, string | readonly string[]> => {
138 if (!h) return {};
139 if (h instanceof Headers) return Object.fromEntries(h.entries());
140 if (Symbol.iterator in h) {
141 return Object.fromEntries(
142 Array.from(
143 h as Iterable<Iterable<string>>,
144 (entry) => Array.from(entry) as [string, string],
145 ),
146 );
147 }
148 const headers: Record<string, string | readonly string[]> = {};
149 for (const [name, value] of Object.entries<
150 string | readonly string[] | undefined
151 >(h)) {
152 if (value !== undefined) headers[name] = value;
153 }
154 return headers;
155 };
156 const res = await fetch(getSpaceMemberAddUrl(spaceName), {
157 ...options,
158 method: "POST",
159 headers: {
160 "Content-Type": "application/json",
161 ...getHeaders(options?.headers),
162 },
163 body: JSON.stringify(addMemberBody),
164 });
165
166 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
167
168 const data: spaceMemberAddResponse["data"] = body ? JSON.parse(body) : {};
169 return {
170 data,
171 status: res.status,
172 headers: res.headers,
173 } as spaceMemberAddResponse;
174};
Added packages/apiclient/auth/space-member-ban.schemas.ts View packages/apiclient/auth/space-member-ban.schemas.ts
@@ -0,0 +1,165 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export interface BanMemberBody {
91 /** @nullable */
92 reason?: string | null;
93}
94
95export type SpaceJoinMethod =
96 "direct" | "invite_link" | "invite_targeted" | "invite_email";
97/**
98 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
99 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
100 */
101export type MessageNotifications = "all" | "mentions" | "nothing";
102export type EnvelopeMemberSummaryData = {
103 /** @nullable */
104 alias_avatar_url?: string | null;
105 /** @nullable */
106 alias_name?: string | null;
107 ban_allow_agent_join: boolean;
108 ban_allow_comment_any: boolean;
109 ban_allow_push_repo: boolean;
110 ban_allow_speak: boolean;
111 /** @nullable */
112 ban_expires_at?: string | null;
113 /** @nullable */
114 ban_reason?: string | null;
115 /** @nullable */
116 banned_at?: string | null;
117 /** @nullable */
118 displayname?: string | null;
119 hide_muted_channels: boolean;
120 id: string;
121 /** @nullable */
122 invited_by?: number | null;
123 join_method: SpaceJoinMethod;
124 joined_at: string;
125 /** @nullable */
126 last_active_at?: string | null;
127 /** @nullable */
128 left_at?: string | null;
129 message_notifications: MessageNotifications;
130 mobile_push: boolean;
131 /** @nullable */
132 mute_until?: string | null;
133 muted: boolean;
134 organization_id: string;
135 permissions: string[];
136 role: SpaceMemberRole;
137 role_keys: string[];
138 suppress_everyone: boolean;
139 suppress_roles: boolean;
140 user_id: number;
141 username: string;
142 version: number;
143};
144
145export interface EnvelopeMemberSummary {
146 code: number;
147 data?: EnvelopeMemberSummaryData;
148 /** @nullable */
149 error?: string | null;
150 /** @nullable */
151 error_code?: string | null;
152 message: string;
153 request_id?: string;
154}
155
156export interface EnvelopeNoData {
157 code: number;
158 data?: unknown;
159 /** @nullable */
160 error?: string | null;
161 /** @nullable */
162 error_code?: string | null;
163 message: string;
164 request_id?: string;
165}
Added packages/apiclient/auth/space-member-ban.ts View packages/apiclient/auth/space-member-ban.ts
@@ -0,0 +1,168 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 BanMemberBody,
91 EnvelopeMemberSummary,
92 EnvelopeNoData,
93} from "./space-member-ban.schemas";
94
95export type spaceMemberBanResponse200 = {
96 data: EnvelopeMemberSummary;
97 status: 200;
98};
99
100export type spaceMemberBanResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceMemberBanResponseSuccess = spaceMemberBanResponse200 & {
106 headers: Headers;
107};
108export type spaceMemberBanResponseError = spaceMemberBanResponse403 & {
109 headers: Headers;
110};
111
112export type spaceMemberBanResponse =
113 spaceMemberBanResponseSuccess | spaceMemberBanResponseError;
114
115export const getSpaceMemberBanUrl = (spaceName: string, memberId: string) => {
116 return `/api/v1/spaces/${spaceName}/members/${memberId}/ban`;
117};
118
119/**
120 * 写 banned_at 并清空角色绑定与直挂权限。封禁优先于一切授权。
121 * @summary 封禁成员
122 */
123export const spaceMemberBan = async (
124 spaceName: string,
125 memberId: string,
126 banMemberBody: BanMemberBody,
127 options?: RequestInit,
128): Promise<spaceMemberBanResponse> => {
129 const getHeaders = (
130 h?: NonNullable<RequestInit["headers"]>,
131 ): Record<string, string | readonly string[]> => {
132 if (!h) return {};
133 if (h instanceof Headers) return Object.fromEntries(h.entries());
134 if (Symbol.iterator in h) {
135 return Object.fromEntries(
136 Array.from(
137 h as Iterable<Iterable<string>>,
138 (entry) => Array.from(entry) as [string, string],
139 ),
140 );
141 }
142 const headers: Record<string, string | readonly string[]> = {};
143 for (const [name, value] of Object.entries<
144 string | readonly string[] | undefined
145 >(h)) {
146 if (value !== undefined) headers[name] = value;
147 }
148 return headers;
149 };
150 const res = await fetch(getSpaceMemberBanUrl(spaceName, memberId), {
151 ...options,
152 method: "POST",
153 headers: {
154 "Content-Type": "application/json",
155 ...getHeaders(options?.headers),
156 },
157 body: JSON.stringify(banMemberBody),
158 });
159
160 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
161
162 const data: spaceMemberBanResponse["data"] = body ? JSON.parse(body) : {};
163 return {
164 data,
165 status: res.status,
166 headers: res.headers,
167 } as spaceMemberBanResponse;
168};
Added packages/apiclient/auth/space-member-get.schemas.ts View packages/apiclient/auth/space-member-get.schemas.ts
@@ -0,0 +1,160 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
Added packages/apiclient/auth/space-member-get.ts View packages/apiclient/auth/space-member-get.ts
@@ -0,0 +1,140 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMemberSummary,
91 EnvelopeNoData,
92} from "./space-member-get.schemas";
93
94export type spaceMemberGetResponse200 = {
95 data: EnvelopeMemberSummary;
96 status: 200;
97};
98
99export type spaceMemberGetResponse404 = {
100 data: EnvelopeNoData;
101 status: 404;
102};
103
104export type spaceMemberGetResponseSuccess = spaceMemberGetResponse200 & {
105 headers: Headers;
106};
107export type spaceMemberGetResponseError = spaceMemberGetResponse404 & {
108 headers: Headers;
109};
110
111export type spaceMemberGetResponse =
112 spaceMemberGetResponseSuccess | spaceMemberGetResponseError;
113
114export const getSpaceMemberGetUrl = (spaceName: string, memberId: string) => {
115 return `/api/v1/spaces/${spaceName}/members/${memberId}`;
116};
117
118/**
119 * 需要 `member.view`。包含别名、通知偏好与封禁附加信息。
120 * @summary 成员详情
121 */
122export const spaceMemberGet = async (
123 spaceName: string,
124 memberId: string,
125 options?: RequestInit,
126): Promise<spaceMemberGetResponse> => {
127 const res = await fetch(getSpaceMemberGetUrl(spaceName, memberId), {
128 ...options,
129 method: "GET",
130 });
131
132 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
133
134 const data: spaceMemberGetResponse["data"] = body ? JSON.parse(body) : {};
135 return {
136 data,
137 status: res.status,
138 headers: res.headers,
139 } as spaceMemberGetResponse;
140};
Added packages/apiclient/auth/space-member-list.schemas.ts View packages/apiclient/auth/space-member-list.schemas.ts
@@ -0,0 +1,171 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export interface EnvelopeNoData {
98 code: number;
99 data?: unknown;
100 /** @nullable */
101 error?: string | null;
102 /** @nullable */
103 error_code?: string | null;
104 message: string;
105 request_id?: string;
106}
107
108export type EnvelopeVecMemberSummaryDataItem = {
109 /** @nullable */
110 alias_avatar_url?: string | null;
111 /** @nullable */
112 alias_name?: string | null;
113 ban_allow_agent_join: boolean;
114 ban_allow_comment_any: boolean;
115 ban_allow_push_repo: boolean;
116 ban_allow_speak: boolean;
117 /** @nullable */
118 ban_expires_at?: string | null;
119 /** @nullable */
120 ban_reason?: string | null;
121 /** @nullable */
122 banned_at?: string | null;
123 /** @nullable */
124 displayname?: string | null;
125 hide_muted_channels: boolean;
126 id: string;
127 /** @nullable */
128 invited_by?: number | null;
129 join_method: SpaceJoinMethod;
130 joined_at: string;
131 /** @nullable */
132 last_active_at?: string | null;
133 /** @nullable */
134 left_at?: string | null;
135 message_notifications: MessageNotifications;
136 mobile_push: boolean;
137 /** @nullable */
138 mute_until?: string | null;
139 muted: boolean;
140 organization_id: string;
141 permissions: string[];
142 role: SpaceMemberRole;
143 role_keys: string[];
144 suppress_everyone: boolean;
145 suppress_roles: boolean;
146 user_id: number;
147 username: string;
148 version: number;
149};
150
151export interface EnvelopeVecMemberSummary {
152 code: number;
153 data?: EnvelopeVecMemberSummaryDataItem[];
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
161
162export type SpaceMemberListParams = {
163 /**
164 * 包含已退出成员
165 */
166 include_inactive?: boolean;
167 /**
168 * 包含已封禁成员
169 */
170 include_banned?: boolean;
171};
Added packages/apiclient/auth/space-member-list.ts View packages/apiclient/auth/space-member-list.ts
@@ -0,0 +1,156 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeVecMemberSummary,
92 SpaceMemberListParams,
93} from "./space-member-list.schemas";
94
95export type spaceMemberListResponse200 = {
96 data: EnvelopeVecMemberSummary;
97 status: 200;
98};
99
100export type spaceMemberListResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceMemberListResponseSuccess = spaceMemberListResponse200 & {
106 headers: Headers;
107};
108export type spaceMemberListResponseError = spaceMemberListResponse403 & {
109 headers: Headers;
110};
111
112export type spaceMemberListResponse =
113 spaceMemberListResponseSuccess | spaceMemberListResponseError;
114
115export const getSpaceMemberListUrl = (
116 spaceName: string,
117 params?: SpaceMemberListParams,
118) => {
119 const normalizedParams = new URLSearchParams();
120
121 Object.entries(params || {}).forEach(([key, value]) => {
122 if (value !== undefined) {
123 normalizedParams.append(key, value === null ? "null" : String(value));
124 }
125 });
126
127 const stringifiedParams = normalizedParams.toString();
128
129 return stringifiedParams.length > 0
130 ? `/api/v1/spaces/${spaceName}/members?${stringifiedParams}`
131 : `/api/v1/spaces/${spaceName}/members`;
132};
133
134/**
135 * 需要 `member.view`。默认只返回活跃成员。
136 * @summary 列示组织成员
137 */
138export const spaceMemberList = async (
139 spaceName: string,
140 params?: SpaceMemberListParams,
141 options?: RequestInit,
142): Promise<spaceMemberListResponse> => {
143 const res = await fetch(getSpaceMemberListUrl(spaceName, params), {
144 ...options,
145 method: "GET",
146 });
147
148 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
149
150 const data: spaceMemberListResponse["data"] = body ? JSON.parse(body) : {};
151 return {
152 data,
153 status: res.status,
154 headers: res.headers,
155 } as spaceMemberListResponse;
156};
Added packages/apiclient/auth/space-member-permissions.schemas.ts View packages/apiclient/auth/space-member-permissions.schemas.ts
@@ -0,0 +1,119 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type PermissionEffect = "allow" | "deny";
90export interface PermissionGrant {
91 effect: PermissionEffect;
92 permission: string;
93}
94
95export interface EnvelopeNoData {
96 code: number;
97 data?: unknown;
98 /** @nullable */
99 error?: string | null;
100 /** @nullable */
101 error_code?: string | null;
102 message: string;
103 request_id?: string;
104}
105
106export interface EnvelopeVecString {
107 code: number;
108 data?: string[];
109 /** @nullable */
110 error?: string | null;
111 /** @nullable */
112 error_code?: string | null;
113 message: string;
114 request_id?: string;
115}
116
117export interface SetRolePermissionsBody {
118 permissions?: PermissionGrant[];
119}
Added packages/apiclient/auth/space-member-permissions.ts View packages/apiclient/auth/space-member-permissions.ts
@@ -0,0 +1,175 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeNoData,
91 EnvelopeVecString,
92 SetRolePermissionsBody,
93} from "./space-member-permissions.schemas";
94
95export type spaceMemberPermissionsResponse200 = {
96 data: EnvelopeVecString;
97 status: 200;
98};
99
100export type spaceMemberPermissionsResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceMemberPermissionsResponseSuccess =
106 spaceMemberPermissionsResponse200 & {
107 headers: Headers;
108 };
109export type spaceMemberPermissionsResponseError =
110 spaceMemberPermissionsResponse403 & {
111 headers: Headers;
112 };
113
114export type spaceMemberPermissionsResponse =
115 spaceMemberPermissionsResponseSuccess | spaceMemberPermissionsResponseError;
116
117export const getSpaceMemberPermissionsUrl = (
118 spaceName: string,
119 memberId: string,
120) => {
121 return `/api/v1/spaces/${spaceName}/members/${memberId}/permissions`;
122};
123
124/**
125 * 整表替换语义。需要 `role.permission.update`,OWNER 不接受直挂覆盖。
126 * @summary 设置成员直挂权限
127 */
128export const spaceMemberPermissions = async (
129 spaceName: string,
130 memberId: string,
131 setRolePermissionsBody: SetRolePermissionsBody,
132 options?: RequestInit,
133): Promise<spaceMemberPermissionsResponse> => {
134 const getHeaders = (
135 h?: NonNullable<RequestInit["headers"]>,
136 ): Record<string, string | readonly string[]> => {
137 if (!h) return {};
138 if (h instanceof Headers) return Object.fromEntries(h.entries());
139 if (Symbol.iterator in h) {
140 return Object.fromEntries(
141 Array.from(
142 h as Iterable<Iterable<string>>,
143 (entry) => Array.from(entry) as [string, string],
144 ),
145 );
146 }
147 const headers: Record<string, string | readonly string[]> = {};
148 for (const [name, value] of Object.entries<
149 string | readonly string[] | undefined
150 >(h)) {
151 if (value !== undefined) headers[name] = value;
152 }
153 return headers;
154 };
155 const res = await fetch(getSpaceMemberPermissionsUrl(spaceName, memberId), {
156 ...options,
157 method: "PUT",
158 headers: {
159 "Content-Type": "application/json",
160 ...getHeaders(options?.headers),
161 },
162 body: JSON.stringify(setRolePermissionsBody),
163 });
164
165 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
166
167 const data: spaceMemberPermissionsResponse["data"] = body
168 ? JSON.parse(body)
169 : {};
170 return {
171 data,
172 status: res.status,
173 headers: res.headers,
174 } as spaceMemberPermissionsResponse;
175};
Added packages/apiclient/auth/space-member-remove.schemas.ts View packages/apiclient/auth/space-member-remove.schemas.ts
@@ -0,0 +1,116 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export interface EnvelopeNoData {
90 code: number;
91 data?: unknown;
92 /** @nullable */
93 error?: string | null;
94 /** @nullable */
95 error_code?: string | null;
96 message: string;
97 request_id?: string;
98}
99
100export interface EnvelopeBool {
101 code: number;
102 data?: boolean;
103 /** @nullable */
104 error?: string | null;
105 /** @nullable */
106 error_code?: string | null;
107 message: string;
108 request_id?: string;
109}
110
111export type SpaceMemberRemoveParams = {
112 /**
113 * 移除原因
114 */
115 reason?: string;
116};
Added packages/apiclient/auth/space-member-remove.ts View packages/apiclient/auth/space-member-remove.ts
@@ -0,0 +1,161 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeBool,
91 EnvelopeNoData,
92 SpaceMemberRemoveParams,
93} from "./space-member-remove.schemas";
94
95export type spaceMemberRemoveResponse200 = {
96 data: EnvelopeBool;
97 status: 200;
98};
99
100export type spaceMemberRemoveResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceMemberRemoveResponseSuccess = spaceMemberRemoveResponse200 & {
106 headers: Headers;
107};
108export type spaceMemberRemoveResponseError = spaceMemberRemoveResponse403 & {
109 headers: Headers;
110};
111
112export type spaceMemberRemoveResponse =
113 spaceMemberRemoveResponseSuccess | spaceMemberRemoveResponseError;
114
115export const getSpaceMemberRemoveUrl = (
116 spaceName: string,
117 memberId: string,
118 params?: SpaceMemberRemoveParams,
119) => {
120 const normalizedParams = new URLSearchParams();
121
122 Object.entries(params || {}).forEach(([key, value]) => {
123 if (value !== undefined) {
124 normalizedParams.append(key, value === null ? "null" : String(value));
125 }
126 });
127
128 const stringifiedParams = normalizedParams.toString();
129
130 return stringifiedParams.length > 0
131 ? `/api/v1/spaces/${spaceName}/members/${memberId}?${stringifiedParams}`
132 : `/api/v1/spaces/${spaceName}/members/${memberId}`;
133};
134
135/**
136 * 需要 `member.remove`。OWNER 不能移除,需先转移所有权。会籍行保留用于复活。
137 * @summary 移除成员
138 */
139export const spaceMemberRemove = async (
140 spaceName: string,
141 memberId: string,
142 params?: SpaceMemberRemoveParams,
143 options?: RequestInit,
144): Promise<spaceMemberRemoveResponse> => {
145 const res = await fetch(
146 getSpaceMemberRemoveUrl(spaceName, memberId, params),
147 {
148 ...options,
149 method: "DELETE",
150 },
151 );
152
153 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
154
155 const data: spaceMemberRemoveResponse["data"] = body ? JSON.parse(body) : {};
156 return {
157 data,
158 status: res.status,
159 headers: res.headers,
160 } as spaceMemberRemoveResponse;
161};
Added packages/apiclient/auth/space-member-role.schemas.ts View packages/apiclient/auth/space-member-role.schemas.ts
@@ -0,0 +1,165 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
161
162export interface SetMemberRoleBody {
163 expected_version?: number;
164 role: SpaceMemberRole;
165}
Added packages/apiclient/auth/space-member-role.ts View packages/apiclient/auth/space-member-role.ts
@@ -0,0 +1,175 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMemberSummary,
91 EnvelopeNoData,
92 SetMemberRoleBody,
93} from "./space-member-role.schemas";
94
95export type spaceMemberRoleResponse200 = {
96 data: EnvelopeMemberSummary;
97 status: 200;
98};
99
100export type spaceMemberRoleResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceMemberRoleResponse409 = {
106 data: EnvelopeNoData;
107 status: 409;
108};
109
110export type spaceMemberRoleResponseSuccess = spaceMemberRoleResponse200 & {
111 headers: Headers;
112};
113export type spaceMemberRoleResponseError = (
114 spaceMemberRoleResponse403 | spaceMemberRoleResponse409
115) & {
116 headers: Headers;
117};
118
119export type spaceMemberRoleResponse =
120 spaceMemberRoleResponseSuccess | spaceMemberRoleResponseError;
121
122export const getSpaceMemberRoleUrl = (spaceName: string, memberId: string) => {
123 return `/api/v1/spaces/${spaceName}/members/${memberId}/role`;
124};
125
126/**
127 * 只接受 MEMBER 与 ADMIN。OWNER 只能通过转移所有权变更。
128 * @summary 改粗粒度角色
129 */
130export const spaceMemberRole = async (
131 spaceName: string,
132 memberId: string,
133 setMemberRoleBody: SetMemberRoleBody,
134 options?: RequestInit,
135): Promise<spaceMemberRoleResponse> => {
136 const getHeaders = (
137 h?: NonNullable<RequestInit["headers"]>,
138 ): Record<string, string | readonly string[]> => {
139 if (!h) return {};
140 if (h instanceof Headers) return Object.fromEntries(h.entries());
141 if (Symbol.iterator in h) {
142 return Object.fromEntries(
143 Array.from(
144 h as Iterable<Iterable<string>>,
145 (entry) => Array.from(entry) as [string, string],
146 ),
147 );
148 }
149 const headers: Record<string, string | readonly string[]> = {};
150 for (const [name, value] of Object.entries<
151 string | readonly string[] | undefined
152 >(h)) {
153 if (value !== undefined) headers[name] = value;
154 }
155 return headers;
156 };
157 const res = await fetch(getSpaceMemberRoleUrl(spaceName, memberId), {
158 ...options,
159 method: "PATCH",
160 headers: {
161 "Content-Type": "application/json",
162 ...getHeaders(options?.headers),
163 },
164 body: JSON.stringify(setMemberRoleBody),
165 });
166
167 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
168
169 const data: spaceMemberRoleResponse["data"] = body ? JSON.parse(body) : {};
170 return {
171 data,
172 status: res.status,
173 headers: res.headers,
174 } as spaceMemberRoleResponse;
175};
Added packages/apiclient/auth/space-member-unban.schemas.ts View packages/apiclient/auth/space-member-unban.schemas.ts
@@ -0,0 +1,160 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
Added packages/apiclient/auth/space-member-unban.ts View packages/apiclient/auth/space-member-unban.ts
@@ -0,0 +1,140 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMemberSummary,
91 EnvelopeNoData,
92} from "./space-member-unban.schemas";
93
94export type spaceMemberUnbanResponse200 = {
95 data: EnvelopeMemberSummary;
96 status: 200;
97};
98
99export type spaceMemberUnbanResponse403 = {
100 data: EnvelopeNoData;
101 status: 403;
102};
103
104export type spaceMemberUnbanResponseSuccess = spaceMemberUnbanResponse200 & {
105 headers: Headers;
106};
107export type spaceMemberUnbanResponseError = spaceMemberUnbanResponse403 & {
108 headers: Headers;
109};
110
111export type spaceMemberUnbanResponse =
112 spaceMemberUnbanResponseSuccess | spaceMemberUnbanResponseError;
113
114export const getSpaceMemberUnbanUrl = (spaceName: string, memberId: string) => {
115 return `/api/v1/spaces/${spaceName}/members/${memberId}/unban`;
116};
117
118/**
119 * 清空 banned_at。已清空的角色不会自动恢复。
120 * @summary 解封成员
121 */
122export const spaceMemberUnban = async (
123 spaceName: string,
124 memberId: string,
125 options?: RequestInit,
126): Promise<spaceMemberUnbanResponse> => {
127 const res = await fetch(getSpaceMemberUnbanUrl(spaceName, memberId), {
128 ...options,
129 method: "POST",
130 });
131
132 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
133
134 const data: spaceMemberUnbanResponse["data"] = body ? JSON.parse(body) : {};
135 return {
136 data,
137 status: res.status,
138 headers: res.headers,
139 } as spaceMemberUnbanResponse;
140};
Added packages/apiclient/auth/space-member-update-self.schemas.ts View packages/apiclient/auth/space-member-update-self.schemas.ts
@@ -0,0 +1,185 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
161
162/**
163 * 会籍更新:管理端可改别名、通知偏好、免打扰与封禁附加信息。
164 * 所有字段缺失表示不变,显式 null 表示清空(仅限 Option 字段)。
165 */
166export interface UpdateMemberBody {
167 /** @nullable */
168 alias_avatar_url?: string | null;
169 /** @nullable */
170 alias_name?: string | null;
171 expected_version?: number;
172 /** @nullable */
173 hide_muted_channels?: boolean | null;
174 message_notifications?: null | MessageNotifications;
175 /** @nullable */
176 mobile_push?: boolean | null;
177 /** @nullable */
178 mute_until?: string | null;
179 /** @nullable */
180 muted?: boolean | null;
181 /** @nullable */
182 suppress_everyone?: boolean | null;
183 /** @nullable */
184 suppress_roles?: boolean | null;
185}
Added packages/apiclient/auth/space-member-update-self.ts View packages/apiclient/auth/space-member-update-self.ts
@@ -0,0 +1,171 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89import type {
90 EnvelopeMemberSummary,
91 EnvelopeNoData,
92 UpdateMemberBody,
93} from "./space-member-update-self.schemas";
94
95export type spaceMemberUpdateSelfResponse200 = {
96 data: EnvelopeMemberSummary;
97 status: 200;
98};
99
100export type spaceMemberUpdateSelfResponse403 = {
101 data: EnvelopeNoData;
102 status: 403;
103};
104
105export type spaceMemberUpdateSelfResponseSuccess =
106 spaceMemberUpdateSelfResponse200 & {
107 headers: Headers;
108 };
109export type spaceMemberUpdateSelfResponseError =
110 spaceMemberUpdateSelfResponse403 & {
111 headers: Headers;
112 };
113
114export type spaceMemberUpdateSelfResponse =
115 spaceMemberUpdateSelfResponseSuccess | spaceMemberUpdateSelfResponseError;
116
117export const getSpaceMemberUpdateSelfUrl = (spaceName: string) => {
118 return `/api/v1/spaces/${spaceName}/members/@me`;
119};
120
121/**
122 * 只允许修改自己的别名、头像与通知偏好;无需 `member.role.update`。
123 * @summary 更新自己的会籍资料
124 */
125export const spaceMemberUpdateSelf = async (
126 spaceName: string,
127 updateMemberBody: UpdateMemberBody,
128 options?: RequestInit,
129): Promise<spaceMemberUpdateSelfResponse> => {
130 const getHeaders = (
131 h?: NonNullable<RequestInit["headers"]>,
132 ): Record<string, string | readonly string[]> => {
133 if (!h) return {};
134 if (h instanceof Headers) return Object.fromEntries(h.entries());
135 if (Symbol.iterator in h) {
136 return Object.fromEntries(
137 Array.from(
138 h as Iterable<Iterable<string>>,
139 (entry) => Array.from(entry) as [string, string],
140 ),
141 );
142 }
143 const headers: Record<string, string | readonly string[]> = {};
144 for (const [name, value] of Object.entries<
145 string | readonly string[] | undefined
146 >(h)) {
147 if (value !== undefined) headers[name] = value;
148 }
149 return headers;
150 };
151 const res = await fetch(getSpaceMemberUpdateSelfUrl(spaceName), {
152 ...options,
153 method: "PATCH",
154 headers: {
155 "Content-Type": "application/json",
156 ...getHeaders(options?.headers),
157 },
158 body: JSON.stringify(updateMemberBody),
159 });
160
161 const body = [204, 205, 304].includes(res.status) ? null : await res.text();
162
163 const data: spaceMemberUpdateSelfResponse["data"] = body
164 ? JSON.parse(body)
165 : {};
166 return {
167 data,
168 status: res.status,
169 headers: res.headers,
170 } as spaceMemberUpdateSelfResponse;
171};
Added packages/apiclient/auth/space-member-update.schemas.ts View packages/apiclient/auth/space-member-update.schemas.ts
@@ -0,0 +1,185 @@
1/**
2 * Generated by orval 🍺
3 * Do not edit manually.
4 * gitdata api
5 *
6 * ## Conventions
7 *
8 * ### Response envelope
9 * Every JSON response uses the same envelope:
10 *
11 * | field | meaning |
12 * |---|---|
13 * | `code` | always equal to the HTTP status code |
14 * | `message` | human-readable result / error summary |
15 * | `data` | payload, `null` for errors and empty results |
16 * | `error` | field-level / technical detail (e.g. validation errors), may be `null` |
17 * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
18 * | `request_id` | correlation id, also returned as the `X-Request-Id` header |
19 *
20 * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
21 * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
22 *
23 * ### Authentication
24 * - `session_cookie`: opaque session carried in the `session` cookie and stored in
25 * Redis. `GET /auth/login` redirects to the same-origin login page;
26 * `POST /auth/logout` revokes the session and clears the cookie.
27 *
28 * ### URL & parameter style
29 * - Paths are `kebab-case`, plural nouns, nesting expresses ownership.
30 * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
31 * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
32 * by the `x-gitdata-service-key` header and is NOT documented here.
33 * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
34 * idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
35 * partial updates use `PATCH`.
36 *
37 * ### Pagination
38 * - Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
39 * response `data` is `{ items, total, limit, offset }`.
40 * - Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
41 * response contains `has_more`.
42 *
43 * ### PATCH semantics (three-state fields)
44 * Update commands use `Option<Option<T>>` for clearable fields:
45 * - field **absent** → unchanged
46 * - field `null` → cleared
47 * - field value → set
48 *
49 * Example: `{"milestone_id": null}` unassigns the milestone; omitting
50 * `milestone_id` leaves it untouched.
51 *
52 * ### 2FA
53 * TOTP enrollment, recovery codes and sensitive-operation verification are
54 * handled by identity; GitData only proxies the account-management endpoints.
55 *
56 * ### Operations
57 * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
58 * - `GET /readyz` — readiness probe: database + redis check, `503` when down.
59 * - Runtime metrics are pushed to the configured OTLP collector (30s interval);
60 * there is no scrape endpoint.
61 * - Cross-origin browser access is disabled by default; the API expects a
62 * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
63 * other origins.
64 *
65 * ### Abuse controls
66 * - Creation endpoints are subject to per-user rolling 24h quotas
67 * (`[quota]` config; 0 disables). Exceeding a quota returns `429`
68 * with `error_code: "rate_limited"`.
69 *
70 * ### Idempotency
71 * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
72 * retrying with the same nonce returns the original message instead of a duplicate.
73 *
74 * ### Resource references
75 * - User references in responses embed a `user` object (`UserDto`) wherever a
76 * single person is shown; raw uuid fields are named `*_id` consistently.
77 * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
78 * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
79 * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
80 *
81 * ### Identifiers
82 * - Issues are addressable by UUID **or** board-scoped number
83 * (e.g. `/issues/{space}/boards/{board}/issues/123`).
84 * - Binary uploads use raw request bodies with a content-type header
85 * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
86 *
87 * OpenAPI spec version: 1.0
88 */
89export type SpaceMemberRole = "member" | "admin" | "owner";
90export type SpaceJoinMethod =
91 "direct" | "invite_link" | "invite_targeted" | "invite_email";
92/**
93 * 会籍的通知偏好,对应旧 `space_members.message_notifications`。
94 * 旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。
95 */
96export type MessageNotifications = "all" | "mentions" | "nothing";
97export type EnvelopeMemberSummaryData = {
98 /** @nullable */
99 alias_avatar_url?: string | null;
100 /** @nullable */
101 alias_name?: string | null;
102 ban_allow_agent_join: boolean;
103 ban_allow_comment_any: boolean;
104 ban_allow_push_repo: boolean;
105 ban_allow_speak: boolean;
106 /** @nullable */
107 ban_expires_at?: string | null;
108 /** @nullable */
109 ban_reason?: string | null;
110 /** @nullable */
111 banned_at?: string | null;
112 /** @nullable */
113 displayname?: string | null;
114 hide_muted_channels: boolean;
115 id: string;
116 /** @nullable */
117 invited_by?: number | null;
118 join_method: SpaceJoinMethod;
119 joined_at: string;
120 /** @nullable */
121 last_active_at?: string | null;
122 /** @nullable */
123 left_at?: string | null;
124 message_notifications: MessageNotifications;
125 mobile_push: boolean;
126 /** @nullable */
127 mute_until?: string | null;
128 muted: boolean;
129 organization_id: string;
130 permissions: string[];
131 role: SpaceMemberRole;
132 role_keys: string[];
133 suppress_everyone: boolean;
134 suppress_roles: boolean;
135 user_id: number;
136 username: string;
137 version: number;
138};
139
140export interface EnvelopeMemberSummary {
141 code: number;
142 data?: EnvelopeMemberSummaryData;
143 /** @nullable */
144 error?: string | null;
145 /** @nullable */
146 error_code?: string | null;
147 message: string;
148 request_id?: string;
149}
150
151export interface EnvelopeNoData {
152 code: number;
153 data?: unknown;
154 /** @nullable */
155 error?: string | null;
156 /** @nullable */
157 error_code?: string | null;
158 message: string;
159 request_id?: string;
160}
161
162/**
163 * 会籍更新:管理端可改别名、通知偏好、免打扰与封禁附加信息。
164 * 所有字段缺失表示不变,显式 null 表示清空(仅限 Option 字段)。
165 */
166export interface UpdateMemberBody {
167 /** @nullable */
168 alias_avatar_url?: string | null;
169 /** @nullable */
170 alias_name?: string | null;
171 expected_version?: number;
172 /** @nullable */
173 hide_muted_channels?: boolean | null;
174 message_notifications?: null | MessageNotifications;
175 /** @nullable */
176 mobile_push?: boolean | null;
177 /** @nullable */
178 mute_until?: string | null;
179 /** @nullable */
180 muted?: boolean | null;
181 /** @nullable */
182 suppress_everyone?: boolean | null;
183 /** @nullable */
184 suppress_roles?: boolean | null;
185}
Added packages/apiclient/auth/space-member-update.ts View packages/apiclient/auth/space-member-update.ts

Diff too large to display.

Added packages/apiclient/auth/space-permission-check.schemas.ts View packages/apiclient/auth/space-permission-check.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-permission-check.ts View packages/apiclient/auth/space-permission-check.ts

Diff too large to display.

Added packages/apiclient/auth/space-restore.schemas.ts View packages/apiclient/auth/space-restore.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-restore.ts View packages/apiclient/auth/space-restore.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-assign.schemas.ts View packages/apiclient/auth/space-role-assign.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-assign.ts View packages/apiclient/auth/space-role-assign.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-create.schemas.ts View packages/apiclient/auth/space-role-create.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-create.ts View packages/apiclient/auth/space-role-create.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-delete.schemas.ts View packages/apiclient/auth/space-role-delete.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-delete.ts View packages/apiclient/auth/space-role-delete.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-get.schemas.ts View packages/apiclient/auth/space-role-get.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-get.ts View packages/apiclient/auth/space-role-get.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-join.schemas.ts View packages/apiclient/auth/space-role-join.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-join.ts View packages/apiclient/auth/space-role-join.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-leave.schemas.ts View packages/apiclient/auth/space-role-leave.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-leave.ts View packages/apiclient/auth/space-role-leave.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-list.schemas.ts View packages/apiclient/auth/space-role-list.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-list.ts View packages/apiclient/auth/space-role-list.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-permissions.schemas.ts View packages/apiclient/auth/space-role-permissions.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-permissions.ts View packages/apiclient/auth/space-role-permissions.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-unassign.schemas.ts View packages/apiclient/auth/space-role-unassign.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-unassign.ts View packages/apiclient/auth/space-role-unassign.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-update.schemas.ts View packages/apiclient/auth/space-role-update.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-role-update.ts View packages/apiclient/auth/space-role-update.ts

Diff too large to display.

Added packages/apiclient/auth/space-transfer.schemas.ts View packages/apiclient/auth/space-transfer.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-transfer.ts View packages/apiclient/auth/space-transfer.ts

Diff too large to display.

Added packages/apiclient/auth/space-update.schemas.ts View packages/apiclient/auth/space-update.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/space-update.ts View packages/apiclient/auth/space-update.ts

Diff too large to display.

Added packages/apiclient/auth/totp-disable.schemas.ts View packages/apiclient/auth/totp-disable.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/totp-disable.ts View packages/apiclient/auth/totp-disable.ts

Diff too large to display.

Added packages/apiclient/auth/totp-enable.schemas.ts View packages/apiclient/auth/totp-enable.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/totp-enable.ts View packages/apiclient/auth/totp-enable.ts

Diff too large to display.

Added packages/apiclient/auth/totp-setup.schemas.ts View packages/apiclient/auth/totp-setup.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/totp-setup.ts View packages/apiclient/auth/totp-setup.ts

Diff too large to display.

Added packages/apiclient/auth/totp-status.schemas.ts View packages/apiclient/auth/totp-status.schemas.ts

Diff too large to display.

Added packages/apiclient/auth/totp-status.ts View packages/apiclient/auth/totp-status.ts

Diff too large to display.

Added packages/apiclient/blame/blame.schemas.ts View packages/apiclient/blame/blame.schemas.ts

Diff too large to display.

Added packages/apiclient/blame/blame.ts View packages/apiclient/blame/blame.ts

Diff too large to display.

Added packages/apiclient/blame/index.ts View packages/apiclient/blame/index.ts

Diff too large to display.

Added packages/apiclient/blobs/blob-content.schemas.ts View packages/apiclient/blobs/blob-content.schemas.ts

Diff too large to display.

Added packages/apiclient/blobs/blob-content.ts View packages/apiclient/blobs/blob-content.ts

Diff too large to display.

Added packages/apiclient/blobs/blob-metadata.schemas.ts View packages/apiclient/blobs/blob-metadata.schemas.ts

Diff too large to display.

Added packages/apiclient/blobs/blob-metadata.ts View packages/apiclient/blobs/blob-metadata.ts

Diff too large to display.

Added packages/apiclient/blobs/index.ts View packages/apiclient/blobs/index.ts

Diff too large to display.

Added packages/apiclient/blobs/list-lfs-pointers.schemas.ts View packages/apiclient/blobs/list-lfs-pointers.schemas.ts

Diff too large to display.

Added packages/apiclient/blobs/list-lfs-pointers.ts View packages/apiclient/blobs/list-lfs-pointers.ts

Diff too large to display.

Added packages/apiclient/branch-protection/add-branch-whitelist.schemas.ts View packages/apiclient/branch-protection/add-branch-whitelist.schemas.ts

Diff too large to display.

Added packages/apiclient/branch-protection/add-branch-whitelist.ts View packages/apiclient/branch-protection/add-branch-whitelist.ts

Diff too large to display.

Added packages/apiclient/branch-protection/index.ts View packages/apiclient/branch-protection/index.ts

Diff too large to display.

Added packages/apiclient/branch-protection/list-branch-whitelists.schemas.ts View packages/apiclient/branch-protection/list-branch-whitelists.schemas.ts

Diff too large to display.

Added packages/apiclient/branch-protection/list-branch-whitelists.ts View packages/apiclient/branch-protection/list-branch-whitelists.ts

Diff too large to display.

Added packages/apiclient/branch-protection/remove-branch-whitelist.schemas.ts View packages/apiclient/branch-protection/remove-branch-whitelist.schemas.ts

Diff too large to display.

Added packages/apiclient/branch-protection/remove-branch-whitelist.ts View packages/apiclient/branch-protection/remove-branch-whitelist.ts

Diff too large to display.

Added packages/apiclient/branches/create-branch.schemas.ts View packages/apiclient/branches/create-branch.schemas.ts

Diff too large to display.

Added packages/apiclient/branches/create-branch.ts View packages/apiclient/branches/create-branch.ts

Diff too large to display.

Added packages/apiclient/branches/delete-branch.schemas.ts View packages/apiclient/branches/delete-branch.schemas.ts

Diff too large to display.

Added packages/apiclient/branches/delete-branch.ts View packages/apiclient/branches/delete-branch.ts

Diff too large to display.

Added packages/apiclient/branches/get-branch.schemas.ts View packages/apiclient/branches/get-branch.schemas.ts

Diff too large to display.

Added packages/apiclient/branches/get-branch.ts View packages/apiclient/branches/get-branch.ts

Diff too large to display.

Added packages/apiclient/branches/index.ts View packages/apiclient/branches/index.ts

Diff too large to display.

Added packages/apiclient/branches/list-branches.schemas.ts View packages/apiclient/branches/list-branches.schemas.ts

Diff too large to display.

Added packages/apiclient/branches/list-branches.ts View packages/apiclient/branches/list-branches.ts

Diff too large to display.

Added packages/apiclient/branches/rename-branch.schemas.ts View packages/apiclient/branches/rename-branch.schemas.ts

Diff too large to display.

Added packages/apiclient/branches/rename-branch.ts View packages/apiclient/branches/rename-branch.ts

Diff too large to display.

Added packages/apiclient/branches/set-default-branch.schemas.ts View packages/apiclient/branches/set-default-branch.schemas.ts

Diff too large to display.

Added packages/apiclient/branches/set-default-branch.ts View packages/apiclient/branches/set-default-branch.ts

Diff too large to display.

Added packages/apiclient/chat/accept-room-invite.schemas.ts View packages/apiclient/chat/accept-room-invite.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/accept-room-invite.ts View packages/apiclient/chat/accept-room-invite.ts

Diff too large to display.

Added packages/apiclient/chat/add-reaction.schemas.ts View packages/apiclient/chat/add-reaction.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/add-reaction.ts View packages/apiclient/chat/add-reaction.ts

Diff too large to display.

Added packages/apiclient/chat/add-room-members.schemas.ts View packages/apiclient/chat/add-room-members.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/add-room-members.ts View packages/apiclient/chat/add-room-members.ts

Diff too large to display.

Added packages/apiclient/chat/approve-hand.schemas.ts View packages/apiclient/chat/approve-hand.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/approve-hand.ts View packages/apiclient/chat/approve-hand.ts

Diff too large to display.

Added packages/apiclient/chat/ban-room-member.schemas.ts View packages/apiclient/chat/ban-room-member.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/ban-room-member.ts View packages/apiclient/chat/ban-room-member.ts

Diff too large to display.

Added packages/apiclient/chat/bulk-delete-messages.schemas.ts View packages/apiclient/chat/bulk-delete-messages.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/bulk-delete-messages.ts View packages/apiclient/chat/bulk-delete-messages.ts

Diff too large to display.

Added packages/apiclient/chat/cancel-hand.schemas.ts View packages/apiclient/chat/cancel-hand.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/cancel-hand.ts View packages/apiclient/chat/cancel-hand.ts

Diff too large to display.

Added packages/apiclient/chat/cancel-reminder.schemas.ts View packages/apiclient/chat/cancel-reminder.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/cancel-reminder.ts View packages/apiclient/chat/cancel-reminder.ts

Diff too large to display.

Added packages/apiclient/chat/close-dm.schemas.ts View packages/apiclient/chat/close-dm.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/close-dm.ts View packages/apiclient/chat/close-dm.ts

Diff too large to display.

Added packages/apiclient/chat/create-attachment.schemas.ts View packages/apiclient/chat/create-attachment.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-attachment.ts View packages/apiclient/chat/create-attachment.ts

Diff too large to display.

Added packages/apiclient/chat/create-bookmark.schemas.ts View packages/apiclient/chat/create-bookmark.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-bookmark.ts View packages/apiclient/chat/create-bookmark.ts

Diff too large to display.

Added packages/apiclient/chat/create-outbound-webhook.schemas.ts View packages/apiclient/chat/create-outbound-webhook.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-outbound-webhook.ts View packages/apiclient/chat/create-outbound-webhook.ts

Diff too large to display.

Added packages/apiclient/chat/create-reminder.schemas.ts View packages/apiclient/chat/create-reminder.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-reminder.ts View packages/apiclient/chat/create-reminder.ts

Diff too large to display.

Added packages/apiclient/chat/create-room-invite.schemas.ts View packages/apiclient/chat/create-room-invite.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-room-invite.ts View packages/apiclient/chat/create-room-invite.ts

Diff too large to display.

Added packages/apiclient/chat/create-room.schemas.ts View packages/apiclient/chat/create-room.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-room.ts View packages/apiclient/chat/create-room.ts

Diff too large to display.

Added packages/apiclient/chat/create-thread.schemas.ts View packages/apiclient/chat/create-thread.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-thread.ts View packages/apiclient/chat/create-thread.ts

Diff too large to display.

Added packages/apiclient/chat/create-webhook.schemas.ts View packages/apiclient/chat/create-webhook.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/create-webhook.ts View packages/apiclient/chat/create-webhook.ts

Diff too large to display.

Added packages/apiclient/chat/delete-bookmark.schemas.ts View packages/apiclient/chat/delete-bookmark.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/delete-bookmark.ts View packages/apiclient/chat/delete-bookmark.ts

Diff too large to display.

Added packages/apiclient/chat/delete-draft.schemas.ts View packages/apiclient/chat/delete-draft.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/delete-draft.ts View packages/apiclient/chat/delete-draft.ts

Diff too large to display.

Added packages/apiclient/chat/delete-emoji.schemas.ts View packages/apiclient/chat/delete-emoji.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/delete-emoji.ts View packages/apiclient/chat/delete-emoji.ts

Diff too large to display.

Added packages/apiclient/chat/delete-message.schemas.ts View packages/apiclient/chat/delete-message.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/delete-message.ts View packages/apiclient/chat/delete-message.ts

Diff too large to display.

Added packages/apiclient/chat/delete-outbound-webhook.schemas.ts View packages/apiclient/chat/delete-outbound-webhook.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/delete-outbound-webhook.ts View packages/apiclient/chat/delete-outbound-webhook.ts

Diff too large to display.

Added packages/apiclient/chat/delete-room.schemas.ts View packages/apiclient/chat/delete-room.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/delete-room.ts View packages/apiclient/chat/delete-room.ts

Diff too large to display.

Added packages/apiclient/chat/delete-webhook.schemas.ts View packages/apiclient/chat/delete-webhook.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/delete-webhook.ts View packages/apiclient/chat/delete-webhook.ts

Diff too large to display.

Added packages/apiclient/chat/deny-hand.schemas.ts View packages/apiclient/chat/deny-hand.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/deny-hand.ts View packages/apiclient/chat/deny-hand.ts

Diff too large to display.

Added packages/apiclient/chat/download-attachment.schemas.ts View packages/apiclient/chat/download-attachment.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/download-attachment.ts View packages/apiclient/chat/download-attachment.ts

Diff too large to display.

Added packages/apiclient/chat/emoji-image.schemas.ts View packages/apiclient/chat/emoji-image.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/emoji-image.ts View packages/apiclient/chat/emoji-image.ts

Diff too large to display.

Added packages/apiclient/chat/finalize-attachment.schemas.ts View packages/apiclient/chat/finalize-attachment.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/finalize-attachment.ts View packages/apiclient/chat/finalize-attachment.ts

Diff too large to display.

Added packages/apiclient/chat/follow-thread.schemas.ts View packages/apiclient/chat/follow-thread.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/follow-thread.ts View packages/apiclient/chat/follow-thread.ts

Diff too large to display.

Added packages/apiclient/chat/forward-message.schemas.ts View packages/apiclient/chat/forward-message.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/forward-message.ts View packages/apiclient/chat/forward-message.ts

Diff too large to display.

Added packages/apiclient/chat/get-attachment.schemas.ts View packages/apiclient/chat/get-attachment.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-attachment.ts View packages/apiclient/chat/get-attachment.ts

Diff too large to display.

Added packages/apiclient/chat/get-draft.schemas.ts View packages/apiclient/chat/get-draft.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-draft.ts View packages/apiclient/chat/get-draft.ts

Diff too large to display.

Added packages/apiclient/chat/get-emoji.schemas.ts View packages/apiclient/chat/get-emoji.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-emoji.ts View packages/apiclient/chat/get-emoji.ts

Diff too large to display.

Added packages/apiclient/chat/get-message.schemas.ts View packages/apiclient/chat/get-message.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-message.ts View packages/apiclient/chat/get-message.ts

Diff too large to display.

Added packages/apiclient/chat/get-presence.schemas.ts View packages/apiclient/chat/get-presence.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-presence.ts View packages/apiclient/chat/get-presence.ts

Diff too large to display.

Added packages/apiclient/chat/get-read-state.schemas.ts View packages/apiclient/chat/get-read-state.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-read-state.ts View packages/apiclient/chat/get-read-state.ts

Diff too large to display.

Added packages/apiclient/chat/get-room-member.schemas.ts View packages/apiclient/chat/get-room-member.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-room-member.ts View packages/apiclient/chat/get-room-member.ts

Diff too large to display.

Added packages/apiclient/chat/get-room-setting.schemas.ts View packages/apiclient/chat/get-room-setting.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-room-setting.ts View packages/apiclient/chat/get-room-setting.ts

Diff too large to display.

Added packages/apiclient/chat/get-room.schemas.ts View packages/apiclient/chat/get-room.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-room.ts View packages/apiclient/chat/get-room.ts

Diff too large to display.

Added packages/apiclient/chat/get-thread.schemas.ts View packages/apiclient/chat/get-thread.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-thread.ts View packages/apiclient/chat/get-thread.ts

Diff too large to display.

Added packages/apiclient/chat/get-voice-layout.schemas.ts View packages/apiclient/chat/get-voice-layout.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/get-voice-layout.ts View packages/apiclient/chat/get-voice-layout.ts

Diff too large to display.

Added packages/apiclient/chat/index.ts View packages/apiclient/chat/index.ts

Diff too large to display.

Added packages/apiclient/chat/join-room.schemas.ts View packages/apiclient/chat/join-room.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/join-room.ts View packages/apiclient/chat/join-room.ts

Diff too large to display.

Added packages/apiclient/chat/kick-participant.schemas.ts View packages/apiclient/chat/kick-participant.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/kick-participant.ts View packages/apiclient/chat/kick-participant.ts

Diff too large to display.

Added packages/apiclient/chat/kick-room-member.schemas.ts View packages/apiclient/chat/kick-room-member.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/kick-room-member.ts View packages/apiclient/chat/kick-room-member.ts

Diff too large to display.

Added packages/apiclient/chat/leave-room.schemas.ts View packages/apiclient/chat/leave-room.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/leave-room.ts View packages/apiclient/chat/leave-room.ts

Diff too large to display.

Added packages/apiclient/chat/list-bookmarks.schemas.ts View packages/apiclient/chat/list-bookmarks.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/list-bookmarks.ts View packages/apiclient/chat/list-bookmarks.ts

Diff too large to display.

Added packages/apiclient/chat/list-dms.schemas.ts View packages/apiclient/chat/list-dms.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/list-dms.ts View packages/apiclient/chat/list-dms.ts

Diff too large to display.

Added packages/apiclient/chat/list-emojis.schemas.ts View packages/apiclient/chat/list-emojis.schemas.ts

Diff too large to display.

Added packages/apiclient/chat/list-emojis.ts View packages/apiclient/chat/list-emojis.ts

Diff too large to display.

Modified view/auth/src/shared/api/index.ts View view/auth/src/shared/api/index.ts
@@ -1,6 +1,10 @@
1// orval 生成物在 ./auth/ 下,`npm run gen` 会清理并重建该目录,因此桶文件放在这一层。
2export * from './auth/auth'
3export * from './auth/auth.schemas'
1// orval 生成物在 packages/apiclient 下,`npm run gen` 会清理并重建该目录。
2export * from '@kenapi/apiclient'
3export type { EnvelopeNoData, PowProofRequest } from '@kenapi/apiclient/auth/auth-login.schemas'
4export type { EnvelopeChallengeResponseData as ChallengeResponse } from '@kenapi/apiclient/auth/auth-challenge.schemas'
5export type { EnvelopeMeResponseData as MeResponse } from '@kenapi/apiclient/auth/auth-me.schemas'
6export type { EnvelopeUserLoginResponseData as UserLoginResponse } from '@kenapi/apiclient/auth/auth-login.schemas'
7export type { UserRegisterRequest } from '@kenapi/apiclient/auth/auth-register.schemas'
48export { AuthError, errorMessage } from './error'
59export type { ApiResponse } from './http'
610export { request, requestInit, secured } from './http'
Modified Dockerfile View Dockerfile
@@ -22,6 +22,7 @@
2222COPY package.json package-lock.json ./
2323RUN npm ci
2424COPY view ./view
25COPY packages ./packages
2526COPY vite.config.ts tsconfig.json tsconfig.app.json tsconfig.node.json \
2627 orval.config.ts steiger.config.ts biome.json ./
2728RUN npm run build
Modified justfile View justfile
@@ -95,9 +95,9 @@
9595 @echo " kenapi http://127.0.0.1:7051 (Swagger: /api/docs)"
9696 @echo " identity http://127.0.0.1:7021 (gRPC: 127.0.0.1:7022)"
9797
98# 重新生成 openapi.json
98# 重新生成 openapi.json 与 packages/apiclient 客户端
9999openapi:
100 @cargo run -p kenapi -- openapi
100 @cargo run -p kenapi -- openapi && npx orval
101101
102102# 校验 openapi 是否与源码一致
103103openapi-check:
@@ -120,6 +120,3 @@
120120
121121identity-web-dev:
122122 npm run dev
123
124identity-openapi:
125 cargo run -p kenapi -- identity-openapi
Modified openapi.json View openapi.json

Diff too large to display.

Modified orval.config.ts View orval.config.ts
@@ -1,21 +1,20 @@
11import { defineConfig } from 'orval'
22
3// 生成 view/auth/src/shared/api/auth 下的 fetch 客户端;OpenApi.Auth.json 来自
4// `cargo run -p kenapi -- identity-openapi`。
3// 唯一的 OpenAPI 文档由 `cargo run -p kenapi -- openapi` 生成到仓库根目录,
4// 这里把它生成为 packages/apiclient 下的 fetch 客户端。
55export default defineConfig({
6 auth: {
7 input: './lib/auth/OpenApi.Auth.json',
6 apiclient: {
7 input: './openapi.json',
88 output: {
9 target: './view/auth/src/shared/api/auth',
10 mode: 'split',
9 target: './packages/apiclient/index.ts',
10 mode: 'tags-operations-split',
1111 client: 'fetch',
1212 httpClient: 'fetch',
1313 clean: true,
14 indexFiles: true,
1514 formatter: 'prettier',
15 baseUrl: '/api/v1',
1616 override: {
1717 enumGenerationType: 'union',
18 mutator: { path: './view/auth/src/shared/lib/http/http.ts', name: 'authClient' },
1918 },
2019 },
2120 },
Modified package.json View package.json
@@ -3,7 +3,7 @@
33 "private": true,
44 "type": "module",
55 "scripts": {
6 "gen": "cargo run -p kenapi -- identity-openapi && orval",
6 "gen": "cargo run -p kenapi -- openapi && orval",
77 "dev": "vite",
88 "build": "tsc -b && vite build",
99 "typecheck": "tsc -b",
Modified tsconfig.app.json View tsconfig.app.json
@@ -8,7 +8,9 @@
88 "allowArbitraryExtensions": true,
99 "skipLibCheck": true,
1010 "paths": {
11 "@/*": ["./view/auth/src/*"]
11 "@/*": ["./view/auth/src/*"],
12 "@kenapi/apiclient": ["./packages/apiclient/index.ts"],
13 "@kenapi/apiclient/*": ["./packages/apiclient/*"]
1214 },
1315
1416 /* Bundler mode */
Modified vite.config.ts View vite.config.ts
@@ -10,7 +10,12 @@
1010 publicDir: 'public',
1111 build: { outDir: '../dist', emptyOutDir: true },
1212 plugins: [react(), tailwindcss()],
13 resolve: { alias: { '@': fileURLToPath(new URL('./view/auth/src', import.meta.url)) } },
13 resolve: {
14 alias: {
15 '@kenapi/apiclient': fileURLToPath(new URL('./packages/apiclient', import.meta.url)),
16 '@': fileURLToPath(new URL('./view/auth/src', import.meta.url)),
17 },
18 },
1419 optimizeDeps: { include: ['@noble/hashes/sha2.js'] },
1520 server: {
1621 port: 15474,