diff --git a/changelog.md b/changelog.md index 7f1324d..819ab96 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2026-02-28 - 2.1.0 - feat(gitlab) +add group- and project-management methods to GitLab client + +- Adds getGroupByPath(fullPath) to fetch a group by full path +- Adds getGroupProjects(groupId, opts?) to list projects in a group (include_subgroups=true, default perPage=50, optional search) +- Adds getDescendantGroups(groupId, opts?) to list descendant subgroups (paginated, default perPage=50, optional search) +- Adds createGroup(name, path, parentId?) to create groups (defaults to private visibility) +- Adds createProject(name, opts?) to create projects with optional path, namespaceId, visibility (default private) and description + ## 2026-02-24 - 2.0.3 - fix() no changes detected; nothing to commit diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 7d17436..2f0f963 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@apiclient.xyz/gitlab', - version: '2.0.3', + version: '2.1.0', description: 'A TypeScript client for the GitLab API, providing easy access to projects, groups, CI/CD variables, and pipelines.' } diff --git a/ts/gitlab.classes.gitlabclient.ts b/ts/gitlab.classes.gitlabclient.ts index 4f66a6f..85b4684 100644 --- a/ts/gitlab.classes.gitlabclient.ts +++ b/ts/gitlab.classes.gitlabclient.ts @@ -125,6 +125,73 @@ export class GitLabClient { } } + // --------------------------------------------------------------------------- + // Groups — scoped queries + // --------------------------------------------------------------------------- + + /** + * Get a single group by its full path (e.g. "foss.global" or "foss.global/push.rocks") + */ + public async getGroupByPath(fullPath: string): Promise { + return this.request( + 'GET', + `/api/v4/groups/${encodeURIComponent(fullPath)}`, + ); + } + + /** + * List projects within a group (includes subgroups when include_subgroups=true) + */ + public async getGroupProjects(groupId: number | string, opts?: IListOptions): Promise { + const page = opts?.page || 1; + const perPage = opts?.perPage || 50; + let url = `/api/v4/groups/${encodeURIComponent(groupId)}/projects?include_subgroups=true&order_by=updated_at&sort=desc&page=${page}&per_page=${perPage}`; + if (opts?.search) { + url += `&search=${encodeURIComponent(opts.search)}`; + } + return this.request('GET', url); + } + + /** + * List all descendant groups (recursive subgroups) within a group + */ + public async getDescendantGroups(groupId: number | string, opts?: IListOptions): Promise { + const page = opts?.page || 1; + const perPage = opts?.perPage || 50; + let url = `/api/v4/groups/${encodeURIComponent(groupId)}/descendant_groups?order_by=name&sort=asc&page=${page}&per_page=${perPage}`; + if (opts?.search) { + url += `&search=${encodeURIComponent(opts.search)}`; + } + return this.request('GET', url); + } + + /** + * Create a new group. Optionally nested under a parent group. + */ + public async createGroup(name: string, path: string, parentId?: number): Promise { + const body: any = { name, path, visibility: 'private' }; + if (parentId) body.parent_id = parentId; + return this.request('POST', '/api/v4/groups', body); + } + + /** + * Create a new project (repository). + */ + public async createProject(name: string, opts?: { + path?: string; + namespaceId?: number; + visibility?: string; + description?: string; + }): Promise { + return this.request('POST', '/api/v4/projects', { + name, + path: opts?.path || name, + namespace_id: opts?.namespaceId, + visibility: opts?.visibility || 'private', + description: opts?.description || '', + }); + } + // --------------------------------------------------------------------------- // Projects // ---------------------------------------------------------------------------