@cms-lab/cli 1.0.10 → 1.2.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.
package/README.md CHANGED
@@ -10,6 +10,7 @@ npx @cms-lab/cli scan
10
10
 
11
11
  ```sh
12
12
  cms-lab init
13
+ cms-lab init --cms strapi --router pages
13
14
  cms-lab doctor
14
15
  cms-lab doctor --debug --verbose 2
15
16
  cms-lab scan --report
@@ -37,6 +38,11 @@ Strapi, Directus, WordPress, Contentful, and Sanity. It validates configured CMS
37
38
  route mappings, route reachability, UID gaps, SEO metadata, image alt text, and
38
39
  project-specific required fields.
39
40
 
41
+ `cms-lab init --cms strapi --router pages` writes a Strapi starter config with
42
+ collections, single types, route examples, and the Strapi relation route helper.
43
+ Use `site.healthPath` or `site.healthUrl` in config when the app root is not the
44
+ right page for the initial health probe.
45
+
40
46
  Debug logs use stderr and support `--debug` plus `--verbose <0|1|2|3>`, so JSON
41
47
  scan output remains clean on stdout. Raw CMS document `data` is redacted from
42
48
  `--json` output, along with document URLs, UIDs, and absolute project paths,
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "./chunk-VARQUY5N.js";
4
+ } from "./chunk-34UP25NH.js";
5
5
 
6
6
  // src/bin.ts
7
7
  var exitCode = await runCli(process.argv.slice(2));
@@ -9,6 +9,7 @@ import {
9
9
  SiteUnreachableError,
10
10
  explainDiagnostic,
11
11
  loadCmsLabConfig,
12
+ resolveSiteHealthUrl,
12
13
  scanDocuments
13
14
  } from "@cms-lab/core";
14
15
  import { fetchContentfulDocuments as defaultFetchContentfulDocuments } from "@cms-lab/contentful";
@@ -325,7 +326,8 @@ function cmsDetails(config) {
325
326
  if (config.provider === "strapi") {
326
327
  return `## CMS details
327
328
 
328
- - Collections: ${config.collections.map((collection) => `${collection.type} (${collection.endpoint})`).join(", ")}`;
329
+ - Collections: ${(config.collections ?? []).map((collection) => `${collection.type} (${collection.endpoint})`).join(", ") || "none"}
330
+ - Single types: ${(config.singleTypes ?? []).map((singleType) => `${singleType.type} (${singleType.endpoint})`).join(", ") || "none"}`;
329
331
  }
330
332
  if (config.provider === "directus") {
331
333
  return `## CMS details
@@ -513,7 +515,7 @@ var noColor = {
513
515
  // src/index.ts
514
516
  async function runCli(argv, dependencies = {}) {
515
517
  let exitCode = 0;
516
- const program = new Command().name("cms-lab").description("Catch CMS bugs before deploy.").version("1.0.10").exitOverride().configureOutput({
518
+ const program = new Command().name("cms-lab").description("Catch CMS bugs before deploy.").version("1.2.0").exitOverride().configureOutput({
517
519
  writeOut: (text) => writeStdout(dependencies, text),
518
520
  writeErr: (text) => writeStderr(dependencies, text)
519
521
  });
@@ -612,12 +614,21 @@ Examples:
612
614
  ).action((code) => {
613
615
  exitCode = runExplain(code, dependencies);
614
616
  });
615
- 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("--repository <name>", "Prismic repository name", "my-repo").option("--url <url>", "Site URL", "http://localhost:3000").addHelpText(
617
+ 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(
618
+ "--cms <provider>",
619
+ "Starter CMS provider: prismic or strapi",
620
+ "prismic"
621
+ ).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(
622
+ "--strapi-url <url>",
623
+ "Strapi REST API URL",
624
+ "http://localhost:1337"
625
+ ).option("--strapi-locale <locale>", "Strapi locale query param").addHelpText(
616
626
  "after",
617
627
  `
618
628
  Examples:
619
629
  cms-lab init
620
630
  cms-lab init --repository my-prismic-repo --url http://localhost:3000
631
+ cms-lab init --cms strapi --router pages --strapi-url http://localhost:1337
621
632
  cms-lab init --config cms-lab.config.ts --force
622
633
  `
623
634
  ).action(async (options) => {
@@ -897,9 +908,10 @@ async function runDoctor(options, dependencies) {
897
908
  `
898
909
  );
899
910
  const endSite = debug.time("site probe", 2);
900
- await fetchSite(config.site.url, dependencies.fetch, timeoutMs, retries);
911
+ const healthUrl = resolveSiteHealthUrl(config.site).toString();
912
+ await fetchSite(healthUrl, dependencies.fetch, timeoutMs, retries);
901
913
  endSite();
902
- writeStdout(dependencies, `site ok - ${config.site.url}
914
+ writeStdout(dependencies, `site ok - ${siteUrlForOutput(healthUrl)}
903
915
  `);
904
916
  const endCms = debug.time("cms fetch", 2);
905
917
  const documents = await fetchCmsDocuments(config.cms, dependencies);
@@ -978,13 +990,7 @@ async function runInit(options, dependencies) {
978
990
  return 2;
979
991
  }
980
992
  await mkdir(dirname(target), { recursive: true });
981
- await writeFile(
982
- target,
983
- starterConfig({
984
- repository: options.repository ?? "my-repo",
985
- url: options.url ?? "http://localhost:3000"
986
- })
987
- );
993
+ await writeFile(target, starterConfig(parseInitOptions(options)));
988
994
  writeStdout(dependencies, `created ${target}
989
995
  `);
990
996
  return 0;
@@ -1206,7 +1212,9 @@ function describeCms(config) {
1206
1212
  }
1207
1213
  if (config.provider === "strapi") {
1208
1214
  return `strapi url=${safeUrl(config.url)} collections=${formatList(
1209
- config.collections.map((collection) => collection.endpoint)
1215
+ (config.collections ?? []).map((collection) => collection.endpoint)
1216
+ )} singleTypes=${formatList(
1217
+ (config.singleTypes ?? []).map((singleType) => singleType.endpoint)
1210
1218
  )}`;
1211
1219
  }
1212
1220
  if (config.provider === "directus") {
@@ -1250,6 +1258,16 @@ function safeUrl(value) {
1250
1258
  return "<invalid-url>";
1251
1259
  }
1252
1260
  }
1261
+ function siteUrlForOutput(value) {
1262
+ try {
1263
+ const url = new URL(value);
1264
+ const auth = url.username || url.password ? "[redacted]@" : "";
1265
+ const hash = url.hash ? "#[redacted]" : "";
1266
+ return `${url.protocol}//${auth}${url.host}${url.pathname}${url.search ? "?[redacted]" : ""}${hash}`;
1267
+ } catch {
1268
+ return redactSensitive(value);
1269
+ }
1270
+ }
1253
1271
  function formatList(values) {
1254
1272
  return values.length > 0 ? values.join(",") : "none";
1255
1273
  }
@@ -1516,12 +1534,33 @@ async function fileExists(path) {
1516
1534
  function plural3(value, singular) {
1517
1535
  return value === 1 ? singular : `${singular}s`;
1518
1536
  }
1537
+ function parseInitOptions(options) {
1538
+ const cms = options.cms ?? "prismic";
1539
+ if (cms !== "prismic" && cms !== "strapi") {
1540
+ throw new ConfigLoadError("--cms must be one of: prismic, strapi");
1541
+ }
1542
+ const router = options.router ?? "app";
1543
+ if (router !== "app" && router !== "pages") {
1544
+ throw new ConfigLoadError("--router must be one of: app, pages");
1545
+ }
1546
+ return {
1547
+ cms,
1548
+ router,
1549
+ repository: options.repository ?? "my-repo",
1550
+ url: options.url ?? "http://localhost:3000",
1551
+ strapiUrl: options.strapiUrl ?? "http://localhost:1337",
1552
+ strapiLocale: options.strapiLocale
1553
+ };
1554
+ }
1519
1555
  function starterConfig(options) {
1556
+ if (options.cms === "strapi") {
1557
+ return strapiStarterConfig(options);
1558
+ }
1520
1559
  return `import { defineConfig } from "@cms-lab/core";
1521
1560
 
1522
1561
  export default defineConfig({
1523
1562
  site: { url: ${JSON.stringify(options.url)} },
1524
- framework: { type: "next", router: "app" },
1563
+ framework: { type: "next", router: ${JSON.stringify(options.router)} },
1525
1564
  cms: {
1526
1565
  provider: "prismic",
1527
1566
  repositoryName: ${JSON.stringify(options.repository)},
@@ -1538,6 +1577,45 @@ export default defineConfig({
1538
1577
  });
1539
1578
  `;
1540
1579
  }
1580
+ function strapiStarterConfig(options) {
1581
+ const localeLine = options.strapiLocale ? `
1582
+ locale: ${JSON.stringify(options.strapiLocale)},` : "";
1583
+ return `import { defineConfig, strapiRelationSlug } from "@cms-lab/core";
1584
+
1585
+ export default defineConfig({
1586
+ site: {
1587
+ url: ${JSON.stringify(options.url)},
1588
+ // Use healthPath when your app's root redirects or errors but a locale route is healthy.
1589
+ // healthPath: "/en",
1590
+ },
1591
+ framework: { type: "next", router: ${JSON.stringify(options.router)} },
1592
+ cms: {
1593
+ provider: "strapi",
1594
+ url: ${JSON.stringify(options.strapiUrl)},
1595
+ token: process.env.STRAPI_TOKEN,${localeLine}
1596
+ collections: [
1597
+ { type: "page", endpoint: "pages", uidField: "slug" },
1598
+ { type: "article", endpoint: "articles", uidField: "slug" },
1599
+ ],
1600
+ singleTypes: [
1601
+ { type: "navbar", endpoint: "navbar" },
1602
+ { type: "footer", endpoint: "footer" },
1603
+ ],
1604
+ },
1605
+ routes: [
1606
+ { type: "page", pattern: "/:slug", getPath: (doc) => \`/\${doc.uid}\` },
1607
+ {
1608
+ type: "article",
1609
+ pattern: "/blog/:topic/:slug",
1610
+ getPath: (doc) => {
1611
+ const topic = strapiRelationSlug(doc.data, "topic") ?? "uncategorized";
1612
+ return \`/blog/\${topic}/\${doc.uid}\`;
1613
+ },
1614
+ },
1615
+ ],
1616
+ });
1617
+ `;
1618
+ }
1541
1619
 
1542
1620
  export {
1543
1621
  runCli
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runCli
3
- } from "./chunk-VARQUY5N.js";
3
+ } from "./chunk-34UP25NH.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.0.10",
3
+ "version": "1.2.0",
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/core": "1.0.10",
51
- "@cms-lab/contentful": "1.0.10",
52
- "@cms-lab/directus": "1.0.10",
53
- "@cms-lab/prismic": "1.0.10",
54
- "@cms-lab/reporter": "1.0.10",
55
- "@cms-lab/next": "1.0.10",
56
- "@cms-lab/sanity": "1.0.10",
57
- "@cms-lab/wordpress": "1.0.10",
58
- "@cms-lab/strapi": "1.0.10"
50
+ "@cms-lab/contentful": "1.2.0",
51
+ "@cms-lab/core": "1.2.0",
52
+ "@cms-lab/directus": "1.2.0",
53
+ "@cms-lab/prismic": "1.2.0",
54
+ "@cms-lab/reporter": "1.2.0",
55
+ "@cms-lab/sanity": "1.2.0",
56
+ "@cms-lab/wordpress": "1.2.0",
57
+ "@cms-lab/strapi": "1.2.0",
58
+ "@cms-lab/next": "1.2.0"
59
59
  },
60
60
  "author": "Afaq Rashid",
61
61
  "scripts": {