@kevisual/cnb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/mod.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './src/index.ts'
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@kevisual/cnb",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "files": [
11
+ "src",
12
+ "mod.ts",
13
+ "agents"
14
+ ],
15
+ "author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
16
+ "license": "MIT",
17
+ "packageManager": "pnpm@10.25.0",
18
+ "type": "module",
19
+ "devDependencies": {
20
+ "@types/bun": "^1.3.4",
21
+ "@types/node": "^25.0.2",
22
+ "dotenv": "^17.2.3"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ }
27
+ }
package/readme.md ADDED
@@ -0,0 +1,5 @@
1
+ # cnb.cool 能做什么
2
+
3
+ ## 简介
4
+
5
+ 纯粹调用api的模式去使用cnb.cool,自动化方案。
@@ -0,0 +1,23 @@
1
+ import { CNBCore, CNBCoreOptions, RequestOptions, Result } from "../cnb-core.ts";
2
+ type AiOptions = CNBCoreOptions<{
3
+ group?: string;
4
+ }>
5
+ class AiBase extends CNBCore {
6
+ group: string;
7
+ constructor(options: AiOptions) {
8
+ super({ token: options.token, cookie: options.cookie });
9
+ this.group = options.group || '';
10
+ }
11
+ autoPr(repo: string, data: { body: string, branch?: string, title: string }): Promise<Result<any>> {
12
+ const group = this.group || '';
13
+ const url = `/${group}/${repo}/-/build/ai/auto-pr`;
14
+ const postData = {
15
+ ...data,
16
+ branch: data.branch || 'refs/heads/main',
17
+ title: data.title || ''
18
+ };
19
+ return this.post({ url, data: postData });
20
+ }
21
+ }
22
+
23
+ export { AiBase };
@@ -0,0 +1,134 @@
1
+ export type CNBCoreOptions<T = {}> = {
2
+ token: string;
3
+ cookie?: string;
4
+ } & T;
5
+
6
+ export type RequestOptions = {
7
+ url?: string;
8
+ method?: string;
9
+ data?: Record<string, any>;
10
+ body?: any;
11
+ params?: Record<string, any>;
12
+ headers?: Record<string, any>;
13
+ useCookie?: boolean;
14
+ useOrigin?: boolean;
15
+ };
16
+ export class CNBCore {
17
+ baseURL = 'https://api.cnb.cool';
18
+ token: string;
19
+ cookie?: string;
20
+ constructor(options: CNBCoreOptions) {
21
+ this.token = options.token;
22
+ this.cookie = options.cookie;
23
+ }
24
+
25
+ async request({ url, method = 'GET', data, params, headers, body, useCookie, useOrigin }: RequestOptions): Promise<any> {
26
+ const defaultHeaders: Record<string, string> = {
27
+ 'Content-Type': 'application/json',
28
+ // 'Accept': 'application/json, application/vnd.cnb.api+json, application/vnd.cnb.web+json',
29
+ 'Accept': 'application/json',
30
+ };
31
+ if (this.token) {
32
+ defaultHeaders['Authorization'] = `Bearer ${this.token}`;
33
+ }
34
+ if (params) {
35
+ const queryString = new URLSearchParams(params).toString();
36
+ url += `?${queryString}`;
37
+ defaultHeaders['Accept'] = 'application/json';
38
+ }
39
+ const _headers = { ...defaultHeaders, ...headers };
40
+ let _body = undefined;
41
+ if (data) {
42
+ _body = JSON.stringify(data);
43
+ }
44
+ if (body) {
45
+ _body = body;
46
+ }
47
+ if (!_headers.Authorization) {
48
+ delete _headers.Authorization;
49
+ }
50
+ if (useCookie) {
51
+ _headers['Cookie'] = this.cookie || "";
52
+ delete _headers.Authorization;
53
+ }
54
+ // console.log('Request URL:', url, data, _headers);
55
+ const response = await fetch(url || '', {
56
+ method,
57
+ headers: _headers,
58
+ body: _body,
59
+ });
60
+ const res = (data: any, message?: string) => {
61
+ if (useOrigin) {
62
+ return data;
63
+ }
64
+ return {
65
+ code: 200,
66
+ message: message || 'success',
67
+ data,
68
+ };
69
+ }
70
+ if (!response.ok) {
71
+ const errorText = await response.text();
72
+ if (useOrigin)
73
+ throw new Error(`Request failed with status ${response.status}: ${errorText}`);
74
+ return res(null, `Request failed with status ${response.status}: ${errorText}`);
75
+ }
76
+
77
+ const contentType = response.headers.get('Content-Type');
78
+ if (contentType && contentType.includes('application/json')) {
79
+ const values = await response.json();
80
+ return res(values);
81
+ } else {
82
+ const text = await response.text();
83
+ return res(text);
84
+ }
85
+ }
86
+ makeUrl(url?: string): string {
87
+ if (url && url.startsWith('http')) {
88
+ return url;
89
+ }
90
+ return new URL(url || '', this.baseURL).toString();
91
+ }
92
+ get<T = any>({ url, ...REST }: RequestOptions): Promise<T> {
93
+ const fullUrl = this.makeUrl(url);
94
+ return this.request({ url: fullUrl, method: 'GET', ...REST });
95
+ }
96
+ post<T = any>({ url, ...REST }: RequestOptions): Promise<T> {
97
+ const fullUrl = this.makeUrl(url);
98
+ return this.request({ url: fullUrl, method: 'POST', ...REST });
99
+ }
100
+ put<T = any>({ url, ...REST }: RequestOptions): Promise<T> {
101
+ const fullUrl = this.makeUrl(url);
102
+ return this.request({ url: fullUrl, method: 'PUT', ...REST });
103
+ }
104
+ delete<T = any>({ url, ...REST }: RequestOptions): Promise<T> {
105
+ const fullUrl = this.makeUrl(url);
106
+ return this.request({ url: fullUrl, method: 'DELETE', ...REST });
107
+ }
108
+ patch<T = any>({ url, ...REST }: RequestOptions): Promise<T> {
109
+ const fullUrl = this.makeUrl(url);
110
+ return this.request({ url: fullUrl, method: 'PATCH', ...REST });
111
+ }
112
+ /**
113
+ * 通过 PUT 请求上传文件内容
114
+ * @param data 包含 URL、token 和文件内容
115
+ * @returns 上传结果
116
+ */
117
+ async putFile(data: { url: string, token: string, content: string | Buffer }): Promise<any> {
118
+ return this.request({
119
+ url: data.url,
120
+ method: 'PUT',
121
+ body: data.content,
122
+ headers: {
123
+ 'Authorization': `Bearer ${data.token}`,
124
+ 'Content-Type': 'application/octet-stream'
125
+ }
126
+ });
127
+ }
128
+ }
129
+
130
+ export type Result<T = any> = {
131
+ code: number;
132
+ message: string;
133
+ data: T
134
+ };
package/src/index.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { CNBCore, CNBCoreOptions } from "./cnb-core.ts";
2
+ import { Workspace } from "./workspace.ts";
3
+ import { KnowledgeBase } from "./knowledge/index.ts";
4
+ import { Repo } from "./repo/index.ts";
5
+ import { User } from "./user/index.ts";
6
+
7
+ type CNBOptions = CNBCoreOptions<{}>;
8
+
9
+ export class CNB extends CNBCore {
10
+ workspace!: Workspace;
11
+ knowledgeBase!: KnowledgeBase;
12
+ repo!: Repo;
13
+ user!: User;
14
+ constructor(options: CNBOptions) {
15
+ super({ token: options.token, cookie: options.cookie });
16
+ this.init(options);
17
+ }
18
+ init(options: CNBOptions) {
19
+ this.workspace = new Workspace(options.token);
20
+ this.knowledgeBase = new KnowledgeBase({ token: options.token, cookie: options.cookie });
21
+ this.repo = new Repo({ token: options.token, cookie: options.cookie });
22
+ this.user = new User({ token: options.token, cookie: options.cookie });
23
+ }
24
+ }
25
+
26
+ export * from './workspace.ts'
27
+ export * from './cnb-core.ts'
28
+ export * from './knowledge/index.ts'
29
+ export * from './repo/index.ts'
@@ -0,0 +1,55 @@
1
+ import { CNBCore, CNBCoreOptions, RequestOptions, Result } from "../cnb-core.ts";
2
+
3
+ type RepoOptions = CNBCoreOptions<{
4
+ group?: string;
5
+ }>
6
+ export class KnowledgeBase extends CNBCore {
7
+ group: string;
8
+ constructor(options: RepoOptions) {
9
+ super({ token: options.token, cookie: options.cookie });
10
+ this.group = options.group || '';
11
+ }
12
+
13
+ queryKnowledgeBase(repo: string, data: {
14
+ query: string,
15
+ score_threshold?: number,
16
+ top_k?: number,
17
+ metadata_filtering_conditions?: MetadataFilteringConditions
18
+ }): Promise<any> {
19
+ const group = this.group || '';
20
+ const url = `/${group}/${repo}/-/knowledge/query`;
21
+ let postData = {
22
+ query: data.query,
23
+ };
24
+ return this.post({ url, data: postData });
25
+ }
26
+ getEmbeddingModels(repo: string): Promise<Result<Array<{ name: string, dimensions: number }>>> {
27
+ const group = this.group || '';
28
+ const url = `/${group}/${repo}/-/knowledge/embedding/models`;
29
+ // bg3-m3 1024
30
+ // hunyuan 1024
31
+ return this.get({ url });
32
+ }
33
+ getBase(repo: string): Promise<Result<any>> {
34
+ const group = this.group || '';
35
+ const url = `/${group}/${repo}/-/knowledge/base`;
36
+ return this.get({ url });
37
+ }
38
+ deleteBase(repo: string): Promise<Result<any>> {
39
+ const group = this.group || '';
40
+ const url = `/${group}/${repo}/-/knowledge/base`;
41
+ return this.request({ url, method: 'DELETE' });
42
+ }
43
+ }
44
+
45
+ type MetadataFilteringConditions = {
46
+ conditions: Array<{
47
+ comparison_operator?: 'is' | 'is not' | 'contains' | 'not contains' | 'start with' | 'end with' | 'is empty' | 'is not empty';
48
+ name?: "position" | "path" | "type",
49
+ /**
50
+ * "is empty" and "is not empty" 时候忽略该字段
51
+ */
52
+ value?: string
53
+ }>
54
+ logical_operator?: 'adn' | 'or'
55
+ }
@@ -0,0 +1,161 @@
1
+ import { CNBCore, CNBCoreOptions, RequestOptions, Result } from "../cnb-core.ts";
2
+
3
+ type RepoOptions = CNBCoreOptions<{
4
+ group?: string;
5
+ }>
6
+ export class Repo extends CNBCore {
7
+ group: string;
8
+ constructor(options: RepoOptions) {
9
+ super({ token: options.token, cookie: options.cookie });
10
+ this.group = options.group || '';
11
+ }
12
+ /**
13
+ * 创建代码仓库
14
+ * @param group e.g. my-group
15
+ * @param data
16
+ * @returns
17
+ */
18
+ createRepo(data: CreateRepoData): Promise<any> {
19
+ const group = this.group || '';
20
+ const url = `/${group}/-/repos`;
21
+ let postData: CreateRepoData = {
22
+ ...data,
23
+ description: data.description || '',
24
+ name: data.name,
25
+ license: data.license || 'Unlicense',
26
+ visibility: data.visibility || 'private',
27
+ };
28
+ return this.post({ url, data: postData });
29
+ }
30
+ async createCommit(repo: string, data: CreateCommitData): Promise<any> {
31
+ const group = this.group || '';
32
+ const commitList = await this.getCommitList(repo, {
33
+ page: 1,
34
+ page_size: 1,
35
+ }, { useOrigin: true }).catch((err) => {
36
+ console.error("Error fetching commit list:", err);
37
+ return []
38
+ });
39
+ const preCommitSha = commitList.length > 0 ? commitList[0].sha : undefined;
40
+ if (!data.parent_commit_sha && preCommitSha) {
41
+ data.parent_commit_sha = preCommitSha;
42
+ }
43
+ const url = `https://cnb.cool/${group}/${repo}/-/git/commits`;
44
+ const postData: CreateCommitData = {
45
+ ...data,
46
+ base_branch: data.base_branch || 'refs/heads/main',
47
+ message: data.message || 'commit from cnb sdk',
48
+ parent_commit_sha: data.parent_commit_sha,
49
+ files: data.files || [],
50
+ new_branch: data.new_branch || 'refs/heads/main',
51
+ };
52
+ if (!postData.parent_commit_sha) {
53
+ delete postData.parent_commit_sha;
54
+ delete postData.base_branch;
55
+ }
56
+ return this.post({ url, data: postData, useCookie: true, });
57
+ }
58
+ createBlobs(repo: string, data: { content: string, encoding?: 'utf-8' | 'base64' }): Promise<any> {
59
+ const group = this.group || '';
60
+ const url = `/${group}/${repo}/-/git/blobs`;
61
+ const postData = {
62
+ content: data.content,
63
+ encoding: data.encoding || 'utf-8',
64
+ };
65
+ return this.post({ url, data: postData });
66
+ }
67
+ uploadFiles(repo: string, data: { ext?: any, name?: string, path?: string, size?: number }): Promise<any> {
68
+ const group = this.group || '';
69
+ const url = `/${group}/${repo}/-/upload/files`
70
+ return this.post({ url, data });
71
+ }
72
+ getCommitList(repo: string, params: { author?: string, commiter?: string, page?: number, page_size?: number, sha?: string, since?: string, until?: string }, opts?: RequestOptions): Promise<any> {
73
+ const group = this.group || '';
74
+ const url = `/${group}/${repo}/-/git/commits`;
75
+ return this.get({ url, params, ...opts });
76
+ }
77
+ getRepoList(params: {
78
+ desc?: boolean;
79
+ filter_type?: 'private' | 'public' | 'secret';
80
+ flags?: 'KnowledgeBase';
81
+ order_by?: 'created_at' | 'last_updated_at' | 'stars' | 'slug_path' | 'forks';
82
+ page?: number;
83
+ page_size?: number;
84
+ role?: 'owner' | 'maintainer' | 'developer' | 'reporter' | 'guest';
85
+ search?: string;
86
+ status?: 'active' | 'archived';
87
+ }): Promise<Result<RepoItem[]>> {
88
+ const url = '/user/repos';
89
+ let _params = {
90
+ ...params,
91
+ page: params.page || 1,
92
+ page_size: params.page_size || 999,
93
+ }
94
+ return this.get({ url, params: _params });
95
+ }
96
+ }
97
+
98
+ type CreateRepoData = {
99
+ description: string;
100
+ license?: 'MIT' | 'Apache-2.0' | 'GPL-3.0' | 'Unlicense';
101
+ name: string;
102
+ visibility: 'private' | 'public' | 'secret';
103
+ }
104
+
105
+ type CreateCommitData = {
106
+ base_branch?: string; // "refs/heads/main"
107
+ new_branch?: string; // "refs/heads/main"
108
+ message?: string;
109
+ parent_commit_sha?: string;
110
+ files?: Array<{
111
+ content: string;
112
+ path: string;
113
+ encoding?: 'raw' | 'utf-8' | 'base64';
114
+ is_delete?: boolean;
115
+ is_executable?: boolean;
116
+ }>;
117
+ }
118
+
119
+ type RepoItem = {
120
+ id: string;
121
+ name: string;
122
+ freeze: boolean;
123
+ status: number;
124
+ visibility_level: 'Public' | 'Private' | 'Secret';
125
+ flags: string;
126
+ created_at: string;
127
+ updated_at: string;
128
+ description: string;
129
+ site: string;
130
+ topics: string;
131
+ license: string;
132
+ display_module: {
133
+ activity: boolean;
134
+ contributors: boolean;
135
+ release: boolean;
136
+ };
137
+ star_count: number;
138
+ fork_count: number;
139
+ mark_count: number;
140
+ last_updated_at: string | null;
141
+ web_url: string;
142
+ path: string;
143
+ tags: string[] | null;
144
+ open_issue_count: number;
145
+ open_pull_request_count: number;
146
+ languages: {
147
+ language: string;
148
+ color: string;
149
+ };
150
+ second_languages: {
151
+ language: string;
152
+ color: string;
153
+ };
154
+ last_update_username: string;
155
+ last_update_nickname: string;
156
+ access: string;
157
+ stared: boolean;
158
+ star_time: string;
159
+ pinned: boolean;
160
+ pinned_time: string;
161
+ }
@@ -0,0 +1,55 @@
1
+ import { CNBCore, CNBCoreOptions } from "../cnb-core.ts";
2
+
3
+ export class User extends CNBCore {
4
+ constructor(options: CNBCoreOptions<{}>) {
5
+ super({ token: options.token, cookie: options.cookie });
6
+ }
7
+
8
+ /**
9
+ * 获取当前用户信息
10
+ * @returns
11
+ */
12
+ getCurrentUser(): Promise<any> {
13
+ const url = `https://cnb.cool/user`;
14
+ return this.get({
15
+ url,
16
+ useCookie: true,
17
+ });
18
+ }
19
+ createAccessToken(data?: { description?: string, scope?: string }): Promise<AccessTokenResponse> {
20
+ const scope = data?.scope || 'mission-manage:rw,mission-delete:rw,group-delete:rw,group-manage:rw,group-resource:rw,account-engage:rw,account-email:r,account-profile:rw,registry-delete:rw,registry-manage:rw,registry-package-delete:rw,registry-package:rw,repo-security:r,repo-delete:rw,repo-manage:rw,repo-basic-info:r,repo-cnb-detail:rw,repo-cnb-history:r,repo-cnb-trigger:rw,repo-commit-status:rw,repo-contents:rw,repo-notes:rw,repo-issue:rw,repo-pr:rw,repo-code:rw'
21
+ const url = 'https://cnb.cool/user/personal_access_tokens'
22
+ return this.post({
23
+ url,
24
+ useCookie: true,
25
+ data: {
26
+ description: data?.description || 'Created at ' + new Date().toISOString(),
27
+ scope: scope,
28
+ }
29
+ })
30
+ }
31
+ getAccessTokens(params?: { page?: number, page_size?: number }): Promise<AccessTokenResponse[]> {
32
+ const url = 'https://cnb.cool/user/personal_access_tokens'
33
+ return this.get({
34
+ url,
35
+ useCookie: true,
36
+ params: {
37
+ ...params,
38
+ page: params?.page || 1,
39
+ page_size: params?.page_size || 20,
40
+ }
41
+ })
42
+ }
43
+ deleteAccessToken(tokenId: string): Promise<any> {
44
+ const url = `https://cnb.cool/user/personal_access_tokens/${tokenId}`
45
+ return this.delete({
46
+ url,
47
+ useCookie: true,
48
+ })
49
+ }
50
+ }
51
+
52
+ type AccessTokenResponse = {
53
+ token: string;
54
+ description: string;
55
+ }
@@ -0,0 +1,207 @@
1
+ /**
2
+ * @title 工作空间管理模块
3
+ * @description 提供云原生构建工作空间的管理功能,包括列表查询、创建、更新和删除工作空间,支持多种过滤条件和分页选项
4
+ * @tags workspace, cloud-native, development-environment, cnb, api
5
+ * @createdAt 2025-12-04
6
+ */
7
+
8
+ import { CNBCore } from "./cnb-core.ts";
9
+
10
+ /**
11
+ * 工作空间列表查询参数
12
+ */
13
+ export interface ListParams {
14
+ /** Git 分支名称,例如 "main" */
15
+ branch?: string;
16
+ /** 查询结束时间,格式 YYYY-MM-DD HH:mm:ssZZ,例如 2024-12-01 00:00:00+0800 */
17
+ end?: string;
18
+ /** 分页页码,默认为 1 */
19
+ page?: number;
20
+ /** 分页大小,默认 20,最大 100 */
21
+ pageSize?: number;
22
+ /** 仓库路径,例如 "groupname/reponame" */
23
+ slug?: string;
24
+ /** 查询开始时间,格式 YYYY-MM-DD HH:mm:ssZZ,例如 2024-12-01 00:00:00+0800 */
25
+ start?: string;
26
+ /** 开发环境状态,running: 开发环境已启动,closed: 开发环境已关闭 */
27
+ status?: 'running' | 'closed';
28
+ }
29
+
30
+ /**
31
+ * 云原生开发环境管理模块
32
+ * https://api.cnb.cool/#/operations/GetWorkspaceDetail
33
+ */
34
+ export class Workspace extends CNBCore {
35
+ constructor(token: string) {
36
+ super({ token });
37
+ }
38
+ /**
39
+ * 删除我的云原生开发环境
40
+ * @param params 删除参数,pipelineId 和 sn 二选一,优先使用 pipelineId
41
+ */
42
+ async deleteWorkspace(params: { pipelineId?: string; sn?: string }): Promise<{ code: number; message: string }> {
43
+ const data: { pipelineId?: string; sn?: string } = {};
44
+
45
+ if (params.pipelineId) {
46
+ data.pipelineId = params.pipelineId;
47
+ } else if (params.sn) {
48
+ data.sn = params.sn;
49
+ } else {
50
+ throw new Error('pipelineId 和 sn 必须提供其中一个');
51
+ }
52
+
53
+ return this.post({ url: '/workspace/delete', data });
54
+ }
55
+ /** 获取我的云原生开发环境列表 */
56
+ async list(params?: ListParams): Promise<WorkspaceResult> {
57
+ return this.get({ url: '/workspace/list', params });
58
+ }
59
+
60
+ /**
61
+ * 停止我的云原生开发环境
62
+ * @param params 停止参数,pipelineId 和 sn 二选一,优先使用 pipelineId
63
+ */
64
+ async stopWorkspace(params: { pipelineId?: string; sn?: string }): Promise<{ buildLogUrl: string; message: string; sn: string }> {
65
+ const data: { pipelineId?: string; sn?: string } = {};
66
+
67
+ if (params.pipelineId) {
68
+ data.pipelineId = params.pipelineId;
69
+ } else if (params.sn) {
70
+ data.sn = params.sn;
71
+ } else {
72
+ throw new Error('pipelineId 和 sn 必须提供其中一个');
73
+ }
74
+
75
+ return this.post({ url: '/workspace/stop', data });
76
+ }
77
+
78
+
79
+
80
+ /**
81
+ * 根据流水线 SN 查询云原生开发访问地址
82
+ * @param repo 仓库路径,例如:groupname/reponame
83
+ * @param sn 流水线构建号
84
+ */
85
+ async getDetail(repo: string, sn: string): Promise<{
86
+ codebuddy: string;
87
+ codebuddycn: string;
88
+ cursor: string;
89
+ jetbrains: Record<string, string>;
90
+ jumpUrl: string;
91
+ remoteSsh: string;
92
+ ssh: string;
93
+ vscode: string;
94
+ 'vscode-insiders': string;
95
+ webide: string;
96
+ }> {
97
+ return this.get({ url: `/${repo}/-/workspace/detail/${sn}` });
98
+ }
99
+ /**
100
+ * 启动云原生开发环境,已存在环境则直接打开,否则重新创建开发环境
101
+ * @param repo 仓库路径,例如:groupname/reponame
102
+ * @param params 启动参数
103
+ * @returns 返回启动结果,包含以下字段:
104
+ */
105
+ async startWorkspace(repo: string, params: { branch?: string; ref?: string }): Promise<{
106
+ /** 仅新创建开发环境时返回,表示创建开发环境的流水线日志地址 */
107
+ buildLogUrl?: string;
108
+ /** 仅新创建开发环境时返回,表示创建开发环境的提示信息 */
109
+ message?: string;
110
+ /** 仅新创建开发环境时返回,表示创建开发环境的流水线 sn */
111
+ sn?: string;
112
+ /** 如果存在开发环境,则返回 WebIDE 访问 url;如果不存在开发环境,则返回启动云原生开发的 loading 页面 url 地址 */
113
+ url: string;
114
+ }> {
115
+ const data: { branch?: string; ref?: string } = {};
116
+
117
+ if (params.branch) {
118
+ data.branch = params.branch;
119
+ }
120
+ if (params.ref) {
121
+ data.ref = params.ref;
122
+ }
123
+
124
+ return this.post({ url: `/${repo}/-/workspace/start`, data });
125
+ }
126
+
127
+ }
128
+
129
+ export type ResultList<T> = {
130
+ hasMore: boolean;
131
+ list: T[];
132
+ pageInfo: {
133
+ page: number;
134
+ pageSize: number;
135
+ };
136
+ total: number;
137
+ }
138
+ /**
139
+ * 工作空间信息接口
140
+ */
141
+ export interface WorkspaceInfo {
142
+ /** 分支名,例如:main */
143
+ branch: string;
144
+ /** 业务 ID */
145
+ business_id: string;
146
+ /** 备份的 commit 数 */
147
+ commit_count: number | null;
148
+ /** 开发环境创建时间,例如:2024-12-02T03:20:22.000Z */
149
+ create_time: string;
150
+ /** 开发环境持续时间,单位:ms(非实时更新) */
151
+ duration: number;
152
+ /** 备份的文件数 */
153
+ file_count: number;
154
+ /** 备份的文件列表,仅前五个备份文件相对路径 */
155
+ file_list: string;
156
+ /** 是否为预览环境,0: 否,1: 是 */
157
+ is_preview: number;
158
+ /** JetBrains IDE 列表 */
159
+ jetbrainsList: any[];
160
+ /** 环境销毁时远程最新的 commit short hash */
161
+ latest_sha: string | null;
162
+ /** 创建环境的子流水线 id */
163
+ pipeline_id: string;
164
+ /** 备份的 stash 数 */
165
+ remote_stash_count: number | null;
166
+ /** 仓库 ID */
167
+ repo_id: string;
168
+ /** 仓库地址 */
169
+ repo_url: string;
170
+ /** 恢复备份代码的流水线 id,如果有值表示备份代码已被恢复(重建环境时会恢复备份代码) */
171
+ restore_id: string | null;
172
+ /** 单个 stash 标识,1: 是,0: 否 */
173
+ single_stash: number;
174
+ /** 仓库路径,例如:groupname/reponame */
175
+ slug: string;
176
+ /** 创建开发环境的流水线 sn */
177
+ sn: string;
178
+ /** 开发环境是否支持 ssh 链接 */
179
+ ssh: boolean;
180
+ /** 本地 stash 数 */
181
+ stash_count: number;
182
+ /** 工作区状态,running: 开发环境已启动,closed:开发环境已关闭 */
183
+ status: string;
184
+ /** 用户名 */
185
+ user_name: string;
186
+ /** 开发环境默认工作区路径 */
187
+ workspace: string;
188
+ }
189
+
190
+ /**
191
+ * 工作空间列表响应结果
192
+ */
193
+ export type WorkspaceResult = {
194
+ /** 是否有更多数据 */
195
+ hasMore: boolean;
196
+ /** 工作空间列表 */
197
+ list: WorkspaceInfo[];
198
+ /** 分页信息 */
199
+ pageInfo: {
200
+ /** 当前页码 */
201
+ page: number;
202
+ /** 每页大小 */
203
+ pageSize: number;
204
+ };
205
+ /** 总数量 */
206
+ total: number;
207
+ }