@grove-dev/core 0.1.5 → 0.2.5
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/LICENSE +21 -0
- package/dist/build-data.d.ts +22 -34
- package/dist/build-data.d.ts.map +1 -1
- package/dist/build-data.js +108 -71
- package/dist/build-data.js.map +1 -1
- package/dist/config.d.ts +15 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -5
- package/dist/config.js.map +1 -1
- package/dist/decisions.d.ts +15 -12
- package/dist/decisions.d.ts.map +1 -1
- package/dist/decisions.js +52 -32
- package/dist/decisions.js.map +1 -1
- package/dist/enrich.d.ts +2 -2
- package/dist/enrich.js +2 -2
- package/dist/importer.d.ts +3 -2
- package/dist/importer.d.ts.map +1 -1
- package/dist/importer.js +2 -23
- package/dist/importer.js.map +1 -1
- package/dist/llms.d.ts +6 -10
- package/dist/llms.d.ts.map +1 -1
- package/dist/llms.js +55 -44
- package/dist/llms.js.map +1 -1
- package/dist/markdown.d.ts +32 -10
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +95 -55
- package/dist/markdown.js.map +1 -1
- package/dist/schema.d.ts +1312 -577
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +414 -475
- package/dist/schema.js.map +1 -1
- package/dist/sitemap.d.ts +4 -13
- package/dist/sitemap.d.ts.map +1 -1
- package/dist/sitemap.js +10 -8
- package/dist/sitemap.js.map +1 -1
- package/dist/validate.d.ts +46 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +214 -31
- package/dist/validate.js.map +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Turtuvshin Byambaa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/build-data.d.ts
CHANGED
|
@@ -1,55 +1,43 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type GroveConfig } from "./schema.js";
|
|
2
2
|
/**
|
|
3
|
-
* The full payload written to data/generated/
|
|
3
|
+
* The full payload written to data/generated/records.full.json.
|
|
4
4
|
* Carries every normalized record, regardless of visibility.
|
|
5
5
|
*/
|
|
6
|
-
export interface
|
|
6
|
+
export interface RecordsFullPayload {
|
|
7
7
|
schemaVersion: number;
|
|
8
|
+
blueprint: string;
|
|
8
9
|
generatedAt: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
totalRecords: number;
|
|
11
|
+
visibleRecords: number;
|
|
12
|
+
records: Array<Record<string, unknown>>;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
* The slim payload written to data/generated/
|
|
15
|
+
* The slim payload written to data/generated/records.index.json.
|
|
15
16
|
* Carries only what list and search pages need.
|
|
16
17
|
*/
|
|
17
|
-
export interface
|
|
18
|
+
export interface RecordsIndexPayload {
|
|
18
19
|
schemaVersion: number;
|
|
20
|
+
blueprint: string;
|
|
19
21
|
generatedAt: string;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
totalRecords: number;
|
|
23
|
+
records: Array<Record<string, unknown>>;
|
|
22
24
|
}
|
|
23
25
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
tagline: string;
|
|
30
|
-
description: string;
|
|
31
|
-
siteUrl: string;
|
|
32
|
-
repoUrl: string;
|
|
33
|
-
itemLabel: string;
|
|
34
|
-
}
|
|
35
|
-
export declare function buildSiteConfigTs(input: SiteConfigTsInput): string;
|
|
36
|
-
/**
|
|
37
|
-
* Read every apps/*.yml in the project, normalize, and build:
|
|
38
|
-
* - data/generated/apps.full.json (full records, all visibility)
|
|
39
|
-
* - data/generated/apps.index.json (slim, visible-only)
|
|
40
|
-
* - data/generated/apps.json (compatibility alias of apps.full.json)
|
|
41
|
-
* - src/data/config.ts (typed view of curated.config.ts)
|
|
26
|
+
* `generate` reads every records/*.yml in the project, normalizes them
|
|
27
|
+
* via the blueprint schema, and writes:
|
|
28
|
+
* - data/generated/records.full.json (full records, all visibility)
|
|
29
|
+
* - data/generated/records.index.json (slim, visible-only)
|
|
30
|
+
* - data/generated/records.json (alias of records.full.json)
|
|
42
31
|
*
|
|
43
|
-
* Returns
|
|
32
|
+
* Returns file paths and counters; throws on schema errors.
|
|
44
33
|
*/
|
|
45
|
-
export interface
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
export interface GenerateResult {
|
|
35
|
+
totalRecords: number;
|
|
36
|
+
visibleRecords: number;
|
|
48
37
|
fullPath: string;
|
|
49
38
|
indexPath: string;
|
|
50
39
|
aliasPath: string;
|
|
51
|
-
configTsPath: string;
|
|
52
40
|
errors: string[];
|
|
53
41
|
}
|
|
54
|
-
export declare function
|
|
42
|
+
export declare function generate(cwd?: string, config?: GroveConfig): Promise<GenerateResult>;
|
|
55
43
|
//# sourceMappingURL=build-data.d.ts.map
|
package/dist/build-data.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-data.d.ts","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build-data.d.ts","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;AA2DrB;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACzC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACzC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,QAAQ,CAC5B,GAAG,SAAgB,EACnB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAoGzB"}
|
package/dist/build-data.js
CHANGED
|
@@ -1,115 +1,152 @@
|
|
|
1
1
|
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { basename, join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { parse as parseYaml } from "yaml";
|
|
4
|
+
import { blueprintKind, recordsFileSchema, toIndexRecord, unwrapDecisions, decisionsFileSchema, } from "./schema.js";
|
|
4
5
|
import { loadConfig } from "./config.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
/**
|
|
7
|
+
* Apply a minimal decisions.yml override to a normalized record. The
|
|
8
|
+
* human curation layer is the single source of truth for visibility:
|
|
9
|
+
* - For project records: decision.visibility (when present) wins
|
|
10
|
+
* over record.health.visibility. The health block's other fields
|
|
11
|
+
* (status, tier, etc.) are untouched.
|
|
12
|
+
* - For resource-hub and ecosystem-map records: decision.visibility
|
|
13
|
+
* is written to the record's top-level `visibility` field (these
|
|
14
|
+
* blueprints have no `health` block).
|
|
15
|
+
*
|
|
16
|
+
* The full override pipeline (with reasons surfaced in the index
|
|
17
|
+
* payload) is a V2 feature; V1 keeps the merge intentional and small.
|
|
9
18
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
28
|
-
|
|
19
|
+
function applyDecision(record, visibilityById) {
|
|
20
|
+
const override = visibilityById.get(record.slug);
|
|
21
|
+
if (!override)
|
|
22
|
+
return record;
|
|
23
|
+
if (record.kind === "project") {
|
|
24
|
+
const existing = record.health;
|
|
25
|
+
const fallback = {
|
|
26
|
+
status: "unknown",
|
|
27
|
+
maturity: "unknown",
|
|
28
|
+
tier: "listed",
|
|
29
|
+
visibility: "keep",
|
|
30
|
+
cleanupCandidate: false,
|
|
31
|
+
staleReason: null,
|
|
32
|
+
confidence: "medium",
|
|
33
|
+
reasons: [],
|
|
34
|
+
};
|
|
35
|
+
const merged = { ...(existing ?? fallback), visibility: override };
|
|
36
|
+
return { ...record, health: merged };
|
|
37
|
+
}
|
|
38
|
+
// Resource-hub / ecosystem-map: no `health` block; the top-level
|
|
39
|
+
// `visibility` field on the base schema is the source of truth.
|
|
40
|
+
return { ...record, visibility: override };
|
|
29
41
|
}
|
|
30
|
-
|
|
31
|
-
const cfg = config ?? (await loadConfig(cwd));
|
|
32
|
-
const appsDir = resolve(cwd, cfg.paths.appsDir);
|
|
33
|
-
const outDir = resolve(cwd, cfg.paths.generatedDir);
|
|
34
|
-
await mkdir(outDir, { recursive: true });
|
|
35
|
-
let entries = [];
|
|
42
|
+
async function loadDecisionVisibility(decisionsPath, cwd) {
|
|
36
43
|
try {
|
|
37
|
-
|
|
44
|
+
const raw = await readFile(resolve(cwd, decisionsPath), "utf8");
|
|
45
|
+
const parsed = decisionsFileSchema.parse(parseYaml(raw) ?? {});
|
|
46
|
+
const decisions = unwrapDecisions(parsed);
|
|
47
|
+
const out = new Map();
|
|
48
|
+
for (const d of decisions)
|
|
49
|
+
out.set(d.id, d.decision.visibility);
|
|
50
|
+
return out;
|
|
38
51
|
}
|
|
39
52
|
catch {
|
|
40
|
-
|
|
53
|
+
// missing or invalid decisions.yml → no overrides
|
|
54
|
+
return new Map();
|
|
41
55
|
}
|
|
56
|
+
}
|
|
57
|
+
export async function generate(cwd = process.cwd(), config) {
|
|
58
|
+
const cfg = config ?? (await loadConfig(cwd));
|
|
59
|
+
const recordsDir = resolve(cwd, cfg.paths.recordsDir);
|
|
60
|
+
const outDir = resolve(cwd, cfg.paths.generatedDir);
|
|
61
|
+
await mkdir(outDir, { recursive: true });
|
|
62
|
+
// Re-emit the site config as JSON alongside the records so the
|
|
63
|
+
// Astro (or any framework) template can pick up the user's
|
|
64
|
+
// branding, theme, and nav without parsing `grove.config.ts`
|
|
65
|
+
// at render time. The CLI runs `generate` ahead of `build`,
|
|
66
|
+
// so this stays in sync with the consumer's config edits.
|
|
67
|
+
const siteConfigPayload = {
|
|
68
|
+
blueprint: cfg.blueprint,
|
|
69
|
+
name: cfg.site.name,
|
|
70
|
+
tagline: cfg.site.tagline,
|
|
71
|
+
description: cfg.site.description ?? cfg.site.tagline,
|
|
72
|
+
siteUrl: cfg.site.url ?? "https://example.com",
|
|
73
|
+
repoUrl: cfg.site.repoUrl ?? "",
|
|
74
|
+
nav: cfg.nav,
|
|
75
|
+
theme: cfg.theme,
|
|
76
|
+
integrations: cfg.integrations,
|
|
77
|
+
};
|
|
78
|
+
await writeFile(join(outDir, "site-config.json"), JSON.stringify(siteConfigPayload, null, 2), "utf8");
|
|
79
|
+
const expectedKind = blueprintKind[cfg.blueprint];
|
|
80
|
+
const entries = await readdir(recordsDir).catch(() => []);
|
|
42
81
|
const files = entries.filter((f) => f.endsWith(".yml")).sort();
|
|
43
|
-
|
|
82
|
+
// Load human curation decisions once; missing file → empty map.
|
|
83
|
+
const visibilityById = await loadDecisionVisibility(cfg.paths.decisions, cwd);
|
|
84
|
+
const out = [];
|
|
44
85
|
const errors = [];
|
|
45
86
|
for (const file of files) {
|
|
46
87
|
const fileSlug = basename(file, ".yml");
|
|
47
88
|
try {
|
|
48
|
-
const text = await readFile(join(
|
|
49
|
-
const raw =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
89
|
+
const text = await readFile(join(recordsDir, file), "utf8");
|
|
90
|
+
const raw = (parseYaml(text) ?? {});
|
|
91
|
+
if (!raw.kind)
|
|
92
|
+
raw.kind = expectedKind;
|
|
93
|
+
const normalized = recordsFileSchema.parse(raw);
|
|
94
|
+
normalized.slug = fileSlug;
|
|
95
|
+
// Apply decisions.yml visibility override on top of the record.
|
|
96
|
+
// The index payload then derives visibility from record.health,
|
|
97
|
+
// which is now the merged result.
|
|
98
|
+
out.push(applyDecision(normalized, visibilityById));
|
|
55
99
|
}
|
|
56
100
|
catch (err) {
|
|
57
101
|
errors.push(`${file}: ${err.message}`);
|
|
58
102
|
}
|
|
59
103
|
}
|
|
60
104
|
if (errors.length > 0) {
|
|
61
|
-
const e = new Error(`
|
|
105
|
+
const e = new Error(`generate failed: ${errors.length} schema error(s)`);
|
|
62
106
|
e.details = errors;
|
|
63
107
|
throw e;
|
|
64
108
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return
|
|
109
|
+
out.sort((a, b) => nameOf(a).localeCompare(nameOf(b)));
|
|
110
|
+
const indexRecords = out
|
|
111
|
+
.map((record) => toIndexRecord(record))
|
|
112
|
+
.filter((r) => {
|
|
113
|
+
const vis = r.visibility;
|
|
114
|
+
return vis !== "hide" && vis !== "remove";
|
|
71
115
|
});
|
|
72
|
-
const indexApps = apps
|
|
73
|
-
.map((app) => toIndexApp(app))
|
|
74
|
-
.filter((a) => a.visibility !== "hide");
|
|
75
116
|
const generatedAt = new Date().toISOString();
|
|
76
117
|
const fullPayload = {
|
|
77
118
|
schemaVersion: 1,
|
|
119
|
+
blueprint: cfg.blueprint,
|
|
78
120
|
generatedAt,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
121
|
+
totalRecords: out.length,
|
|
122
|
+
visibleRecords: indexRecords.length,
|
|
123
|
+
records: out,
|
|
82
124
|
};
|
|
83
125
|
const indexPayload = {
|
|
84
126
|
schemaVersion: 1,
|
|
127
|
+
blueprint: cfg.blueprint,
|
|
85
128
|
generatedAt,
|
|
86
|
-
|
|
87
|
-
|
|
129
|
+
totalRecords: indexRecords.length,
|
|
130
|
+
records: indexRecords,
|
|
88
131
|
};
|
|
89
|
-
const fullPath = join(outDir, "
|
|
90
|
-
const indexPath = join(outDir, "
|
|
91
|
-
const aliasPath = join(outDir, "
|
|
132
|
+
const fullPath = join(outDir, "records.full.json");
|
|
133
|
+
const indexPath = join(outDir, "records.index.json");
|
|
134
|
+
const aliasPath = join(outDir, "records.json");
|
|
92
135
|
await writeFile(fullPath, JSON.stringify(fullPayload, null, 2), "utf8");
|
|
93
136
|
await writeFile(indexPath, JSON.stringify(indexPayload, null, 2), "utf8");
|
|
94
137
|
await writeFile(aliasPath, JSON.stringify(fullPayload, null, 2), "utf8");
|
|
95
|
-
const configTsPath = resolve(cwd, "src/data/config.ts");
|
|
96
|
-
const configTs = buildSiteConfigTs({
|
|
97
|
-
name: cfg.name,
|
|
98
|
-
tagline: cfg.tagline,
|
|
99
|
-
description: cfg.description ?? cfg.tagline,
|
|
100
|
-
siteUrl: cfg.siteUrl ?? "https://example.com",
|
|
101
|
-
repoUrl: cfg.repoUrl ?? "",
|
|
102
|
-
itemLabel: cfg.itemLabel,
|
|
103
|
-
});
|
|
104
|
-
await writeFile(configTsPath, configTs, "utf8");
|
|
105
138
|
return {
|
|
106
|
-
|
|
107
|
-
|
|
139
|
+
totalRecords: out.length,
|
|
140
|
+
visibleRecords: indexRecords.length,
|
|
108
141
|
fullPath,
|
|
109
142
|
indexPath,
|
|
110
143
|
aliasPath,
|
|
111
|
-
configTsPath,
|
|
112
144
|
errors,
|
|
113
145
|
};
|
|
114
146
|
}
|
|
147
|
+
function nameOf(record) {
|
|
148
|
+
if (record.kind === "resource")
|
|
149
|
+
return record.title;
|
|
150
|
+
return record.name;
|
|
151
|
+
}
|
|
115
152
|
//# sourceMappingURL=build-data.js.map
|
package/dist/build-data.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-data.js","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"build-data.js","sourceRoot":"","sources":["../src/build-data.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export type {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type GroveConfig } from "./schema.js";
|
|
2
|
+
export type { GroveConfig };
|
|
3
|
+
/**
|
|
4
|
+
* Load the Grove project config. The config file is the single source
|
|
5
|
+
* of truth for blueprint, site metadata, paths, integrations, theme,
|
|
6
|
+
* and component overrides.
|
|
7
|
+
*
|
|
8
|
+
* Default name: `grove.config.ts`. Override with the second arg.
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadConfig(cwd?: string, configPath?: string): Promise<GroveConfig>;
|
|
11
|
+
/**
|
|
12
|
+
* Define and validate a Grove config. Used at the bottom of a
|
|
13
|
+
* `grove.config.ts` file so editors get good type hints.
|
|
14
|
+
*/
|
|
15
|
+
export declare function defineConfig(config: GroveConfig): GroveConfig;
|
|
5
16
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAElE,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,GAAG,SAAgB,EACnB,UAAU,SAAoB,GAC7B,OAAO,CAAC,WAAW,CAAC,CAMtB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE7D"}
|
package/dist/config.js
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import { createJiti } from "jiti";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { groveConfigSchema } from "./schema.js";
|
|
4
|
+
/**
|
|
5
|
+
* Load the Grove project config. The config file is the single source
|
|
6
|
+
* of truth for blueprint, site metadata, paths, integrations, theme,
|
|
7
|
+
* and component overrides.
|
|
8
|
+
*
|
|
9
|
+
* Default name: `grove.config.ts`. Override with the second arg.
|
|
10
|
+
*/
|
|
11
|
+
export async function loadConfig(cwd = process.cwd(), configPath = "grove.config.ts") {
|
|
5
12
|
const resolved = resolve(cwd, configPath);
|
|
6
13
|
const jiti = createJiti(import.meta.url);
|
|
7
|
-
const mod = await jiti.import(resolved, { default: true });
|
|
14
|
+
const mod = (await jiti.import(resolved, { default: true }));
|
|
8
15
|
const raw = mod.default ?? mod.config ?? mod;
|
|
9
|
-
return
|
|
16
|
+
return groveConfigSchema.parse(raw);
|
|
10
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Define and validate a Grove config. Used at the bottom of a
|
|
20
|
+
* `grove.config.ts` file so editors get good type hints.
|
|
21
|
+
*/
|
|
11
22
|
export function defineConfig(config) {
|
|
12
|
-
return
|
|
23
|
+
return groveConfigSchema.parse(config);
|
|
13
24
|
}
|
|
14
25
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,aAAa,CAAC;AAIlE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,EACnB,UAAU,GAAG,iBAAiB;IAE9B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAA4B,CAAC;IACxF,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC;IAC7C,OAAO,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,OAAO,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC"}
|
package/dist/decisions.d.ts
CHANGED
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
|
|
3
|
-
export interface ReviewCandidate {
|
|
1
|
+
import { type GroveConfig, type Resource } from "./schema.js";
|
|
2
|
+
export interface CleanupCandidate {
|
|
4
3
|
slug: string;
|
|
5
4
|
name: string;
|
|
6
|
-
|
|
5
|
+
url: string;
|
|
7
6
|
status: string;
|
|
8
7
|
tier: string;
|
|
9
8
|
staleReason: string | null;
|
|
10
9
|
lastCommitAt: string | null;
|
|
11
10
|
stars: number;
|
|
12
11
|
}
|
|
13
|
-
export interface
|
|
12
|
+
export interface CleanupReport {
|
|
14
13
|
generatedAt: string;
|
|
14
|
+
blueprint: string;
|
|
15
15
|
totalCandidates: number;
|
|
16
|
-
candidates:
|
|
16
|
+
candidates: CleanupCandidate[];
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
19
|
-
export declare function
|
|
18
|
+
/** Filter records down to the ones that need a human curation pass. */
|
|
19
|
+
export declare function pickCleanupCandidates(records: Resource[]): Resource[];
|
|
20
20
|
/**
|
|
21
|
-
* Read every
|
|
22
|
-
*
|
|
21
|
+
* Read every record YAML under `config.paths.recordsDir`, normalize,
|
|
22
|
+
* then write `data/generated/cleanup-report.json` with the list of
|
|
23
|
+
* records that need human attention (stale / unknown / cleanup).
|
|
24
|
+
*
|
|
25
|
+
* V1 name for what was previously `review`.
|
|
23
26
|
*/
|
|
24
|
-
export declare function
|
|
25
|
-
report:
|
|
27
|
+
export declare function cleanupStale(cwd?: string, config?: GroveConfig): Promise<{
|
|
28
|
+
report: CleanupReport;
|
|
26
29
|
path: string;
|
|
27
30
|
}>;
|
|
28
31
|
//# sourceMappingURL=decisions.d.ts.map
|
package/dist/decisions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decisions.d.ts","sourceRoot":"","sources":["../src/decisions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decisions.d.ts","sourceRoot":"","sources":["../src/decisions.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAsBD,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAOrE;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,GAAG,SAAgB,EACnB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAmClD"}
|
package/dist/decisions.js
CHANGED
|
@@ -1,56 +1,76 @@
|
|
|
1
1
|
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { basename, join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { parse as parseYaml } from "yaml";
|
|
4
|
+
import { blueprintKind, recordsFileSchema, } from "./schema.js";
|
|
4
5
|
import { loadConfig } from "./config.js";
|
|
5
|
-
function toCandidate(
|
|
6
|
+
function toCandidate(record) {
|
|
7
|
+
const name = record.kind === "resource" ? record.title : record.name;
|
|
8
|
+
const url = record.links?.github ?? record.links?.website ?? record.links?.source ?? "";
|
|
9
|
+
const health = record
|
|
10
|
+
.health;
|
|
11
|
+
const gh = record
|
|
12
|
+
.github?.repository;
|
|
6
13
|
return {
|
|
7
|
-
slug:
|
|
8
|
-
name
|
|
9
|
-
|
|
10
|
-
status:
|
|
11
|
-
tier:
|
|
12
|
-
staleReason:
|
|
13
|
-
lastCommitAt:
|
|
14
|
-
stars:
|
|
14
|
+
slug: record.slug,
|
|
15
|
+
name,
|
|
16
|
+
url,
|
|
17
|
+
status: health?.status ?? "unknown",
|
|
18
|
+
tier: health?.tier ?? "experimental",
|
|
19
|
+
staleReason: health?.staleReason ?? null,
|
|
20
|
+
lastCommitAt: gh?.pushed_at ?? null,
|
|
21
|
+
stars: gh?.stargazers_count ?? 0,
|
|
15
22
|
};
|
|
16
23
|
}
|
|
17
|
-
/**
|
|
18
|
-
export function
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
/** Filter records down to the ones that need a human curation pass. */
|
|
25
|
+
export function pickCleanupCandidates(records) {
|
|
26
|
+
return records.filter((r) => {
|
|
27
|
+
const health = r.health;
|
|
28
|
+
if (health?.cleanupCandidate)
|
|
29
|
+
return true;
|
|
30
|
+
if (health?.status === "unknown" || health?.status === "needs_review")
|
|
31
|
+
return true;
|
|
32
|
+
return false;
|
|
33
|
+
});
|
|
22
34
|
}
|
|
23
35
|
/**
|
|
24
|
-
* Read every
|
|
25
|
-
*
|
|
36
|
+
* Read every record YAML under `config.paths.recordsDir`, normalize,
|
|
37
|
+
* then write `data/generated/cleanup-report.json` with the list of
|
|
38
|
+
* records that need human attention (stale / unknown / cleanup).
|
|
39
|
+
*
|
|
40
|
+
* V1 name for what was previously `review`.
|
|
26
41
|
*/
|
|
27
|
-
export async function
|
|
42
|
+
export async function cleanupStale(cwd = process.cwd(), config) {
|
|
28
43
|
const cfg = config ?? (await loadConfig(cwd));
|
|
29
|
-
const
|
|
44
|
+
const recordsDir = resolve(cwd, cfg.paths.recordsDir);
|
|
30
45
|
const outDir = resolve(cwd, cfg.paths.generatedDir);
|
|
31
46
|
await mkdir(outDir, { recursive: true });
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
entries = await readdir(appsDir);
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
entries = [];
|
|
38
|
-
}
|
|
47
|
+
const expectedKind = blueprintKind[cfg.blueprint];
|
|
48
|
+
const entries = await readdir(recordsDir).catch(() => []);
|
|
39
49
|
const files = entries.filter((f) => f.endsWith(".yml")).sort();
|
|
40
|
-
const
|
|
50
|
+
const records = [];
|
|
41
51
|
for (const file of files) {
|
|
42
52
|
const fileSlug = basename(file, ".yml");
|
|
43
|
-
const text = await readFile(join(
|
|
44
|
-
const raw =
|
|
45
|
-
|
|
53
|
+
const text = await readFile(join(recordsDir, file), "utf8");
|
|
54
|
+
const raw = (parseYaml(text) ?? {});
|
|
55
|
+
if (!raw.kind)
|
|
56
|
+
raw.kind = expectedKind;
|
|
57
|
+
try {
|
|
58
|
+
const normalized = recordsFileSchema.parse(raw);
|
|
59
|
+
normalized.slug = fileSlug;
|
|
60
|
+
records.push(normalized);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// skip — validation surfaces the error
|
|
64
|
+
}
|
|
46
65
|
}
|
|
47
|
-
const candidates =
|
|
66
|
+
const candidates = pickCleanupCandidates(records).map(toCandidate);
|
|
48
67
|
const report = {
|
|
49
68
|
generatedAt: new Date().toISOString(),
|
|
69
|
+
blueprint: cfg.blueprint,
|
|
50
70
|
totalCandidates: candidates.length,
|
|
51
71
|
candidates,
|
|
52
72
|
};
|
|
53
|
-
const path = join(outDir, "
|
|
73
|
+
const path = join(outDir, "cleanup-report.json");
|
|
54
74
|
await writeFile(path, JSON.stringify(report, null, 2), "utf8");
|
|
55
75
|
return { report, path };
|
|
56
76
|
}
|
package/dist/decisions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decisions.js","sourceRoot":"","sources":["../src/decisions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"decisions.js","sourceRoot":"","sources":["../src/decisions.ts"],"names":[],"mappings":"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"}
|
package/dist/enrich.d.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* the page render doesn't include the standard "X license" link text.
|
|
8
8
|
*
|
|
9
9
|
* The returned shape is compatible with the GitHub REST `repository`
|
|
10
|
-
* block used in `data/
|
|
11
|
-
* sync can fill in the rest of the fields.
|
|
10
|
+
* block used in `data/records/<slug>.yml` for `kind: project` records,
|
|
11
|
+
* so a subsequent token-backed sync can fill in the rest of the fields.
|
|
12
12
|
*/
|
|
13
13
|
export interface EnrichedFields {
|
|
14
14
|
license: string | null;
|