Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
node_modules/
dist/
docs/.vitepress/cache/
docs/.vitepress/dist/
coverage/
*.log
.DS_Store
*.tgz
*.local
*.local.*
*.local.*
398 changes: 398 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

89 changes: 89 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { existsSync, readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { resolve } from 'node:path';
import { defineConfig } from 'vitepress';

const docsRoot = fileURLToPath(new URL('../', import.meta.url));

function readSidebar(relativePath: string, fallback: unknown[]) {
const path = resolve(docsRoot, relativePath);
if (!existsSync(path)) return fallback;
return JSON.parse(readFileSync(path, 'utf8'));
}

const referenceSidebar = readSidebar('reference/typedoc-sidebar.json', [
{ text: 'Reference', items: [{ text: '概览', link: '/reference/' }] },
]);

const zentaoApiSidebar = readSidebar('zentao-api/sidebar.json', [
{ text: 'ZenTao API', items: [{ text: '概览', link: '/zentao-api/' }] },
]);

export default defineConfig({
lang: 'zh-CN',
title: 'zentao-api',
description: 'Browser and Node.js SDK for ZenTao API v2',
base: '/',
lastUpdated: true,
cleanUrls: true,
markdown: {
lineNumbers: true,
theme: {
light: 'github-light',
dark: 'github-dark',
},
},
themeConfig: {
siteTitle: 'zentao-api',
nav: [
{ text: 'Guide', link: '/guide/', activeMatch: '/guide/' },
{ text: 'Reference', link: '/reference/', activeMatch: '/reference/' },
{ text: 'ZenTao API', link: '/zentao-api/', activeMatch: '/zentao-api/' },
],
sidebar: {
'/guide/': [
{
text: 'Guide',
items: [
{ text: '快速开始', link: '/guide/' },
{ text: '安装与配置', link: '/guide/installation' },
{ text: '运行环境', link: '/guide/environments' },
{ text: '常见 API 示例', link: '/guide/examples' },
{ text: 'Profile 与错误处理', link: '/guide/profiles-and-errors' },
],
},
],
'/reference/': referenceSidebar,
'/zentao-api/': zentaoApiSidebar,
},
search: {
provider: 'local',
},
outline: {
level: [2, 3],
label: '本页目录',
},
editLink: {
pattern: 'https://github.com/catouse/zentao-api/edit/main/docs/:path',
text: '在 GitHub 上编辑此页',
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/catouse/zentao-api' },
],
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2026-present zentao-api contributors',
},
docFooter: {
prev: '上一页',
next: '下一页',
},
lastUpdated: {
text: '最后更新',
formatOptions: {
dateStyle: 'short',
timeStyle: 'short',
},
},
},
});
81 changes: 81 additions & 0 deletions docs/guide/environments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# 运行环境

`zentao-api` 支持服务端运行时、浏览器打包工具和 script 标签引入。不同环境的主要差异在于跨域、安全和本地 profile 存储。

## Node.js 18+

Node.js 18+ 已内置 `fetch`,可以直接使用 SDK。

```ts
import { ZentaoClient } from 'zentao-api';

const client = new ZentaoClient({
baseUrl: 'https://zentao.example.com',
token: process.env.ZENTAO_TOKEN,
});

const projects = await client.get('/projects');
```

在 Node.js 中,`insecure: true` 可用于连接使用自签名证书的测试环境。

```ts
const client = new ZentaoClient({
baseUrl: 'https://zentao.example.com',
token: process.env.ZENTAO_TOKEN,
insecure: true,
});
```

## Bun

Bun 项目可以使用同样的 ESM 导入方式。

```ts
import { ZentaoClient, request } from 'zentao-api';

ZentaoClient.init({
baseUrl: Bun.env.ZENTAO_URL!,
token: Bun.env.ZENTAO_TOKEN!,
});

const products = await request('product/list');
```

## 浏览器打包工具

在 Vite、Webpack、Rspack 等浏览器打包工具中,从包根导入即可。

```ts
import { ZentaoClient } from 'zentao-api';

const client = new ZentaoClient({
baseUrl: 'https://zentao.example.com',
token: 'browser-token',
});
```

浏览器直接请求禅道服务端时,服务端必须允许 CORS。浏览器代码也会暴露 token;如果 token 不能暴露给前端,请通过后端代理转发请求。

## CDN/script 标签

浏览器构建包会把 API 暴露到 `window.ZentaoAPI`。

```html
<script src="https://cdn.jsdelivr.net/npm/zentao-api@latest/dist/browser/zentao-api.global.js"></script>
<script>
const client = new window.ZentaoAPI.ZentaoClient('https://zentao.example.com');
console.log(window.ZentaoAPI.VERSION);
</script>
```

## Profile 存储位置

启用 `persistProfiles` 后,登录信息会持久化到当前运行时可用的本地存储。

| 环境 | 存储位置 |
| --- | --- |
| Node.js / Bun | `~/.config/zentao/zentao.json` |
| 浏览器 | `localStorage` |

浏览器隐私模式、受限 iframe 或无持久化文件系统的运行时可能无法保存 profile。
88 changes: 88 additions & 0 deletions docs/guide/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# 常见 API 示例

本页示例使用高阶 `request("module/action")`。可用模块和动作来自 SDK 模块注册表,完整列表见 [ZenTao API](/zentao-api/)。

## 获取产品列表

```ts
import { ZentaoClient, request } from 'zentao-api';

ZentaoClient.init({
baseUrl: 'https://zentao.example.com',
token: 'your-token',
});

const result = await request('product/list', {
recPerPage: 20,
pageID: 1,
});

console.log(result.data);
console.log(result.pager);
```

## 获取 Bug 列表

Bug 列表支持按产品、项目或执行范围查询。传入对应范围 ID 后,SDK 会根据模块动作定义组装路径。

```ts
const bugs = await request('bug/list', {
productID: 1,
status: 'active',
recPerPage: 20,
});
```

## 解决 Bug

```ts
const result = await request('bug/resolve', {
bugID: 1001,
resolution: 'fixed',
resolvedBuild: 12,
});

console.log(result.status);
```

## 创建任务

```ts
const task = await request('task/create', {
execution: 1,
name: '实现文档站',
type: 'devel',
assignedTo: 'dev1',
});
```

## 直接调用 REST 路径

当你需要调用尚未注册到模块系统的接口时,可以使用底层 `ZentaoClient.request()`。

```ts
import { ZentaoClient } from 'zentao-api';

const client = new ZentaoClient({
baseUrl: 'https://zentao.example.com',
token: 'your-token',
});

const raw = await client.request('/products/1', {
method: 'GET',
});
```

## 限制返回列表数量

`limit` 只影响 SDK 归一化后的 `data` 数组,不改变服务端返回页大小。

```ts
const bugs = await request(
'bug/list',
{ productID: 1, recPerPage: 100 },
{ limit: '10' },
);

console.log(bugs.data);
```
75 changes: 75 additions & 0 deletions docs/guide/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# 快速开始

`zentao-api` 是一个面向禅道 API v2 的 JavaScript/TypeScript SDK,可在 Node.js 18+、Bun、浏览器打包工具和 CDN/script 标签场景中使用。

SDK 提供两层调用方式:

- `ZentaoClient`:直接调用禅道 REST 路径,例如 `client.get('/products')`。
- `request("module/action")`:基于内置模块注册表调用常见禅道 API,例如 `request('product/list')`。

## 安装

::: code-group

```sh [npm]
npm install zentao-api
```

```sh [bun]
bun add zentao-api
```

```sh [pnpm]
pnpm add zentao-api
```

:::

## 创建客户端

```ts
import { ZentaoClient } from 'zentao-api';

const client = new ZentaoClient({
baseUrl: 'https://zentao.example.com',
token: 'your-token',
});

const products = await client.get('/products');
```

`baseUrl` 是禅道站点根地址,SDK 会自动拼接 `/api.php/v2`。

## 使用账号密码登录

```ts
import { ZentaoClient } from 'zentao-api';

const client = new ZentaoClient('https://zentao.example.com');
const token = await client.login('admin', 'password');
```

登录成功后,返回的 token 会写入当前客户端实例,后续请求会自动携带 `Token` 请求头。

## 使用模块请求

```ts
import { ZentaoClient, request, setGlobalOptions } from 'zentao-api';

ZentaoClient.init({
baseUrl: 'https://zentao.example.com',
token: 'your-token',
});

setGlobalOptions({ recPerPage: '50' });

const result = await request('product/list', {});
```

模块请求的名称固定为 `"module/action"`。可用模块和动作见 [ZenTao API](/zentao-api/)。

## 下一步

- 阅读 [安装与配置](./installation.md) 了解客户端选项。
- 阅读 [运行环境](./environments.md) 了解 Node.js、Bun 和浏览器差异。
- 阅读 [常见 API 示例](./examples.md) 直接套用常见调用方式。
Loading
Loading