@andrebuzeli/git-mcp 15.8.3 → 15.8.5

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.
@@ -1,203 +1,203 @@
1
- import { Octokit } from "@octokit/rest";
2
- import axios from "axios";
3
- import { getProvidersEnv } from "../utils/repoHelpers.js";
4
-
5
- export class ProviderManager {
6
- constructor() {
7
- const { githubToken, giteaUrl, giteaToken } = getProvidersEnv();
8
- this.githubToken = githubToken || "";
9
- this.giteaUrl = giteaUrl || "";
10
- this.giteaToken = giteaToken || "";
11
- this.github = this.githubToken ? new Octokit({ auth: this.githubToken }) : null;
12
- this._githubOwner = "";
13
- this._giteaOwner = "";
14
- this._ownerFetchedAt = 0;
15
- this._remoteUrlsCache = new Map(); // Cache para URLs de remotes
16
- this._cacheExpiry = 10 * 60 * 1000; // 10 minutos
17
- }
18
-
19
- async getGitHubOwner() {
20
- if (!this.github) return "";
21
- const now = Date.now();
22
- if (this._githubOwner && now - this._ownerFetchedAt < 5 * 60 * 1000) return this._githubOwner;
23
- try {
24
- const me = await this.github.rest.users.getAuthenticated();
25
- this._githubOwner = me.data.login || "";
26
- this._ownerFetchedAt = now;
27
- return this._githubOwner;
28
- } catch {
29
- return "";
30
- }
31
- }
32
-
33
- async getGiteaOwner() {
34
- if (!this.giteaUrl || !this.giteaToken) return "";
35
- const now = Date.now();
36
- if (this._giteaOwner && now - this._ownerFetchedAt < 5 * 60 * 1000) return this._giteaOwner;
37
- try {
38
- const r = await axios.get(`${this.giteaUrl}/api/v1/user`, {
39
- headers: { Authorization: `token ${this.giteaToken}` },
40
- timeout: 8000,
41
- });
42
- const d = r.data || {};
43
- this._giteaOwner = d.login || d.username || "";
44
- this._ownerFetchedAt = now;
45
- return this._giteaOwner;
46
- } catch {
47
- return "";
48
- }
49
- }
50
-
51
- async getRemoteUrls(repoName) {
52
- const cacheKey = `urls_${repoName}`;
53
- const now = Date.now();
54
-
55
- // Verificar cache
56
- if (this._remoteUrlsCache.has(cacheKey)) {
57
- const cached = this._remoteUrlsCache.get(cacheKey);
58
- if (now - cached.timestamp < this._cacheExpiry) {
59
- return cached.urls;
60
- }
61
- }
62
-
63
- const urls = {};
64
-
65
- // GitHub URL
66
- if (this.github) {
67
- const owner = await this.getGitHubOwner();
68
- if (owner) {
69
- urls.github = `https://github.com/${owner}/${repoName}.git`;
70
- }
71
- }
72
-
73
- // Gitea URL
74
- if (this.giteaUrl && this.giteaToken) {
75
- const owner = await this.getGiteaOwner();
76
- if (owner) {
77
- const base = this.giteaUrl.replace(/\/$/, "");
78
- urls.gitea = `${base}/${owner}/${repoName}.git`;
79
- }
80
- }
81
-
82
- // Cachear resultado
83
- this._remoteUrlsCache.set(cacheKey, { urls, timestamp: now });
84
-
85
- return urls;
86
- }
87
-
88
- async ensureRepos({ repoName, createIfMissing = true, description = "Managed by git-mcpv2", isPublic = false }) {
89
- // Por padrão, repositórios são PRIVADOS. Use isPublic=true para público.
90
- const isPrivate = !isPublic;
91
- const results = { github: null, gitea: null };
92
- // GitHub
93
- if (this.github) {
94
- const owner = await this.getGitHubOwner();
95
- if (owner) {
96
- try {
97
- const full = `${owner}/${repoName}`;
98
- try {
99
- await this.github.rest.repos.get({ owner, repo: repoName });
100
- results.github = { ok: true, repo: full, created: false };
101
- } catch {
102
- if (createIfMissing) {
103
- const cr = await this.github.rest.repos.createForAuthenticatedUser({
104
- name: repoName,
105
- description,
106
- private: isPrivate,
107
- auto_init: false,
108
- });
109
- results.github = { ok: true, repo: cr.data.full_name, created: true };
110
- } else {
111
- results.github = { ok: false, error: "missing" };
112
- }
113
- }
114
- } catch (e) {
115
- results.github = { ok: false, error: String(e?.message || e) };
116
- }
117
- }
118
- }
119
- // Gitea
120
- if (this.giteaUrl && this.giteaToken) {
121
- const owner = await this.getGiteaOwner();
122
- if (owner) {
123
- try {
124
- const base = this.giteaUrl.replace(/\/$/, "");
125
- const getRepo = await axios.get(`${base}/api/v1/repos/${owner}/${repoName}`,
126
- { headers: { Authorization: `token ${this.giteaToken}` }, timeout: 8000 });
127
- if (getRepo.status === 200) {
128
- results.gitea = { ok: true, repo: `${owner}/${repoName}`, created: false };
129
- }
130
- } catch (e) {
131
- if (createIfMissing) {
132
- try {
133
- const cr = await axios.post(`${this.giteaUrl}/api/v1/user/repos`,
134
- { name: repoName, description, private: isPrivate, auto_init: false },
135
- { headers: { Authorization: `token ${this.giteaToken}` }, timeout: 8000 });
136
- results.gitea = { ok: true, repo: `${cr.data?.owner?.login || owner}/${repoName}`, created: true };
137
- } catch (err) {
138
- results.gitea = { ok: false, error: String(err?.message || err) };
139
- }
140
- } else {
141
- results.gitea = { ok: false, error: "missing" };
142
- }
143
- }
144
- }
145
- }
146
- return results;
147
- }
148
-
149
- async listAllRepos(options = {}) {
150
- const { maxPages = 10, perPage = 100 } = options;
151
- const results = { github: [], gitea: [] };
152
-
153
- // GitHub - com paginação
154
- if (this.github) {
155
- try {
156
- let page = 1;
157
- let hasMore = true;
158
- while (hasMore && page <= maxPages) {
159
- const { data } = await this.github.rest.repos.listForAuthenticatedUser({
160
- per_page: perPage,
161
- page,
162
- visibility: "all"
163
- });
164
- results.github.push(...data.map(r => ({
165
- name: r.name,
166
- fullName: r.full_name,
167
- url: r.html_url,
168
- isPrivate: r.private
169
- })));
170
- hasMore = data.length === perPage;
171
- page++;
172
- }
173
- } catch (e) {
174
- console.error("GitHub List Error:", e.message);
175
- }
176
- }
177
-
178
- // Gitea - com paginação
179
- if (this.giteaUrl && this.giteaToken) {
180
- try {
181
- let page = 1;
182
- let hasMore = true;
183
- const base = this.giteaUrl.replace(/\/$/, "");
184
- while (hasMore && page <= maxPages) {
185
- const { data } = await axios.get(`${base}/api/v1/user/repos?limit=${perPage}&page=${page}`, {
186
- headers: { Authorization: `token ${this.giteaToken}` }
187
- });
188
- results.gitea.push(...data.map(r => ({
189
- name: r.name,
190
- fullName: r.full_name,
191
- url: r.html_url,
192
- isPrivate: r.private
193
- })));
194
- hasMore = data.length === perPage;
195
- page++;
196
- }
197
- } catch (e) {
198
- console.error("Gitea List Error:", e.message);
199
- }
200
- }
201
- return results;
202
- }
203
- }
1
+ import { Octokit } from "@octokit/rest";
2
+ import axios from "axios";
3
+ import { getProvidersEnv } from "../utils/repoHelpers.js";
4
+
5
+ export class ProviderManager {
6
+ constructor() {
7
+ const { githubToken, giteaUrl, giteaToken } = getProvidersEnv();
8
+ this.githubToken = githubToken || "";
9
+ this.giteaUrl = giteaUrl || "";
10
+ this.giteaToken = giteaToken || "";
11
+ this.github = this.githubToken ? new Octokit({ auth: this.githubToken }) : null;
12
+ this._githubOwner = "";
13
+ this._giteaOwner = "";
14
+ this._ownerFetchedAt = 0;
15
+ this._remoteUrlsCache = new Map(); // Cache para URLs de remotes
16
+ this._cacheExpiry = 10 * 60 * 1000; // 10 minutos
17
+ }
18
+
19
+ async getGitHubOwner() {
20
+ if (!this.github) return "";
21
+ const now = Date.now();
22
+ if (this._githubOwner && now - this._ownerFetchedAt < 5 * 60 * 1000) return this._githubOwner;
23
+ try {
24
+ const me = await this.github.rest.users.getAuthenticated();
25
+ this._githubOwner = me.data.login || "";
26
+ this._ownerFetchedAt = now;
27
+ return this._githubOwner;
28
+ } catch {
29
+ return "";
30
+ }
31
+ }
32
+
33
+ async getGiteaOwner() {
34
+ if (!this.giteaUrl || !this.giteaToken) return "";
35
+ const now = Date.now();
36
+ if (this._giteaOwner && now - this._ownerFetchedAt < 5 * 60 * 1000) return this._giteaOwner;
37
+ try {
38
+ const r = await axios.get(`${this.giteaUrl}/api/v1/user`, {
39
+ headers: { Authorization: `token ${this.giteaToken}` },
40
+ timeout: 8000,
41
+ });
42
+ const d = r.data || {};
43
+ this._giteaOwner = d.login || d.username || "";
44
+ this._ownerFetchedAt = now;
45
+ return this._giteaOwner;
46
+ } catch {
47
+ return "";
48
+ }
49
+ }
50
+
51
+ async getRemoteUrls(repoName) {
52
+ const cacheKey = `urls_${repoName}`;
53
+ const now = Date.now();
54
+
55
+ // Verificar cache
56
+ if (this._remoteUrlsCache.has(cacheKey)) {
57
+ const cached = this._remoteUrlsCache.get(cacheKey);
58
+ if (now - cached.timestamp < this._cacheExpiry) {
59
+ return cached.urls;
60
+ }
61
+ }
62
+
63
+ const urls = {};
64
+
65
+ // GitHub URL
66
+ if (this.github) {
67
+ const owner = await this.getGitHubOwner();
68
+ if (owner) {
69
+ urls.github = `https://github.com/${owner}/${repoName}.git`;
70
+ }
71
+ }
72
+
73
+ // Gitea URL
74
+ if (this.giteaUrl && this.giteaToken) {
75
+ const owner = await this.getGiteaOwner();
76
+ if (owner) {
77
+ const base = this.giteaUrl.replace(/\/$/, "");
78
+ urls.gitea = `${base}/${owner}/${repoName}.git`;
79
+ }
80
+ }
81
+
82
+ // Cachear resultado
83
+ this._remoteUrlsCache.set(cacheKey, { urls, timestamp: now });
84
+
85
+ return urls;
86
+ }
87
+
88
+ async ensureRepos({ repoName, createIfMissing = true, description = "Managed by git-mcpv2", isPublic = false }) {
89
+ // Por padrão, repositórios são PRIVADOS. Use isPublic=true para público.
90
+ const isPrivate = !isPublic;
91
+ const results = { github: null, gitea: null };
92
+ // GitHub
93
+ if (this.github) {
94
+ const owner = await this.getGitHubOwner();
95
+ if (owner) {
96
+ try {
97
+ const full = `${owner}/${repoName}`;
98
+ try {
99
+ await this.github.rest.repos.get({ owner, repo: repoName });
100
+ results.github = { ok: true, repo: full, created: false };
101
+ } catch {
102
+ if (createIfMissing) {
103
+ const cr = await this.github.rest.repos.createForAuthenticatedUser({
104
+ name: repoName,
105
+ description,
106
+ private: isPrivate,
107
+ auto_init: false,
108
+ });
109
+ results.github = { ok: true, repo: cr.data.full_name, created: true };
110
+ } else {
111
+ results.github = { ok: false, error: "missing" };
112
+ }
113
+ }
114
+ } catch (e) {
115
+ results.github = { ok: false, error: String(e?.message || e) };
116
+ }
117
+ }
118
+ }
119
+ // Gitea
120
+ if (this.giteaUrl && this.giteaToken) {
121
+ const owner = await this.getGiteaOwner();
122
+ if (owner) {
123
+ try {
124
+ const base = this.giteaUrl.replace(/\/$/, "");
125
+ const getRepo = await axios.get(`${base}/api/v1/repos/${owner}/${repoName}`,
126
+ { headers: { Authorization: `token ${this.giteaToken}` }, timeout: 8000 });
127
+ if (getRepo.status === 200) {
128
+ results.gitea = { ok: true, repo: `${owner}/${repoName}`, created: false };
129
+ }
130
+ } catch (e) {
131
+ if (createIfMissing) {
132
+ try {
133
+ const cr = await axios.post(`${this.giteaUrl}/api/v1/user/repos`,
134
+ { name: repoName, description, private: isPrivate, auto_init: false },
135
+ { headers: { Authorization: `token ${this.giteaToken}` }, timeout: 8000 });
136
+ results.gitea = { ok: true, repo: `${cr.data?.owner?.login || owner}/${repoName}`, created: true };
137
+ } catch (err) {
138
+ results.gitea = { ok: false, error: String(err?.message || err) };
139
+ }
140
+ } else {
141
+ results.gitea = { ok: false, error: "missing" };
142
+ }
143
+ }
144
+ }
145
+ }
146
+ return results;
147
+ }
148
+
149
+ async listAllRepos(options = {}) {
150
+ const { maxPages = 10, perPage = 100 } = options;
151
+ const results = { github: [], gitea: [] };
152
+
153
+ // GitHub - com paginação
154
+ if (this.github) {
155
+ try {
156
+ let page = 1;
157
+ let hasMore = true;
158
+ while (hasMore && page <= maxPages) {
159
+ const { data } = await this.github.rest.repos.listForAuthenticatedUser({
160
+ per_page: perPage,
161
+ page,
162
+ visibility: "all"
163
+ });
164
+ results.github.push(...data.map(r => ({
165
+ name: r.name,
166
+ fullName: r.full_name,
167
+ url: r.html_url,
168
+ isPrivate: r.private
169
+ })));
170
+ hasMore = data.length === perPage;
171
+ page++;
172
+ }
173
+ } catch (e) {
174
+ console.error("GitHub List Error:", e.message);
175
+ }
176
+ }
177
+
178
+ // Gitea - com paginação
179
+ if (this.giteaUrl && this.giteaToken) {
180
+ try {
181
+ let page = 1;
182
+ let hasMore = true;
183
+ const base = this.giteaUrl.replace(/\/$/, "");
184
+ while (hasMore && page <= maxPages) {
185
+ const { data } = await axios.get(`${base}/api/v1/user/repos?limit=${perPage}&page=${page}`, {
186
+ headers: { Authorization: `token ${this.giteaToken}` }
187
+ });
188
+ results.gitea.push(...data.map(r => ({
189
+ name: r.name,
190
+ fullName: r.full_name,
191
+ url: r.html_url,
192
+ isPrivate: r.private
193
+ })));
194
+ hasMore = data.length === perPage;
195
+ page++;
196
+ }
197
+ } catch (e) {
198
+ console.error("Gitea List Error:", e.message);
199
+ }
200
+ }
201
+ return results;
202
+ }
203
+ }