@scriptdb/storage 1.1.0 → 1.1.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/dist/index.d.mts +201 -0
- package/dist/index.d.ts +201 -0
- package/dist/index.js +119 -18
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +655 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +2 -5
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { simpleGit } from "simple-git";
|
|
5
|
+
var Storage = class {
|
|
6
|
+
constructor(repoPath, gitRoot) {
|
|
7
|
+
this.repo = null;
|
|
8
|
+
this.repoPath = repoPath;
|
|
9
|
+
this.gitRoot = gitRoot || repoPath;
|
|
10
|
+
}
|
|
11
|
+
async initialize(repoPath = null) {
|
|
12
|
+
try {
|
|
13
|
+
if (repoPath) {
|
|
14
|
+
this.repoPath = repoPath;
|
|
15
|
+
}
|
|
16
|
+
if (!fs.existsSync(this.repoPath)) {
|
|
17
|
+
fs.mkdirSync(this.repoPath, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
this.repo = simpleGit(this.gitRoot);
|
|
20
|
+
if (!fs.existsSync(path.join(this.gitRoot, ".git"))) {
|
|
21
|
+
try {
|
|
22
|
+
await this.repo.init();
|
|
23
|
+
await this.setupBasicConfig();
|
|
24
|
+
} catch (error) {
|
|
25
|
+
throw new Error(`Failed to initialize git repository: ${error.message}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return this.repo;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
throw new Error(`Failed to initialize repository: ${error.message}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async addFile(filePath, content) {
|
|
34
|
+
try {
|
|
35
|
+
const fullPath = path.join(this.repoPath, filePath);
|
|
36
|
+
const dir = path.dirname(fullPath);
|
|
37
|
+
if (!fs.existsSync(dir)) {
|
|
38
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
fs.writeFileSync(fullPath, content);
|
|
41
|
+
if (!this.repo) {
|
|
42
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
43
|
+
}
|
|
44
|
+
const gitRelativePath = path.relative(this.gitRoot, fullPath);
|
|
45
|
+
await this.repo.add(gitRelativePath);
|
|
46
|
+
return {
|
|
47
|
+
success: true,
|
|
48
|
+
message: `File ${filePath} added successfully`,
|
|
49
|
+
path: fullPath
|
|
50
|
+
};
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
message: `Failed to add file: ${error.message}`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async updateFile(filePath, content) {
|
|
59
|
+
try {
|
|
60
|
+
const fullPath = path.join(this.repoPath, filePath);
|
|
61
|
+
if (!fs.existsSync(fullPath)) {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
message: `File ${filePath} does not exist`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
fs.writeFileSync(fullPath, content);
|
|
68
|
+
if (!this.repo) {
|
|
69
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
70
|
+
}
|
|
71
|
+
const gitRelativePath = path.relative(this.gitRoot, fullPath);
|
|
72
|
+
await this.repo.add(gitRelativePath);
|
|
73
|
+
return {
|
|
74
|
+
success: true,
|
|
75
|
+
message: `File ${filePath} updated successfully`,
|
|
76
|
+
path: fullPath
|
|
77
|
+
};
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
message: `Failed to update file: ${error.message}`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async getFile(filePath) {
|
|
86
|
+
try {
|
|
87
|
+
const fullPath = path.join(this.repoPath, filePath);
|
|
88
|
+
if (!fs.existsSync(fullPath)) {
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
message: `File ${filePath} does not exist`
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const content = fs.readFileSync(fullPath, "utf8");
|
|
95
|
+
return {
|
|
96
|
+
success: true,
|
|
97
|
+
content,
|
|
98
|
+
path: fullPath
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
message: `Failed to read file: ${error.message}`
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async deleteFile(filePath) {
|
|
108
|
+
try {
|
|
109
|
+
const fullPath = path.join(this.repoPath, filePath);
|
|
110
|
+
if (!fs.existsSync(fullPath)) {
|
|
111
|
+
return {
|
|
112
|
+
success: false,
|
|
113
|
+
message: `File ${filePath} does not exist`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
fs.unlinkSync(fullPath);
|
|
117
|
+
if (!this.repo) {
|
|
118
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
119
|
+
}
|
|
120
|
+
const gitRelativePath = path.relative(this.gitRoot, fullPath);
|
|
121
|
+
await this.repo.add(gitRelativePath);
|
|
122
|
+
return {
|
|
123
|
+
success: true,
|
|
124
|
+
message: `File ${filePath} deleted successfully`
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
return {
|
|
128
|
+
success: false,
|
|
129
|
+
message: `Failed to delete file: ${error.message}`
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async commit(message) {
|
|
134
|
+
try {
|
|
135
|
+
const status = await this.getStatus();
|
|
136
|
+
if (status.staged.length === 0) {
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
message: "No staged changes to commit"
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (!this.repo) {
|
|
143
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
144
|
+
}
|
|
145
|
+
await this.repo.commit(message);
|
|
146
|
+
return {
|
|
147
|
+
success: true,
|
|
148
|
+
message: "Changes committed successfully"
|
|
149
|
+
};
|
|
150
|
+
} catch (error) {
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
message: `Failed to commit changes: ${error.message}`
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async getStatus() {
|
|
158
|
+
try {
|
|
159
|
+
if (!this.repo) {
|
|
160
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
161
|
+
}
|
|
162
|
+
const status = await this.repo.status();
|
|
163
|
+
const staged = [];
|
|
164
|
+
const unstaged = [];
|
|
165
|
+
const untracked = [];
|
|
166
|
+
status.modified.forEach((file) => {
|
|
167
|
+
unstaged.push(file);
|
|
168
|
+
});
|
|
169
|
+
status.created.forEach((file) => {
|
|
170
|
+
staged.push(file);
|
|
171
|
+
});
|
|
172
|
+
status.deleted.forEach((file) => {
|
|
173
|
+
unstaged.push(file);
|
|
174
|
+
});
|
|
175
|
+
status.renamed.forEach((file) => {
|
|
176
|
+
staged.push(file.to);
|
|
177
|
+
});
|
|
178
|
+
status.not_added.forEach((file) => {
|
|
179
|
+
untracked.push(file);
|
|
180
|
+
});
|
|
181
|
+
status.staged.forEach((file) => {
|
|
182
|
+
staged.push(file);
|
|
183
|
+
});
|
|
184
|
+
return {
|
|
185
|
+
staged,
|
|
186
|
+
unstaged,
|
|
187
|
+
untracked,
|
|
188
|
+
clean: status.isClean()
|
|
189
|
+
};
|
|
190
|
+
} catch (error) {
|
|
191
|
+
return {
|
|
192
|
+
staged: [],
|
|
193
|
+
unstaged: [],
|
|
194
|
+
untracked: [],
|
|
195
|
+
clean: false,
|
|
196
|
+
error: error.message
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async getHistory(filePath) {
|
|
201
|
+
try {
|
|
202
|
+
if (!this.repo) {
|
|
203
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
204
|
+
}
|
|
205
|
+
const log = await this.repo.log({ file: filePath });
|
|
206
|
+
return log.all.map((commit) => ({
|
|
207
|
+
hash: commit.hash.substring(0, 7),
|
|
208
|
+
message: commit.message || "",
|
|
209
|
+
date: commit.date || "",
|
|
210
|
+
author: commit.author_name || ""
|
|
211
|
+
}));
|
|
212
|
+
} catch (error) {
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Set Git configuration values
|
|
218
|
+
* @param config - Configuration object
|
|
219
|
+
* @param scope - Configuration scope ('local', 'global', 'system')
|
|
220
|
+
* @returns Result of the operation
|
|
221
|
+
*/
|
|
222
|
+
async setConfig(config, scope = "local") {
|
|
223
|
+
try {
|
|
224
|
+
if (!this.repo) {
|
|
225
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
226
|
+
}
|
|
227
|
+
const results = [];
|
|
228
|
+
if (config.userName) {
|
|
229
|
+
await this.repo.raw(["config", `--${scope}`, "user.name", config.userName]);
|
|
230
|
+
results.push({ key: "user.name", value: config.userName, scope });
|
|
231
|
+
}
|
|
232
|
+
if (config.userEmail) {
|
|
233
|
+
await this.repo.raw(["config", `--${scope}`, "user.email", config.userEmail]);
|
|
234
|
+
results.push({ key: "user.email", value: config.userEmail, scope });
|
|
235
|
+
}
|
|
236
|
+
if (config.options && typeof config.options === "object") {
|
|
237
|
+
for (const [key, value] of Object.entries(config.options)) {
|
|
238
|
+
await this.repo.raw(["config", `--${scope}`, key, value]);
|
|
239
|
+
results.push({ key, value, scope });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
success: true,
|
|
244
|
+
message: `Configuration updated successfully`,
|
|
245
|
+
changes: results
|
|
246
|
+
};
|
|
247
|
+
} catch (error) {
|
|
248
|
+
return {
|
|
249
|
+
success: false,
|
|
250
|
+
message: `Failed to set configuration: ${error.message}`
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get Git configuration value
|
|
256
|
+
* @param key - Configuration key (e.g., 'user.name')
|
|
257
|
+
* @param scope - Configuration scope ('local', 'global', 'system')
|
|
258
|
+
* @returns Result containing the configuration value
|
|
259
|
+
*/
|
|
260
|
+
async getConfig(key, scope = "local") {
|
|
261
|
+
try {
|
|
262
|
+
if (!this.repo) {
|
|
263
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
264
|
+
}
|
|
265
|
+
const result = await this.repo.raw(["config", `--${scope}`, "--get", key]);
|
|
266
|
+
return {
|
|
267
|
+
success: true,
|
|
268
|
+
key,
|
|
269
|
+
value: result.trim(),
|
|
270
|
+
scope
|
|
271
|
+
};
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (error.message.includes("exit code: 1")) {
|
|
274
|
+
return {
|
|
275
|
+
success: false,
|
|
276
|
+
message: `Configuration key '${key}' not found in ${scope} scope`
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
success: false,
|
|
281
|
+
message: `Failed to get configuration for ${key}: ${error.message}`
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Get all Git configuration values
|
|
287
|
+
* @param scope - Configuration scope ('local', 'global', 'system')
|
|
288
|
+
* @returns Result containing all configuration values
|
|
289
|
+
*/
|
|
290
|
+
async listConfig(scope = "local") {
|
|
291
|
+
try {
|
|
292
|
+
if (!this.repo) {
|
|
293
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
294
|
+
}
|
|
295
|
+
const result = await this.repo.raw(["config", `--${scope}`, "--list"]);
|
|
296
|
+
const lines = result.trim().split("\n");
|
|
297
|
+
const config = {};
|
|
298
|
+
lines.forEach((line) => {
|
|
299
|
+
const [key, value] = line.split("=");
|
|
300
|
+
if (key) {
|
|
301
|
+
config[key] = value || "";
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
return {
|
|
305
|
+
success: true,
|
|
306
|
+
scope,
|
|
307
|
+
config
|
|
308
|
+
};
|
|
309
|
+
} catch (error) {
|
|
310
|
+
return {
|
|
311
|
+
success: false,
|
|
312
|
+
message: `Failed to list configuration: ${error.message}`,
|
|
313
|
+
scope
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Set up a basic configuration for the repository
|
|
319
|
+
* @param userName - User name (optional, defaults to 'Sandbox Storage')
|
|
320
|
+
* @param userEmail - User email (optional, defaults to 'sandbox@example.com')
|
|
321
|
+
* @param additionalConfig - Additional configuration options (optional)
|
|
322
|
+
* @returns Result of the operation
|
|
323
|
+
*/
|
|
324
|
+
async setupBasicConfig(userName = "Sandbox Storage", userEmail = "sandbox@example.com", additionalConfig = {}) {
|
|
325
|
+
const config = {
|
|
326
|
+
userName,
|
|
327
|
+
userEmail,
|
|
328
|
+
options: {
|
|
329
|
+
"core.autocrlf": "false",
|
|
330
|
+
// Important for cross-platform compatibility
|
|
331
|
+
"core.filemode": "false",
|
|
332
|
+
// Important for cross-platform compatibility
|
|
333
|
+
...additionalConfig
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
return this.setConfig(config, "local");
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Add a remote repository
|
|
340
|
+
* @param name - Remote name (e.g., 'origin')
|
|
341
|
+
* @param url - Remote repository URL
|
|
342
|
+
* @returns Result of the operation
|
|
343
|
+
*/
|
|
344
|
+
async addRemote(name, url) {
|
|
345
|
+
try {
|
|
346
|
+
if (!this.repo) {
|
|
347
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
348
|
+
}
|
|
349
|
+
await this.repo.addRemote(name, url);
|
|
350
|
+
return {
|
|
351
|
+
success: true,
|
|
352
|
+
message: `Remote '${name}' added successfully`,
|
|
353
|
+
name,
|
|
354
|
+
url
|
|
355
|
+
};
|
|
356
|
+
} catch (error) {
|
|
357
|
+
return {
|
|
358
|
+
success: false,
|
|
359
|
+
message: `Failed to add remote '${name}': ${error.message}`
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Remove a remote repository
|
|
365
|
+
* @param name - Remote name to remove
|
|
366
|
+
* @returns Result of the operation
|
|
367
|
+
*/
|
|
368
|
+
async removeRemote(name) {
|
|
369
|
+
try {
|
|
370
|
+
if (!this.repo) {
|
|
371
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
372
|
+
}
|
|
373
|
+
await this.repo.removeRemote(name);
|
|
374
|
+
return {
|
|
375
|
+
success: true,
|
|
376
|
+
message: `Remote '${name}' removed successfully`,
|
|
377
|
+
name
|
|
378
|
+
};
|
|
379
|
+
} catch (error) {
|
|
380
|
+
return {
|
|
381
|
+
success: false,
|
|
382
|
+
message: `Failed to remove remote '${name}': ${error.message}`
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* List all remote repositories
|
|
388
|
+
* @returns Result containing the list of remotes
|
|
389
|
+
*/
|
|
390
|
+
async listRemotes() {
|
|
391
|
+
try {
|
|
392
|
+
if (!this.repo) {
|
|
393
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
394
|
+
}
|
|
395
|
+
const remotes = await this.repo.getRemotes(true);
|
|
396
|
+
return {
|
|
397
|
+
success: true,
|
|
398
|
+
remotes: remotes.map((remote) => ({
|
|
399
|
+
name: remote.name,
|
|
400
|
+
refs: remote.refs.fetch,
|
|
401
|
+
pushUrl: remote.refs.push
|
|
402
|
+
}))
|
|
403
|
+
};
|
|
404
|
+
} catch (error) {
|
|
405
|
+
return {
|
|
406
|
+
success: false,
|
|
407
|
+
message: `Failed to list remotes: ${error.message}`,
|
|
408
|
+
remotes: []
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Push changes to a remote repository
|
|
414
|
+
* @param remote - Remote name (defaults to 'origin')
|
|
415
|
+
* @param branch - Branch to push (defaults to current branch)
|
|
416
|
+
* @param options - Additional options
|
|
417
|
+
* @returns Result of the operation
|
|
418
|
+
*/
|
|
419
|
+
async push(remote = "origin", branch = "main", options = {}) {
|
|
420
|
+
try {
|
|
421
|
+
if (!this.repo) {
|
|
422
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
423
|
+
}
|
|
424
|
+
const remotes = await this.listRemotes();
|
|
425
|
+
const remoteExists = remotes.remotes.some((r) => r.name === remote);
|
|
426
|
+
if (!remoteExists) {
|
|
427
|
+
return {
|
|
428
|
+
success: false,
|
|
429
|
+
message: `Remote '${remote}' does not exist`
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (!branch || branch === "current") {
|
|
433
|
+
try {
|
|
434
|
+
const status = await this.repo.status();
|
|
435
|
+
branch = status.current || "main";
|
|
436
|
+
} catch {
|
|
437
|
+
branch = "main";
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const pushOptions = {};
|
|
441
|
+
if (options.force) {
|
|
442
|
+
pushOptions["--force"] = null;
|
|
443
|
+
}
|
|
444
|
+
if (options.setUpstream !== false) {
|
|
445
|
+
pushOptions["-u"] = null;
|
|
446
|
+
}
|
|
447
|
+
await this.repo.push(remote, branch, pushOptions);
|
|
448
|
+
return {
|
|
449
|
+
success: true,
|
|
450
|
+
message: `Successfully pushed to ${remote}/${branch}`,
|
|
451
|
+
remote,
|
|
452
|
+
branch
|
|
453
|
+
};
|
|
454
|
+
} catch (error) {
|
|
455
|
+
if (error.message.includes("could not find remote") || error.message.includes("does not appear to be a git repository")) {
|
|
456
|
+
return {
|
|
457
|
+
success: false,
|
|
458
|
+
message: `Remote '${remote}' does not exist or is not a valid git repository`
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
if (error.message.includes("authentication failed")) {
|
|
462
|
+
return {
|
|
463
|
+
success: false,
|
|
464
|
+
message: `Authentication failed. Please check your credentials.`
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
success: false,
|
|
469
|
+
message: `Failed to push to ${remote}/${branch}: ${error.message}`
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Pull changes from a remote repository
|
|
475
|
+
* @param remote - Remote name (defaults to 'origin')
|
|
476
|
+
* @param branch - Branch to pull from (defaults to current branch)
|
|
477
|
+
* @param options - Additional options
|
|
478
|
+
* @returns Result of the operation
|
|
479
|
+
*/
|
|
480
|
+
async pull(remote = "origin", branch = "main", options = {}) {
|
|
481
|
+
try {
|
|
482
|
+
if (!this.repo) {
|
|
483
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
484
|
+
}
|
|
485
|
+
const remotes = await this.listRemotes();
|
|
486
|
+
const remoteExists = remotes.remotes.some((r) => r.name === remote);
|
|
487
|
+
if (!remoteExists) {
|
|
488
|
+
return {
|
|
489
|
+
success: false,
|
|
490
|
+
message: `Remote '${remote}' does not exist`
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
if (!branch || branch === "current") {
|
|
494
|
+
try {
|
|
495
|
+
const status = await this.repo.status();
|
|
496
|
+
branch = status.current || "main";
|
|
497
|
+
} catch {
|
|
498
|
+
branch = "main";
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
const pullOptions = [];
|
|
502
|
+
if (options.allowUnrelatedHistories) {
|
|
503
|
+
pullOptions.push("--allow-unrelated-histories");
|
|
504
|
+
}
|
|
505
|
+
await this.repo.pull(remote, branch, pullOptions);
|
|
506
|
+
return {
|
|
507
|
+
success: true,
|
|
508
|
+
message: `Successfully pulled from ${remote}/${branch}`,
|
|
509
|
+
remote,
|
|
510
|
+
branch
|
|
511
|
+
};
|
|
512
|
+
} catch (error) {
|
|
513
|
+
if (error.message.includes("could not find remote")) {
|
|
514
|
+
return {
|
|
515
|
+
success: false,
|
|
516
|
+
message: `Remote '${remote}' does not exist`
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
if (error.message.includes("authentication failed")) {
|
|
520
|
+
return {
|
|
521
|
+
success: false,
|
|
522
|
+
message: `Authentication failed. Please check your credentials.`
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
if (error.message.includes("conflict")) {
|
|
526
|
+
return {
|
|
527
|
+
success: false,
|
|
528
|
+
message: `Merge conflict occurred. Please resolve conflicts manually.`
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
success: false,
|
|
533
|
+
message: `Failed to pull from ${remote}/${branch}: ${error.message}`
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Fetch changes from a remote repository without merging
|
|
539
|
+
* @param remote - Remote name (defaults to 'origin')
|
|
540
|
+
* @param branch - Branch to fetch (defaults to 'main')
|
|
541
|
+
* @param options - Additional options
|
|
542
|
+
* @returns Result of the operation
|
|
543
|
+
*/
|
|
544
|
+
async fetch(remote = "origin", branch = "main", options = {}) {
|
|
545
|
+
try {
|
|
546
|
+
if (!this.repo) {
|
|
547
|
+
throw new Error("Repository not initialized. Call initialize() first.");
|
|
548
|
+
}
|
|
549
|
+
const remotes = await this.listRemotes();
|
|
550
|
+
const remoteExists = remotes.remotes.some((r) => r.name === remote);
|
|
551
|
+
if (!remoteExists) {
|
|
552
|
+
return {
|
|
553
|
+
success: false,
|
|
554
|
+
message: `Remote '${remote}' does not exist`
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
const fetchOptions = {};
|
|
558
|
+
if (options.prune) {
|
|
559
|
+
fetchOptions["--prune"] = null;
|
|
560
|
+
}
|
|
561
|
+
await this.repo.fetch(remote, branch, fetchOptions);
|
|
562
|
+
return {
|
|
563
|
+
success: true,
|
|
564
|
+
message: `Successfully fetched from ${remote}/${branch}`,
|
|
565
|
+
remote,
|
|
566
|
+
branch
|
|
567
|
+
};
|
|
568
|
+
} catch (error) {
|
|
569
|
+
if (error.message.includes("could not find remote")) {
|
|
570
|
+
return {
|
|
571
|
+
success: false,
|
|
572
|
+
message: `Remote '${remote}' does not exist`
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
if (error.message.includes("authentication failed")) {
|
|
576
|
+
return {
|
|
577
|
+
success: false,
|
|
578
|
+
message: `Authentication failed. Please check your credentials.`
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
return {
|
|
582
|
+
success: false,
|
|
583
|
+
message: `Failed to fetch from ${remote}/${branch}: ${error.message}`
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Clone a remote repository
|
|
589
|
+
* @param url - Repository URL to clone
|
|
590
|
+
* @param targetPath - Directory to clone into (optional)
|
|
591
|
+
* @param options - Additional options
|
|
592
|
+
* @returns Result of the operation
|
|
593
|
+
*/
|
|
594
|
+
async clone(url, targetPath = null, options = {}) {
|
|
595
|
+
try {
|
|
596
|
+
const clonePath = targetPath || this.repoPath;
|
|
597
|
+
const cloneOptions = {};
|
|
598
|
+
if (options.bare) {
|
|
599
|
+
cloneOptions["--bare"] = null;
|
|
600
|
+
}
|
|
601
|
+
if (options.branch) {
|
|
602
|
+
cloneOptions["--branch"] = options.branch;
|
|
603
|
+
}
|
|
604
|
+
if (options.depth) {
|
|
605
|
+
cloneOptions["--depth"] = options.depth.toString();
|
|
606
|
+
}
|
|
607
|
+
const git = simpleGit();
|
|
608
|
+
await git.clone(url, clonePath, cloneOptions);
|
|
609
|
+
if (!targetPath) {
|
|
610
|
+
this.repoPath = clonePath;
|
|
611
|
+
this.repo = simpleGit(clonePath);
|
|
612
|
+
}
|
|
613
|
+
return {
|
|
614
|
+
success: true,
|
|
615
|
+
message: `Repository cloned successfully from ${url}`,
|
|
616
|
+
url,
|
|
617
|
+
path: clonePath
|
|
618
|
+
};
|
|
619
|
+
} catch (error) {
|
|
620
|
+
return {
|
|
621
|
+
success: false,
|
|
622
|
+
message: `Failed to clone repository from ${url}: ${error.message}`
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
listFiles() {
|
|
627
|
+
return new Promise((resolve) => {
|
|
628
|
+
try {
|
|
629
|
+
const files = [];
|
|
630
|
+
const traverse = (dir, relativePath = "") => {
|
|
631
|
+
const items = fs.readdirSync(dir);
|
|
632
|
+
items.forEach((item) => {
|
|
633
|
+
const itemPath = path.join(dir, item);
|
|
634
|
+
const itemRelativePath = path.join(relativePath, item);
|
|
635
|
+
if (fs.statSync(itemPath).isDirectory()) {
|
|
636
|
+
traverse(itemPath, itemRelativePath);
|
|
637
|
+
} else {
|
|
638
|
+
files.push(itemRelativePath);
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
};
|
|
642
|
+
traverse(this.repoPath);
|
|
643
|
+
resolve(files.filter((file) => !file.startsWith(".git")));
|
|
644
|
+
} catch (error) {
|
|
645
|
+
resolve([]);
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
var index_default = Storage;
|
|
651
|
+
export {
|
|
652
|
+
Storage,
|
|
653
|
+
index_default as default
|
|
654
|
+
};
|
|
655
|
+
//# sourceMappingURL=index.mjs.map
|