@molecule/api-git-provider-gitlab 1.0.2

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/README.md ADDED
@@ -0,0 +1,81 @@
1
+ <!--
2
+ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
+ Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
+ Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
+ To change this document, edit the module-level JSDoc in src/index.ts.
6
+ Generated: 2026-08-07T00:19:23.397Z
7
+ -->
8
+
9
+ # @molecule/api-git-provider-gitlab
10
+
11
+ > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
12
+ > It is written to be read by coding agents as much as by people, and is generated from this
13
+ > package's source — edit `src/index.ts` JSDoc, not this file.
14
+
15
+ `@molecule/api-git-provider-gitlab` — a `@molecule/api-git-provider` bond.
16
+
17
+ Register it with `registerGitProvider(provider)` in `setupBonds()`; the app
18
+ then never names this host. See the core package for the interface and for
19
+ why `basicAuthUsername` may be null.
20
+
21
+ ## Quick Start
22
+
23
+ ```typescript
24
+ import { registerGitProvider } from '@molecule/api-git-provider'
25
+ import { provider } from '@molecule/api-git-provider-gitlab'
26
+
27
+ registerGitProvider(provider)
28
+ ```
29
+
30
+ ## Type
31
+
32
+ `provider`
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ npm install @molecule/api-git-provider-gitlab @molecule/api-git-provider @molecule/api-http
38
+ ```
39
+
40
+ ## API
41
+
42
+ ### Constants
43
+
44
+ #### `provider`
45
+
46
+ The GitLab provider.
47
+
48
+ ```typescript
49
+ const provider: GitProvider
50
+ ```
51
+
52
+ ## Core Interface
53
+
54
+ Implements `@molecule/api-git-provider` interface.
55
+
56
+ ## Bond Wiring
57
+
58
+ Setup function to register this provider with the core interface:
59
+
60
+ ```typescript
61
+ import { registerGitProvider } from '@molecule/api-git-provider'
62
+ import { provider } from '@molecule/api-git-provider-gitlab'
63
+
64
+ export function setupGitProviderGitlab(): void {
65
+ registerGitProvider(provider)
66
+ }
67
+ ```
68
+
69
+ ## Injection Notes
70
+
71
+ ### Requirements
72
+
73
+ Peer dependencies:
74
+
75
+ - `@molecule/api-git-provider` ^1.0.2
76
+ - `@molecule/api-http` ^1.0.1
77
+
78
+ ### Runtime Dependencies
79
+
80
+ - `@molecule/api-git-provider`
81
+ - `@molecule/api-http`
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `@molecule/api-git-provider-gitlab` — a `@molecule/api-git-provider` bond.
3
+ *
4
+ * Register it with `registerGitProvider(provider)` in `setupBonds()`; the app
5
+ * then never names this host. See the core package for the interface and for
6
+ * why `basicAuthUsername` may be null.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { registerGitProvider } from '@molecule/api-git-provider'
11
+ * import { provider } from '@molecule/api-git-provider-gitlab'
12
+ *
13
+ * registerGitProvider(provider)
14
+ * ```
15
+ *
16
+ * @module
17
+ */
18
+ export * from './provider.js';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,eAAe,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `@molecule/api-git-provider-gitlab` — a `@molecule/api-git-provider` bond.
3
+ *
4
+ * Register it with `registerGitProvider(provider)` in `setupBonds()`; the app
5
+ * then never names this host. See the core package for the interface and for
6
+ * why `basicAuthUsername` may be null.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { registerGitProvider } from '@molecule/api-git-provider'
11
+ * import { provider } from '@molecule/api-git-provider-gitlab'
12
+ *
13
+ * registerGitProvider(provider)
14
+ * ```
15
+ *
16
+ * @module
17
+ */
18
+ export * from './provider.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * GitLab git-hosting provider.
3
+ *
4
+ * @module
5
+ */
6
+ import type { GitProvider } from '@molecule/api-git-provider';
7
+ /** The GitLab provider. */
8
+ export declare const provider: GitProvider;
9
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAEV,WAAW,EAGZ,MAAM,4BAA4B,CAAA;AAwCnC,2BAA2B;AAC3B,eAAO,MAAM,QAAQ,EAAE,WAmEtB,CAAA"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * GitLab git-hosting provider.
3
+ *
4
+ * @module
5
+ */
6
+ /**
7
+ * Normalize GitLab's project shape.
8
+ *
9
+ * Two mappings differ from the obvious:
10
+ * - privacy is a `visibility` STRING (`private`/`internal`/`public`), not a
11
+ * boolean, and `internal` is not public — treating it as such would show a
12
+ * company-internal repo as world-readable in a picker.
13
+ * - `statistics.repository_size` is BYTES and only present when the caller
14
+ * asked for statistics; the normalized field is KB, so it converts.
15
+ *
16
+ * @param project - GitLab's project JSON.
17
+ * @returns The normalized repository, or null when unusable.
18
+ */
19
+ const normalize = (project) => {
20
+ if (!project.path_with_namespace || !project.http_url_to_repo)
21
+ return null;
22
+ const bytes = project.statistics?.repository_size;
23
+ return {
24
+ fullName: project.path_with_namespace,
25
+ url: project.http_url_to_repo,
26
+ private: typeof project.visibility === 'string' ? project.visibility !== 'public' : null,
27
+ defaultBranch: project.default_branch ?? null,
28
+ sizeKb: typeof bytes === 'number' ? Math.round(bytes / 1024) : null,
29
+ updatedAt: project.last_activity_at ?? null,
30
+ description: project.description ?? null,
31
+ };
32
+ };
33
+ /** The GitLab provider. */
34
+ export const provider = {
35
+ id: 'gitlab',
36
+ label: 'GitLab',
37
+ defaultHost: 'gitlab.com',
38
+ auth: {
39
+ kind: 'oauth',
40
+ authorizeUrl: 'https://gitlab.com/oauth/authorize',
41
+ tokenUrl: 'https://gitlab.com/oauth/token',
42
+ // `write_repository` is the git-over-HTTPS push scope and `read_repository`
43
+ // pairs with it for fetch. `read_api` is REQUIRED as well, and is the one
44
+ // that gets forgotten: the *_repository scopes cover only the git protocol,
45
+ // NOT the REST API, so without it the OAuth flow succeeds and then the repo
46
+ // picker 403s — a failure that looks nothing like a missing scope. The
47
+ // registered GitLab application must enable all three.
48
+ scope: 'read_api read_repository write_repository',
49
+ },
50
+ // GitLab expects the literal `oauth2` as the basic-auth username, NOT
51
+ // GitHub's `x-access-token`. Getting this wrong fails at push time as an
52
+ // opaque 401, far from the code that chose it.
53
+ basicAuthUsername: 'oauth2',
54
+ apiBaseForHost(host) {
55
+ // Uniform for gitlab.com and self-hosted alike — unlike GitHub, there is no
56
+ // separate API host.
57
+ return `https://${host}/api/v4`;
58
+ },
59
+ apiHeaders(token) {
60
+ const headers = { 'user-agent': 'molecule-dev' };
61
+ if (token)
62
+ headers.authorization = `Bearer ${token}`;
63
+ return headers;
64
+ },
65
+ async listRepositories(input) {
66
+ const { get } = await import('@molecule/api-http');
67
+ const base = this.apiBaseForHost(input.host);
68
+ const response = await get(`${base}/projects?membership=true&order_by=last_activity_at&sort=desc` +
69
+ `&per_page=${input.perPage}&page=${input.page}&statistics=true`, { headers: this.apiHeaders(input.token), timeout: 15_000 });
70
+ return (response.data ?? []).flatMap((project) => {
71
+ const normalized = normalize(project);
72
+ return normalized ? [normalized] : [];
73
+ });
74
+ },
75
+ async getRepository(input) {
76
+ const { get } = await import('@molecule/api-http');
77
+ const base = this.apiBaseForHost(input.host);
78
+ try {
79
+ // GitLab addresses a project by its URL-ENCODED path, not by owner/name
80
+ // path segments — `group/sub/app` must arrive as one encoded component or
81
+ // the API reads it as a different route entirely.
82
+ const response = await get(`${base}/projects/${encodeURIComponent(input.path)}?statistics=true`, { headers: this.apiHeaders(input.token), timeout: 15_000 });
83
+ return response.data ? normalize(response.data) : null;
84
+ }
85
+ catch (error) {
86
+ const status = error?.response?.status;
87
+ if (status === 404)
88
+ return null;
89
+ throw error;
90
+ }
91
+ },
92
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@molecule/api-git-provider-gitlab",
3
+ "version": "1.0.2",
4
+ "description": "Git hosting provider for GitLab (gitlab.com) — OAuth endpoints, token auth shape, repository listing and lookup.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "test": "vitest run",
11
+ "test:watch": "vitest"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "keywords": [
24
+ "molecule",
25
+ "git",
26
+ "provider",
27
+ "gitlab"
28
+ ],
29
+ "license": "Apache-2.0",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/molecule-dev/molecule.git",
33
+ "directory": "packages/api/bonds/git-provider/gitlab"
34
+ },
35
+ "devDependencies": {
36
+ "@molecule/api-git-provider": "1.0.2",
37
+ "@molecule/api-http": "1.0.1",
38
+ "@types/node": "26.1.2",
39
+ "typescript": "6.0.3",
40
+ "vitest": "4.1.10"
41
+ },
42
+ "peerDependencies": {
43
+ "@molecule/api-git-provider": "^1.0.2",
44
+ "@molecule/api-http": "^1.0.1"
45
+ }
46
+ }