gitxplain 0.1.6 → 0.1.9

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,267 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import os from "node:os";
4
- import { execFileSync } from "node:child_process";
5
-
6
- const CONFIG_DIR = path.join(os.homedir(), ".gitxplain");
7
- const CONNECTION_FILE = path.join(CONFIG_DIR, "git-connection.json");
8
-
9
- function ensureConfigDir() {
10
- if (!fs.existsSync(CONFIG_DIR)) {
11
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
12
- }
13
- }
14
-
15
- export async function saveGitConnection(token, provider = "github", userInfo = null) {
16
- ensureConfigDir();
17
- const connection = {
18
- token,
19
- provider,
20
- user: userInfo || {},
21
- connectedAt: new Date().toISOString()
22
- };
23
- fs.writeFileSync(CONNECTION_FILE, JSON.stringify(connection, null, 2), "utf8");
24
- }
25
-
26
- export function loadGitConnection() {
27
- try {
28
- if (fs.existsSync(CONNECTION_FILE)) {
29
- const data = fs.readFileSync(CONNECTION_FILE, "utf8");
30
- return JSON.parse(data);
31
- }
32
- } catch (error) {
33
- // If file is corrupted, return null
34
- return null;
35
- }
36
- return null;
37
- }
38
-
39
- export function isGitConnected() {
40
- return loadGitConnection() !== null;
41
- }
42
-
43
- export function clearGitConnection() {
44
- try {
45
- if (fs.existsSync(CONNECTION_FILE)) {
46
- fs.unlinkSync(CONNECTION_FILE);
47
- }
48
- } catch (error) {
49
- // Ignore errors during cleanup
50
- }
51
- }
52
-
53
- export function getGitUserInfo() {
54
- try {
55
- const name = execFileSync("git", ["config", "user.name"], {
56
- encoding: "utf8",
57
- stdio: ["ignore", "pipe", "pipe"]
58
- }).trim();
59
- const email = execFileSync("git", ["config", "user.email"], {
60
- encoding: "utf8",
61
- stdio: ["ignore", "pipe", "pipe"]
62
- }).trim();
63
- return { name, email };
64
- } catch {
65
- return { name: "Unknown", email: "unknown@example.com" };
66
- }
67
- }
68
-
69
- export async function verifyGitToken(token, provider = "github") {
70
- try {
71
- if (provider === "github") {
72
- const response = await fetch("https://api.github.com/user", {
73
- headers: {
74
- Authorization: `Bearer ${token}`,
75
- Accept: "application/vnd.github.v3+json",
76
- "User-Agent": "gitxplain"
77
- }
78
- });
79
-
80
- if (!response.ok) {
81
- const errorData = await response.json();
82
- throw new Error(
83
- errorData.message || `GitHub API returned status ${response.status}`
84
- );
85
- }
86
-
87
- return await response.json();
88
- }
89
- } catch (error) {
90
- throw error;
91
- }
92
- }
93
-
94
- export async function fetchGitHubRepositories(token) {
95
- try {
96
- const response = await fetch("https://api.github.com/user/repos?per_page=30&sort=updated", {
97
- headers: {
98
- Authorization: `Bearer ${token}`,
99
- Accept: "application/vnd.github.v3+json",
100
- "User-Agent": "gitxplain"
101
- }
102
- });
103
-
104
- if (!response.ok) {
105
- throw new Error(`Failed to fetch repositories: ${response.statusText}`);
106
- }
107
-
108
- const repos = await response.json();
109
- return repos.map((repo) => ({
110
- name: repo.name,
111
- owner: repo.owner.login,
112
- description: repo.description,
113
- url: repo.html_url,
114
- language: repo.language,
115
- stars: repo.stargazers_count,
116
- updated_at: repo.updated_at
117
- }));
118
- } catch (error) {
119
- throw new Error(`Failed to fetch GitHub repositories: ${error.message}`);
120
- }
121
- }
122
-
123
- export async function fetchGitHubCommits(token, owner, repo) {
124
- try {
125
- const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/commits?per_page=15`, {
126
- headers: {
127
- Authorization: `Bearer ${token}`,
128
- Accept: "application/vnd.github.v3+json",
129
- "User-Agent": "gitxplain"
130
- }
131
- });
132
-
133
- if (!response.ok) {
134
- throw new Error(`Failed to fetch commits: ${response.statusText}`);
135
- }
136
-
137
- const commits = await response.json();
138
- return commits.map((commitData) => ({
139
- sha: commitData.sha.substring(0, 7),
140
- fullSha: commitData.sha,
141
- message: commitData.commit.message.split('\n')[0],
142
- author: commitData.commit.author.name,
143
- date: commitData.commit.author.date
144
- }));
145
- } catch (error) {
146
- throw new Error(`Failed to fetch GitHub commits: ${error.message}`);
147
- }
148
- }
149
-
150
- export async function fetchCommitDetails(token, owner, repo, sha) {
151
- try {
152
- const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/commits/${sha}`, {
153
- headers: {
154
- Authorization: `Bearer ${token}`,
155
- Accept: "application/vnd.github.v3+json",
156
- "User-Agent": "gitxplain"
157
- }
158
- });
159
-
160
- if (!response.ok) {
161
- throw new Error(`Failed to fetch commit details: ${response.statusText}`);
162
- }
163
-
164
- const data = await response.json();
165
- return {
166
- sha: data.sha,
167
- stats: data.stats,
168
- files: (data.files || []).map(f => ({
169
- filename: f.filename,
170
- status: f.status,
171
- additions: f.additions,
172
- deletions: f.deletions,
173
- patch: f.patch || "No patch available or binary file"
174
- }))
175
- };
176
- } catch (error) {
177
- throw new Error(`Failed to fetch commit details: ${error.message}`);
178
- }
179
- }
180
-
181
- export async function fetchRepoTree(token, owner, repo, sha) {
182
- try {
183
- const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees/${sha}?recursive=1`, {
184
- headers: {
185
- Authorization: `Bearer ${token}`,
186
- Accept: "application/vnd.github.v3+json",
187
- "User-Agent": "gitxplain"
188
- }
189
- });
190
-
191
- if (!response.ok) {
192
- throw new Error(`Failed to fetch repo tree: ${response.statusText}`);
193
- }
194
-
195
- const data = await response.json();
196
- const paths = (data.tree || [])
197
- .filter(t => t.type === 'blob' || t.type === 'tree')
198
- .map(t => t.path);
199
-
200
- if (paths.length > 200) {
201
- return [...paths.slice(0, 200), `... and ${paths.length - 200} more items truncated`];
202
- }
203
- return paths;
204
- } catch (error) {
205
- return ["Failed to load repository file structure."];
206
- }
207
- }
208
-
209
- export async function downloadCommitArchive(token, owner, repo, sha, destPath) {
210
- try {
211
- const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/zipball/${sha}`, {
212
- headers: {
213
- Authorization: `Bearer ${token}`,
214
- Accept: "application/vnd.github.v3+json",
215
- "User-Agent": "gitxplain"
216
- },
217
- redirect: 'follow'
218
- });
219
-
220
- if (!response.ok) {
221
- throw new Error(`Failed to fetch zipball: ${response.statusText}`);
222
- }
223
-
224
- const arrayBuffer = await response.arrayBuffer();
225
- fs.writeFileSync(destPath, Buffer.from(arrayBuffer));
226
- return true;
227
- } catch (error) {
228
- throw new Error(`Failed to download archive: ${error.message}`);
229
- }
230
- }
231
-
232
- export async function fetchFileContent(token, owner, repo, sha, filePath) {
233
- try {
234
- const response = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/${sha}/${filePath}`, {
235
- headers: {
236
- Authorization: `Bearer ${token}`,
237
- "User-Agent": "gitxplain"
238
- }
239
- });
240
- if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);
241
- return await response.text();
242
- } catch (error) {
243
- throw new Error(`Failed to fetch file content: ${error.message}`);
244
- }
245
- }
246
-
247
- export async function fetchRepoIssues(token, owner, repo) {
248
- try {
249
- const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/issues?state=open&per_page=10`, {
250
- headers: {
251
- Authorization: `Bearer ${token}`,
252
- Accept: "application/vnd.github.v3+json",
253
- "User-Agent": "gitxplain"
254
- }
255
- });
256
- if (!response.ok) throw new Error(`Failed to fetch issues: ${response.statusText}`);
257
- const issues = await response.json();
258
- return issues.map(i => ({
259
- number: i.number,
260
- title: i.title,
261
- user: i.user.login,
262
- url: i.html_url
263
- }));
264
- } catch (error) {
265
- throw new Error(`Failed to fetch issues: ${error.message}`);
266
- }
267
- }