759ae5e
/* tslint:disable */
/* eslint-disable */
/**
* gitdata api - version 1.0
*
*
## Conventions
### Response envelope
Every JSON response uses the same envelope:
| field | meaning |
|---|---|
| `code` | always equal to the HTTP status code |
| `message` | human-readable result / error summary |
| `data` | payload, `null` for errors and empty results |
| `error` | field-level / technical detail (e.g. validation errors), may be `null` |
| `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` |
| `request_id` / `log_id` | correlation ids, also returned as `X-Request-Id` / `X-Log-Id` headers |
Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`.
- `POST /auth/logout` is idempotent: repeating it always succeeds with `200`.
### Authentication
- `session_cookie`: KenOAuth access token carried in the `gitdata_session`
cookie. `GET /auth/login` starts the OIDC authorization-code + PKCE flow;
`POST /auth/refresh` rotates the access/refresh pair; `POST /auth/logout`
revokes the KenOAuth session and clears both cookies.
- `basic_access_key`: HTTP Basic auth with a KenOAuth-issued access key.
**Scope: git repository endpoints only** (`/repos/*`, `/graphql`); it is NOT
accepted by chat/issues/space/user endpoints.
### URL & parameter style
- Paths are `kebab-case`, plural nouns, nesting expresses ownership.
- Query/path/JSON field names are `snake_case`; enum values are `snake_case`.
- All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded
by the `x-gitdata-service-key` header and is NOT documented here.
- State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen);
idempotent whole-resource state uses `PUT` (default branch, pin, read-state);
partial updates use `PATCH`.
### Pagination
- Offset style: `?limit=&offset=` (default 50, max 100 unless stated),
response `data` is `{ items, total, limit, offset }`.
- Cursor style (chat message/sequence data): `?before_seq=&after_seq=&limit=`,
response contains `has_more`.
### PATCH semantics (three-state fields)
Update commands use `Option<Option<T>>` for clearable fields:
- field **absent** → unchanged
- field `null` → cleared
- field value → set
Example: `{"milestone_id": null}` unassigns the milestone; omitting
`milestone_id` leaves it untouched.
### 2FA
TOTP enrollment, recovery codes and sensitive-operation verification are
handled by KenOAuth; GitData only proxies the account-management endpoints.
### Operations
- `GET /healthz` — liveness probe (no auth, outside `/api/v1`).
- `GET /readyz` — readiness probe: database + redis check, `503` when down.
- Runtime metrics are pushed to the configured OTLP collector (30s interval);
there is no scrape endpoint.
- Cross-origin browser access is disabled by default; the API expects a
same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist
other origins.
### Abuse controls
- Creation endpoints are subject to per-user rolling 24h quotas
(`[quota]` config; 0 disables). Exceeding a quota returns `429`
with `error_code: "rate_limited"`.
### Idempotency
- `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room;
retrying with the same nonce returns the original message instead of a duplicate.
### Resource references
- User references in responses embed a `user` object (`UserDto`) wherever a
single person is shown; raw uuid fields are named `*_id` consistently.
- Viewer-specific state is embedded, not fetched separately: `RepoDto.me`
carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller
watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist.
### Identifiers
- Issues are addressable by UUID **or** board-scoped number
(e.g. `/issues/{space}/boards/{board}/issues/123`).
- Binary uploads use raw request bodies with a content-type header
(e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON).
*
* OpenAPI version: 3.1.0
*
*
* NOTE: This file is auto generated by the alova's vscode plugin.
*
* https://alova.js.org/devtools/vscode
*
* **Do not edit the file manually.**
*/
import type { Alova, MethodType, AlovaGenerics, AlovaMethodCreateConfig } from 'alova';
import { Method } from 'alova';
import apiDefinitions from './apiDefinitions';
const cache = Object.create(null);
const createFunctionalProxy = (array: (string | symbol)[], alovaInstance: Alova<AlovaGenerics>, configMap: any) => {
const apiPathKey = array.join('.') as keyof typeof apiDefinitions;
if (cache[apiPathKey]) {
return cache[apiPathKey];
}
// create a new proxy instance
const proxy = new Proxy(function () {}, {
get(_, property) {
// record the target property, so that it can get the completed accessing paths
const newArray = [...array, property];
// always return a new proxy to continue recording accessing paths.
return createFunctionalProxy(newArray, alovaInstance, configMap);
},
apply(_, __, [config]) {
const apiItem = apiDefinitions[apiPathKey];
if (!apiItem) {
throw new Error(`the api path of \`${apiPathKey}\` is not found`);
}
const mergedConfig = {
...configMap[apiPathKey],
...config
};
const [method, url] = apiItem;
const pathParams = mergedConfig.pathParams;
const urlReplaced = url!.replace(/\{([^}]+)\}/g, (_, key) => {
const pathParam = pathParams[key];
return pathParam;
});
delete mergedConfig.pathParams;
let data = mergedConfig.data;
if (Object.prototype.toString.call(data) === '[object Object]' && typeof FormData !== 'undefined') {
let hasBlobData = false;
const formData = new FormData();
for (const key in data) {
if (Array.isArray(data[key])) {
for (const ele of data[key]) {
formData.append(key, ele);
if (ele instanceof Blob) {
hasBlobData = true;
}
}
} else {
formData.append(key, data[key]);
if (data[key] instanceof Blob) {
hasBlobData = true;
}
}
}
data = hasBlobData ? formData : data;
}
return new Method(method!.toUpperCase() as MethodType, alovaInstance, urlReplaced, mergedConfig, data);
}
});
cache[apiPathKey] = proxy;
return proxy;
};
export const createApis = (alovaInstance: Alova<AlovaGenerics>, configMap: any) => {
const Apis = new Proxy({} as Apis, {
get(_, property) {
return createFunctionalProxy([property], alovaInstance, configMap);
}
});
return Apis;
};
export const mountApis = (Apis: Apis) => {
// define global variable `Apis`
(globalThis as any).Apis = Apis;
};
type MethodConfig<T> = AlovaMethodCreateConfig<
(typeof import('./index'))['alovaInstance'] extends Alova<infer AG> ? AG : any,
any,
T
>;
type APISofParameters<Tag extends string, Url extends string> = Tag extends keyof Apis
? Url extends keyof Apis[Tag]
? Apis[Tag][Url] extends (...args: any) => any
? Parameters<Apis[Tag][Url]>
: any
: any
: any;
type MethodsConfigMap = {
[P in keyof typeof import('./apiDefinitions').default]?: MethodConfig<
P extends `${infer Tag}.${infer Url}` ? Parameters<NonNullable<APISofParameters<Tag, Url>[0]>['transform']>[0] : any
>;
};
export const withConfigType = <Config extends MethodsConfigMap>(config: Config) => config;