@grove-dev/core 0.15.0 → 0.17.0

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.
@@ -2,7 +2,7 @@
2
2
  * The record normalizer: the one place that turns the three record
3
3
  * layers into the record every output is built from.
4
4
  *
5
- * 1. Human source — `paths.recordsDir/<slug>.yml`, patched by
5
+ * 1. Human source — a record file (see "Formats" below), patched by
6
6
  * `paths.overrides`.
7
7
  * 2. Generated cache — `paths.githubCache/<slug>.json` (GitHub
8
8
  * metadata and health, written by
@@ -13,18 +13,160 @@
13
13
  * 3. Decisions — `paths.decisions`, which has the final say on
14
14
  * visibility.
15
15
  *
16
+ * Formats — all supported permanently, and mixable within one site:
17
+ *
18
+ * - YAML only: `paths.recordsDir/<slug>.yml`, for data-only sites.
19
+ * - YAML + pointer: the same file with `content: ./…/<slug>.md`
20
+ * pointing at a Markdown body. `records.deprecateContentPointer`
21
+ * opts in to a `record_format_deprecated` warning for these.
22
+ * - Markdown: `paths.bodiesDir/<slug>.md`, YAML frontmatter (at least
23
+ * `name`, or `title` on a resource hub) plus the review body. A `.md`
24
+ * file a YAML record points at through `content:` is that record's
25
+ * body, never a record of its own.
26
+ *
16
27
  * `generate()` (browse, collections, SEO, sitemap, llms), `grove check`,
17
28
  * `grove cleanup` and `grove readme generate` all read records through
18
29
  * {@link loadNormalizedRecords}, so they cannot disagree about a
19
30
  * record's fields or whether it is visible.
20
31
  */
21
32
  import { readdir, readFile } from 'node:fs/promises';
22
- import { basename, join, relative, resolve } from 'node:path';
33
+ import { basename, join, relative, resolve, sep } from 'node:path';
23
34
  import { parse as parseYaml } from 'yaml';
24
35
  import { ZodError } from 'zod';
36
+ import { readContentFile, splitFrontmatter } from './content-body.js';
25
37
  import { githubSyncFreshnessOptions, loadGithubCache, resolveRecordGithub, } from './github-cache.js';
26
38
  import { classifyHealth } from './health.js';
27
39
  import { blueprintKind, decisionsFileSchema, healthFileSchema, overridesFileSchema, recordsFileSchema, recordVisibility, unwrapDecisions, unwrapHealth, unwrapOverrides, } from './schema.js';
40
+ function isMapping(value) {
41
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
42
+ }
43
+ /** True when a Markdown record's body holds anything but whitespace. */
44
+ function hasBody(body) {
45
+ return body !== undefined && /\S/.test(body);
46
+ }
47
+ /** `./`-prefixed, `/`-separated path relative to `cwd`: the form `content:` pointers use. */
48
+ function contentPointerFor(cwd, path) {
49
+ return `./${relative(cwd, path).split(sep).join('/')}`;
50
+ }
51
+ /** Candidate absolute paths for a `content:` pointer, as the build resolves it. */
52
+ function pointerCandidates(cwd, pointer) {
53
+ return [resolve(cwd, pointer), resolve(cwd, 'apps', 'example', pointer)];
54
+ }
55
+ /**
56
+ * Discover and read every record file, in both formats, without merging
57
+ * any layer. A file that cannot be parsed is returned with an issue and
58
+ * no `data`. The same slug in both formats is a `duplicate_slug_format`
59
+ * error on both files: neither silently wins.
60
+ */
61
+ export async function readRecordSources(config, cwd = process.cwd()) {
62
+ const recordsDir = resolve(cwd, config.paths.recordsDir);
63
+ const bodiesDir = resolve(cwd, config.paths.bodiesDir ?? 'content/records');
64
+ // The field every record of this blueprint must have: frontmatter
65
+ // without it belongs to some other document.
66
+ const labelKey = blueprintKind[config.blueprint] === 'resource' ? 'title' : 'name';
67
+ const sources = [];
68
+ const issue = (source, code, message, severity = 'error') => ({
69
+ code,
70
+ severity,
71
+ slug: source.slug,
72
+ file: source.file,
73
+ message: `${source.slug}: ${message}`,
74
+ });
75
+ // ── YAML records ───────────────────────────────────────────────────
76
+ // Their `content:` pointers are collected first: a Markdown file one
77
+ // of them points at is that record's body, not a record.
78
+ const pointedAt = new Set();
79
+ const yamlFiles = (await readdir(recordsDir).catch(() => []))
80
+ .filter((name) => name.endsWith('.yml'))
81
+ .sort();
82
+ for (const name of yamlFiles) {
83
+ const path = join(recordsDir, name);
84
+ const source = {
85
+ slug: basename(name, '.yml'),
86
+ format: 'yaml',
87
+ path,
88
+ file: relative(cwd, path),
89
+ issues: [],
90
+ };
91
+ sources.push(source);
92
+ // `schema: 'core'` disables custom-tag interpretation: a record with
93
+ // `!!binary` / `!!js/function` must not become a host object.
94
+ let raw;
95
+ try {
96
+ raw = parseYaml(await readFile(path, 'utf8'), { schema: 'core' });
97
+ }
98
+ catch (err) {
99
+ source.issues.push(issue(source, 'schema_error', err.message));
100
+ continue;
101
+ }
102
+ if (!isMapping(raw)) {
103
+ source.issues.push(issue(source, 'schema_error', 'record file is empty or not a YAML mapping'));
104
+ continue;
105
+ }
106
+ source.data = raw;
107
+ if (typeof raw.content === 'string' && raw.content) {
108
+ source.format = 'yaml+content';
109
+ for (const candidate of pointerCandidates(cwd, raw.content))
110
+ pointedAt.add(candidate);
111
+ }
112
+ }
113
+ // ── Markdown records ───────────────────────────────────────────────
114
+ const markdownFiles = (await readdir(bodiesDir).catch(() => []))
115
+ .filter((name) => name.endsWith('.md'))
116
+ .sort();
117
+ for (const name of markdownFiles) {
118
+ const path = join(bodiesDir, name);
119
+ if (pointedAt.has(path))
120
+ continue;
121
+ const { frontmatter, body, hasFrontmatter } = splitFrontmatter(await readFile(path, 'utf8'));
122
+ // No frontmatter: a body nothing points at, or an unrelated page.
123
+ // Neither is a record.
124
+ if (!hasFrontmatter)
125
+ continue;
126
+ const source = {
127
+ slug: basename(name, '.md'),
128
+ format: 'markdown',
129
+ path,
130
+ file: relative(cwd, path),
131
+ issues: [],
132
+ };
133
+ let raw;
134
+ try {
135
+ raw = parseYaml(frontmatter, { schema: 'core' });
136
+ }
137
+ catch (err) {
138
+ source.issues.push(issue(source, 'schema_error', `frontmatter: ${err.message}`));
139
+ sources.push(source);
140
+ continue;
141
+ }
142
+ // A record declares at least its name (`title` on a resource hub);
143
+ // frontmatter without it is some other document's.
144
+ if (!isMapping(raw) || raw[labelKey] === undefined)
145
+ continue;
146
+ source.data = raw;
147
+ source.body = body;
148
+ sources.push(source);
149
+ }
150
+ // ── One slug, one format ───────────────────────────────────────────
151
+ const bySlug = new Map();
152
+ for (const source of sources) {
153
+ bySlug.set(source.slug, [...(bySlug.get(source.slug) ?? []), source]);
154
+ }
155
+ for (const group of bySlug.values()) {
156
+ if (group.length < 2)
157
+ continue;
158
+ const files = group.map((source) => source.file).join(' and ');
159
+ for (const source of group) {
160
+ source.issues.push(issue(source, 'duplicate_slug_format', `record is defined twice (${files}); keep one format and delete the other`));
161
+ }
162
+ }
163
+ sources.sort((a, b) => {
164
+ const nameA = basename(a.path);
165
+ const nameB = basename(b.path);
166
+ return nameA < nameB ? -1 : nameA > nameB ? 1 : 0;
167
+ });
168
+ return { sources };
169
+ }
28
170
  /** Read an optional side file; a missing or invalid file yields `fallback`. */
29
171
  async function readSideFile(path, cwd, parse, fallback) {
30
172
  try {
@@ -61,15 +203,13 @@ export function applyDecisionVisibility(record, visibility) {
61
203
  }
62
204
  return { ...record, visibility };
63
205
  }
64
- function isMapping(value) {
65
- return value !== null && typeof value === 'object' && !Array.isArray(value);
66
- }
67
206
  /**
68
- * Discover, parse and merge every record under `config.paths.recordsDir`.
207
+ * Discover, parse and merge every record, in either format (see
208
+ * {@link readRecordSources}).
69
209
  *
70
210
  * Per record, lowest to highest precedence:
71
211
  *
72
- * 1. the record file (`paths.recordsDir/<slug>.yml`)
212
+ * 1. the record file (YAML, or a Markdown record's frontmatter)
73
213
  * 2. the GitHub sync cache, which supplies `github` / `health` over a
74
214
  * legacy inline copy ({@link resolveRecordGithub})
75
215
  * 3. the `paths.overrides` patch (shallow, top-level fields)
@@ -86,12 +226,9 @@ function isMapping(value) {
86
226
  * or invalid side files are treated as empty; `grove check` reports them.
87
227
  */
88
228
  export async function loadNormalizedRecords(config, cwd = process.cwd()) {
89
- const recordsDir = resolve(cwd, config.paths.recordsDir);
90
229
  const expectedKind = blueprintKind[config.blueprint];
91
- const files = (await readdir(recordsDir).catch(() => []))
92
- .filter((file) => file.endsWith('.yml'))
93
- .sort();
94
- const [githubCache, decisions, healthBySlug, patches] = await Promise.all([
230
+ const [{ sources }, githubCache, decisions, healthBySlug, patches] = await Promise.all([
231
+ readRecordSources(config, cwd),
95
232
  loadGithubCache(config, cwd),
96
233
  loadDecisionVisibility(config, cwd),
97
234
  loadHealthEntries(config, cwd),
@@ -100,58 +237,67 @@ export async function loadNormalizedRecords(config, cwd = process.cwd()) {
100
237
  const cachePath = relative(cwd, githubCache.dir) || '.';
101
238
  // A stale sync resolves as `status: unknown` rather than old values.
102
239
  const freshness = githubSyncFreshnessOptions(config);
240
+ const warnPointer = config.records?.deprecateContentPointer === true;
103
241
  const entries = [];
104
- for (const name of files) {
105
- const slug = basename(name, '.yml');
106
- const path = join(recordsDir, name);
107
- const file = relative(cwd, path);
108
- const entry = { slug, file, issues: [], syncStale: false };
242
+ for (const source of sources) {
243
+ const { slug, file, format } = source;
244
+ const entry = {
245
+ slug,
246
+ file,
247
+ format,
248
+ issues: [...source.issues],
249
+ syncStale: false,
250
+ };
109
251
  entries.push(entry);
110
- const fail = (code, message) => entry.issues.push({ code, severity: 'error', slug, file, message: `${slug}: ${message}` });
111
- // `schema: 'core'` disables custom-tag interpretation: a record with
112
- // `!!binary` / `!!js/function` must not become a host object.
113
- let raw;
114
- try {
115
- raw = parseYaml(await readFile(path, 'utf8'), { schema: 'core' });
116
- }
117
- catch (err) {
118
- fail('schema_error', err.message);
252
+ const push = (code, message, severity) => entry.issues.push({ code, severity, slug, file, message: `${slug}: ${message}` });
253
+ const data = source.data;
254
+ if (!data || entry.issues.some((issue) => issue.severity === 'error'))
119
255
  continue;
256
+ const raw = { ...data };
257
+ if (format === 'markdown') {
258
+ // The file is the record's body. A pointer elsewhere would give it
259
+ // two bodies, so it is an error rather than silently ignored.
260
+ if (raw.content !== undefined) {
261
+ push('markdown_content_pointer', 'a Markdown record is its own body; remove `content:` from its frontmatter', 'error');
262
+ continue;
263
+ }
264
+ // `content` points at the record's own file, so every renderer that
265
+ // reads a body through `content` works unchanged. A blank body is
266
+ // no body: the record then reads exactly like a YAML record with
267
+ // no pointer (no "no notes yet" fallback, no skeleton warning).
268
+ if (hasBody(source.body))
269
+ raw.content = contentPointerFor(cwd, source.path);
270
+ if (raw.slug === undefined)
271
+ raw.slug = slug;
120
272
  }
121
- if (!isMapping(raw)) {
122
- fail('schema_error', 'record file is empty or not a YAML mapping');
123
- continue;
273
+ else if (format === 'yaml+content' && warnPointer) {
274
+ push('record_format_deprecated', `YAML record with a \`content:\` pointer; move it to one Markdown file with frontmatter (${config.paths.bodiesDir ?? 'content/records'}/${slug}.md)`, 'warning');
124
275
  }
125
276
  // Cache wins over a legacy inline copy; a disagreement is a second
126
277
  // source of truth, so name the fields.
127
278
  const resolved = resolveRecordGithub(raw, githubCache.entries.get(slug), freshness);
128
279
  entry.syncStale = resolved.syncStale !== undefined;
129
280
  if (resolved.conflicts.length > 0) {
130
- entry.issues.push({
131
- code: 'github_cache_mismatch',
132
- severity: 'warning',
133
- slug,
134
- file,
135
- message: `${slug}: inline github/health disagrees with ${cachePath}/${slug}.json — ${resolved.conflicts.join(', ')}. The cache wins; run \`grove migrate github-cache\` to drop the inline copy.`,
136
- });
281
+ push('github_cache_mismatch', `inline github/health disagrees with ${cachePath}/${slug}.json — ${resolved.conflicts.join(', ')}. The cache wins; run \`grove migrate github-cache\` to drop the inline copy.`, 'warning');
137
282
  }
138
283
  const merged = resolved.record;
139
284
  if (!merged.kind)
140
285
  merged.kind = expectedKind;
141
286
  const patch = patches.get(slug);
287
+ const input = patch ? { ...merged, ...patch } : merged;
142
288
  let base;
143
289
  try {
144
- base = recordsFileSchema.parse(patch ? { ...merged, ...patch } : merged);
290
+ base = recordsFileSchema.parse(input);
145
291
  }
146
292
  catch (err) {
147
293
  if (err instanceof ZodError) {
148
- for (const issue of err.issues) {
149
- const where = issue.path.length > 0 ? issue.path.join('.') : '(root)';
150
- fail('zod_error', `${where} ${issue.message}`);
294
+ for (const zodIssue of err.issues) {
295
+ const where = zodIssue.path.length > 0 ? zodIssue.path.join('.') : '(root)';
296
+ push('zod_error', `${where} ${zodIssue.message}`, 'error');
151
297
  }
152
298
  }
153
299
  else {
154
- fail('schema_error', err.message);
300
+ push('schema_error', err.message, 'error');
155
301
  }
156
302
  continue;
157
303
  }
@@ -174,13 +320,21 @@ export async function loadNormalizedRecords(config, cwd = process.cwd()) {
174
320
  if (decision && record.kind === 'project' && !record.health)
175
321
  healthSource = 'decision';
176
322
  record = applyDecisionVisibility(record, decision);
323
+ let body;
324
+ if (format === 'markdown')
325
+ body = hasBody(source.body) ? source.body : undefined;
326
+ else if (base.content) {
327
+ body = readContentFile(base.content, pointerCandidates(cwd, base.content))?.body;
328
+ }
177
329
  entry.record = {
178
330
  slug,
179
331
  file,
332
+ format,
333
+ ...(body !== undefined ? { body } : {}),
180
334
  record,
181
335
  base,
182
336
  visibility: recordVisibility(record),
183
- declaredSlug: raw.slug,
337
+ declaredSlug: format === 'markdown' ? data.slug : input.slug,
184
338
  provenance: {
185
339
  github: resolved.github,
186
340
  health: healthSource,
@@ -1 +1 @@
1
- {"version":3,"file":"normalize-records.js","sourceRoot":"","sources":["../src/normalize-records.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"normalize-records.js","sourceRoot":"","sources":["../src/normalize-records.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Codemod one YAML record into a Markdown record: YAML frontmatter
3
+ * followed by the record's review body. `grove migrate markdown-records`
4
+ * runs it over a whole site; the normalizer
5
+ * (`loadNormalizedRecords`) must read the result back to the same
6
+ * record, and {@link yamlRecordToMarkdown} refuses rather than write a
7
+ * file it would not.
8
+ *
9
+ * Every field is kept except the three the normalizer derives
10
+ * identically for a Markdown record:
11
+ *
12
+ * - `slug`, when it equals the file name (the file name is the slug);
13
+ * - `kind`, when it equals the blueprint's kind (filled in on read);
14
+ * - `content`, the pointer (a Markdown record is its own body).
15
+ *
16
+ * Each top-level field keeps its own text: its value, style, quoting
17
+ * and any `#` comments directly above it move with it. Only the order
18
+ * of the fields changes, to {@link MARKDOWN_RECORD_FIELD_ORDER}.
19
+ */
20
+ /**
21
+ * Frontmatter field order. What a contributor writes comes first (what
22
+ * it is, what it runs on, where to get it, why it is listed), then the
23
+ * reviewer's fields. A field not listed here keeps its original
24
+ * relative order, after the contributor fields and before the reviewer
25
+ * ones.
26
+ */
27
+ export declare const MARKDOWN_RECORD_FIELD_ORDER: {
28
+ readonly contributor: readonly ["name", "title", "repoUrl", "projectType", "type", "category", "topic", "stack", "stacks", "summary", "description", "sourceDescription", "platforms", "licenses", "links", "distribution", "logoUrl", "screenshots", "tags", "bestFor", "whyListed", "caveats", "difficulty", "codebaseSize", "author", "publishedAt", "founded", "location", "members", "parent", "related", "relations", "seo", "addedAt"];
29
+ readonly reviewer: readonly ["source", "curation", "scores", "visibility"];
30
+ };
31
+ export interface YamlRecordToMarkdownOptions {
32
+ /**
33
+ * The kind the blueprint gives every record (`project`, `resource`,
34
+ * `entity`); a `kind:` with this value is dropped.
35
+ */
36
+ kind?: string;
37
+ /**
38
+ * The field that marks frontmatter as a record: `name`, or `title` on
39
+ * a resource hub. The loader ignores a Markdown file without it, so a
40
+ * record without it is refused.
41
+ */
42
+ labelKey?: string;
43
+ /**
44
+ * The record's review body, verbatim, without frontmatter. Omitted or
45
+ * `''` for a record with no body.
46
+ */
47
+ body?: string;
48
+ }
49
+ export type YamlRecordToMarkdownResult = {
50
+ ok: true;
51
+ /** The Markdown record: `---`, frontmatter, `---`, then the body byte-for-byte. */
52
+ text: string;
53
+ /** Top-level fields left out because the normalizer derives them. */
54
+ dropped: string[];
55
+ } | {
56
+ ok: false;
57
+ /** Why the record cannot be converted as it stands. */
58
+ reason: string;
59
+ };
60
+ /**
61
+ * Turn one YAML record's text (and its body) into a Markdown record.
62
+ * Refuses, with a reason, a record that is not a YAML mapping, still
63
+ * carries inline `github`/`health`, has no `labelKey`, or would not
64
+ * read back as the same fields and the same body.
65
+ */
66
+ export declare function yamlRecordToMarkdown(slug: string, yamlText: string, options?: YamlRecordToMarkdownOptions): YamlRecordToMarkdownResult;
67
+ //# sourceMappingURL=record-markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-markdown.d.ts","sourceRoot":"","sources":["../src/record-markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B;;;CAsC9B,CAAC;AAKX,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,0BAA0B,GAClC;IACE,EAAE,EAAE,IAAI,CAAC;IACT,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GACD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA4GN;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,2BAAgC,GACxC,0BAA0B,CA6D5B"}