ya-git-jira 1.3.0 → 1.5.0

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.
Files changed (74) hide show
  1. package/bin/git-bump.ts +7 -4
  2. package/bin/{git-jira-issues.ts → git-jira-issue-list.ts} +10 -7
  3. package/bin/git-jira-issue-show.ts +40 -0
  4. package/bin/git-jira-issue.ts +14 -25
  5. package/bin/git-jira-start.ts +8 -5
  6. package/bin/git-jira.ts +9 -6
  7. package/bin/git-lab-group-list.ts +35 -0
  8. package/bin/git-lab-group.ts +25 -0
  9. package/bin/git-lab-merge-active.ts +41 -0
  10. package/bin/git-lab-merge-todo.ts +36 -0
  11. package/bin/git-lab-merge-train-list.ts +26 -0
  12. package/bin/git-lab-merge-train.ts +25 -0
  13. package/bin/git-lab-merge.ts +29 -0
  14. package/bin/git-lab-namespace-list.ts +27 -0
  15. package/bin/git-lab-namespace.ts +24 -0
  16. package/bin/{git-lab-projects.ts → git-lab-project-list.ts} +13 -10
  17. package/bin/git-lab-project-pipeline-list.ts +46 -0
  18. package/bin/git-lab-project-pipeline.ts +24 -0
  19. package/bin/git-lab-project-whereami.ts +43 -0
  20. package/bin/git-lab-project.ts +28 -0
  21. package/bin/git-lab-whoami.ts +8 -5
  22. package/bin/git-lab.ts +18 -8
  23. package/bin/gitj.ts +7 -5
  24. package/build.ts +1 -1
  25. package/bun.lockb +0 -0
  26. package/dist/bin/git-bump.js +55 -17
  27. package/dist/bin/{git-jira-issues.js → git-jira-issue-list.js} +71 -28
  28. package/dist/bin/{git-lab-mergetrain.js → git-jira-issue-show.js} +100 -43
  29. package/dist/bin/git-jira-issue.js +106 -33
  30. package/dist/bin/git-jira-start.js +70 -27
  31. package/dist/bin/git-jira.js +117 -59
  32. package/dist/bin/git-lab-group-list.js +2793 -0
  33. package/dist/bin/git-lab-group.js +2805 -0
  34. package/dist/bin/git-lab-groups.js +1992 -0
  35. package/dist/bin/git-lab-merge-active.js +2798 -0
  36. package/dist/bin/git-lab-merge-todo.js +2793 -0
  37. package/dist/bin/git-lab-merge-train-list.js +2754 -0
  38. package/dist/bin/git-lab-merge-train.js +2766 -0
  39. package/dist/bin/git-lab-merge.js +2865 -0
  40. package/dist/bin/git-lab-namespace-list.js +1967 -0
  41. package/dist/bin/git-lab-namespace.js +1979 -0
  42. package/dist/bin/git-lab-namespaces.js +1984 -0
  43. package/dist/bin/git-lab-project-list.js +2761 -0
  44. package/dist/bin/git-lab-project-pipeline-list.js +2800 -0
  45. package/dist/bin/git-lab-project-pipeline.js +2812 -0
  46. package/dist/bin/git-lab-project-whereami.js +2764 -0
  47. package/dist/bin/git-lab-project.js +2805 -0
  48. package/dist/bin/git-lab-projects-list.js +1996 -0
  49. package/dist/bin/git-lab-projects-whereami.js +1999 -0
  50. package/dist/bin/git-lab-projects.js +138 -35
  51. package/dist/bin/git-lab-whoami.js +100 -56
  52. package/dist/bin/git-lab.js +1123 -58
  53. package/dist/bin/gitj.js +1260 -172
  54. package/dist/index.js +881 -35
  55. package/index.ts +1 -1
  56. package/lib/gitlab/api.ts +46 -0
  57. package/lib/gitlab/config.ts +21 -0
  58. package/lib/gitlab/dlog.ts +2 -0
  59. package/lib/gitlab/group.ts +12 -0
  60. package/lib/gitlab/index.ts +8 -0
  61. package/lib/gitlab/merge-request.ts +31 -0
  62. package/lib/gitlab/merge-trains.ts +19 -0
  63. package/lib/gitlab/namespace.ts +12 -0
  64. package/lib/gitlab/pipeline.ts +32 -0
  65. package/lib/gitlab/project.ts +78 -0
  66. package/lib/gitlab/user.ts +13 -0
  67. package/lib/is_main.ts +21 -2
  68. package/lib/jira.ts +12 -7
  69. package/lib/package.ts +35 -0
  70. package/package.json +21 -4
  71. package/tests/all-help.test.ts +46 -0
  72. package/tests/git.test.ts +8 -7
  73. package/tests/gitj.test.ts +1 -1
  74. package/lib/gitlab.ts +0 -86
package/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "./lib/json.ts"
2
2
  export * from "./lib/git.ts"
3
- export * from "./lib/gitlab.ts"
3
+ export * from "./lib/gitlab"
4
4
  export * from "./lib/is_main.ts"
5
5
  export * from "./lib/jira.ts"
6
6
  export * from "./lib/spawn.ts"
@@ -0,0 +1,46 @@
1
+ import type { JSONValue } from "../json"
2
+ import { getGitlabConfig } from "./config"
3
+
4
+ function getNextLink(link: string | null): string | undefined {
5
+ if (!link) {
6
+ return undefined
7
+ }
8
+ const regex = /<([^>]+)>; rel="next"/
9
+ const match = link.match(regex)
10
+ const next = match ? match[1] : undefined
11
+ return next
12
+ }
13
+
14
+ export async function gitlabApi(endpoint: string): Promise<JSONValue> {
15
+ if (endpoint.startsWith("/")) {
16
+ console.warn(`gitlabApi: endpoint ${endpoint} starts with /, removing it`)
17
+ endpoint = endpoint.slice(1)
18
+ }
19
+ const method = "GET"
20
+ const { host, token } = await getGitlabConfig()
21
+ const base = `https://${host}/api/v4`
22
+ const requested = 100
23
+ const sep = endpoint.includes('?') ? '&' : '?'
24
+ const uri = `${base}/${endpoint}${sep}per_page=${requested}`
25
+ const headers = new Headers()
26
+ headers.append("Accept", "application/json")
27
+ headers.append('Private-Token', token)
28
+ const options = {
29
+ method,
30
+ headers,
31
+ }
32
+ let request = new Request(uri, options)
33
+ const response = await fetch(request)
34
+ let link = getNextLink(response.headers.get('Link'))
35
+ let partial = (await response.json()) as Array<JSONValue>
36
+ let result: Array<JSONValue> = partial
37
+ while (partial.length == requested && link)
38
+ {
39
+ let request = new Request(link, options)
40
+ const next_response = await fetch(request)
41
+ link = getNextLink(next_response.headers.get('Link'))
42
+ partial = (await next_response.json()) as Array<JSONValue>
43
+ result = result.concat(partial)
44
+ }
45
+ return result;
46
+ }
@@ -0,0 +1,21 @@
1
+ import { getConfig } from "../git"
2
+
3
+ export interface GitlabConfig {
4
+ host: string
5
+ user: string
6
+ token: string
7
+ }
8
+
9
+ const hostP = getConfig("gitlab.host")
10
+ const userP = getConfig("user.email")
11
+ const tokenP = getConfig("gitlab.token")
12
+
13
+ export async function getGitlabConfig(): Promise<GitlabConfig> {
14
+ const host = await hostP
15
+ if (!host) throw new Error("gitlab.host not in git config")
16
+ const user = await userP
17
+ if (!user) throw new Error("user.email not in git config")
18
+ const token = await tokenP
19
+ if (!token) throw new Error("gitlab.token not in git config")
20
+ return { host, user, token }
21
+ }
@@ -0,0 +1,2 @@
1
+ import debug from 'debug'
2
+ export const dlog = debug('gitlab')
@@ -0,0 +1,12 @@
1
+ import { gitlabApi } from './api'
2
+ import { JSONValue } from '../json'
3
+
4
+ export type Group = JSONValue & {
5
+ id: number
6
+ name: string
7
+ full_path: string
8
+ }
9
+
10
+ export async function getGroups(): Promise<Array<Group>> {
11
+ return await gitlabApi(`groups`) as Array<Group>
12
+ }
@@ -0,0 +1,8 @@
1
+ export * from './api'
2
+ export * from './config'
3
+ export * from './group'
4
+ export * from './merge-request'
5
+ export * from './namespace'
6
+ export * from './pipeline'
7
+ export * from './project'
8
+ export * from './user'
@@ -0,0 +1,31 @@
1
+ import { projectScopedGet } from './project'
2
+ import type { JSONValue } from '../json'
3
+ import { whoami } from './user'
4
+ import { gitlabApi } from './api'
5
+
6
+ export type MergeRequest = JSONValue & {
7
+ id: number
8
+ title : string
9
+ description : string
10
+ state : string
11
+ source_branch: string
12
+ target_branch: string
13
+ web_url: string
14
+ merge_status: string
15
+ }
16
+
17
+ export async function getMergeRequest(id: string): Promise<MergeRequest> {
18
+ return await projectScopedGet(`merge_requests/${id}`) as MergeRequest
19
+ }
20
+
21
+ export async function getMyMergeRequestsInProgress() : Promise<Array<MergeRequest>>
22
+ {
23
+ const me = await whoami()
24
+ return await gitlabApi(`merge_requests?state=opened&author_id=${me.id}`) as Array<MergeRequest>
25
+ }
26
+
27
+ export async function getMyMergeRequestsToReview() : Promise<Array<MergeRequest>>
28
+ {
29
+ const me = await whoami()
30
+ return await gitlabApi(`merge_requests?state=opened&reviewer_id=${me.id}`) as Array<MergeRequest>
31
+ }
@@ -0,0 +1,19 @@
1
+ import { projectScopedGet } from './project'
2
+ import type { JSONValue } from '../json'
3
+
4
+ export type MergeTrain = JSONValue & {
5
+ id: number
6
+ merge_request: {
7
+ title: string
8
+ web_url: string
9
+ }
10
+ user: {
11
+ username: string
12
+ }
13
+ target_branch: string
14
+ status: string
15
+ }
16
+
17
+ export async function getMergeTrains(): Promise<MergeTrain[]> {
18
+ return await projectScopedGet(`merge_trains`) as MergeTrain[]
19
+ }
@@ -0,0 +1,12 @@
1
+ import { gitlabApi } from "./api"
2
+ import { JSONValue } from "../json"
3
+
4
+ type Namespace = JSONValue & {
5
+ id: number
6
+ name: string
7
+ full_path: string
8
+ }
9
+
10
+ export async function getNamespaces(): Promise<Namespace[]> {
11
+ return await gitlabApi(`namespaces`) as Namespace[]
12
+ }
@@ -0,0 +1,32 @@
1
+ import { dlog } from "./dlog"
2
+ import { projectScopedGet } from "./project"
3
+ import { whoami } from "./user"
4
+ import type { JSONValue } from "../json"
5
+
6
+ export type Pipeline = JSONValue & {
7
+ id: number
8
+ status: string
9
+ ref: string
10
+ sha: string
11
+ web_url: string
12
+ updated_at: string // datetime string like "2021-03-18T15:00:00.000Z"
13
+ }
14
+
15
+ export type PipelineStatus = 'success' | 'running'
16
+
17
+ export interface GetPipelineOptions {
18
+ days: number
19
+ status: PipelineStatus
20
+ }
21
+
22
+ export async function getProjectPipelines(options: GetPipelineOptions): Promise<Array<Pipeline>> {
23
+ const { days, status } = options
24
+ const me = await whoami()
25
+ const username = me.username
26
+ const date = new Date()
27
+ const pastDate = date.getDate() - days;
28
+ date.setDate(pastDate)
29
+ const updated = date.toISOString()
30
+ dlog(`updated: ${updated}`)
31
+ return await projectScopedGet(`pipelines?status=${status}&username=${username}&updated_after=${updated}`) as Array<Pipeline>
32
+ }
@@ -0,0 +1,78 @@
1
+ import { getGitlabConfig } from "./config"
2
+ import { getRemote } from "../git"
3
+ import { gitlabApi } from "./api"
4
+ import { type JSONValue } from "../json"
5
+ import path from 'node:path'
6
+ import { dlog } from "./dlog"
7
+
8
+ export type Project = JSONValue & {
9
+ id: number
10
+ name: string
11
+ path: string
12
+ path_with_namespace: string
13
+ visibility: string
14
+ ssh_url_to_repo: string
15
+ }
16
+
17
+ export async function getProjects(match: string): Promise<Array<Project>> {
18
+ let search = ''
19
+ if (match) {
20
+ const m = encodeURIComponent(match)
21
+ search = `&search=${m}`
22
+ }
23
+ const projects = await gitlabApi(`projects?membership=true&simple=true${search}`)
24
+ if (!projects) {
25
+ throw new Error(`No projects!`)
26
+ } else if (!Array.isArray(projects)) {
27
+ console.log(projects)
28
+ throw new Error(`Projects is not an array!`)
29
+ }
30
+ const projs = projects as Array<Project>
31
+
32
+ const filtered = projs.filter((p: Project): boolean => {
33
+ return p.path_with_namespace.toLowerCase().includes(match.toLowerCase())
34
+ })
35
+ return filtered
36
+ }
37
+
38
+ // git@gitlab.com:etagen-internal/linear-generator-config.git
39
+ export async function findProject(ssh_url: string): Promise<Project | undefined> {
40
+ const parts = ssh_url.split(':')
41
+ if (parts.length != 2) {
42
+ throw new Error(`${ssh_url} is invalid, could not be split into two parts at :`)
43
+ }
44
+ const name = path.basename(parts[1], '.git')
45
+
46
+ const projects = await getProjects(name) as Array<Project>
47
+ const project = projects.find((p: Project): boolean => {
48
+ return p.ssh_url_to_repo === ssh_url
49
+ })
50
+ return project
51
+ }
52
+
53
+ export async function projectScopedGet(endpoint: string): Promise<JSONValue> {
54
+ if (endpoint.startsWith("/")) {
55
+ console.warn(`gitlabApi: endpoint ${endpoint} starts with /, removing it`)
56
+ endpoint = endpoint.slice(1)
57
+ }
58
+ const method = "GET"
59
+ const { host, token } = await getGitlabConfig()
60
+ const remote = await getRemote()
61
+ const project = await findProject(remote)
62
+ if (!project) {
63
+ throw new Error(`Could not find project for remote ${remote}`)
64
+ }
65
+ const base = `https://${host}/api/v4/projects/${project.id}`
66
+ const uri = `${base}/${endpoint}`
67
+ dlog(`projectScopedGet uri: ${uri}`)
68
+ const headers = new Headers()
69
+ headers.append("Accept", "application/json")
70
+ headers.append('Private-Token', token)
71
+ const options = {
72
+ method,
73
+ headers,
74
+ }
75
+ const request = new Request(uri, options)
76
+ const response = await fetch(request)
77
+ return await response.json()
78
+ }
@@ -0,0 +1,13 @@
1
+ import type { JSONValue } from "../json"
2
+ import { gitlabApi } from "./api"
3
+
4
+ export type User = JSONValue & {
5
+ id: number
6
+ name: string
7
+ username: string
8
+ email: string
9
+ }
10
+
11
+ export async function whoami(): Promise<User> {
12
+ return await gitlabApi("user") as User
13
+ }
package/lib/is_main.ts CHANGED
@@ -1,5 +1,24 @@
1
1
  import path from 'node:path'
2
+
3
+ function justBase(filename: string): string {
4
+ const ext = path.extname(filename)
5
+ const base = path.basename(filename, ext)
6
+ return base
7
+ }
8
+
2
9
  export function isMain(self: string): boolean {
3
- const exe = path.basename(Bun.argv[1]).split('.')[0]
4
- return exe == self || import.meta.main
10
+ const arg1 = Bun.argv[1]
11
+ const argv1Base = justBase(arg1)
12
+ const selfBase = justBase(self)
13
+ const result = argv1Base === selfBase
14
+ // if (result) {
15
+ // console.log({
16
+ // arg1,
17
+ // self,
18
+ // argv1Base,
19
+ // selfBase,
20
+ // result,
21
+ // })
22
+ // }
23
+ return result
5
24
  }
package/lib/jira.ts CHANGED
@@ -25,11 +25,14 @@ export async function getJiraConfig(): Promise<JiraConfig> {
25
25
  return { host, token }
26
26
  }
27
27
 
28
- export async function get(endpoint: string): Promise<JSONValue> {
28
+ export async function jiraApi(endpoint: string): Promise<JSONValue> {
29
+ if (endpoint.startsWith("/")) {
30
+ console.warn(`jiraApi: endpoint ${endpoint} starts with /`)
31
+ endpoint = endpoint.slice(1)
32
+ }
29
33
  const method = "GET"
30
34
  const { host, token } = await getJiraConfig()
31
- const base = `https://${host}/rest/api/3`
32
- const uri = `${base}/${endpoint}`
35
+ const uri = `https://${host}/rest/api/3/${endpoint}`
33
36
  const auth = `Basic ${token}`
34
37
  const headers = new Headers()
35
38
  headers.append("Authorization", auth)
@@ -40,11 +43,13 @@ export async function get(endpoint: string): Promise<JSONValue> {
40
43
  }
41
44
  const request = new Request(uri, options)
42
45
  const response = await fetch(request)
43
- return await response.json()
46
+ const result = await response.json()
47
+ return result;
44
48
  }
45
49
 
46
50
  export async function getIssue(issue: string): Promise<Issue> {
47
- return await get(`/issue/${issue}`) as Issue
51
+ const result = await jiraApi(`issue/${issue}`) as Issue
52
+ return result
48
53
  }
49
54
 
50
55
  type Myself = JSONValue & {
@@ -52,7 +57,7 @@ type Myself = JSONValue & {
52
57
  }
53
58
 
54
59
  export async function getMyself(): Promise<Myself> {
55
- return await get("/myself") as Myself
60
+ return await jiraApi("/myself") as Myself
56
61
  }
57
62
 
58
63
  type SearchResponse = JSONValue & {
@@ -63,6 +68,6 @@ export async function myUnresolvedIssues(): Promise<Array<Issue>> {
63
68
  const myself = await getMyself()
64
69
  const myselfId = myself.accountId
65
70
  const jql = `assignee = ${myselfId} AND resolution = Unresolved`
66
- const issues = await get(`/search?jql=${encodeURIComponent(jql)}`) as SearchResponse
71
+ const issues = await jiraApi(`/search?jql=${encodeURIComponent(jql)}`) as SearchResponse
67
72
  return issues.issues
68
73
  }
package/lib/package.ts ADDED
@@ -0,0 +1,35 @@
1
+
2
+ import path from 'node:path'
3
+ import fs from 'node:fs'
4
+
5
+ export function findPackageJson()
6
+ {
7
+ const cwd = import.meta.dir
8
+ let dir = cwd
9
+ while (dir !== '/') {
10
+ const packageJson = path.join(dir, 'package.json')
11
+ if (fs.existsSync(packageJson)) {
12
+ return packageJson
13
+ }
14
+ dir = path.dirname(dir)
15
+ }
16
+ return null
17
+ }
18
+
19
+ export async function getPackageJson()
20
+ {
21
+ const packagePath = findPackageJson()
22
+ if (!packagePath) {
23
+ throw new Error(`No package.json found in ${import.meta.dir} or any parent directory`)
24
+ }
25
+ const packageJsonText = fs.readFileSync(packagePath, 'utf8')
26
+ return JSON.parse(packageJsonText)
27
+ }
28
+
29
+ const packageJsonPromise = getPackageJson()
30
+
31
+ export async function getPackageVersion()
32
+ {
33
+ const packageJson = await packageJsonPromise
34
+ return packageJson.version
35
+ }
package/package.json CHANGED
@@ -1,16 +1,30 @@
1
1
  {
2
2
  "name": "ya-git-jira",
3
3
  "description": "git extensions for Jira integration. Assumes bun is installed.",
4
- "version": "1.3.0",
4
+ "version": "1.5.0",
5
5
  "module": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "git-bump": "dist/bin/git-bump.js",
9
+ "git-jira-issue-list": "dist/bin/git-jira-issue-list.js",
10
+ "git-jira-issue-show": "dist/bin/git-jira-issue-show.js",
9
11
  "git-jira-issue": "dist/bin/git-jira-issue.js",
10
- "git-jira-issues": "dist/bin/git-jira-issues.js",
11
12
  "git-jira-start": "dist/bin/git-jira-start.js",
12
13
  "git-jira": "dist/bin/git-jira.js",
13
- "git-lab-projects": "dist/bin/git-lab-projects.js",
14
+ "git-lab-group-list": "dist/bin/git-lab-group-list.js",
15
+ "git-lab-group": "dist/bin/git-lab-group.js",
16
+ "git-lab-merge-active": "dist/bin/git-lab-merge-active.js",
17
+ "git-lab-merge-todo": "dist/bin/git-lab-merge-todo.js",
18
+ "git-lab-merge-train-list": "dist/bin/git-lab-merge-train-list.js",
19
+ "git-lab-merge-train": "dist/bin/git-lab-merge-train.js",
20
+ "git-lab-merge": "dist/bin/git-lab-merge.js",
21
+ "git-lab-namespace-list": "dist/bin/git-lab-namespace-list.js",
22
+ "git-lab-namespace": "dist/bin/git-lab-namespace.js",
23
+ "git-lab-project-list": "dist/bin/git-lab-project-list.js",
24
+ "git-lab-project-pipeline": "dist/bin/git-lab-project-pipeline.js",
25
+ "git-lab-project-pipeline-list": "dist/bin/git-lab-project-pipeline-list.js",
26
+ "git-lab-project-whereami": "dist/bin/git-lab-project-whereami.js",
27
+ "git-lab-project": "dist/bin/git-lab-project.js",
14
28
  "git-lab-whoami": "dist/bin/git-lab-whoami.js",
15
29
  "git-lab": "dist/bin/git-lab.js",
16
30
  "gitj": "dist/bin/gitj.js"
@@ -21,7 +35,9 @@
21
35
  },
22
36
  "devDependencies": {
23
37
  "@types/commander": "^2.12.2",
24
- "bun-types": "latest"
38
+ "@types/debug": "^4.1.8",
39
+ "bun-types": "latest",
40
+ "typescript": "latest"
25
41
  },
26
42
  "directories": {
27
43
  "lib": "lib"
@@ -32,6 +48,7 @@
32
48
  "dependencies": {
33
49
  "commander": "^11.0.0",
34
50
  "cuid": "^3.0.0",
51
+ "debug": "^4.3.4",
35
52
  "glob": "^10.3.4"
36
53
  },
37
54
  "main": "dist/start.js dist/bump.js",
@@ -0,0 +1,46 @@
1
+ import { readdirSync } from 'fs';
2
+ import { describe, expect, test } from 'bun:test';
3
+ import { doCommand } from '..';
4
+
5
+ import { getPackageJson, getPackageVersion } from '../lib/package'
6
+ const version = await getPackageVersion()
7
+
8
+
9
+ describe('bin scripts', () => {
10
+ const binDir = './bin';
11
+
12
+ const scripts = readdirSync(binDir).filter((file) => {
13
+ return file.endsWith('.ts');
14
+ });
15
+
16
+ describe('--help', () => {
17
+ scripts.forEach((script) => {
18
+ const stem = script.split('/').pop()?.split('-').pop()?.split('.').shift();
19
+ test(`"${script} --help" should contain 'Usage: ${stem}'"`, async () => {
20
+ const output = await doCommand(['bun', 'run', `${binDir}/${script}`, '--help']);
21
+ expect(output).toContain(`Usage: ${stem}`);
22
+ });
23
+ });
24
+ });
25
+
26
+ describe('--version', () => {
27
+ scripts.forEach((script) => {
28
+ test(`"${script} --version" should contain '${version}'"`, async () => {
29
+ const output = await doCommand(['bun', 'run', `${binDir}/${script}`, '--version']);
30
+ expect(output).toContain(version);
31
+ });
32
+ });
33
+ });
34
+
35
+ describe('all bin/* exist in package.json', async () => {
36
+ const packageJson = await getPackageJson();
37
+ const bin = packageJson.bin;
38
+ scripts.forEach((script) => {
39
+ test(`"${script}" should be in package.json`, () => {
40
+ expect(script).toEndWith('.ts')
41
+ script = script.slice(0, -3)
42
+ expect(bin[script]).toBeDefined();
43
+ });
44
+ });
45
+ })
46
+ });
package/tests/git.test.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { test, expect } from "bun:test"
2
- import { findProject, getRemote } from ".."
2
+ import { findProject } from "../lib/gitlab/project"
3
+ import { getRemote } from "../lib/git"
3
4
 
4
5
  test("testing works", async (): Promise<void> => {
5
6
  expect(true).toBe(true)
@@ -13,13 +14,13 @@ test("getRemote", async (): Promise<void> => {
13
14
  test("findProject linear-generator", async (): Promise<void> => {
14
15
  const ssh_url = "git@gitlab.com:etagen-internal/linear-generator.git"
15
16
  const project = await findProject(ssh_url)
16
- expect(project.ssh_url_to_repo).toBe(ssh_url)
17
- expect(project.id).toBe(4053065)
18
- })
17
+ expect(project?.ssh_url_to_repo).toBe(ssh_url)
18
+ expect(project?.id).toBe(4053065)
19
+ }, 15000)
19
20
 
20
21
  test("findProject eta-lib/base", async (): Promise<void> => {
21
22
  const ssh_url = "git@gitlab.com:etagen-internal/eta-lib/base.git"
22
23
  const project = await findProject(ssh_url)
23
- expect(project.ssh_url_to_repo).toBe(ssh_url)
24
- expect(project.id).toBe(42470523)
25
- })
24
+ expect(project?.ssh_url_to_repo).toBe(ssh_url)
25
+ expect(project?.id).toBe(42470523)
26
+ }, 15000)
@@ -10,7 +10,7 @@ test("gitj works", async (): Promise<void> => {
10
10
  const { out, code }: SpawnResult = await spawn(["bun", "run", "bin/gitj.ts"])
11
11
  expect(out).toMatch("Usage:")
12
12
  expect(out).toMatch("Bump the version number in the current branch")
13
- expect(out).toMatch("A set of commands for working with Jira")
13
+ expect(out).toMatch("Commands for working with Jira")
14
14
  expect(code).toBe(0)
15
15
  })
16
16
 
package/lib/gitlab.ts DELETED
@@ -1,86 +0,0 @@
1
- import { getConfig, getRemote } from "./git"
2
- import type { JSONValue } from "./json"
3
- import path from 'node:path'
4
-
5
- export interface GitlabConfig {
6
- host: string
7
- user: string
8
- token: string
9
- }
10
-
11
- export async function getGitlabConfig(): Promise<GitlabConfig> {
12
- const host = await getConfig("gitlab.host")
13
- if (!host) throw new Error("gitlab.host not in git config")
14
- const user = await getConfig("user.email")
15
- if (!user) throw new Error("user.email not in git config")
16
- const token = await getConfig("gitlab.token")
17
- if (!token) throw new Error("gitlab.token not in git config")
18
- return { host, user, token }
19
- }
20
-
21
- export async function get(endpoint: string): Promise<JSONValue> {
22
- const method = "GET"
23
- const { host, token } = await getGitlabConfig()
24
- const base = `https://${host}/api/v4`
25
- const uri = `${base}/${endpoint}`
26
- const headers = new Headers()
27
- headers.append("Accept", "application/json")
28
- headers.append('Private-Token', token)
29
- const options = {
30
- method,
31
- headers,
32
- }
33
- const request = new Request(uri, options)
34
- const response = await fetch(request)
35
- return await response.json()
36
- }
37
-
38
- export type User = JSONValue & {
39
- id: number
40
- name: string
41
- username: string
42
- email: string
43
- }
44
-
45
- export async function whoami(): Promise<User> {
46
- return await get("/user") as User
47
- }
48
-
49
- export type Project = JSONValue & {
50
- id: number
51
- name: string
52
- path: string
53
- path_with_namespace: string
54
- visibility: string
55
- ssh_url_to_repo: string
56
- }
57
-
58
- export async function getProjects(paths: string[]): Promise<Array<Project>> {
59
- let search: string = ""
60
- if (paths.length > 0) {
61
- search = '&search=' + paths.join(",")
62
- }
63
- return await get(`/projects?visibility=private&membership=true&simple=true${search}`) as Array<Project>
64
- }
65
-
66
- // git@gitlab.com:etagen-internal/linear-generator-config.git
67
- export async function findProject(ssh_url: string): Promise<Project> {
68
- const parts = ssh_url.split(':')
69
- if (parts.length != 2) {
70
- throw new Error(`${ssh_url} is invalid, could not be split into two parts at :`)
71
- }
72
- const name = path.basename(parts[1], '.git')
73
-
74
- const projects = await getProjects([name])
75
- const project = projects.find((p: Project): boolean => {
76
- return p.ssh_url_to_repo === ssh_url
77
- })
78
- if (!project) {
79
- throw new Error(`No project with ssh_url_to_repo ${ssh_url} found`)
80
- }
81
- return project
82
- }
83
-
84
- export async function getMergeRequest(id: string): Promise<JSONValue> {
85
- return await get(`/merge_requests/${id}`)
86
- }