@grove-dev/core 0.3.1 → 0.3.4
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 +16 -142
- package/dist/build-data.d.ts.map +1 -1
- package/dist/build-data.js +13 -4
- package/dist/build-data.js.map +1 -1
- package/dist/contributors.d.ts +3 -0
- package/dist/contributors.d.ts.map +1 -1
- package/dist/contributors.js +46 -36
- package/dist/contributors.js.map +1 -1
- package/dist/directory-client.d.ts +11 -0
- package/dist/directory-client.d.ts.map +1 -0
- package/dist/directory-client.js +11 -0
- package/dist/directory-client.js.map +1 -0
- package/dist/directory-display.d.ts +27 -0
- package/dist/directory-display.d.ts.map +1 -0
- package/dist/directory-display.js +104 -0
- package/dist/directory-display.js.map +1 -0
- package/dist/directory-format.d.ts +29 -0
- package/dist/directory-format.d.ts.map +1 -0
- package/dist/directory-format.js +72 -0
- package/dist/directory-format.js.map +1 -0
- package/dist/directory-lenses.d.ts +59 -0
- package/dist/directory-lenses.d.ts.map +1 -0
- package/dist/directory-lenses.js +199 -0
- package/dist/directory-lenses.js.map +1 -0
- package/dist/directory-repo.d.ts +20 -0
- package/dist/directory-repo.d.ts.map +1 -0
- package/dist/directory-repo.js +31 -0
- package/dist/directory-repo.js.map +1 -0
- package/dist/directory-scores.d.ts +37 -0
- package/dist/directory-scores.d.ts.map +1 -0
- package/dist/directory-scores.js +76 -0
- package/dist/directory-scores.js.map +1 -0
- package/dist/directory-search.d.ts +119 -0
- package/dist/directory-search.d.ts.map +1 -0
- package/dist/directory-search.js +398 -0
- package/dist/directory-search.js.map +1 -0
- package/dist/directory-taxonomy.d.ts +19 -0
- package/dist/directory-taxonomy.d.ts.map +1 -0
- package/dist/directory-taxonomy.js +36 -0
- package/dist/directory-taxonomy.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -6
- package/dist/index.js.map +1 -1
- package/dist/llms.js +1 -1
- package/dist/llms.js.map +1 -1
- package/dist/prepare.d.ts +20 -0
- package/dist/prepare.d.ts.map +1 -0
- package/dist/prepare.js +75 -0
- package/dist/prepare.js.map +1 -0
- package/dist/schema.d.ts +56 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +38 -0
- package/dist/schema.js.map +1 -1
- package/dist/site-artifacts.d.ts +15 -0
- package/dist/site-artifacts.d.ts.map +1 -0
- package/dist/site-artifacts.js +122 -0
- package/dist/site-artifacts.js.map +1 -0
- package/dist/validate.js +4 -2
- package/dist/validate.js.map +1 -1
- package/package.json +9 -2
- package/dist/build-data.test.d.ts +0 -2
- package/dist/build-data.test.d.ts.map +0 -1
- package/dist/build-data.test.js +0 -196
- package/dist/build-data.test.js.map +0 -1
- package/dist/contributors.test.d.ts +0 -2
- package/dist/contributors.test.d.ts.map +0 -1
- package/dist/contributors.test.js +0 -79
- package/dist/contributors.test.js.map +0 -1
- package/dist/decisions.test.d.ts +0 -2
- package/dist/decisions.test.d.ts.map +0 -1
- package/dist/decisions.test.js +0 -205
- package/dist/decisions.test.js.map +0 -1
- package/dist/enrich.test.d.ts +0 -2
- package/dist/enrich.test.d.ts.map +0 -1
- package/dist/enrich.test.js +0 -105
- package/dist/enrich.test.js.map +0 -1
- package/dist/github-client.test.d.ts +0 -2
- package/dist/github-client.test.d.ts.map +0 -1
- package/dist/github-client.test.js +0 -176
- package/dist/github-client.test.js.map +0 -1
- package/dist/github.test.d.ts +0 -2
- package/dist/github.test.d.ts.map +0 -1
- package/dist/github.test.js +0 -73
- package/dist/github.test.js.map +0 -1
- package/dist/health.test.d.ts +0 -2
- package/dist/health.test.d.ts.map +0 -1
- package/dist/health.test.js +0 -183
- package/dist/health.test.js.map +0 -1
- package/dist/importer.test.d.ts +0 -2
- package/dist/importer.test.d.ts.map +0 -1
- package/dist/importer.test.js +0 -173
- package/dist/importer.test.js.map +0 -1
- package/dist/llms.test.d.ts +0 -2
- package/dist/llms.test.d.ts.map +0 -1
- package/dist/llms.test.js +0 -39
- package/dist/llms.test.js.map +0 -1
- package/dist/public-api.test.d.ts +0 -2
- package/dist/public-api.test.d.ts.map +0 -1
- package/dist/public-api.test.js +0 -13
- package/dist/public-api.test.js.map +0 -1
- package/dist/sitemap.test.d.ts +0 -2
- package/dist/sitemap.test.d.ts.map +0 -1
- package/dist/sitemap.test.js +0 -35
- package/dist/sitemap.test.js.map +0 -1
- package/dist/slug.test.d.ts +0 -2
- package/dist/slug.test.d.ts.map +0 -1
- package/dist/slug.test.js +0 -101
- package/dist/slug.test.js.map +0 -1
- package/dist/validate.test.d.ts +0 -2
- package/dist/validate.test.d.ts.map +0 -1
- package/dist/validate.test.js +0 -272
- package/dist/validate.test.js.map +0 -1
package/dist/enrich.test.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
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
|
package/dist/enrich.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"enrich.test.js","sourceRoot":"","sources":["../src/enrich.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-client.test.d.ts","sourceRoot":"","sources":["../src/github-client.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,176 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-client.test.js","sourceRoot":"","sources":["../src/github-client.test.ts"],"names":[],"mappings":"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"}
|
package/dist/github.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github.test.d.ts","sourceRoot":"","sources":["../src/github.test.ts"],"names":[],"mappings":""}
|
package/dist/github.test.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
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
|
package/dist/github.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/health.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health.test.d.ts","sourceRoot":"","sources":["../src/health.test.ts"],"names":[],"mappings":""}
|
package/dist/health.test.js
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @grove-dev/core — health classification unit tests.
|
|
3
|
-
*
|
|
4
|
-
* Pins the boundary cases around the threshold ladder in
|
|
5
|
-
* `classifyHealth`. The thresholds are not a parameter — they're
|
|
6
|
-
* burned into the function — so the only thing these tests can do
|
|
7
|
-
* is pin them. A future PR that bumps any threshold will need to
|
|
8
|
-
* update at least one test name, which is exactly the intent:
|
|
9
|
-
* "the day someone raises the inactive cutoff from 730 to 800 days,
|
|
10
|
-
* the build breaks at the test name so a deliberate decision is
|
|
11
|
-
* made."
|
|
12
|
-
*
|
|
13
|
-
* The function also has a "fabricate" path — calling it with no
|
|
14
|
-
* `github` arg returns the canonical unknown health block. This
|
|
15
|
-
* shape is the V1 single source of truth that `applyDecision` in
|
|
16
|
-
* `build-data.ts` reuses for its no-health-block merge, so pinning
|
|
17
|
-
* it here means downstream code can't drift.
|
|
18
|
-
*/
|
|
19
|
-
import { describe, it, expect } from "vitest";
|
|
20
|
-
import { classifyHealth } from "./health.js";
|
|
21
|
-
function makeGithub(overrides = {}) {
|
|
22
|
-
return {
|
|
23
|
-
fullName: "owner/repo",
|
|
24
|
-
stars: 10,
|
|
25
|
-
forks: 0,
|
|
26
|
-
openIssues: 0,
|
|
27
|
-
archived: false,
|
|
28
|
-
disabled: false,
|
|
29
|
-
pushedAt: null,
|
|
30
|
-
updatedAt: null,
|
|
31
|
-
latestReleaseAt: null,
|
|
32
|
-
license: null,
|
|
33
|
-
topics: [],
|
|
34
|
-
language: null,
|
|
35
|
-
defaultBranch: "main",
|
|
36
|
-
...overrides,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
describe("classifyHealth — fabrication path (no GitHub metadata)", () => {
|
|
40
|
-
it("returns the canonical unknown health block when no github is supplied", () => {
|
|
41
|
-
// The shape is the V1 single source of truth — applyDecision in
|
|
42
|
-
// build-data.ts calls classifyHealth(slug) without github to
|
|
43
|
-
// fabricate a default health block. Pin every field.
|
|
44
|
-
const result = classifyHealth("my-slug");
|
|
45
|
-
expect(result).toEqual({
|
|
46
|
-
id: "my-slug",
|
|
47
|
-
health: {
|
|
48
|
-
status: "unknown",
|
|
49
|
-
maturity: "unknown",
|
|
50
|
-
tier: "experimental",
|
|
51
|
-
visibility: "keep",
|
|
52
|
-
cleanupCandidate: false,
|
|
53
|
-
staleReason: null,
|
|
54
|
-
confidence: "low",
|
|
55
|
-
reasons: ["No GitHub metadata available"],
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
it("the unknown block is what applyDecision fabricates — verify the visibility override path", () => {
|
|
60
|
-
// Without this test, a future refactor could change the
|
|
61
|
-
// unknown shape (e.g. tier: "hidden") and silently break the
|
|
62
|
-
// applyDecision merge in build-data.ts. The unknown block MUST
|
|
63
|
-
// have visibility: "keep" so the override is a meaningful
|
|
64
|
-
// *change*, not a no-op.
|
|
65
|
-
const { health } = classifyHealth("x");
|
|
66
|
-
expect(health.visibility).toBe("keep");
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
describe("classifyHealth — status thresholds (pushedAt)", () => {
|
|
70
|
-
const NOW = Date.now();
|
|
71
|
-
const daysAgo = (n) => new Date(NOW - n * 86_400_000).toISOString();
|
|
72
|
-
it("active: pushed within 6 months (≤ 183 days)", () => {
|
|
73
|
-
const result = classifyHealth("a", makeGithub({ pushedAt: daysAgo(0) }));
|
|
74
|
-
expect(result.health.status).toBe("active");
|
|
75
|
-
});
|
|
76
|
-
it("active boundary: 180 days is well inside the active window", () => {
|
|
77
|
-
// Pin the boundary just below 183 so the test is stable across
|
|
78
|
-
// floating-point rounding of `Date.now() - N*86_400_000`. The
|
|
79
|
-
// exact-183-day edge case is `183.0000000347` days, which the
|
|
80
|
-
// `<= 183` check rejects — testing 180 instead makes the
|
|
81
|
-
// intent (active window is ~6 months) obvious without
|
|
82
|
-
// coupling to the float math.
|
|
83
|
-
const result = classifyHealth("a", makeGithub({ pushedAt: daysAgo(180) }));
|
|
84
|
-
expect(result.health.status).toBe("active");
|
|
85
|
-
});
|
|
86
|
-
it("stale boundary: 184 days is the first day a record becomes stale", () => {
|
|
87
|
-
// 184 days is the first value that reliably falls on the
|
|
88
|
-
// "stale" side of the 183-day cutoff. The 183-day mark itself
|
|
89
|
-
// is load-bearing in production (a record turns 6 months old
|
|
90
|
-
// on this exact day) but is sensitive to ms rounding — pin
|
|
91
|
-
// 184 here so a future threshold bump is visible immediately
|
|
92
|
-
// and the test does not flake.
|
|
93
|
-
const result = classifyHealth("a", makeGithub({ pushedAt: daysAgo(184) }));
|
|
94
|
-
expect(result.health.status).toBe("stale");
|
|
95
|
-
});
|
|
96
|
-
it("stale: pushed between 184 and 548 days (6-18 months)", () => {
|
|
97
|
-
const result = classifyHealth("a", makeGithub({ pushedAt: daysAgo(400) }));
|
|
98
|
-
expect(result.health.status).toBe("stale");
|
|
99
|
-
});
|
|
100
|
-
it("needs_review: pushed between 548 and 730 days (18-24 months)", () => {
|
|
101
|
-
const result = classifyHealth("a", makeGithub({ pushedAt: daysAgo(600) }));
|
|
102
|
-
expect(result.health.status).toBe("needs_review");
|
|
103
|
-
});
|
|
104
|
-
it("inactive: pushed > 730 days (2+ years)", () => {
|
|
105
|
-
const result = classifyHealth("a", makeGithub({ pushedAt: daysAgo(800) }));
|
|
106
|
-
expect(result.health.status).toBe("inactive");
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
describe("classifyHealth — maturity ladder", () => {
|
|
110
|
-
it("archived overrides everything: status='archived', tier='hidden'", () => {
|
|
111
|
-
const result = classifyHealth("a", makeGithub({ archived: true, stars: 5000 }));
|
|
112
|
-
expect(result.health.status).toBe("archived");
|
|
113
|
-
expect(result.health.tier).toBe("hidden");
|
|
114
|
-
expect(result.health.cleanupCandidate).toBe(true);
|
|
115
|
-
expect(result.health.staleReason).toBe("github_archived");
|
|
116
|
-
});
|
|
117
|
-
it("popular + active → maturity='mature' and status gets promoted to 'mature'", () => {
|
|
118
|
-
// 500+ stars AND active + maintained → the function promotes
|
|
119
|
-
// status from 'active' to 'mature'. This is the threshold
|
|
120
|
-
// where the "Recently active" filter would no longer match a
|
|
121
|
-
// project even though it's actively maintained — pin it.
|
|
122
|
-
const result = classifyHealth("a", makeGithub({
|
|
123
|
-
stars: 600,
|
|
124
|
-
pushedAt: new Date(Date.now() - 30 * 86_400_000).toISOString(),
|
|
125
|
-
license: "MIT",
|
|
126
|
-
}));
|
|
127
|
-
expect(result.health.maturity).toBe("mature");
|
|
128
|
-
expect(result.health.status).toBe("mature");
|
|
129
|
-
});
|
|
130
|
-
it("popular but no maintenance signals → maturity='useful' (NOT mature)", () => {
|
|
131
|
-
// 500+ stars but no recent release/license — popular but the
|
|
132
|
-
// maintenance boost does not apply. Maturity caps at 'useful'.
|
|
133
|
-
const result = classifyHealth("a", makeGithub({
|
|
134
|
-
stars: 600,
|
|
135
|
-
pushedAt: new Date(Date.now() - 30 * 86_400_000).toISOString(),
|
|
136
|
-
license: null,
|
|
137
|
-
latestReleaseAt: null,
|
|
138
|
-
}));
|
|
139
|
-
expect(result.health.maturity).toBe("useful");
|
|
140
|
-
});
|
|
141
|
-
it("mid stars (50-499) + maintained → 'useful'", () => {
|
|
142
|
-
const result = classifyHealth("a", makeGithub({
|
|
143
|
-
stars: 100,
|
|
144
|
-
pushedAt: new Date(Date.now() - 30 * 86_400_000).toISOString(),
|
|
145
|
-
license: "MIT",
|
|
146
|
-
}));
|
|
147
|
-
expect(result.health.maturity).toBe("useful");
|
|
148
|
-
});
|
|
149
|
-
it("low stars and no signals → 'experimental'", () => {
|
|
150
|
-
const result = classifyHealth("a", makeGithub({
|
|
151
|
-
stars: 5,
|
|
152
|
-
pushedAt: new Date(Date.now() - 30 * 86_400_000).toISOString(),
|
|
153
|
-
license: null,
|
|
154
|
-
latestReleaseAt: null,
|
|
155
|
-
}));
|
|
156
|
-
expect(result.health.maturity).toBe("experimental");
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
describe("classifyHealth — tier ladder", () => {
|
|
160
|
-
const pushed = new Date(Date.now() - 30 * 86_400_000).toISOString();
|
|
161
|
-
it("hidden when status is archived", () => {
|
|
162
|
-
const r = classifyHealth("a", makeGithub({ archived: true }));
|
|
163
|
-
expect(r.health.tier).toBe("hidden");
|
|
164
|
-
expect(r.health.visibility).toBe("hide");
|
|
165
|
-
});
|
|
166
|
-
it("hidden when status is inactive", () => {
|
|
167
|
-
const r = classifyHealth("a", makeGithub({ pushedAt: new Date(Date.now() - 800 * 86_400_000).toISOString() }));
|
|
168
|
-
expect(r.health.tier).toBe("hidden");
|
|
169
|
-
});
|
|
170
|
-
it("curated when stars >= 500", () => {
|
|
171
|
-
const r = classifyHealth("a", makeGithub({ stars: 500, pushedAt: pushed }));
|
|
172
|
-
expect(r.health.tier).toBe("curated");
|
|
173
|
-
});
|
|
174
|
-
it("listed when stars >= 50 (but < 500)", () => {
|
|
175
|
-
const r = classifyHealth("a", makeGithub({ stars: 50, pushedAt: pushed }));
|
|
176
|
-
expect(r.health.tier).toBe("listed");
|
|
177
|
-
});
|
|
178
|
-
it("experimental when stars < 50", () => {
|
|
179
|
-
const r = classifyHealth("a", makeGithub({ stars: 49, pushedAt: pushed }));
|
|
180
|
-
expect(r.health.tier).toBe("experimental");
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
//# sourceMappingURL=health.test.js.map
|
package/dist/health.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health.test.js","sourceRoot":"","sources":["../src/health.test.ts"],"names":[],"mappings":"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"}
|
package/dist/importer.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"importer.test.d.ts","sourceRoot":"","sources":["../src/importer.test.ts"],"names":[],"mappings":""}
|