@grove-dev/core 0.2.14 → 0.2.19

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.
Files changed (68) hide show
  1. package/README.md +2 -2
  2. package/dist/build-data.d.ts.map +1 -1
  3. package/dist/build-data.js +19 -12
  4. package/dist/build-data.js.map +1 -1
  5. package/dist/build-data.test.d.ts +2 -0
  6. package/dist/build-data.test.d.ts.map +1 -0
  7. package/dist/build-data.test.js +171 -0
  8. package/dist/build-data.test.js.map +1 -0
  9. package/dist/decisions.test.d.ts +2 -0
  10. package/dist/decisions.test.d.ts.map +1 -0
  11. package/dist/decisions.test.js +205 -0
  12. package/dist/decisions.test.js.map +1 -0
  13. package/dist/enrich.test.d.ts +2 -0
  14. package/dist/enrich.test.d.ts.map +1 -0
  15. package/dist/enrich.test.js +105 -0
  16. package/dist/enrich.test.js.map +1 -0
  17. package/dist/github-client.d.ts.map +1 -1
  18. package/dist/github-client.js +4 -1
  19. package/dist/github-client.js.map +1 -1
  20. package/dist/github-client.test.d.ts +2 -0
  21. package/dist/github-client.test.d.ts.map +1 -0
  22. package/dist/github-client.test.js +176 -0
  23. package/dist/github-client.test.js.map +1 -0
  24. package/dist/github.d.ts.map +1 -1
  25. package/dist/github.js +6 -2
  26. package/dist/github.js.map +1 -1
  27. package/dist/github.test.d.ts +2 -0
  28. package/dist/github.test.d.ts.map +1 -0
  29. package/dist/github.test.js +73 -0
  30. package/dist/github.test.js.map +1 -0
  31. package/dist/health.test.d.ts +2 -0
  32. package/dist/health.test.d.ts.map +1 -0
  33. package/dist/health.test.js +183 -0
  34. package/dist/health.test.js.map +1 -0
  35. package/dist/importer.test.d.ts +2 -0
  36. package/dist/importer.test.d.ts.map +1 -0
  37. package/dist/importer.test.js +173 -0
  38. package/dist/importer.test.js.map +1 -0
  39. package/dist/index.d.ts +36 -16
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +44 -16
  42. package/dist/index.js.map +1 -1
  43. package/dist/llms.d.ts.map +1 -1
  44. package/dist/llms.js +6 -4
  45. package/dist/llms.js.map +1 -1
  46. package/dist/markdown.d.ts.map +1 -1
  47. package/dist/markdown.js +16 -10
  48. package/dist/markdown.js.map +1 -1
  49. package/dist/parseReadme.d.ts.map +1 -1
  50. package/dist/parseReadme.js +5 -1
  51. package/dist/parseReadme.js.map +1 -1
  52. package/dist/schema.d.ts +1 -14
  53. package/dist/schema.d.ts.map +1 -1
  54. package/dist/schema.js +14 -60
  55. package/dist/schema.js.map +1 -1
  56. package/dist/slug.d.ts +10 -0
  57. package/dist/slug.d.ts.map +1 -1
  58. package/dist/slug.js +10 -0
  59. package/dist/slug.js.map +1 -1
  60. package/dist/slug.test.d.ts +2 -0
  61. package/dist/slug.test.d.ts.map +1 -0
  62. package/dist/slug.test.js +101 -0
  63. package/dist/slug.test.js.map +1 -0
  64. package/dist/validate.test.d.ts +2 -0
  65. package/dist/validate.test.d.ts.map +1 -0
  66. package/dist/validate.test.js +249 -0
  67. package/dist/validate.test.js.map +1 -0
  68. package/package.json +2 -2
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @grove-dev/core — enrich.ts unit tests.
3
+ *
4
+ * `enrichFromGithubHtml` makes network calls to github.com and
5
+ * img.shields.io. The unit suite is offline, so we test:
6
+ * - the validation gate (an unparseable repo URL returns
7
+ * `{error: "invalid_repo_url"}` with empty fields)
8
+ * - the 404 / 429 / generic error short-circuits
9
+ * - the HTML parsing for license, language, topics, homepage
10
+ * via `fetch` mock
11
+ */
12
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
13
+ import { enrichFromGithubHtml } from "./enrich.js";
14
+ const SAMPLE_HTML = `
15
+ <html>
16
+ <head>
17
+ <title>owner/repo: A real project</title>
18
+ </head>
19
+ <body>
20
+ <a href="/topics/awesome" rel="nofollow">awesome</a>
21
+ <a href="/topics/list" rel="nofollow">list</a>
22
+ <a href="/topics/awesome" rel="nofollow">awesome</a>
23
+ <span class="color-fg-default text-bold mr-1">TypeScript</span>
24
+ <a href="https://example.com" rel="nofollow">Homepage</a>
25
+ <span>
26
+ <a href="/owner/repo/blob/main/LICENSE" itemprop="license">MIT License</a>
27
+ </span>
28
+ </body>
29
+ </html>
30
+ `;
31
+ describe("enrichFromGithubHtml — input validation", () => {
32
+ it("returns an empty-fields + error result for an unparseable URL", async () => {
33
+ // `getOwnerRepoFromUrl` only matches github.com URLs, so
34
+ // anything else gets the "invalid_repo_url" short-circuit
35
+ // without a network round-trip. Pin the exact shape.
36
+ const r = await enrichFromGithubHtml("https://example.com/owner/repo");
37
+ expect(r).toEqual({
38
+ fields: { license: null, language: null, topics: [], homepage: null },
39
+ error: "invalid_repo_url",
40
+ });
41
+ });
42
+ });
43
+ describe("enrichFromGithubHtml — HTTP short-circuits", () => {
44
+ let originalFetch;
45
+ beforeEach(() => {
46
+ originalFetch = globalThis.fetch;
47
+ });
48
+ afterEach(() => {
49
+ globalThis.fetch = originalFetch;
50
+ vi.restoreAllMocks();
51
+ });
52
+ it("returns notFound=true on a 404", async () => {
53
+ globalThis.fetch = vi.fn(async () => new Response("not found", { status: 404 }));
54
+ const r = await enrichFromGithubHtml("https://github.com/owner/does-not-exist");
55
+ expect(r.notFound).toBe(true);
56
+ expect(r.fields).toEqual({ license: null, language: null, topics: [], homepage: null });
57
+ });
58
+ it("returns rateLimited=true on a 429", async () => {
59
+ globalThis.fetch = vi.fn(async () => new Response("slow down", { status: 429 }));
60
+ const r = await enrichFromGithubHtml("https://github.com/owner/repo");
61
+ expect(r.rateLimited).toBe(true);
62
+ });
63
+ it("returns error='<status>' on other non-2xx responses", async () => {
64
+ globalThis.fetch = vi.fn(async () => new Response("server error", { status: 500 }));
65
+ const r = await enrichFromGithubHtml("https://github.com/owner/repo");
66
+ expect(r.error).toContain("500");
67
+ });
68
+ it("returns the error message string when fetch itself throws", async () => {
69
+ globalThis.fetch = vi.fn(async () => {
70
+ throw new Error("ECONNRESET");
71
+ });
72
+ const r = await enrichFromGithubHtml("https://github.com/owner/repo");
73
+ expect(r.error).toBe("ECONNRESET");
74
+ });
75
+ });
76
+ describe("enrichFromGithubHtml — HTML extraction", () => {
77
+ let originalFetch;
78
+ beforeEach(() => {
79
+ originalFetch = globalThis.fetch;
80
+ });
81
+ afterEach(() => {
82
+ globalThis.fetch = originalFetch;
83
+ vi.restoreAllMocks();
84
+ });
85
+ it("extracts license, language, topics (deduped), and homepage from a sample page", async () => {
86
+ // Mock only the github.com page; the shields.io fallback is
87
+ // not exercised here because the HTML already contains the
88
+ // license link.
89
+ globalThis.fetch = vi.fn(async (input) => {
90
+ const url = String(input);
91
+ if (url.startsWith("https://github.com/")) {
92
+ return new Response(SAMPLE_HTML, { status: 200 });
93
+ }
94
+ // shields.io (not called in this test, but keep the mock honest).
95
+ return new Response("not found", { status: 404 });
96
+ });
97
+ const r = await enrichFromGithubHtml("https://github.com/owner/repo");
98
+ expect(r.error).toBeUndefined();
99
+ expect(r.fields.license).toBe("MIT");
100
+ expect(r.fields.language).toBe("TypeScript");
101
+ expect(r.fields.topics).toEqual(["awesome", "list"]); // deduped
102
+ expect(r.fields.homepage).toBe("https://example.com");
103
+ });
104
+ });
105
+ //# sourceMappingURL=enrich.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrich.test.js","sourceRoot":"","sources":["../src/enrich.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"github-client.d.ts","sourceRoot":"","sources":["../src/github-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;CAC9B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,SAAa,GAAG,MAAM,CAMzE;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/C;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuC3F;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,CAAC,EAC/B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GACzC,OAAO,CAAC,CAAC,EAAE,CAAC,CAad"}
1
+ {"version":3,"file":"github-client.d.ts","sourceRoot":"","sources":["../src/github-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;CAC9B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,SAAa,GAAG,MAAM,CAMzE;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/C;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuC3F;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,CAAC,EAC/B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GACzC,OAAO,CAAC,CAAC,EAAE,CAAC,CAed"}
@@ -81,7 +81,10 @@ export async function pLimit(concurrency, items, fn) {
81
81
  const i = next++;
82
82
  if (i >= items.length)
83
83
  return;
84
- out[i] = await fn(items[i], i);
84
+ const item = items[i];
85
+ if (item === undefined)
86
+ return;
87
+ out[i] = await fn(item, i);
85
88
  }
86
89
  };
87
90
  const workers = Array.from({ length: Math.max(1, concurrency) }, () => worker());
@@ -1 +1 @@
1
- {"version":3,"file":"github-client.js","sourceRoot":"","sources":["../src/github-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github-client.js","sourceRoot":"","sources":["../src/github-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=github-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-client.test.d.ts","sourceRoot":"","sources":["../src/github-client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * @grove-dev/core — github-client.ts unit tests.
3
+ *
4
+ * Tests cover the pure-logic helpers (`rateLimitWaitMs`, `sleep`,
5
+ * `pLimit`) and the HTTP path stub via a global `fetch` mock.
6
+ * The brief flagged `ghFetch` as audit-worthy (exponential backoff
7
+ * + rate-limit handling); the test pins the contract:
8
+ * - 429 / 403 (rate-limit) waits then retries
9
+ * - 5xx retries up to `attempts`
10
+ * - non-retryable 4xx returns immediately
11
+ * - exhausted attempts throw
12
+ */
13
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
14
+ import { rateLimitWaitMs, sleep, pLimit, ghFetch } from "./github-client.js";
15
+ describe("rateLimitWaitMs", () => {
16
+ it("returns 0 when the header is missing", () => {
17
+ const res = new Response("", { status: 200 });
18
+ expect(rateLimitWaitMs(res)).toBe(0);
19
+ });
20
+ it("returns 0 when the reset time is in the past", () => {
21
+ const res = new Response("", { status: 200, headers: { "x-ratelimit-reset": String(Math.floor(Date.now() / 1000) - 60) } });
22
+ expect(rateLimitWaitMs(res)).toBe(0);
23
+ });
24
+ it("returns the delta to the reset time, capped at 5 minutes", () => {
25
+ // Reset 30 seconds in the future → expect ~30000ms (capped not triggered).
26
+ const res = new Response("", { status: 200, headers: { "x-ratelimit-reset": String(Math.floor(Date.now() / 1000) + 30) } });
27
+ const wait = rateLimitWaitMs(res);
28
+ expect(wait).toBeGreaterThan(20_000);
29
+ expect(wait).toBeLessThan(35_000);
30
+ });
31
+ it("caps the wait at the supplied capMs (default 5 minutes)", () => {
32
+ // Reset 1 hour in the future → capped at 5 minutes = 300_000ms.
33
+ const res = new Response("", { status: 200, headers: { "x-ratelimit-reset": String(Math.floor(Date.now() / 1000) + 3600) } });
34
+ expect(rateLimitWaitMs(res)).toBe(5 * 60_000);
35
+ // Custom cap is honoured.
36
+ expect(rateLimitWaitMs(res, 1_000)).toBe(1_000);
37
+ });
38
+ });
39
+ describe("sleep", () => {
40
+ it("resolves immediately for non-positive input", async () => {
41
+ const start = Date.now();
42
+ await sleep(0);
43
+ await sleep(-100);
44
+ expect(Date.now() - start).toBeLessThan(50);
45
+ });
46
+ it("waits approximately the requested duration", async () => {
47
+ const start = Date.now();
48
+ await sleep(100);
49
+ const elapsed = Date.now() - start;
50
+ expect(elapsed).toBeGreaterThanOrEqual(90); // tolerance for timer skew
51
+ expect(elapsed).toBeLessThan(250);
52
+ });
53
+ });
54
+ describe("pLimit", () => {
55
+ it("runs every item and preserves order", async () => {
56
+ const items = [1, 2, 3, 4, 5];
57
+ const fn = vi.fn(async (n) => n * 10);
58
+ const result = await pLimit(2, items, fn);
59
+ expect(result).toEqual([10, 20, 30, 40, 50]);
60
+ expect(fn).toHaveBeenCalledTimes(5);
61
+ });
62
+ it("respects the concurrency cap (max in-flight workers)", async () => {
63
+ let inFlight = 0;
64
+ let maxInFlight = 0;
65
+ const fn = async () => {
66
+ inFlight++;
67
+ maxInFlight = Math.max(maxInFlight, inFlight);
68
+ await sleep(20);
69
+ inFlight--;
70
+ return "done";
71
+ };
72
+ await pLimit(2, [1, 2, 3, 4, 5, 6], fn);
73
+ expect(maxInFlight).toBeLessThanOrEqual(2);
74
+ expect(maxInFlight).toBe(2); // we expect the cap to actually be hit
75
+ });
76
+ it("returns an empty array for an empty input", async () => {
77
+ const fn = vi.fn(async () => "x");
78
+ expect(await pLimit(1, [], fn)).toEqual([]);
79
+ expect(fn).not.toHaveBeenCalled();
80
+ });
81
+ it("works with concurrency=1 (serial execution)", async () => {
82
+ const order = [];
83
+ const fn = async (n) => {
84
+ order.push(n);
85
+ return n;
86
+ };
87
+ await pLimit(1, [1, 2, 3], fn);
88
+ expect(order).toEqual([1, 2, 3]);
89
+ });
90
+ });
91
+ describe("ghFetch", () => {
92
+ let originalFetch;
93
+ beforeEach(() => {
94
+ originalFetch = globalThis.fetch;
95
+ });
96
+ afterEach(() => {
97
+ globalThis.fetch = originalFetch;
98
+ vi.restoreAllMocks();
99
+ });
100
+ it("returns the response on a 200 (no retry)", async () => {
101
+ const calls = [];
102
+ globalThis.fetch = vi.fn(async (input) => {
103
+ calls.push(String(input));
104
+ return new Response("{}", { status: 200, headers: { "content-type": "application/json" } });
105
+ });
106
+ const res = await ghFetch("/repos/owner/repo");
107
+ expect(res.status).toBe(200);
108
+ expect(calls).toHaveLength(1);
109
+ });
110
+ it("retries on 5xx and succeeds on the second attempt", async () => {
111
+ let calls = 0;
112
+ globalThis.fetch = vi.fn(async () => {
113
+ calls++;
114
+ if (calls === 1)
115
+ return new Response("oops", { status: 503 });
116
+ return new Response("{}", { status: 200 });
117
+ });
118
+ const res = await ghFetch("/repos/owner/repo", { attempts: 3 });
119
+ expect(res.status).toBe(200);
120
+ expect(calls).toBe(2);
121
+ });
122
+ it("returns the 5xx response on the final attempt (does NOT throw)", async () => {
123
+ // Pin the *current* behaviour: ghFetch retries 5xx up to
124
+ // `attempts - 1` times, then returns whatever the last
125
+ // response was — even if it's a 5xx. The throw path is
126
+ // reserved for network errors (the `catch (err)` block
127
+ // around `fetch()` itself), not for HTTP error status codes.
128
+ // This is the right contract for a "be tolerant of transient
129
+ // 5xx" wrapper — callers check the status themselves.
130
+ let calls = 0;
131
+ globalThis.fetch = vi.fn(async () => {
132
+ calls++;
133
+ return new Response("nope", { status: 500 });
134
+ });
135
+ const res = await ghFetch("/repos/owner/repo", { attempts: 3 });
136
+ expect(res.status).toBe(500);
137
+ // 1 initial + 2 retries (3rd attempt is the final, no more
138
+ // retry, returns the response).
139
+ expect(calls).toBe(3);
140
+ });
141
+ it("throws after exhausting attempts when fetch itself errors (network failure)", async () => {
142
+ // The throw path is for network errors, not HTTP status codes.
143
+ globalThis.fetch = vi.fn(async () => {
144
+ throw new Error("ECONNREFUSED");
145
+ });
146
+ await expect(ghFetch("/repos/owner/repo", { attempts: 2 })).rejects.toThrow(/ECONNREFUSED/);
147
+ });
148
+ it("does NOT retry on a non-retryable 4xx (e.g. 404)", async () => {
149
+ let calls = 0;
150
+ globalThis.fetch = vi.fn(async () => {
151
+ calls++;
152
+ return new Response("not found", { status: 404 });
153
+ });
154
+ const res = await ghFetch("/repos/owner/repo", { attempts: 5 });
155
+ expect(res.status).toBe(404);
156
+ expect(calls).toBe(1);
157
+ });
158
+ it("waits for rate-limit reset on a 403 with x-ratelimit-remaining=0", async () => {
159
+ let calls = 0;
160
+ globalThis.fetch = vi.fn(async () => {
161
+ calls++;
162
+ if (calls === 1) {
163
+ // Rate-limited. Reset in 1 second.
164
+ return new Response("rate", {
165
+ status: 403,
166
+ headers: { "x-ratelimit-remaining": "0", "x-ratelimit-reset": String(Math.floor(Date.now() / 1000) + 1) },
167
+ });
168
+ }
169
+ return new Response("{}", { status: 200 });
170
+ });
171
+ const res = await ghFetch("/repos/owner/repo", { attempts: 2 });
172
+ expect(res.status).toBe(200);
173
+ expect(calls).toBe(2);
174
+ });
175
+ });
176
+ //# sourceMappingURL=github-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-client.test.js","sourceRoot":"","sources":["../src/github-client.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAQrF;AAiCD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,qBAA2B,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAsBnI"}
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAWrF;AAiCD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,qBAA2B,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAsBnI"}
package/dist/github.js CHANGED
@@ -4,9 +4,13 @@ export function parseGithubRepoUrl(url) {
4
4
  const match = url.match(/^https?:\/\/github\.com\/([^/\s]+)\/([^/#?\s]+)(?:[/?#].*)?$/i);
5
5
  if (!match)
6
6
  return undefined;
7
+ const owner = match[1];
8
+ const repo = match[2];
9
+ if (!owner || !repo)
10
+ return undefined;
7
11
  return {
8
- owner: match[1],
9
- repo: match[2].replace(/\.git$/, ""),
12
+ owner,
13
+ repo: repo.replace(/\.git$/, ""),
10
14
  };
11
15
  }
12
16
  async function githubJson(path, token) {
@@ -1 +1 @@
1
- {"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=github.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.test.d.ts","sourceRoot":"","sources":["../src/github.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @grove-dev/core — github.ts (URL parsing + metadata fetch)
3
+ * unit tests.
4
+ *
5
+ * `parseGithubRepoUrl` is pure logic and trivially testable.
6
+ * `fetchGithubMetadata` makes real HTTP calls — we test the URL
7
+ * parser end-to-end and verify the function is exported with the
8
+ * right signature; the network path itself is exercised by the
9
+ * `sync github` CLI command in production (not by the unit suite,
10
+ * which is offline).
11
+ */
12
+ import { describe, it, expect } from "vitest";
13
+ import { parseGithubRepoUrl } from "./github.js";
14
+ describe("parseGithubRepoUrl", () => {
15
+ it("returns undefined for an empty or undefined input", () => {
16
+ expect(parseGithubRepoUrl("")).toBeUndefined();
17
+ expect(parseGithubRepoUrl(undefined)).toBeUndefined();
18
+ });
19
+ it("parses a canonical https URL", () => {
20
+ expect(parseGithubRepoUrl("https://github.com/owner/repo")).toEqual({
21
+ owner: "owner",
22
+ repo: "repo",
23
+ });
24
+ });
25
+ it("parses an http URL", () => {
26
+ expect(parseGithubRepoUrl("http://github.com/owner/repo")).toEqual({
27
+ owner: "owner",
28
+ repo: "repo",
29
+ });
30
+ });
31
+ it("strips a trailing .git suffix from the repo name", () => {
32
+ // `git clone` URLs end in .git — the parser must trim it so
33
+ // downstream API calls (e.g. /repos/owner/repo) hit the real
34
+ // repo, not a 404 because we asked for "repo.git".
35
+ expect(parseGithubRepoUrl("https://github.com/owner/repo.git")).toEqual({
36
+ owner: "owner",
37
+ repo: "repo",
38
+ });
39
+ });
40
+ it("ignores query strings and fragments", () => {
41
+ // A URL with a fragment (e.g. from a permalink) should still
42
+ // resolve to the same owner/repo.
43
+ expect(parseGithubRepoUrl("https://github.com/owner/repo#readme")).toEqual({
44
+ owner: "owner",
45
+ repo: "repo",
46
+ });
47
+ expect(parseGithubRepoUrl("https://github.com/owner/repo?tab=readme-ov-file")).toEqual({
48
+ owner: "owner",
49
+ repo: "repo",
50
+ });
51
+ });
52
+ it("returns undefined for non-GitHub URLs", () => {
53
+ expect(parseGithubRepoUrl("https://gitlab.com/owner/repo")).toBeUndefined();
54
+ expect(parseGithubRepoUrl("https://example.com/owner/repo")).toBeUndefined();
55
+ });
56
+ it("returns undefined for malformed GitHub URLs", () => {
57
+ // Missing repo segment.
58
+ expect(parseGithubRepoUrl("https://github.com/owner")).toBeUndefined();
59
+ // Owner with whitespace.
60
+ expect(parseGithubRepoUrl("https://github.com/own er/repo")).toBeUndefined();
61
+ // Empty owner.
62
+ expect(parseGithubRepoUrl("https://github.com//repo")).toBeUndefined();
63
+ });
64
+ it("is case-insensitive on the host", () => {
65
+ // GITHUB.COM should still match — the regex has the /i flag
66
+ // and humans do type uppercase sometimes.
67
+ expect(parseGithubRepoUrl("https://GITHUB.COM/Owner/Repo")).toEqual({
68
+ owner: "Owner",
69
+ repo: "Repo",
70
+ });
71
+ });
72
+ });
73
+ //# sourceMappingURL=github.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.test.js","sourceRoot":"","sources":["../src/github.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAsB,MAAM,aAAa,CAAC;AAErE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/C,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,kBAAkB,CAAC,+BAA+B,CAAC,CAAC,CAAC,OAAO,CAAC;YAClE,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;SACW,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,kBAAkB,CAAC,8BAA8B,CAAC,CAAC,CAAC,OAAO,CAAC;YACjE,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,4DAA4D;QAC5D,6DAA6D;QAC7D,mDAAmD;QACnD,MAAM,CAAC,kBAAkB,CAAC,mCAAmC,CAAC,CAAC,CAAC,OAAO,CAAC;YACtE,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,6DAA6D;QAC7D,kCAAkC;QAClC,MAAM,CAAC,kBAAkB,CAAC,sCAAsC,CAAC,CAAC,CAAC,OAAO,CAAC;YACzE,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,MAAM,CAAC,kBAAkB,CAAC,kDAAkD,CAAC,CAAC,CAAC,OAAO,CAAC;YACrF,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,kBAAkB,CAAC,+BAA+B,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC5E,MAAM,CAAC,kBAAkB,CAAC,gCAAgC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,wBAAwB;QACxB,MAAM,CAAC,kBAAkB,CAAC,0BAA0B,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACvE,yBAAyB;QACzB,MAAM,CAAC,kBAAkB,CAAC,gCAAgC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7E,eAAe;QACf,MAAM,CAAC,kBAAkB,CAAC,0BAA0B,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,4DAA4D;QAC5D,0CAA0C;QAC1C,MAAM,CAAC,kBAAkB,CAAC,+BAA+B,CAAC,CAAC,CAAC,OAAO,CAAC;YAClE,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=health.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.test.d.ts","sourceRoot":"","sources":["../src/health.test.ts"],"names":[],"mappings":""}