feat(net-tools): 支持Gitlab的服务注入
Some checks failed
/ release (push) Failing after 24s

This commit is contained in:
zhaoyingbo 2024-11-17 02:49:46 +00:00
parent 478b8b4da3
commit 1cebc94640
18 changed files with 1574 additions and 520 deletions

255
package-lock.json generated
View File

@ -12,6 +12,7 @@
"packages/*"
],
"dependencies": {
"@gitbeaker/rest": "^41.2.0",
"lodash": "^4.17.21",
"winston": "3.14.2",
"winston-daily-rotate-file": "5.0.0"
@ -576,6 +577,48 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@gitbeaker/core": {
"version": "41.2.0",
"resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-41.2.0.tgz",
"integrity": "sha512-kd9iwBBoBZB/MiZOclOWLN4QX/WoBb/WwB5o7JkAH9bS7jv2gB5hblKgmmxUfxKhT5wJasqNMk/VhFcZmOSHKg==",
"license": "MIT",
"dependencies": {
"@gitbeaker/requester-utils": "^41.2.0",
"qs": "^6.12.2",
"xcase": "^2.0.1"
},
"engines": {
"node": ">=18.20.0"
}
},
"node_modules/@gitbeaker/requester-utils": {
"version": "41.2.0",
"resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-41.2.0.tgz",
"integrity": "sha512-mgGSAvyEes1Mt845NqxqDLDDRwGqiEIxiR6p2LgmZJQEoTgPRkuEhSJxF/5bJK401eReR/TgOdP0IVmLK9owFA==",
"license": "MIT",
"dependencies": {
"picomatch-browser": "^2.2.6",
"qs": "^6.12.2",
"rate-limiter-flexible": "^4.0.1",
"xcase": "^2.0.1"
},
"engines": {
"node": ">=18.20.0"
}
},
"node_modules/@gitbeaker/rest": {
"version": "41.2.0",
"resolved": "https://registry.npmjs.org/@gitbeaker/rest/-/rest-41.2.0.tgz",
"integrity": "sha512-+ozz5gq+ZnipBHSLTrGShScLSqW7lQ7NEgBjZKjtBAVSVPZHyCCEwDnvGOKo6D3RI5HndLGS3MXZ590IpLMg1g==",
"license": "MIT",
"dependencies": {
"@gitbeaker/core": "^41.2.0",
"@gitbeaker/requester-utils": "^41.2.0"
},
"engines": {
"node": ">=18.20.0"
}
},
"node_modules/@humanwhocodes/module-importer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
@ -3062,6 +3105,25 @@
"dev": true,
"license": "ISC"
},
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -4053,6 +4115,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
@ -4306,6 +4385,27 @@
"is-arrayish": "^0.2.1"
}
},
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.4"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
@ -5138,7 +5238,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@ -5195,6 +5294,25 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-pkg-repo": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz",
@ -5612,6 +5730,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@ -5668,6 +5798,42 @@
"node": ">=4"
}
},
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@ -5679,7 +5845,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@ -9279,6 +9444,18 @@
"node": ">= 6"
}
},
"node_modules/object-inspect": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
"integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -9851,6 +10028,18 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/picomatch-browser": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/picomatch-browser/-/picomatch-browser-2.2.6.tgz",
"integrity": "sha512-0ypsOQt9D4e3hziV8O4elD9uN0z/jtUEfxVRtNaAAtXIyUx9m/SzlO020i8YNL2aL/E6blOvvHQcin6HZlFy/w==",
"license": "MIT",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pidtree": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
@ -10128,6 +10317,21 @@
"teleport": ">=0.2.0"
}
},
"node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -10159,6 +10363,12 @@
"node": ">=8"
}
},
"node_modules/rate-limiter-flexible": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-4.0.1.tgz",
"integrity": "sha512-2/dGHpDFpeA0+755oUkW+EKyklqLS9lu0go9pDsbhqQjZcxfRyJ6LA4JI0+HAdZ2bemD/oOjUeZQB2lCZqXQfQ==",
"license": "ISC"
},
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@ -10746,6 +10956,23 @@
"dev": true,
"license": "ISC"
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
@ -10782,6 +11009,24 @@
"node": ">=8"
}
},
"node_modules/side-channel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.4",
"object-inspect": "^1.13.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
@ -12030,6 +12275,12 @@
"node": ">=6"
}
},
"node_modules/xcase": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/xcase/-/xcase-2.0.1.tgz",
"integrity": "sha512-UmFXIPU+9Eg3E9m/728Bii0lAIuoc+6nbrNUKaRPJOFp91ih44qqGlWtxMB6kXFrRD6po+86ksHM5XHCfk6iPw==",
"license": "MIT"
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",

View File

@ -39,6 +39,7 @@
"typescript-eslint": "8.1.0"
},
"dependencies": {
"@gitbeaker/rest": "^41.2.0",
"lodash": "^4.17.21",
"winston": "3.14.2",
"winston-daily-rotate-file": "5.0.0"

View File

@ -18,6 +18,7 @@
"license": "ISC",
"dependencies": {
"@egg/logger": "^1.4.4",
"winston": "*"
"winston": "*",
"@gitbeaker/rest": "*"
}
}
}

View File

@ -0,0 +1,35 @@
import type { Gitlab } from "../types"
import GitlabBaseService from "./base"
class Badge extends GitlabBaseService {
/**
* GitLab
* @returns {Promise<Gitlab.Badge[]>} GitLab
*/
async getList(): Promise<Gitlab.Badge[]> {
const URL = `/projects/${this.project_id}/badges`
return this.errorWarp<Gitlab.Badge[]>(() => this.get(URL), [])
}
/**
* GitLab
* @param {BadgeSetParams} badge -
* @returns {Promise<Gitlab.Badge | null>}
*/
async set(badge: Gitlab.BadgeSetParams): Promise<Gitlab.Badge | null> {
const URL = `/projects/${badge.id}/badges/${badge.badge_id}`
return this.errorWarp<Gitlab.Badge>(() => this.put(URL, badge), null)
}
/**
* GitLab
* @param {BadgeSetParams} badge -
* @returns {Promise<Gitlab.Badge | null>}
*/
async add(badge: Gitlab.BadgeSetParams): Promise<Gitlab.Badge | null> {
const URL = `/projects/${badge.id}/badges`
return this.errorWarp<Gitlab.Badge>(() => this.post(URL, badge), null)
}
}
export default Badge

View File

@ -0,0 +1,38 @@
import NetToolBase from "../netTool/base"
import type { Gitlab } from "../types"
class GitlabBaseService extends NetToolBase {
public project_id: number = 0;
public merge_request_iid: number = 0;
constructor(baseUrl: string, authKey: string, requestId: string) {
super({
prefix: baseUrl,
requestId,
headers: { "PRIVATE-TOKEN": authKey },
})
}
/**
* GitLab
* @template T
* @param {() => Promise<T>} func -
* @param {any} default_value -
* @returns {Promise<T>} promise
*/
protected async errorWarp<T = any>(
func: () => Promise<T>,
default_value: any
): Promise<T> {
try {
let response = {} as T & Gitlab.Error
response = (await func()) as T & Gitlab.Error
if (response.message === "404 Project Not Found") return default_value
return response
} catch {
return default_value
}
}
}
export default GitlabBaseService

View File

@ -0,0 +1,16 @@
import type { Gitlab } from "../types"
import GitlabBaseService from "./base"
class Commit extends GitlabBaseService {
/**
*
* @param {string} sha - SHA
* @returns {Promise<Gitlab.MergeRequest[]>} promise
*/
async getMr(sha: string): Promise<Gitlab.MergeRequest[]> {
const URL = `/projects/${this.project_id}/repository/commits/${sha}/merge_requests`
return this.errorWarp<Gitlab.MergeRequest[]>(() => this.get(URL), [])
}
}
export default Commit

View File

@ -0,0 +1,34 @@
import { DiscussionSchema } from "@gitbeaker/rest"
import type { Gitlab } from "../types"
import GitlabBaseService from "./base"
class Discussions extends GitlabBaseService {
/**
* IID
* @returns {Promise<DiscussionSchema[]>} Promise
*/
async getList(): Promise<DiscussionSchema[]> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}/discussions`
return this.errorWarp<DiscussionSchema[]>(() => this.get(URL), [])
}
/**
*
* @param {string} body -
* @param {CreateRangeDiscussionPosition} position -
* @returns {Promise<DiscussionSchema | null>} Promise
*/
async create2Mr(
body: string,
position: Gitlab.CreateRangeDiscussionPosition
): Promise<DiscussionSchema | null> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}/discussions`
return this.errorWarp<DiscussionSchema>(
() => this.post(URL, { body, position }),
null
)
}
}
export default Discussions

View File

@ -0,0 +1,68 @@
import Badge from "./badge"
import Commit from "./commit"
import Discussions from "./discussions"
import MergeRequests from "./mergeRequests"
import Notes from "./notes"
import Pipelines from "./pipelines"
import Project from "./project"
import Repository from "./repository"
class GitlabService {
badge: Badge
commit: Commit
discussions: Discussions
mergeRequests: MergeRequests
notes: Notes
pipelines: Pipelines
project: Project
repository: Repository
/**
* GitLab
* @param {string} baseUrl - GitLab URL
* @param {string} authKey -
* @param {string} requestId - ID
*/
constructor(baseUrl: string, authKey: string, requestId: string) {
this.badge = new Badge(baseUrl, authKey, requestId)
this.commit = new Commit(baseUrl, authKey, requestId)
this.discussions = new Discussions(baseUrl, authKey, requestId)
this.mergeRequests = new MergeRequests(baseUrl, authKey, requestId)
this.notes = new Notes(baseUrl, authKey, requestId)
this.pipelines = new Pipelines(baseUrl, authKey, requestId)
this.project = new Project(baseUrl, authKey, requestId)
this.repository = new Repository(baseUrl, authKey, requestId)
}
/**
* ID
* @param {number} project_id - ID
*/
setProjectId(project_id: number) {
this.badge.project_id = project_id
this.commit.project_id = project_id
this.discussions.project_id = project_id
this.mergeRequests.project_id = project_id
this.notes.project_id = project_id
this.pipelines.project_id = project_id
this.project.project_id = project_id
this.repository.project_id = project_id
}
/**
* IID
* @param {number} merge_request_iid - IID
*/
setMergeRequestIid(merge_request_iid: number) {
this.badge.merge_request_iid = merge_request_iid
this.commit.merge_request_iid = merge_request_iid
this.discussions.merge_request_iid = merge_request_iid
this.mergeRequests.merge_request_iid = merge_request_iid
this.notes.merge_request_iid = merge_request_iid
this.pipelines.merge_request_iid = merge_request_iid
this.project.merge_request_iid = merge_request_iid
this.repository.merge_request_iid = merge_request_iid
}
}
export default GitlabService

View File

@ -0,0 +1,62 @@
import type {
ExpandedMergeRequestSchema,
MergeRequestChangesSchema,
MergeRequestDiffVersionsSchema,
MergeRequestNoteSchema,
} from "@gitbeaker/rest"
import GitlabBaseService from "./base"
class MergeRequests extends GitlabBaseService {
/**
*
* @param {number} [page=1] -
* @param {number} [per_page=20] -
* @returns {Promise<MergeRequestNoteSchema[]>} Promise
*/
async getComments(
page: number = 1,
per_page: number = 20
): Promise<MergeRequestNoteSchema[]> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}/notes?page=${page}&per_page=${per_page}`
return this.errorWarp<MergeRequestNoteSchema[]>(() => this.get(URL), [])
}
/**
*
* @returns {Promise<MergeRequestChangesSchema | null>} Promise
*/
async getChanges(): Promise<MergeRequestChangesSchema | null> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}/changes`
return this.errorWarp<MergeRequestChangesSchema | null>(
() => this.get(URL),
null
)
}
/**
*
* @returns {Promise<ExpandedMergeRequestSchema | null>} Promise
*/
async getDetail(): Promise<ExpandedMergeRequestSchema | null> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}`
return this.errorWarp<ExpandedMergeRequestSchema | null>(
() => this.get(URL),
null
)
}
/**
*
* @returns {Promise<MergeRequestDiffVersionsSchema[]>} Promise
*/
async getDiffVersions(): Promise<MergeRequestDiffVersionsSchema[]> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}/versions`
return this.errorWarp<MergeRequestDiffVersionsSchema[]>(
() => this.get(URL),
[]
)
}
}
export default MergeRequests

View File

@ -0,0 +1,34 @@
import { MergeRequestNoteSchema } from "@gitbeaker/rest"
import GitlabBaseService from "./base"
class Notes extends GitlabBaseService {
/**
*
* @param {string} body -
* @returns {Promise<MergeRequestNoteSchema>} - Promise
*/
async create(body: string): Promise<MergeRequestNoteSchema> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}/notes`
return this.errorWarp<MergeRequestNoteSchema>(
() => this.post(URL, { body }),
null
)
}
/**
*
* @param {number} note_id - ID
* @param {string} body -
* @returns {Promise<MergeRequestNoteSchema>} - Promise
*/
async modify(note_id: number, body: string): Promise<MergeRequestNoteSchema> {
const URL = `/projects/${this.project_id}/merge_requests/${this.merge_request_iid}/notes/${note_id}`
return this.errorWarp<MergeRequestNoteSchema>(
() => this.put(URL, { body }),
null
)
}
}
export default Notes

View File

@ -0,0 +1,43 @@
import type { Gitlab } from "../types"
import GitlabBaseService from "./base"
class Pipelines extends GitlabBaseService {
/**
* GitLab流水线的详细信息
* @param {number} pipeline_id - 线ID
* @param {string} created_at - 线
* @returns Promise
*/
async getDetail(pipeline_id: number, created_at?: string) {
const URL = `/projects/${this.project_id}/pipelines/${pipeline_id}`
const res = await this.errorWarp<Gitlab.PipelineDetail>(
() => this.get(URL),
null
)
if (res === null) return null
return { ...res, created_at }
}
/**
* GitLab流水线列表
* @param {number} [page=1] - 1
* @returns {Promise<Gitlab.Pipeline[]>} 线promise
*/
async getList(page = 1): Promise<Gitlab.Pipeline[]> {
const URL = `/projects/${this.project_id}/pipelines`
const params = { scope: "finished", per_page: 100, page }
return this.errorWarp<Gitlab.Pipeline[]>(() => this.get(URL, params), [])
}
/**
* GitLab流水线的任务列表
* @param {number} pipeline_id - 线ID
* @returns {Promise<Gitlab.Job[]>} promise
*/
async getJobs(pipeline_id: number): Promise<Gitlab.Job[]> {
const URL = `/projects/${this.project_id}/pipelines/${pipeline_id}/jobs`
return this.errorWarp<Gitlab.Job[]>(() => this.get(URL), [])
}
}
export default Pipelines

View File

@ -0,0 +1,19 @@
import type { Gitlab } from "../types"
import GitlabBaseService from "./base"
class Project extends GitlabBaseService {
/**
* GitLab
* @returns {Promise<Gitlab.ProjDetail | null>} promise
*/
async getDetail(): Promise<Gitlab.ProjDetail | null> {
const projectId =
typeof this.project_id === "string"
? encodeURIComponent(this.project_id)
: this.project_id
const URL = `/projects/${projectId}`
return this.errorWarp<Gitlab.ProjDetail>(() => this.get(URL), null)
}
}
export default Project

View File

@ -0,0 +1,16 @@
import GitlabBaseService from "./base"
class Repository extends GitlabBaseService {
/**
*
* @param {string} path -
* @param {string} ref -
* @returns {Promise<string>} Promise
*/
async getFileContent(path: string, ref: string): Promise<string> {
const URL = `/projects/${this.project_id}/repository/files/${encodeURIComponent(path)}/raw?ref=${ref}`
return this.errorWarp<string>(() => this.get(URL), "")
}
}
export default Repository

View File

@ -1,517 +1,7 @@
import logger from "@egg/logger"
import { Logger } from "winston"
import GitlabService from "./gitlabServer"
import NetTool from "./netTool"
import NetToolBase from "./netTool/base"
import type { Gitlab, NetErrorDetail, NetRequestParams } from "./types"
interface NetRequestParams {
url: string
method: string
queryParams?: any
payload?: any
additionalHeaders?: Record<string, string>
}
interface NetErrorDetail {
response: Response | null
code: number
message: string
data?: any
}
export class NetError extends Error {
public response: Response | null
public code: number
public message: string
public data?: any
constructor({ response, code, message, data }: NetErrorDetail) {
super(message)
this.response = response
this.code = code
this.message = message
this.data = data
}
}
/**
* HTTP请求的方法
*/
class NetToolBase {
protected prefix: string
protected headers: Record<string, string>
protected getHeaders: () => Promise<Record<string, string>>
protected logger: Logger
protected requestId: string
/**
*
*
* @param {Object} params -
* @param {string} [params.prefix] - URL前缀
* @param {Record<string, string>} [params.headers] -
* @param {Function} [params.getHeaders] -
* @param {string} [params.requestId] - ID
*/
constructor({
prefix,
headers,
getHeaders,
requestId,
}: {
prefix?: string
headers?: Record<string, string>
getHeaders?: () => Promise<Record<string, string>>
requestId?: string
} = {}) {
this.prefix = prefix || ""
this.headers = headers || {}
this.getHeaders = getHeaders || (async () => ({}))
this.requestId = requestId || ""
this.logger = logger.child({ requestId })
}
/**
*
*
* @param {Object} params -
* @param {string} [params.prefix] - URL前缀
* @param {Record<string, string>} [params.headers] -
* @param {Function} [params.getHeaders] -
* @param {string} [params.requestId] - ID
* @returns
*/
child({
prefix,
headers,
getHeaders,
requestId,
}: {
prefix?: string
headers?: Record<string, string>
getHeaders?: () => Promise<Record<string, string>>
requestId?: string
} = {}) {
return new NetToolBase({
prefix: prefix || this.prefix,
headers: headers || this.headers,
getHeaders: getHeaders || this.getHeaders,
requestId: requestId || this.requestId,
})
}
/**
*
* @param {string} url -
* @param {string} method - 使HTTP方法
* @param {Record<string, string>} headers -
* @param {any} requestBody -
* @param {any} responseBody -
* @param {number} requestTime -
* @param {Response} [response] -
* @returns
*/
private logResponse(
url: string,
method: string,
headers: Record<string, string>,
requestBody: any,
responseBody: any,
requestTime: number,
response?: Response
) {
const responseLog = {
ok: response?.ok,
status: response?.status,
statusText: response?.statusText,
url,
method: method,
requestHeaders: headers,
responseHeaders: response?.headers,
requestBody,
responseBody,
requestTime,
responseTime: new Date().getTime(),
}
this.logger.http(JSON.stringify(responseLog, null, 2))
return responseLog
}
/**
* Promise
* @param url - URL
* @param method - 使HTTP方法
* @param queryParams - URL中的查询参数
* @param payload -
* @param additionalHeaders -
* @returns Promise
* @throws
*/
protected async request<T = any>({
url,
method,
queryParams,
payload,
additionalHeaders,
}: NetRequestParams): Promise<T> {
// 拼接完整的URL
let fullUrl = `${this.prefix}${url}`
if (queryParams) {
if (typeof queryParams === "string") {
fullUrl = `${fullUrl}?${queryParams}`
} else {
const queryString = new URLSearchParams(queryParams).toString()
if (queryString) fullUrl = `${fullUrl}?${queryString}`
}
}
// 设置请求头
const headers = {
...this.headers,
...(await this.getHeaders()),
...(additionalHeaders || {}),
} as Record<string, string>
// 设置请求Header
if (!(payload instanceof FormData)) {
headers["Content-Type"] = "application/json"
}
// 处理请求数据
const body = payload instanceof FormData ? payload : JSON.stringify(payload)
// 获取响应数据
let resData: any = null
let resText: string = ""
let res: Response
// 开始计时
const requestTime = new Date().getTime()
try {
res = await fetch(fullUrl, {
method,
body,
headers,
})
try {
resText = await res.text()
resData = JSON.parse(resText)
} catch {
/* empty */
}
} catch (error: any) {
// 网络请求异常如请求超时、DNS解析失败、CORS请求被阻止等
this.logResponse(
fullUrl,
method,
headers,
payload,
resData || resText,
requestTime
)
throw new NetError({
response: null,
code: 1,
message: error.message || "网络请求异常",
})
}
// 记录响应
this.logResponse(
fullUrl,
method,
headers,
payload,
resData || resText,
requestTime,
res
)
// http 错误码异常
if (!res.ok) {
throw new NetError({
response: res,
code: resData.code || res.status,
message: resData.message || resData.msg || resText || res.statusText,
data: resData.data,
})
}
// http 错误码正常,但解析异常
if (!resData) {
throw new NetError({
response: res,
code: 1,
message: "解析响应数据异常",
})
}
// 响应数据异常
if ("code" in resData && resData.code !== 0) {
throw new NetError({
response: res,
code: resData.code,
message: resData.message || resData.msg || "网络请求失败",
})
}
return resData as T
}
/**
* GET请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected get<T = any>(
url: string,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({ url, method: "get", queryParams, additionalHeaders })
}
/**
* POST请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected post<T = any>(
url: string,
payload?: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "post",
payload,
queryParams,
additionalHeaders,
})
}
/**
* PUT请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected put<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "put",
payload,
queryParams,
additionalHeaders,
})
}
/**
* DELETE请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected del<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "delete",
payload,
queryParams,
additionalHeaders,
})
}
/**
* PATCH请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected patch<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "patch",
payload,
queryParams,
additionalHeaders,
})
}
}
class NetTool extends NetToolBase {
public request<T = any>({
url,
method,
queryParams,
payload,
additionalHeaders,
}: NetRequestParams): Promise<T> {
return super.request<T>({
url,
method,
queryParams,
payload,
additionalHeaders,
})
}
public get<T = any>(
url: string,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.get<T>(url, queryParams, additionalHeaders)
}
public post<T = any>(
url: string,
payload?: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.post<T>(url, payload, queryParams, additionalHeaders)
}
public put<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.put<T>(url, payload, queryParams, additionalHeaders)
}
public del<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.del<T>(url, payload, queryParams, additionalHeaders)
}
public patch<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.patch<T>(url, payload, queryParams, additionalHeaders)
}
/**
* 400 Bad Request的响应对象
*
* @param message -
* @returns 400 Bad Request的响应对象
*/
badRequest(message: string) {
this.logger.error(`return a bad request response: ${message}`)
return Response.json(
{ code: 400, message, requestId: this.requestId },
{ status: 400 }
)
}
/**
* 404 Not Found的响应对象
*
* @param message -
* @returns 404 Not Found的响应对象
*/
notFound(message: string) {
this.logger.error(`return a not found response: ${message}`)
return Response.json(
{ code: 404, message, requestId: this.requestId },
{ status: 404 }
)
}
/**
* 500 Internal Server Error的响应对象
*
* @param message -
* @param data -
* @returns 500 Internal Server Error的响应对象
*/
serverError(message: string, data?: any) {
this.logger.error(`return a server error response: ${message}`)
return Response.json(
{ code: 500, message, data, requestId: this.requestId },
{ status: 500 }
)
}
/**
* 200 OK的响应对象
*
* @param data -
* @returns 200 OK的响应对象
*/
ok(data?: any) {
this.logger.info(
`return a ok response${data ? ": " + JSON.stringify(data) : ""}`
)
return Response.json({
code: 0,
message: "success",
data,
requestId: this.requestId,
})
}
/**
* 200 OK的响应对象
*
* @param data -
* @returns 200 OK的响应对象
*/
json(data = {}) {
this.logger.info(`return a json response: ${JSON.stringify(data)}`)
return Response.json(data)
}
/**
*
* @param data -
* @param status -
* @returns
*/
custom(data = null as any, status = 200) {
this.logger.info(
`return a ${status} response${data ? ": " + JSON.stringify(data) : ""}`
)
return new Response(data, { status: status })
}
/**
* 200 OK的健康检查响应对象
*
* @param message -
* @returns 200 OK的健康检查响应对象
*/
healthCheck(message = "success") {
return Response.json({ code: 0, message })
}
}
export { NetTool, NetToolBase }
export { GitlabService, NetTool, NetToolBase }
export type { Gitlab, NetErrorDetail, NetRequestParams }

View File

@ -0,0 +1,353 @@
import logger from "@egg/logger"
import { Logger } from "winston"
import { NetErrorDetail, NetRequestParams } from "../types"
export class NetError extends Error {
public response: Response | null
public code: number
public message: string
public data?: any
constructor({ response, code, message, data }: NetErrorDetail) {
super(message)
this.response = response
this.code = code
this.message = message
this.data = data
}
}
/**
* HTTP请求的方法
*/
class NetToolBase {
protected prefix: string
protected headers: Record<string, string>
protected getHeaders: () => Promise<Record<string, string>>
protected logger: Logger
protected requestId: string
/**
*
*
* @param {Object} params -
* @param {string} [params.prefix] - URL前缀
* @param {Record<string, string>} [params.headers] -
* @param {Function} [params.getHeaders] -
* @param {string} [params.requestId] - ID
*/
constructor({
prefix,
headers,
getHeaders,
requestId,
}: {
prefix?: string
headers?: Record<string, string>
getHeaders?: () => Promise<Record<string, string>>
requestId?: string
} = {}) {
this.prefix = prefix || ""
this.headers = headers || {}
this.getHeaders = getHeaders || (async () => ({}))
this.requestId = requestId || ""
this.logger = logger.child({ requestId })
}
/**
*
*
* @param {Object} params -
* @param {string} [params.prefix] - URL前缀
* @param {Record<string, string>} [params.headers] -
* @param {Function} [params.getHeaders] -
* @param {string} [params.requestId] - ID
* @returns
*/
child({
prefix,
headers,
getHeaders,
requestId,
}: {
prefix?: string
headers?: Record<string, string>
getHeaders?: () => Promise<Record<string, string>>
requestId?: string
} = {}) {
return new NetToolBase({
prefix: prefix || this.prefix,
headers: headers || this.headers,
getHeaders: getHeaders || this.getHeaders,
requestId: requestId || this.requestId,
})
}
/**
*
* @param {string} url -
* @param {string} method - 使HTTP方法
* @param {Record<string, string>} headers -
* @param {any} requestBody -
* @param {any} responseBody -
* @param {number} requestTime -
* @param {Response} [response] -
* @returns
*/
private logResponse(
url: string,
method: string,
headers: Record<string, string>,
requestBody: any,
responseBody: any,
requestTime: number,
response?: Response
) {
const responseLog = {
ok: response?.ok,
status: response?.status,
statusText: response?.statusText,
url,
method: method,
requestHeaders: headers,
responseHeaders: response?.headers,
requestBody,
responseBody,
requestTime,
responseTime: new Date().getTime(),
}
this.logger.http(JSON.stringify(responseLog, null, 2))
return responseLog
}
/**
* Promise
* @param url - URL
* @param method - 使HTTP方法
* @param queryParams - URL中的查询参数
* @param payload -
* @param additionalHeaders -
* @returns Promise
* @throws
*/
protected async request<T = any>({
url,
method,
queryParams,
payload,
additionalHeaders,
}: NetRequestParams): Promise<T> {
// 拼接完整的URL
let fullUrl = `${this.prefix}${url}`
if (queryParams) {
if (typeof queryParams === "string") {
fullUrl = `${fullUrl}?${queryParams}`
} else {
const queryString = new URLSearchParams(queryParams).toString()
if (queryString) fullUrl = `${fullUrl}?${queryString}`
}
}
// 设置请求头
const headers = {
...this.headers,
...(await this.getHeaders()),
...(additionalHeaders || {}),
} as Record<string, string>
// 设置请求Header
if (!(payload instanceof FormData)) {
headers["Content-Type"] = "application/json"
}
// 处理请求数据
const body = payload instanceof FormData ? payload : JSON.stringify(payload)
// 获取响应数据
let resData: any = null
let resText: string = ""
let res: Response
// 开始计时
const requestTime = new Date().getTime()
try {
res = await fetch(fullUrl, {
method,
body,
headers,
})
try {
resText = await res.text()
resData = JSON.parse(resText)
} catch {
/* empty */
}
} catch (error: any) {
// 网络请求异常如请求超时、DNS解析失败、CORS请求被阻止等
this.logResponse(
fullUrl,
method,
headers,
payload,
resData || resText,
requestTime
)
throw new NetError({
response: null,
code: 1,
message: error.message || "网络请求异常",
})
}
// 记录响应
this.logResponse(
fullUrl,
method,
headers,
payload,
resData || resText,
requestTime,
res
)
// http 错误码异常
if (!res.ok) {
throw new NetError({
response: res,
code: resData.code || res.status,
message: resData.message || resData.msg || resText || res.statusText,
data: resData.data,
})
}
// http 错误码正常,但解析异常
if (!resData) {
throw new NetError({
response: res,
code: 1,
message: "解析响应数据异常",
})
}
// 响应数据异常
if ("code" in resData && resData.code !== 0) {
throw new NetError({
response: res,
code: resData.code,
message: resData.message || resData.msg || "网络请求失败",
})
}
return resData as T
}
/**
* GET请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected get<T = any>(
url: string,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({ url, method: "get", queryParams, additionalHeaders })
}
/**
* POST请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected post<T = any>(
url: string,
payload?: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "post",
payload,
queryParams,
additionalHeaders,
})
}
/**
* PUT请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected put<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "put",
payload,
queryParams,
additionalHeaders,
})
}
/**
* DELETE请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected del<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "delete",
payload,
queryParams,
additionalHeaders,
})
}
/**
* PATCH请求并返回一个解析为响应数据的Promise
*
* @param url - URL
* @param payload -
* @param queryParams - URL中的查询参数
* @param additionalHeaders -
* @returns Promise
*/
protected patch<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return this.request({
url,
method: "patch",
payload,
queryParams,
additionalHeaders,
})
}
}
export default NetToolBase

View File

@ -0,0 +1,155 @@
import { NetRequestParams } from "../types"
import NetToolBase from "./base"
class NetTool extends NetToolBase {
public request<T = any>({
url,
method,
queryParams,
payload,
additionalHeaders,
}: NetRequestParams): Promise<T> {
return super.request<T>({
url,
method,
queryParams,
payload,
additionalHeaders,
})
}
public get<T = any>(
url: string,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.get<T>(url, queryParams, additionalHeaders)
}
public post<T = any>(
url: string,
payload?: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.post<T>(url, payload, queryParams, additionalHeaders)
}
public put<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.put<T>(url, payload, queryParams, additionalHeaders)
}
public del<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.del<T>(url, payload, queryParams, additionalHeaders)
}
public patch<T = any>(
url: string,
payload: any,
queryParams?: any,
additionalHeaders?: any
): Promise<T> {
return super.patch<T>(url, payload, queryParams, additionalHeaders)
}
/**
* 400 Bad Request的响应对象
*
* @param message -
* @returns 400 Bad Request的响应对象
*/
badRequest(message: string) {
this.logger.error(`return a bad request response: ${message}`)
return Response.json(
{ code: 400, message, requestId: this.requestId },
{ status: 400 }
)
}
/**
* 404 Not Found的响应对象
*
* @param message -
* @returns 404 Not Found的响应对象
*/
notFound(message: string) {
this.logger.error(`return a not found response: ${message}`)
return Response.json(
{ code: 404, message, requestId: this.requestId },
{ status: 404 }
)
}
/**
* 500 Internal Server Error的响应对象
*
* @param message -
* @param data -
* @returns 500 Internal Server Error的响应对象
*/
serverError(message: string, data?: any) {
this.logger.error(`return a server error response: ${message}`)
return Response.json(
{ code: 500, message, data, requestId: this.requestId },
{ status: 500 }
)
}
/**
* 200 OK的响应对象
*
* @param data -
* @returns 200 OK的响应对象
*/
ok(data?: any) {
this.logger.info(
`return a ok response${data ? ": " + JSON.stringify(data) : ""}`
)
return Response.json({
code: 0,
message: "success",
data,
requestId: this.requestId,
})
}
/**
* 200 OK的响应对象
*
* @param data -
* @returns 200 OK的响应对象
*/
json(data = {}) {
this.logger.info(`return a json response: ${JSON.stringify(data)}`)
return Response.json(data)
}
/**
*
* @param data -
* @param status -
* @returns
*/
custom(data = null as any, status = 200) {
this.logger.info(
`return a ${status} response${data ? ": " + JSON.stringify(data) : ""}`
)
return new Response(data, { status: status })
}
/**
* 200 OK的健康检查响应对象
*
* @param message -
* @returns 200 OK的健康检查响应对象
*/
healthCheck(message = "success") {
return Response.json({ code: 0, message })
}
}
export default NetTool

View File

@ -0,0 +1,420 @@
export namespace Gitlab {
export interface InitParams {
baseUrl: string
requestId: string
authKey: string
project_id?: number
merge_request_iid?: number
}
/* 错误 */
export interface Error {
/**
*
*/
message: string
}
/* 用户 */
export interface User {
/**
* ID
*/
id: number
/**
*
*/
username: string
/**
*
*/
name: string
/**
*
*/
state: string
/**
* URL
*/
avatar_url: string
/**
* URL
*/
web_url: string
}
/* 项目详情 */
export interface ProjDetail {
/**
* ID
*/
id: number
/**
*
*/
description: string
/**
*
*/
name: string
/**
*
*/
path_with_namespace: string
/**
* URL
*/
web_url: string
/**
* URL
*/
avatar_url?: any
/**
*
*/
message?: string
}
/* 管道详情 */
export interface PipelineDetail {
/**
* ID
*/
id: number
/**
* ID
*/
project_id: number
/**
*
*/
ref: string
/**
*
*/
status: string
/**
* URL
*/
web_url: string
/**
*
*/
user: User
/**
*
*/
started_at: string
/**
*
*/
finished_at: string
/**
*
*/
duration: number
/**
*
*/
queued_duration: number
/**
*
*/
message?: string
}
/* 管道 */
export interface Pipeline {
/**
* ID
*/
id: number
/**
* ID
*/
project_id: number
/**
* SHA值
*/
sha: string
/**
*
*/
ref: string
/**
*
*/
status: string
/**
*
*/
source: string
/**
*
*/
created_at: string
/**
*
*/
updated_at: string
/**
* URL
*/
web_url: string
}
/* 任务 */
export interface Job {
status: string
stage: string
}
/* 徽章 */
export interface Badge {
/**
* ID
*/
id: number
/**
*
*/
name: string
/**
* URL
*/
link_url: string
/**
* URL
*/
image_url: string
/**
* URL
*/
rendered_link_url: string
/**
* URL
*/
rendered_image_url: string
/**
*
*/
kind: "project" | "group"
}
/* 管道事件 */
export interface PipelineEvent {
/**
*
*/
object_attributes: {
/**
* ID
*/
id: number
/**
*
*/
ref: string
/**
* SHA值
*/
sha: string
/**
*
*/
status: string
/**
*
*/
created_at: string
/**
*
*/
finished_at: string
/**
*
*/
duration: number
}
/**
*
*/
user: {
/**
*
*/
name: string
/**
*
*/
username: string
}
/**
*
*/
project: {
/**
* ID
*/
id: number
/**
* web URL
*/
web_url: string
/**
*
*/
path_with_namespace: string
}
/**
*
*/
commit: {
/**
* ID
*/
id: string
/**
*
*/
title: string
/**
* URL
*/
url: string
}
/**
*
*/
builds: {
/**
* ID
*/
id: number
/**
*
*/
stage: string
/**
*
*/
status: string
/**
*
* @example 2024-07-29 15:49:21 +0800
*/
finished_at: string | null
}[]
}
/* 合并请求 */
export interface MergeRequest {
/**
*
*/
title: string
/**
*
*/
target_branch: string
/**
*
*/
source_branch: string
/**
*
*/
author: {
/**
*
*/
username: string
/**
*
*/
name: string
}
/**
* SHA值
*/
sha: string
/**
* SHA值
*/
merge_commit_sha: string
/**
*
*/
references: {
/**
*
*/
full: string
}
/**
* web URL
*/
web_url: string
}
/* 合并请求事件 */
export interface MergeRequestEvent {
/**
*
*/
object_kind: "merge_request"
/**
*
*/
event_type: "merge_request"
/**
*
*/
project: {
/**
* ID
*/
id: number
}
/**
*
*/
object_attributes: {
/**
* ID
*/
iid: number
/**
*
*/
state: "opened" | "closed" | "reopened" | "merged"
/**
*
*/
changes?: any
}
}
/**
* GitLab
*/
export type BadgeSetParams = Omit<Badge, "kind" | "name"> & {
badge_id?: number
}
export interface CreateRangeDiscussionPosition {
base_sha: string
start_sha: string
head_sha: string
new_path: string
old_path: string
position_type: "text"
new_line: number
line_range: {
start: {
line_code: string
}
end: {
line_code: string
}
}
}
}

View File

@ -0,0 +1,18 @@
import type { Gitlab } from "./gitlab"
export interface NetRequestParams {
url: string
method: string
queryParams?: any
payload?: any
additionalHeaders?: Record<string, string>
}
export interface NetErrorDetail {
response: Response | null
code: number
message: string
data?: any
}
export type { Gitlab }