@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.
- package/README.md +2 -2
- package/dist/build-data.d.ts.map +1 -1
- package/dist/build-data.js +19 -12
- package/dist/build-data.js.map +1 -1
- package/dist/build-data.test.d.ts +2 -0
- package/dist/build-data.test.d.ts.map +1 -0
- package/dist/build-data.test.js +171 -0
- package/dist/build-data.test.js.map +1 -0
- package/dist/decisions.test.d.ts +2 -0
- package/dist/decisions.test.d.ts.map +1 -0
- package/dist/decisions.test.js +205 -0
- package/dist/decisions.test.js.map +1 -0
- package/dist/enrich.test.d.ts +2 -0
- package/dist/enrich.test.d.ts.map +1 -0
- package/dist/enrich.test.js +105 -0
- package/dist/enrich.test.js.map +1 -0
- package/dist/github-client.d.ts.map +1 -1
- package/dist/github-client.js +4 -1
- package/dist/github-client.js.map +1 -1
- package/dist/github-client.test.d.ts +2 -0
- package/dist/github-client.test.d.ts.map +1 -0
- package/dist/github-client.test.js +176 -0
- package/dist/github-client.test.js.map +1 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +6 -2
- package/dist/github.js.map +1 -1
- package/dist/github.test.d.ts +2 -0
- package/dist/github.test.d.ts.map +1 -0
- package/dist/github.test.js +73 -0
- package/dist/github.test.js.map +1 -0
- package/dist/health.test.d.ts +2 -0
- package/dist/health.test.d.ts.map +1 -0
- package/dist/health.test.js +183 -0
- package/dist/health.test.js.map +1 -0
- package/dist/importer.test.d.ts +2 -0
- package/dist/importer.test.d.ts.map +1 -0
- package/dist/importer.test.js +173 -0
- package/dist/importer.test.js.map +1 -0
- package/dist/index.d.ts +36 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -16
- package/dist/index.js.map +1 -1
- package/dist/llms.d.ts.map +1 -1
- package/dist/llms.js +6 -4
- package/dist/llms.js.map +1 -1
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +16 -10
- package/dist/markdown.js.map +1 -1
- package/dist/parseReadme.d.ts.map +1 -1
- package/dist/parseReadme.js +5 -1
- package/dist/parseReadme.js.map +1 -1
- package/dist/schema.d.ts +1 -14
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +14 -60
- package/dist/schema.js.map +1 -1
- package/dist/slug.d.ts +10 -0
- package/dist/slug.d.ts.map +1 -1
- package/dist/slug.js +10 -0
- package/dist/slug.js.map +1 -1
- package/dist/slug.test.d.ts +2 -0
- package/dist/slug.test.d.ts.map +1 -0
- package/dist/slug.test.js +101 -0
- package/dist/slug.test.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +249 -0
- package/dist/validate.test.js.map +1 -0
- 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":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;CAgBnB,CAAC;AAEF,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,yDAAyD;QACzD,0DAA0D;QAC1D,qDAAqD;QACrD,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,gCAAgC,CAAC,CAAC;QACvE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAChB,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;YACrE,KAAK,EAAE,kBAAkB;SAC1B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;IAC1D,IAAI,aAA2B,CAAC;IAEhC,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;QACjC,EAAE,CAAC,eAAe,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAiB,CAAC;QACjG,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,yCAAyC,CAAC,CAAC;QAChF,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAiB,CAAC;QACjG,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,+BAA+B,CAAC,CAAC;QACtE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAiB,CAAC;QACpG,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,+BAA+B,CAAC,CAAC;QACtE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC,CAAiB,CAAC;QACnB,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,+BAA+B,CAAC,CAAC;QACtE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,IAAI,aAA2B,CAAC;IAEhC,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;QACjC,EAAE,CAAC,eAAe,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,4DAA4D;QAC5D,2DAA2D;QAC3D,gBAAgB;QAChB,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACvC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,GAAG,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;gBAC1C,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,kEAAkE;YAClE,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC,CAAiB,CAAC;QAEnB,MAAM,CAAC,GAAG,MAAM,oBAAoB,CAAC,+BAA+B,CAAC,CAAC;QACtE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU;QAChE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -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,
|
|
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"}
|
package/dist/github-client.js
CHANGED
|
@@ -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
|
-
|
|
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 @@
|
|
|
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":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7E,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5H,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,2EAA2E;QAC3E,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5H,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,gEAAgE;QAChE,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9H,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAC9C,0BAA0B;QAC1B,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;QACf,MAAM,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC,CAAC,2BAA2B;QACvE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,MAAM,EAAE,GAAG,KAAK,IAAI,EAAE;YACpB,QAAQ,EAAE,CAAC;YACX,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAC9C,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;YAChB,QAAQ,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QACF,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,WAAW,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,uCAAuC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAS,EAAE,EAAE;YAC7B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,CAAC;QACX,CAAC,CAAC;QACF,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,IAAI,aAA2B,CAAC;IAEhC,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;QACjC,EAAE,CAAC,eAAe,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACvC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1B,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAC9F,CAAC,CAAiB,CAAC;QAEnB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAClC,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9D,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAiB,CAAC;QAEnB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,yDAAyD;QACzD,uDAAuD;QACvD,uDAAuD;QACvD,uDAAuD;QACvD,6DAA6D;QAC7D,6DAA6D;QAC7D,sDAAsD;QACtD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAClC,KAAK,EAAE,CAAC;YACR,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAiB,CAAC;QAEnB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,2DAA2D;QAC3D,gCAAgC;QAChC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,+DAA+D;QAC/D,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QAClC,CAAC,CAAiB,CAAC;QAEnB,MAAM,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAClC,KAAK,EAAE,CAAC;YACR,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC,CAAiB,CAAC;QAEnB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAClC,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,mCAAmC;gBACnC,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE;oBAC1B,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE,EAAE,uBAAuB,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;iBAC1G,CAAC,CAAC;YACL,CAAC;YACD,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAiB,CAAC;QAEnB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/github.d.ts.map
CHANGED
|
@@ -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,
|
|
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
|
|
9
|
-
repo:
|
|
12
|
+
owner,
|
|
13
|
+
repo: repo.replace(/\.git$/, ""),
|
|
10
14
|
};
|
|
11
15
|
}
|
|
12
16
|
async function githubJson(path, token) {
|
package/dist/github.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,kBAAkB,CAAC,GAAuB;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACzF,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"health.test.d.ts","sourceRoot":"","sources":["../src/health.test.ts"],"names":[],"mappings":""}
|