@morphllm/gitmorph-sdk 0.2.1

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/api.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ interface RequestOptions {
2
+ host: string;
3
+ token: string;
4
+ body?: unknown;
5
+ params?: Record<string, string>;
6
+ }
7
+ export declare function apiRequest<T = unknown>(method: string, path: string, options: RequestOptions): Promise<T>;
8
+ export declare function apiRequestRaw(method: string, path: string, options: RequestOptions): Promise<string>;
9
+ export {};
10
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAmCD,wBAAsB,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,CAAC,CAAC,CAcZ;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,CAAC,CAWjB"}
@@ -0,0 +1,13 @@
1
+ import { GitMorphRepo } from "./repo.js";
2
+ import type { GitMorphOptions, Repository, MirrorOptions, MirrorResult, GrepAllOptions, GrepAllResult } from "./types.js";
3
+ export declare class GitMorph {
4
+ private token;
5
+ private host;
6
+ constructor(options?: GitMorphOptions);
7
+ private get auth();
8
+ repo(slug: string): GitMorphRepo;
9
+ getRepositoryInfo(slug: string): Promise<Repository>;
10
+ mirror(source: string, options?: MirrorOptions): Promise<MirrorResult>;
11
+ grepAll(options: GrepAllOptions): Promise<GrepAllResult>;
12
+ }
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EAEd,MAAM,YAAY,CAAC;AAyBpB,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,IAAI,CAAS;gBAET,OAAO,CAAC,EAAE,eAAe;IAMrC,OAAO,KAAK,IAAI,GAEf;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAK1B,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAKpD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAMtE,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CA0B/D"}
@@ -0,0 +1,8 @@
1
+ export declare function resolveAuth(options?: {
2
+ token?: string;
3
+ host?: string;
4
+ }): {
5
+ token: string;
6
+ host: string;
7
+ };
8
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA6BA,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAoBA"}
@@ -0,0 +1,18 @@
1
+ export declare class GitMorphError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class AuthenticationError extends GitMorphError {
5
+ constructor(message?: string);
6
+ }
7
+ export declare class ApiError extends GitMorphError {
8
+ status: number;
9
+ url: string;
10
+ constructor(message: string, status: number, url: string);
11
+ }
12
+ export declare class MirrorError extends GitMorphError {
13
+ constructor(message: string);
14
+ }
15
+ export declare class GrepError extends GitMorphError {
16
+ constructor(message: string);
17
+ }
18
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,aAAa;gBACxC,OAAO,CAAC,EAAE,MAAM;CAO7B;AAED,qBAAa,QAAS,SAAQ,aAAa;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;gBAEA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAMzD;AAED,qBAAa,WAAY,SAAQ,aAAa;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,SAAU,SAAQ,aAAa;gBAC9B,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,5 @@
1
+ export { GitMorph } from "./client.js";
2
+ export { GitMorphRepo } from "./repo.js";
3
+ export type { GitMorphOptions, Repository, User, MirrorOptions, MirrorResult, LineRange, ReadFileOptions, FileContent, GrepOptions, GrepSubmatch, GrepMatch, GrepResult, GrepAllOptions, GrepAllMatch, GrepAllResult, FileContentEntry, GlobOptions, GlobResult, ListDirOptions, ListDirEntry, ListDirResult, ListBranchesOptions, Branch, BranchCommit, ListCommitsOptions, Commit, CommitUser, } from "./types.js";
4
+ export { GitMorphError, AuthenticationError, ApiError, MirrorError, GrepError, } from "./errors.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EACV,eAAe,EACf,UAAU,EACV,IAAI,EACJ,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAU,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,MAAM,EACN,YAAY,EACZ,kBAAkB,EAClB,MAAM,EACN,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,QAAQ,EACR,WAAW,EACX,SAAS,GACV,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,547 @@
1
+ // src/config.ts
2
+ import { readFileSync } from "fs";
3
+ import { join } from "path";
4
+
5
+ // src/errors.ts
6
+ class GitMorphError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "GitMorphError";
10
+ }
11
+ }
12
+
13
+ class AuthenticationError extends GitMorphError {
14
+ constructor(message) {
15
+ super(message ?? "Not authenticated. Provide a token or configure ~/.config/gm/config.json");
16
+ this.name = "AuthenticationError";
17
+ }
18
+ }
19
+
20
+ class ApiError extends GitMorphError {
21
+ status;
22
+ url;
23
+ constructor(message, status, url) {
24
+ super(message);
25
+ this.name = "ApiError";
26
+ this.status = status;
27
+ this.url = url;
28
+ }
29
+ }
30
+
31
+ class MirrorError extends GitMorphError {
32
+ constructor(message) {
33
+ super(message);
34
+ this.name = "MirrorError";
35
+ }
36
+ }
37
+
38
+ class GrepError extends GitMorphError {
39
+ constructor(message) {
40
+ super(message);
41
+ this.name = "GrepError";
42
+ }
43
+ }
44
+
45
+ // src/config.ts
46
+ var DEFAULT_HOST = "gitmorph.com";
47
+ function configPath() {
48
+ const dir = process.env.GM_CONFIG_DIR || join(process.env.HOME || "", ".config", "gm");
49
+ return join(dir, "config.json");
50
+ }
51
+ function loadConfig() {
52
+ try {
53
+ const raw = readFileSync(configPath(), "utf-8");
54
+ return JSON.parse(raw);
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+ function resolveAuth(options) {
60
+ const token = options?.token || process.env.GM_TOKEN || loadConfig()?.token || null;
61
+ if (!token) {
62
+ throw new AuthenticationError;
63
+ }
64
+ const host = options?.host || process.env.GM_HOST || loadConfig()?.host || DEFAULT_HOST;
65
+ return { token, host };
66
+ }
67
+
68
+ // src/api.ts
69
+ function buildUrl(path, options) {
70
+ const baseUrl = `https://${options.host}/api/v1`;
71
+ const url = new URL(path.startsWith("/") ? `${baseUrl}${path}` : `${baseUrl}/${path}`);
72
+ if (options.params) {
73
+ for (const [key, value] of Object.entries(options.params)) {
74
+ url.searchParams.set(key, value);
75
+ }
76
+ }
77
+ return url;
78
+ }
79
+ function buildHeaders(options) {
80
+ const headers = {
81
+ Authorization: `token ${options.token}`
82
+ };
83
+ if (options.body) {
84
+ headers["Content-Type"] = "application/json";
85
+ headers["Accept"] = "application/json";
86
+ } else {
87
+ headers["Accept"] = "application/json";
88
+ }
89
+ return headers;
90
+ }
91
+ async function handleErrorResponse(res, url) {
92
+ let message = `API request failed: ${res.status}`;
93
+ try {
94
+ const body = await res.json();
95
+ if (body.message)
96
+ message = body.message;
97
+ } catch {}
98
+ throw new ApiError(message, res.status, url.toString());
99
+ }
100
+ async function apiRequest(method, path, options) {
101
+ const url = buildUrl(path, options);
102
+ const headers = buildHeaders(options);
103
+ const res = await fetch(url.toString(), {
104
+ method,
105
+ headers,
106
+ body: options.body ? JSON.stringify(options.body) : undefined
107
+ });
108
+ if (!res.ok)
109
+ return handleErrorResponse(res, url);
110
+ if (res.status === 204)
111
+ return;
112
+ return await res.json();
113
+ }
114
+ async function apiRequestRaw(method, path, options) {
115
+ const url = buildUrl(path, options);
116
+ const headers = {
117
+ Authorization: `token ${options.token}`
118
+ };
119
+ const res = await fetch(url.toString(), { method, headers });
120
+ if (!res.ok)
121
+ return handleErrorResponse(res, url);
122
+ return res.text();
123
+ }
124
+
125
+ // src/mirror.ts
126
+ var SERVICE_MAP = {
127
+ github: "github",
128
+ gitea: "gitea",
129
+ gitlab: "gitlab"
130
+ };
131
+ function parseSource(source, options) {
132
+ let cloneAddr;
133
+ let service;
134
+ let owner;
135
+ let repoName;
136
+ if (source.startsWith("https://") || source.startsWith("http://")) {
137
+ const url = new URL(source);
138
+ const pathParts = url.pathname.replace(/^\//, "").replace(/\.git$/, "").split("/");
139
+ if (pathParts.length < 2 || !pathParts[0] || !pathParts[1]) {
140
+ throw new MirrorError(`Cannot parse source URL: "${source}". Expected "https://host/owner/repo".`);
141
+ }
142
+ owner = pathParts[0];
143
+ repoName = pathParts[1];
144
+ cloneAddr = `${url.origin}/${owner}/${repoName}.git`;
145
+ const hostname = url.hostname;
146
+ if (hostname.includes("github"))
147
+ service = SERVICE_MAP.github;
148
+ else if (hostname.includes("gitlab"))
149
+ service = SERVICE_MAP.gitlab;
150
+ else if (hostname.includes("gitea"))
151
+ service = SERVICE_MAP.gitea;
152
+ else
153
+ service = SERVICE_MAP[options?.source ?? "github"];
154
+ } else {
155
+ const parts = source.replace(/\.git$/, "").split("/");
156
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
157
+ throw new MirrorError(`Invalid source: "${source}". Expected "owner/repo" or a full URL.`);
158
+ }
159
+ owner = parts[0];
160
+ repoName = parts[1];
161
+ const serviceKey = options?.source ?? "github";
162
+ service = SERVICE_MAP[serviceKey];
163
+ const hostMap = {
164
+ github: "https://github.com",
165
+ gitlab: "https://gitlab.com",
166
+ gitea: "https://gitea.com"
167
+ };
168
+ cloneAddr = `${hostMap[serviceKey]}/${owner}/${repoName}.git`;
169
+ }
170
+ return {
171
+ cloneAddr,
172
+ service,
173
+ repoName: options?.repoName ?? repoName,
174
+ owner
175
+ };
176
+ }
177
+ async function mirrorRepository(source, auth, options) {
178
+ const { cloneAddr, service, repoName } = parseSource(source, options);
179
+ const body = {
180
+ clone_addr: cloneAddr,
181
+ repo_name: repoName,
182
+ service,
183
+ mirror: true,
184
+ private: options?.private ?? false,
185
+ wiki: options?.wiki ?? false,
186
+ issues: options?.issues ?? false,
187
+ pull_requests: options?.pullRequests ?? false,
188
+ releases: options?.releases ?? false,
189
+ labels: options?.labels ?? false,
190
+ milestones: options?.milestones ?? false,
191
+ lfs: options?.lfs ?? false
192
+ };
193
+ try {
194
+ return await apiRequest("POST", "/repos/migrate", {
195
+ ...auth,
196
+ body
197
+ });
198
+ } catch (err) {
199
+ if (err instanceof Error && "status" in err)
200
+ throw err;
201
+ throw new MirrorError(err.message);
202
+ }
203
+ }
204
+
205
+ // src/repo.ts
206
+ class GitMorphRepo {
207
+ owner;
208
+ name;
209
+ auth;
210
+ treeCache = new Map;
211
+ defaultRef;
212
+ repoId;
213
+ constructor(owner, name, auth) {
214
+ this.owner = owner;
215
+ this.name = name;
216
+ this.auth = auth;
217
+ }
218
+ async resolveRepoInfo() {
219
+ if (this.defaultRef && this.repoId) {
220
+ return { ref: this.defaultRef, id: this.repoId };
221
+ }
222
+ const info = await apiRequest("GET", `/repos/${this.owner}/${this.name}`, this.auth);
223
+ this.defaultRef = info.default_branch;
224
+ this.repoId = info.id;
225
+ return { ref: this.defaultRef, id: this.repoId };
226
+ }
227
+ async resolveRef(ref) {
228
+ if (ref)
229
+ return ref;
230
+ const info = await this.resolveRepoInfo();
231
+ return info.ref;
232
+ }
233
+ async resolveRepoId() {
234
+ const info = await this.resolveRepoInfo();
235
+ return info.id;
236
+ }
237
+ async fetchTree(ref) {
238
+ if (this.treeCache.has(ref)) {
239
+ return { entries: this.treeCache.get(ref), truncated: false };
240
+ }
241
+ const encodedRef = encodeURIComponent(ref);
242
+ const firstPage = await apiRequest("GET", `/repos/${this.owner}/${this.name}/git/trees/${encodedRef}`, { ...this.auth, params: { recursive: "true", per_page: "10000" } });
243
+ let allEntries = [...firstPage.tree];
244
+ let truncated = firstPage.truncated;
245
+ if (truncated && firstPage.total_count && firstPage.total_count > allEntries.length) {
246
+ let page = 2;
247
+ while (allEntries.length < firstPage.total_count) {
248
+ const nextPage = await apiRequest("GET", `/repos/${this.owner}/${this.name}/git/trees/${encodedRef}`, { ...this.auth, params: { recursive: "true", per_page: "10000", page: String(page) } });
249
+ if (!nextPage.tree.length)
250
+ break;
251
+ allEntries = allEntries.concat(nextPage.tree);
252
+ truncated = nextPage.truncated;
253
+ page++;
254
+ }
255
+ }
256
+ this.treeCache.set(ref, allEntries);
257
+ return { entries: allEntries, truncated };
258
+ }
259
+ async fetchRaw(path, ref) {
260
+ const encodedRef = encodeURIComponent(ref);
261
+ return apiRequestRaw("GET", `/repos/${this.owner}/${this.name}/raw/${path}`, { ...this.auth, params: { ref: encodedRef } });
262
+ }
263
+ async readFile(path, options) {
264
+ const ref = await this.resolveRef(options?.ref);
265
+ if (options?.lines) {
266
+ for (const range of options.lines) {
267
+ if (range.start < 1) {
268
+ throw new GitMorphError(`LineRange.start must be >= 1, got ${range.start}`);
269
+ }
270
+ if (range.end < range.start) {
271
+ throw new GitMorphError(`LineRange.end (${range.end}) must be >= start (${range.start})`);
272
+ }
273
+ }
274
+ }
275
+ const rawContent = await this.fetchRaw(path, ref);
276
+ const allLines = rawContent.split(`
277
+ `);
278
+ const totalLines = allLines.length;
279
+ if (!options?.lines) {
280
+ return { path, content: rawContent, totalLines };
281
+ }
282
+ const clampedRanges = [];
283
+ const extracted = [];
284
+ for (const range of options.lines) {
285
+ const start = Math.min(range.start, totalLines);
286
+ const end = Math.min(range.end, totalLines);
287
+ clampedRanges.push({ start, end });
288
+ extracted.push(allLines.slice(start - 1, end).join(`
289
+ `));
290
+ }
291
+ return {
292
+ path,
293
+ content: extracted.join(`
294
+ `),
295
+ totalLines,
296
+ lines: clampedRanges
297
+ };
298
+ }
299
+ async grep(options) {
300
+ if (!options.pattern) {
301
+ throw new GrepError("pattern is required");
302
+ }
303
+ const repoId = await this.resolveRepoId();
304
+ const params = {
305
+ q: options.pattern,
306
+ repo_id: String(repoId)
307
+ };
308
+ if (options.language)
309
+ params.l = options.language;
310
+ if (options.maxMatches)
311
+ params.limit = String(Math.min(options.maxMatches, 50));
312
+ if (options.page)
313
+ params.page = String(options.page);
314
+ const response = await apiRequest("GET", "/repos/code/search", { ...this.auth, params });
315
+ if (!response.ok) {
316
+ throw new GrepError("Code search returned ok=false");
317
+ }
318
+ const matches = [];
319
+ const caseSensitive = options.caseSensitive ?? false;
320
+ const flags = caseSensitive ? "g" : "gi";
321
+ let regex = null;
322
+ try {
323
+ regex = new RegExp(options.pattern, flags);
324
+ } catch {}
325
+ for (const item of response.data) {
326
+ for (const line of item.lines) {
327
+ const plainContent = line.content.replace(/<[^>]*>/g, "");
328
+ const submatches = [];
329
+ if (regex) {
330
+ regex.lastIndex = 0;
331
+ let m;
332
+ while ((m = regex.exec(plainContent)) !== null) {
333
+ submatches.push({
334
+ match: m[0],
335
+ startOffset: m.index,
336
+ endOffset: m.index + m[0].length
337
+ });
338
+ if (!regex.global)
339
+ break;
340
+ }
341
+ }
342
+ matches.push({
343
+ path: item.filename,
344
+ lineNumber: line.num,
345
+ lineContent: plainContent,
346
+ submatches
347
+ });
348
+ }
349
+ }
350
+ return { matches, total: response.total };
351
+ }
352
+ async getFileContents(paths, options) {
353
+ if (paths.length === 0)
354
+ return [];
355
+ const ref = await this.resolveRef(options?.ref);
356
+ const encodedBody = JSON.stringify({ files: paths });
357
+ const raw = await apiRequest("GET", `/repos/${this.owner}/${this.name}/file-contents`, {
358
+ ...this.auth,
359
+ params: { ref, body: encodedBody }
360
+ });
361
+ return raw.map((item) => {
362
+ if (!item)
363
+ return null;
364
+ return {
365
+ name: item.name,
366
+ path: item.path,
367
+ sha: item.sha,
368
+ size: item.size,
369
+ encoding: item.encoding,
370
+ content: item.content ? item.encoding === "base64" ? Buffer.from(item.content, "base64").toString("utf-8") : item.content : null,
371
+ downloadUrl: item.download_url
372
+ };
373
+ });
374
+ }
375
+ async glob(options) {
376
+ const ref = await this.resolveRef(options.ref);
377
+ const encodedRef = encodeURIComponent(ref);
378
+ const params = new URLSearchParams;
379
+ for (const p of options.patterns) {
380
+ params.append("pattern", p);
381
+ }
382
+ if (options.prefix)
383
+ params.set("prefix", options.prefix);
384
+ if (options.sizes === false)
385
+ params.set("sizes", "false");
386
+ if (options.limit)
387
+ params.set("limit", String(options.limit));
388
+ const url = `/repos/${this.owner}/${this.name}/git/trees/${encodedRef}/glob?${params.toString()}`;
389
+ const data = await apiRequest("GET", url, this.auth);
390
+ return {
391
+ entries: data.tree,
392
+ truncated: data.truncated
393
+ };
394
+ }
395
+ async listBranches(options) {
396
+ const params = {};
397
+ if (options?.page)
398
+ params.page = String(options.page);
399
+ if (options?.limit)
400
+ params.limit = String(options.limit);
401
+ const raw = await apiRequest("GET", `/repos/${this.owner}/${this.name}/branches`, { ...this.auth, params });
402
+ return raw.map((b) => ({
403
+ name: b.name,
404
+ commit: {
405
+ id: b.commit?.id ?? "",
406
+ message: b.commit?.message ?? "",
407
+ url: b.commit?.url ?? "",
408
+ timestamp: b.commit?.timestamp ?? "",
409
+ author: {
410
+ name: b.commit?.author?.name ?? "",
411
+ email: b.commit?.author?.email ?? ""
412
+ }
413
+ },
414
+ protected: b.protected ?? false
415
+ }));
416
+ }
417
+ async listCommits(options) {
418
+ const params = {
419
+ stat: "false",
420
+ verification: "false",
421
+ files: "false"
422
+ };
423
+ if (options?.sha)
424
+ params.sha = options.sha;
425
+ if (options?.path)
426
+ params.path = options.path;
427
+ if (options?.since)
428
+ params.since = options.since;
429
+ if (options?.until)
430
+ params.until = options.until;
431
+ if (options?.page)
432
+ params.page = String(options.page);
433
+ if (options?.limit)
434
+ params.limit = String(options.limit);
435
+ const raw = await apiRequest("GET", `/repos/${this.owner}/${this.name}/commits`, { ...this.auth, params });
436
+ return raw.map((c) => ({
437
+ sha: c.sha ?? "",
438
+ message: c.commit?.message ?? "",
439
+ author: {
440
+ name: c.commit?.author?.name ?? "",
441
+ email: c.commit?.author?.email ?? "",
442
+ date: c.commit?.author?.date ?? ""
443
+ },
444
+ committer: {
445
+ name: c.commit?.committer?.name ?? "",
446
+ email: c.commit?.committer?.email ?? "",
447
+ date: c.commit?.committer?.date ?? ""
448
+ },
449
+ html_url: c.html_url ?? "",
450
+ parents: (c.parents ?? []).map((p) => ({
451
+ sha: p.sha ?? "",
452
+ url: p.url ?? ""
453
+ }))
454
+ }));
455
+ }
456
+ async listDir(options) {
457
+ const ref = await this.resolveRef(options?.ref);
458
+ const { entries: treeEntries, truncated } = await this.fetchTree(ref);
459
+ const prefix = options?.path?.replace(/\/$/, "") ?? "";
460
+ const filtered = treeEntries.filter((e) => {
461
+ if (prefix && !e.path.startsWith(prefix))
462
+ return false;
463
+ if (!options?.recursive) {
464
+ const relative = prefix ? e.path.slice(prefix.length).replace(/^\//, "") : e.path;
465
+ if (relative.includes("/"))
466
+ return false;
467
+ }
468
+ return true;
469
+ });
470
+ const entries = filtered.map((e) => ({
471
+ path: e.path,
472
+ type: e.type === "blob" ? "file" : "dir",
473
+ size: e.size,
474
+ mode: e.mode
475
+ }));
476
+ return { entries, truncated };
477
+ }
478
+ }
479
+
480
+ // src/utils.ts
481
+ function parseRepoSlug(input) {
482
+ const cleaned = input.replace(/\.git$/, "");
483
+ const parts = cleaned.split("/");
484
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
485
+ throw new GitMorphError(`Invalid repo format: "${input}". Expected "owner/repo".`);
486
+ }
487
+ return { owner: parts[0], name: parts[1] };
488
+ }
489
+
490
+ // src/client.ts
491
+ class GitMorph {
492
+ token;
493
+ host;
494
+ constructor(options) {
495
+ const auth = resolveAuth(options);
496
+ this.token = auth.token;
497
+ this.host = auth.host;
498
+ }
499
+ get auth() {
500
+ return { token: this.token, host: this.host };
501
+ }
502
+ repo(slug) {
503
+ const { owner, name } = parseRepoSlug(slug);
504
+ return new GitMorphRepo(owner, name, this.auth);
505
+ }
506
+ async getRepositoryInfo(slug) {
507
+ const { owner, name } = parseRepoSlug(slug);
508
+ return apiRequest("GET", `/repos/${owner}/${name}`, this.auth);
509
+ }
510
+ async mirror(source, options) {
511
+ const repository = await mirrorRepository(source, this.auth, options);
512
+ const repo = this.repo(repository.full_name);
513
+ return { repository, repo };
514
+ }
515
+ async grepAll(options) {
516
+ const params = {
517
+ q: options.pattern
518
+ };
519
+ if (options.language)
520
+ params.l = options.language;
521
+ if (options.page)
522
+ params.page = String(options.page);
523
+ if (options.limit)
524
+ params.limit = String(Math.min(options.limit, 50));
525
+ if (options.sortByStars)
526
+ params.sort_by_stars = "true";
527
+ const response = await apiRequest("GET", "/repos/code/search", { ...this.auth, params });
528
+ const matches = response.data.map((item) => ({
529
+ repoId: item.repo_id,
530
+ repoName: item.repo_name,
531
+ filename: item.filename,
532
+ commitId: item.commit_id,
533
+ language: item.language,
534
+ lines: item.lines.map((l) => ({ num: l.num, content: l.content }))
535
+ }));
536
+ return { matches, total: response.total };
537
+ }
538
+ }
539
+ export {
540
+ MirrorError,
541
+ GrepError,
542
+ GitMorphRepo,
543
+ GitMorphError,
544
+ GitMorph,
545
+ AuthenticationError,
546
+ ApiError
547
+ };
@@ -0,0 +1,6 @@
1
+ import type { Repository, MirrorOptions } from "./types.js";
2
+ export declare function mirrorRepository(source: string, auth: {
3
+ token: string;
4
+ host: string;
5
+ }, options?: MirrorOptions): Promise<Repository>;
6
+ //# sourceMappingURL=mirror.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror.d.ts","sourceRoot":"","sources":["../src/mirror.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmE5D,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrC,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,UAAU,CAAC,CA2BrB"}
package/dist/repo.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import type { ReadFileOptions, FileContent, GrepOptions, GrepResult, FileContentEntry, GlobOptions, GlobResult, ListDirOptions, ListDirResult, ListBranchesOptions, Branch, ListCommitsOptions, Commit } from "./types.js";
2
+ export declare class GitMorphRepo {
3
+ private owner;
4
+ private name;
5
+ private auth;
6
+ private treeCache;
7
+ private defaultRef?;
8
+ private repoId?;
9
+ constructor(owner: string, name: string, auth: {
10
+ token: string;
11
+ host: string;
12
+ });
13
+ private resolveRepoInfo;
14
+ private resolveRef;
15
+ private resolveRepoId;
16
+ private fetchTree;
17
+ private fetchRaw;
18
+ readFile(path: string, options?: ReadFileOptions): Promise<FileContent>;
19
+ grep(options: GrepOptions): Promise<GrepResult>;
20
+ getFileContents(paths: string[], options?: {
21
+ ref?: string;
22
+ }): Promise<(FileContentEntry | null)[]>;
23
+ glob(options: GlobOptions): Promise<GlobResult>;
24
+ listBranches(options?: ListBranchesOptions): Promise<Branch[]>;
25
+ listCommits(options?: ListCommitsOptions): Promise<Commit[]>;
26
+ listDir(options?: ListDirOptions): Promise<ListDirResult>;
27
+ }
28
+ //# sourceMappingURL=repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,eAAe,EACf,WAAW,EACX,WAAW,EAEX,UAAU,EAEV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,cAAc,EAEd,aAAa,EACb,mBAAmB,EACnB,MAAM,EAEN,kBAAkB,EAClB,MAAM,EAGP,MAAM,YAAY,CAAC;AAqCpB,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAkC;IAC9C,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAC,CAAS;gBAGtB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;YAOzB,eAAe;YAcf,UAAU;YAMV,aAAa;YAKb,SAAS;YAkCT,QAAQ;IAWhB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IA0CvE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAyE/C,eAAe,CACnB,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GACzB,OAAO,CAAC,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAC;IAmCjC,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAuB/C,YAAY,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA6B9D,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA0C5D,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAyBhE"}
@@ -0,0 +1,223 @@
1
+ export interface GitMorphOptions {
2
+ token?: string;
3
+ host?: string;
4
+ }
5
+ export interface User {
6
+ id: number;
7
+ login: string;
8
+ full_name: string;
9
+ email: string;
10
+ avatar_url: string;
11
+ created: string;
12
+ is_admin: boolean;
13
+ }
14
+ export interface Repository {
15
+ id: number;
16
+ owner: User;
17
+ name: string;
18
+ full_name: string;
19
+ description: string;
20
+ private: boolean;
21
+ fork: boolean;
22
+ mirror: boolean;
23
+ archived: boolean;
24
+ size: number;
25
+ stars_count: number;
26
+ forks_count: number;
27
+ open_issues_count: number;
28
+ default_branch: string;
29
+ created_at: string;
30
+ updated_at: string;
31
+ html_url: string;
32
+ ssh_url: string;
33
+ clone_url: string;
34
+ website: string;
35
+ has_issues: boolean;
36
+ has_wiki: boolean;
37
+ has_pull_requests: boolean;
38
+ language: string;
39
+ }
40
+ export interface MirrorOptions {
41
+ source?: "github" | "gitlab" | "gitea";
42
+ repoName?: string;
43
+ private?: boolean;
44
+ wiki?: boolean;
45
+ issues?: boolean;
46
+ pullRequests?: boolean;
47
+ releases?: boolean;
48
+ labels?: boolean;
49
+ milestones?: boolean;
50
+ lfs?: boolean;
51
+ }
52
+ export interface MirrorResult {
53
+ repository: Repository;
54
+ repo: import("./repo.js").GitMorphRepo;
55
+ }
56
+ /**
57
+ * 1-indexed, inclusive on both ends.
58
+ * `{ start: 1, end: 5 }` returns lines 1, 2, 3, 4, 5.
59
+ */
60
+ export interface LineRange {
61
+ start: number;
62
+ end: number;
63
+ }
64
+ export interface ReadFileOptions {
65
+ ref?: string;
66
+ lines?: LineRange[];
67
+ }
68
+ export interface FileContent {
69
+ path: string;
70
+ content: string;
71
+ totalLines: number;
72
+ lines?: LineRange[];
73
+ }
74
+ export interface GrepOptions {
75
+ pattern: string;
76
+ language?: string;
77
+ caseSensitive?: boolean;
78
+ maxMatches?: number;
79
+ page?: number;
80
+ }
81
+ export interface GrepSubmatch {
82
+ match: string;
83
+ startOffset: number;
84
+ endOffset: number;
85
+ }
86
+ export interface GrepMatch {
87
+ path: string;
88
+ lineNumber: number;
89
+ lineContent: string;
90
+ submatches: GrepSubmatch[];
91
+ }
92
+ export interface GrepResult {
93
+ matches: GrepMatch[];
94
+ total: number;
95
+ }
96
+ export interface GrepAllOptions {
97
+ pattern: string;
98
+ language?: string;
99
+ page?: number;
100
+ limit?: number;
101
+ sortByStars?: boolean;
102
+ }
103
+ export interface GrepAllMatch {
104
+ repoId: number;
105
+ repoName: string;
106
+ filename: string;
107
+ commitId: string;
108
+ language: string;
109
+ lines: {
110
+ num: number;
111
+ content: string;
112
+ }[];
113
+ }
114
+ export interface GrepAllResult {
115
+ matches: GrepAllMatch[];
116
+ total: number;
117
+ }
118
+ export interface FileContentEntry {
119
+ name: string;
120
+ path: string;
121
+ sha: string;
122
+ size: number;
123
+ encoding: string | null;
124
+ content: string | null;
125
+ downloadUrl: string | null;
126
+ }
127
+ export interface ListDirOptions {
128
+ path?: string;
129
+ ref?: string;
130
+ recursive?: boolean;
131
+ }
132
+ export interface ListDirEntry {
133
+ path: string;
134
+ type: "file" | "dir";
135
+ size?: number;
136
+ mode: string;
137
+ }
138
+ export interface ListDirResult {
139
+ entries: ListDirEntry[];
140
+ truncated: boolean;
141
+ }
142
+ export interface ListBranchesOptions {
143
+ /** Page number (1-indexed). */
144
+ page?: number;
145
+ /** Results per page (default determined by server, typically 50). */
146
+ limit?: number;
147
+ }
148
+ export interface BranchCommit {
149
+ id: string;
150
+ message: string;
151
+ url: string;
152
+ timestamp: string;
153
+ author: {
154
+ name: string;
155
+ email: string;
156
+ };
157
+ }
158
+ export interface Branch {
159
+ name: string;
160
+ commit: BranchCommit;
161
+ protected: boolean;
162
+ }
163
+ export interface ListCommitsOptions {
164
+ /** Branch name or SHA to list commits from. Defaults to the repo's default branch. */
165
+ sha?: string;
166
+ /** Only include commits that affect this file/directory path. */
167
+ path?: string;
168
+ /** ISO 8601 date — only commits after this date. */
169
+ since?: string;
170
+ /** ISO 8601 date — only commits before this date. */
171
+ until?: string;
172
+ /** Page number (1-indexed). */
173
+ page?: number;
174
+ /** Results per page (default determined by server, typically 50). */
175
+ limit?: number;
176
+ }
177
+ export interface CommitUser {
178
+ name: string;
179
+ email: string;
180
+ date: string;
181
+ }
182
+ export interface Commit {
183
+ sha: string;
184
+ message: string;
185
+ author: CommitUser;
186
+ committer: CommitUser;
187
+ html_url: string;
188
+ parents: {
189
+ sha: string;
190
+ url: string;
191
+ }[];
192
+ }
193
+ export interface GlobOptions {
194
+ /** Doublestar glob patterns, e.g. ["**\/*.ts"]. */
195
+ patterns: string[];
196
+ /** Branch, tag, or commit SHA. Defaults to the repo's default branch. */
197
+ ref?: string;
198
+ /** Optional directory prefix to narrow the search. */
199
+ prefix?: string;
200
+ /** Include file sizes (default true). Set false for faster responses. */
201
+ sizes?: boolean;
202
+ /** Maximum number of results (default 1000). */
203
+ limit?: number;
204
+ }
205
+ export interface GlobResult {
206
+ entries: TreeEntry[];
207
+ truncated: boolean;
208
+ }
209
+ export interface TreeEntry {
210
+ path: string;
211
+ mode: string;
212
+ type: "blob" | "tree" | "commit";
213
+ size?: number;
214
+ sha: string;
215
+ }
216
+ export interface TreeResponse {
217
+ sha: string;
218
+ tree: TreeEntry[];
219
+ truncated: boolean;
220
+ total_count?: number;
221
+ page?: number;
222
+ }
223
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function parseRepoSlug(input: string): {
2
+ owner: string;
3
+ name: string;
4
+ };
5
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAS5E"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@morphllm/gitmorph-sdk",
3
+ "version": "0.2.1",
4
+ "description": "TypeScript SDK for GitMorph",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "bun build ./src/index.ts --outdir dist --target node --format esm && tsc --emitDeclarationOnly --outDir dist",
20
+ "prepublishOnly": "bun run build"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "devDependencies": {
26
+ "bun-types": "latest",
27
+ "typescript": "^5.0.0"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/morphllm/gitmorph"
32
+ },
33
+ "license": "MIT"
34
+ }