@cms-lab/cli 1.2.3 → 1.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/README.md +4 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-M5O5QRR3.js → chunk-4XXHRNEA.js} +109 -8
- package/dist/index.js +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ npx @cms-lab/cli scan
|
|
|
11
11
|
```sh
|
|
12
12
|
cms-lab init
|
|
13
13
|
cms-lab init --cms strapi --router pages
|
|
14
|
+
cms-lab init --cms directus --router pages
|
|
14
15
|
cms-lab doctor
|
|
15
16
|
cms-lab doctor --debug --verbose 2
|
|
16
17
|
cms-lab scan --report
|
|
@@ -38,10 +39,12 @@ cms-lab explain CMS-ROUTE-404
|
|
|
38
39
|
cms-lab supports Next.js App Router and Pages Router projects using Prismic,
|
|
39
40
|
Strapi, Directus, WordPress, Contentful, and Sanity. It validates configured CMS
|
|
40
41
|
route mappings, route reachability, UID gaps, SEO metadata, image alt text, and
|
|
41
|
-
project-specific required fields.
|
|
42
|
+
project-specific required fields and relationship minimums.
|
|
42
43
|
|
|
43
44
|
`cms-lab init --cms strapi --router pages` writes a Strapi starter config with
|
|
44
45
|
collections, single types, route examples, and the Strapi relation route helper.
|
|
46
|
+
`cms-lab init --cms directus --router pages` writes a Directus starter config
|
|
47
|
+
with branch, menu item, category, and non-routable pricing collection examples.
|
|
45
48
|
Use `site.healthPath` or `site.healthUrl` in config when the app root is not the
|
|
46
49
|
right page for the initial health probe.
|
|
47
50
|
|
package/dist/bin.js
CHANGED
|
@@ -100,6 +100,9 @@ function groupForDiagnostic(diagnostic) {
|
|
|
100
100
|
if (diagnostic.code.startsWith("CMS-FIELD")) {
|
|
101
101
|
return "fields";
|
|
102
102
|
}
|
|
103
|
+
if (diagnostic.code.startsWith("CMS-RELATIONSHIP")) {
|
|
104
|
+
return "relationships";
|
|
105
|
+
}
|
|
103
106
|
if (diagnostic.code.startsWith("SEO-")) {
|
|
104
107
|
return "seo";
|
|
105
108
|
}
|
|
@@ -372,7 +375,8 @@ function checksSummary(config) {
|
|
|
372
375
|
`- Routes: ${checkState(checks?.routes)}`,
|
|
373
376
|
`- SEO: ${checkState(checks?.seo)}`,
|
|
374
377
|
`- Image alt text: ${checkState(checks?.a11y ?? checks?.images)}`,
|
|
375
|
-
`- Required fields: ${requiredFieldsSummary(config)}
|
|
378
|
+
`- Required fields: ${requiredFieldsSummary(config)}`,
|
|
379
|
+
`- Relationship rules: ${relationshipRulesSummary(config)}`
|
|
376
380
|
];
|
|
377
381
|
return lines.join("\n");
|
|
378
382
|
}
|
|
@@ -398,6 +402,15 @@ function requiredFieldsSummary(config) {
|
|
|
398
402
|
(field) => `${field.type}.${field.path} (${field.severity ?? "error"})`
|
|
399
403
|
).join(", ");
|
|
400
404
|
}
|
|
405
|
+
function relationshipRulesSummary(config) {
|
|
406
|
+
const relationships = config.checks?.relationships ?? [];
|
|
407
|
+
if (relationships.length === 0) {
|
|
408
|
+
return "default";
|
|
409
|
+
}
|
|
410
|
+
return relationships.map(
|
|
411
|
+
(rule) => `${rule.from} -> ${rule.to} (${rule.where.fromField} = ${rule.where.toField}, min ${rule.min ?? 1}, ${rule.severity ?? "warning"})`
|
|
412
|
+
).join(", ");
|
|
413
|
+
}
|
|
401
414
|
function projectLabel(project) {
|
|
402
415
|
if (project.framework === "next" && project.router === "app") {
|
|
403
416
|
return "Next.js App Router";
|
|
@@ -565,7 +578,7 @@ var noColor = {
|
|
|
565
578
|
// src/index.ts
|
|
566
579
|
async function runCli(argv, dependencies = {}) {
|
|
567
580
|
let exitCode = 0;
|
|
568
|
-
const program = new Command().name("cms-lab").description("Catch CMS bugs before deploy.").version("1.2.
|
|
581
|
+
const program = new Command().name("cms-lab").description("Catch CMS bugs before deploy.").version("1.2.5").exitOverride().configureOutput({
|
|
569
582
|
writeOut: (text) => writeStdout(dependencies, text),
|
|
570
583
|
writeErr: (text) => writeStderr(dependencies, text)
|
|
571
584
|
});
|
|
@@ -669,19 +682,20 @@ Examples:
|
|
|
669
682
|
});
|
|
670
683
|
program.command("init").description("Create a starter cms-lab.config.ts file.").option("--config <path>", "Config file path", "cms-lab.config.ts").option("--force", "Overwrite an existing config file").option(
|
|
671
684
|
"--cms <provider>",
|
|
672
|
-
"Starter CMS provider: prismic or
|
|
685
|
+
"Starter CMS provider: prismic, strapi, or directus",
|
|
673
686
|
"prismic"
|
|
674
687
|
).option("--router <router>", "Next.js router: app or pages", "app").option("--repository <name>", "Prismic repository name", "my-repo").option("--url <url>", "Site URL", "http://localhost:3000").option(
|
|
675
688
|
"--strapi-url <url>",
|
|
676
689
|
"Strapi REST API URL",
|
|
677
690
|
"http://localhost:1337"
|
|
678
|
-
).option("--strapi-locale <locale>", "Strapi locale query param").addHelpText(
|
|
691
|
+
).option("--strapi-locale <locale>", "Strapi locale query param").option("--directus-url <url>", "Directus API URL", "http://localhost:8055").addHelpText(
|
|
679
692
|
"after",
|
|
680
693
|
`
|
|
681
694
|
Examples:
|
|
682
695
|
cms-lab init
|
|
683
696
|
cms-lab init --repository my-prismic-repo --url http://localhost:3000
|
|
684
697
|
cms-lab init --cms strapi --router pages --strapi-url http://localhost:1337
|
|
698
|
+
cms-lab init --cms directus --router pages --directus-url http://localhost:8055
|
|
685
699
|
cms-lab init --config cms-lab.config.ts --force
|
|
686
700
|
`
|
|
687
701
|
).action(async (options) => {
|
|
@@ -1403,7 +1417,14 @@ function assertTypeFilterMatched(documents, types) {
|
|
|
1403
1417
|
);
|
|
1404
1418
|
}
|
|
1405
1419
|
function parseCheckGroups(values) {
|
|
1406
|
-
const allowed = /* @__PURE__ */ new Set([
|
|
1420
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
1421
|
+
"routes",
|
|
1422
|
+
"seo",
|
|
1423
|
+
"a11y",
|
|
1424
|
+
"images",
|
|
1425
|
+
"fields",
|
|
1426
|
+
"relationships"
|
|
1427
|
+
]);
|
|
1407
1428
|
const groups = splitList(values);
|
|
1408
1429
|
for (const group of groups) {
|
|
1409
1430
|
if (!allowed.has(group)) {
|
|
@@ -1621,8 +1642,10 @@ function plural3(value, singular) {
|
|
|
1621
1642
|
}
|
|
1622
1643
|
function parseInitOptions(options) {
|
|
1623
1644
|
const cms = options.cms ?? "prismic";
|
|
1624
|
-
if (cms !== "prismic" && cms !== "strapi") {
|
|
1625
|
-
throw new ConfigLoadError(
|
|
1645
|
+
if (cms !== "prismic" && cms !== "strapi" && cms !== "directus") {
|
|
1646
|
+
throw new ConfigLoadError(
|
|
1647
|
+
"--cms must be one of: prismic, strapi, directus"
|
|
1648
|
+
);
|
|
1626
1649
|
}
|
|
1627
1650
|
const router = options.router ?? "app";
|
|
1628
1651
|
if (router !== "app" && router !== "pages") {
|
|
@@ -1634,13 +1657,17 @@ function parseInitOptions(options) {
|
|
|
1634
1657
|
repository: options.repository ?? "my-repo",
|
|
1635
1658
|
url: options.url ?? "http://localhost:3000",
|
|
1636
1659
|
strapiUrl: options.strapiUrl ?? "http://localhost:1337",
|
|
1637
|
-
strapiLocale: options.strapiLocale
|
|
1660
|
+
strapiLocale: options.strapiLocale,
|
|
1661
|
+
directusUrl: options.directusUrl ?? "http://localhost:8055"
|
|
1638
1662
|
};
|
|
1639
1663
|
}
|
|
1640
1664
|
function starterConfig(options) {
|
|
1641
1665
|
if (options.cms === "strapi") {
|
|
1642
1666
|
return strapiStarterConfig(options);
|
|
1643
1667
|
}
|
|
1668
|
+
if (options.cms === "directus") {
|
|
1669
|
+
return directusStarterConfig(options);
|
|
1670
|
+
}
|
|
1644
1671
|
return `import { defineConfig } from "@cms-lab/core";
|
|
1645
1672
|
|
|
1646
1673
|
export default defineConfig({
|
|
@@ -1662,6 +1689,80 @@ export default defineConfig({
|
|
|
1662
1689
|
});
|
|
1663
1690
|
`;
|
|
1664
1691
|
}
|
|
1692
|
+
function directusStarterConfig(options) {
|
|
1693
|
+
return `import { defineConfig, readCmsDataPath } from "@cms-lab/core";
|
|
1694
|
+
|
|
1695
|
+
export default defineConfig({
|
|
1696
|
+
site: {
|
|
1697
|
+
url: ${JSON.stringify(options.url)},
|
|
1698
|
+
// Use healthPath when your app's root redirects or errors but a locale route is healthy.
|
|
1699
|
+
// healthPath: "/en",
|
|
1700
|
+
},
|
|
1701
|
+
framework: { type: "next", router: ${JSON.stringify(options.router)} },
|
|
1702
|
+
cms: {
|
|
1703
|
+
provider: "directus",
|
|
1704
|
+
url: ${JSON.stringify(options.directusUrl)},
|
|
1705
|
+
token: process.env.DIRECTUS_TOKEN,
|
|
1706
|
+
collections: [
|
|
1707
|
+
{ type: "branch", collection: "branches", uidField: "slug" },
|
|
1708
|
+
{ type: "menu_item", collection: "menu_items", uidField: "slug" },
|
|
1709
|
+
{ type: "category", collection: "menu_categories", uidField: "slug" },
|
|
1710
|
+
{
|
|
1711
|
+
type: "pricing",
|
|
1712
|
+
collection: "item_branch_pricing",
|
|
1713
|
+
uidField: "id",
|
|
1714
|
+
routable: false,
|
|
1715
|
+
},
|
|
1716
|
+
],
|
|
1717
|
+
},
|
|
1718
|
+
routes: [
|
|
1719
|
+
{
|
|
1720
|
+
type: "branch",
|
|
1721
|
+
pattern: "/branches/:slug",
|
|
1722
|
+
getPath: (doc) => \`/branches/\${doc.uid}\`,
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
type: "category",
|
|
1726
|
+
pattern: "/categories/:slug",
|
|
1727
|
+
getPath: (doc) => \`/categories/\${doc.uid}\`,
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
type: "menu_item",
|
|
1731
|
+
pattern: "/menu/:branch/:slug",
|
|
1732
|
+
getPath: (doc) => {
|
|
1733
|
+
const branch =
|
|
1734
|
+
readCmsDataPath(doc.data, "branch.slug") ??
|
|
1735
|
+
readCmsDataPath(doc.data, "branch_id.slug") ??
|
|
1736
|
+
"branch";
|
|
1737
|
+
|
|
1738
|
+
return \`/menu/\${branch}/\${doc.uid}\`;
|
|
1739
|
+
},
|
|
1740
|
+
},
|
|
1741
|
+
],
|
|
1742
|
+
checks: {
|
|
1743
|
+
fields: {
|
|
1744
|
+
required: [
|
|
1745
|
+
{ type: "branch", path: "name" },
|
|
1746
|
+
{ type: "branch", path: "city" },
|
|
1747
|
+
{ type: "menu_item", path: "name" },
|
|
1748
|
+
{ type: "menu_item", path: "base_price", severity: "warning" },
|
|
1749
|
+
{ type: "pricing", path: "price", severity: "warning" },
|
|
1750
|
+
{ type: "pricing", path: "is_available", severity: "warning" },
|
|
1751
|
+
],
|
|
1752
|
+
},
|
|
1753
|
+
relationships: [
|
|
1754
|
+
{
|
|
1755
|
+
from: "menu_item",
|
|
1756
|
+
to: "pricing",
|
|
1757
|
+
where: { fromField: "id", toField: "menu_item_id" },
|
|
1758
|
+
min: 1,
|
|
1759
|
+
severity: "warning",
|
|
1760
|
+
},
|
|
1761
|
+
],
|
|
1762
|
+
},
|
|
1763
|
+
});
|
|
1764
|
+
`;
|
|
1765
|
+
}
|
|
1665
1766
|
function strapiStarterConfig(options) {
|
|
1666
1767
|
const localeLine = options.strapiLocale ? `
|
|
1667
1768
|
locale: ${JSON.stringify(options.strapiLocale)},` : "";
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cms-lab/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
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.
|
|
51
|
-
"@cms-lab/core": "1.2.
|
|
52
|
-
"@cms-lab/
|
|
53
|
-
"@cms-lab/
|
|
54
|
-
"@cms-lab/
|
|
55
|
-
"@cms-lab/
|
|
56
|
-
"@cms-lab/
|
|
57
|
-
"@cms-lab/
|
|
58
|
-
"@cms-lab/
|
|
50
|
+
"@cms-lab/contentful": "1.2.5",
|
|
51
|
+
"@cms-lab/core": "1.2.5",
|
|
52
|
+
"@cms-lab/directus": "1.2.5",
|
|
53
|
+
"@cms-lab/next": "1.2.5",
|
|
54
|
+
"@cms-lab/prismic": "1.2.5",
|
|
55
|
+
"@cms-lab/reporter": "1.2.5",
|
|
56
|
+
"@cms-lab/sanity": "1.2.5",
|
|
57
|
+
"@cms-lab/strapi": "1.2.5",
|
|
58
|
+
"@cms-lab/wordpress": "1.2.5"
|
|
59
59
|
},
|
|
60
60
|
"author": "Afaq Rashid",
|
|
61
61
|
"scripts": {
|