@cms-lab/cli 1.2.4 → 1.2.6

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 CHANGED
@@ -39,7 +39,7 @@ cms-lab explain CMS-ROUTE-404
39
39
  cms-lab supports Next.js App Router and Pages Router projects using Prismic,
40
40
  Strapi, Directus, WordPress, Contentful, and Sanity. It validates configured CMS
41
41
  route mappings, route reachability, UID gaps, SEO metadata, image alt text, and
42
- project-specific required fields.
42
+ project-specific required fields and relationship minimums.
43
43
 
44
44
  `cms-lab init --cms strapi --router pages` writes a Strapi starter config with
45
45
  collections, single types, route examples, and the Strapi relation route helper.
@@ -59,6 +59,8 @@ CI strictness can be raised with `--fail-on warning`, `--max-warnings <count>`,
59
59
  Exports include local HTML (`--report`), share-safe local HTML
60
60
  (`--report --share-report`), Markdown (`--markdown`), JUnit XML (`--junit`),
61
61
  and redacted Slack incoming webhook summaries (`--slack-webhook <url>`).
62
+ Terminal, JSON, Markdown, and HTML outputs include repeated-finding summaries
63
+ when many documents hit the same content type/template issue.
62
64
  Share-safe HTML redacts CMS source IDs and local project paths while keeping
63
65
  diagnostic codes, severity, route paths, and field paths visible. Slack
64
66
  notifications send counts and diagnostic codes only, never raw CMS payloads,
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "./chunk-R7T3O3TT.js";
4
+ } from "./chunk-3XQEUDBT.js";
5
5
 
6
6
  // src/bin.ts
7
7
  var exitCode = await runCli(process.argv.slice(2));
@@ -35,6 +35,20 @@ function renderMarkdownSummary(result, status) {
35
35
  lines.push("No diagnostics found.", "");
36
36
  return lines.join("\n");
37
37
  }
38
+ const repeatedGroups = (result.diagnosticGroups ?? []).filter(
39
+ (group) => group.count > 1
40
+ );
41
+ if (repeatedGroups.length > 0) {
42
+ lines.push("## Repeated Findings", "");
43
+ lines.push("| Group | Code | Count | Examples |");
44
+ lines.push("| --- | --- | ---: | --- |");
45
+ for (const group of repeatedGroups) {
46
+ lines.push(
47
+ `| ${escapeMarkdown(group.label)} | ${escapeMarkdown(group.code)} | ${group.count} | ${escapeMarkdown(group.examples.join(", "))} |`
48
+ );
49
+ }
50
+ lines.push("");
51
+ }
38
52
  lines.push("## Diagnostics", "");
39
53
  lines.push("| Severity | Code | Message | Source |");
40
54
  lines.push("| --- | --- | --- | --- |");
@@ -100,6 +114,9 @@ function groupForDiagnostic(diagnostic) {
100
114
  if (diagnostic.code.startsWith("CMS-FIELD")) {
101
115
  return "fields";
102
116
  }
117
+ if (diagnostic.code.startsWith("CMS-RELATIONSHIP")) {
118
+ return "relationships";
119
+ }
103
120
  if (diagnostic.code.startsWith("SEO-")) {
104
121
  return "seo";
105
122
  }
@@ -372,7 +389,8 @@ function checksSummary(config) {
372
389
  `- Routes: ${checkState(checks?.routes)}`,
373
390
  `- SEO: ${checkState(checks?.seo)}`,
374
391
  `- Image alt text: ${checkState(checks?.a11y ?? checks?.images)}`,
375
- `- Required fields: ${requiredFieldsSummary(config)}`
392
+ `- Required fields: ${requiredFieldsSummary(config)}`,
393
+ `- Relationship rules: ${relationshipRulesSummary(config)}`
376
394
  ];
377
395
  return lines.join("\n");
378
396
  }
@@ -398,6 +416,15 @@ function requiredFieldsSummary(config) {
398
416
  (field) => `${field.type}.${field.path} (${field.severity ?? "error"})`
399
417
  ).join(", ");
400
418
  }
419
+ function relationshipRulesSummary(config) {
420
+ const relationships = config.checks?.relationships ?? [];
421
+ if (relationships.length === 0) {
422
+ return "default";
423
+ }
424
+ return relationships.map(
425
+ (rule) => `${rule.from} -> ${rule.to} (${rule.where.fromField} = ${rule.where.toField}, min ${rule.min ?? 1}, ${rule.severity ?? "warning"})`
426
+ ).join(", ");
427
+ }
401
428
  function projectLabel(project) {
402
429
  if (project.framework === "next" && project.router === "app") {
403
430
  return "Next.js App Router";
@@ -493,6 +520,7 @@ function formatPrettyResult(result, options = {}) {
493
520
  result.diagnostics.filter((diagnostic) => diagnostic.severity === "info"),
494
521
  paint.cyan
495
522
  );
523
+ appendRepeatedGroups(lines, result.diagnosticGroups ?? [], paint.bold);
496
524
  lines.push("");
497
525
  lines.push("summary");
498
526
  lines.push(` errors ${result.summary.errors}`);
@@ -551,6 +579,18 @@ function appendGroup(lines, title, diagnostics, color) {
551
579
  }
552
580
  lines.push("");
553
581
  }
582
+ function appendRepeatedGroups(lines, groups, formatTitle) {
583
+ const repeated = groups.filter((group) => group.count > 1);
584
+ if (repeated.length === 0) {
585
+ return;
586
+ }
587
+ lines.push(formatTitle("repeated"));
588
+ for (const group of repeated) {
589
+ const examples = group.examples.length > 0 ? ` (${group.examples.join(", ")})` : "";
590
+ lines.push(` ${group.label} - ${group.code} x${group.count}${examples}`);
591
+ }
592
+ lines.push("");
593
+ }
554
594
  function plural2(value, singular) {
555
595
  return value === 1 ? singular : `${singular}s`;
556
596
  }
@@ -565,7 +605,7 @@ var noColor = {
565
605
  // src/index.ts
566
606
  async function runCli(argv, dependencies = {}) {
567
607
  let exitCode = 0;
568
- const program = new Command().name("cms-lab").description("Catch CMS bugs before deploy.").version("1.2.4").exitOverride().configureOutput({
608
+ const program = new Command().name("cms-lab").description("Catch CMS bugs before deploy.").version("1.2.6").exitOverride().configureOutput({
569
609
  writeOut: (text) => writeStdout(dependencies, text),
570
610
  writeErr: (text) => writeStderr(dependencies, text)
571
611
  });
@@ -1404,7 +1444,14 @@ function assertTypeFilterMatched(documents, types) {
1404
1444
  );
1405
1445
  }
1406
1446
  function parseCheckGroups(values) {
1407
- const allowed = /* @__PURE__ */ new Set(["routes", "seo", "a11y", "images", "fields"]);
1447
+ const allowed = /* @__PURE__ */ new Set([
1448
+ "routes",
1449
+ "seo",
1450
+ "a11y",
1451
+ "images",
1452
+ "fields",
1453
+ "relationships"
1454
+ ]);
1408
1455
  const groups = splitList(values);
1409
1456
  for (const group of groups) {
1410
1457
  if (!allowed.has(group)) {
@@ -1730,6 +1777,15 @@ export default defineConfig({
1730
1777
  { type: "pricing", path: "is_available", severity: "warning" },
1731
1778
  ],
1732
1779
  },
1780
+ relationships: [
1781
+ {
1782
+ from: "menu_item",
1783
+ to: "pricing",
1784
+ where: { fromField: "id", toField: "menu_item_id" },
1785
+ min: 1,
1786
+ severity: "warning",
1787
+ },
1788
+ ],
1733
1789
  },
1734
1790
  });
1735
1791
  `;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runCli
3
- } from "./chunk-R7T3O3TT.js";
3
+ } from "./chunk-3XQEUDBT.js";
4
4
  export {
5
5
  runCli
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cms-lab/cli",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "type": "module",
5
5
  "description": "Catch CMS bugs before deploy.",
6
6
  "license": "MIT",
@@ -47,15 +47,15 @@
47
47
  "dependencies": {
48
48
  "commander": "^14.0.2",
49
49
  "picocolors": "^1.1.1",
50
- "@cms-lab/contentful": "1.2.4",
51
- "@cms-lab/next": "1.2.4",
52
- "@cms-lab/directus": "1.2.4",
53
- "@cms-lab/core": "1.2.4",
54
- "@cms-lab/reporter": "1.2.4",
55
- "@cms-lab/sanity": "1.2.4",
56
- "@cms-lab/prismic": "1.2.4",
57
- "@cms-lab/strapi": "1.2.4",
58
- "@cms-lab/wordpress": "1.2.4"
50
+ "@cms-lab/directus": "1.2.6",
51
+ "@cms-lab/core": "1.2.6",
52
+ "@cms-lab/next": "1.2.6",
53
+ "@cms-lab/reporter": "1.2.6",
54
+ "@cms-lab/prismic": "1.2.6",
55
+ "@cms-lab/wordpress": "1.2.6",
56
+ "@cms-lab/sanity": "1.2.6",
57
+ "@cms-lab/contentful": "1.2.6",
58
+ "@cms-lab/strapi": "1.2.6"
59
59
  },
60
60
  "author": "Afaq Rashid",
61
61
  "scripts": {