@clarify-labs/cli 0.11.8 → 0.11.10

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/output/cli.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
- const require_engine = require("./engine-pubnVIwZ.cjs");
2
+ const require_engine = require("./engine-BuYsLjJN.cjs");
3
3
  let node_path = require("node:path");
4
4
  let node_fs_promises = require("node:fs/promises");
5
+ let node_child_process = require("node:child_process");
5
6
  let node_fs = require("node:fs");
6
7
  let vite = require("vite");
7
8
  let zod = require("zod");
@@ -11,7 +12,6 @@ let node_os = require("node:os");
11
12
  let node_module = require("node:module");
12
13
  let cac = require("cac");
13
14
  let _clarify_labs_templates = require("@clarify-labs/templates");
14
- let node_child_process = require("node:child_process");
15
15
  let _modelcontextprotocol_sdk_server_mcp_js = require("@modelcontextprotocol/sdk/server/mcp.js");
16
16
  let _modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
17
17
  //#region source/core/runtime/log.ts
package/output/cli.js CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { a as createClarifyTempDir, c as cliPackageVersion, i as findRouteConflicts, l as cliPackageVersionWithCaret, n as createClarifyEngine, o as deserializeSearchIndex, r as createClarifyRuntimeAliases, s as searchMcpIndex, u as createViteAdapter } from "./engine-B_0YOc2B.js";
2
+ import { a as createClarifyTempDir, c as cliPackageVersion, i as findRouteConflicts, l as cliPackageVersionWithCaret, n as createClarifyEngine, o as deserializeSearchIndex, r as createClarifyRuntimeAliases, s as searchMcpIndex, u as createViteAdapter } from "./engine-DisWfZp-.js";
3
3
  import { dirname, extname, isAbsolute, join, normalize, relative, resolve } from "node:path";
4
4
  import { lstat, mkdir, readFile, stat, writeFile } from "node:fs/promises";
5
+ import { spawnSync } from "node:child_process";
5
6
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
7
  import { build, createLogger, createServer } from "vite";
7
8
  import { z } from "zod";
@@ -11,7 +12,6 @@ import { homedir } from "node:os";
11
12
  import { createRequire } from "node:module";
12
13
  import { cac } from "cac";
13
14
  import { copyTemplateDirectory, getTemplateDirectory, resolveTemplate } from "@clarify-labs/templates";
14
- import { spawnSync } from "node:child_process";
15
15
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
16
16
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
17
17
  //#region source/core/runtime/log.ts
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { ClarifyVariableValue } from '../../types.js';
2
+ import { ClarifyNavbarMenuItem, ClarifyVariableValue } from '../../types.js';
3
3
  export declare const clarifyFeaturesConfigSchema: z.ZodObject<{
4
4
  search: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodDefault<z.ZodObject<{
5
5
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -126,11 +126,7 @@ export declare const clarifyProjectConfigSchema: z.ZodObject<{
126
126
  }>>;
127
127
  }, z.core.$strict>>;
128
128
  navigation: z.ZodOptional<z.ZodObject<{
129
- links: z.ZodOptional<z.ZodArray<z.ZodObject<{
130
- label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
131
- href: z.ZodString;
132
- external: z.ZodOptional<z.ZodBoolean>;
133
- }, z.core.$strict>>>;
129
+ menus: z.ZodOptional<z.ZodArray<z.ZodType<ClarifyNavbarMenuItem, unknown, z.core.$ZodTypeInternals<ClarifyNavbarMenuItem, unknown>>>>;
134
130
  tabs: z.ZodOptional<z.ZodArray<z.ZodObject<{
135
131
  tab: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
136
132
  icon: z.ZodOptional<z.ZodString>;
@@ -143,14 +139,12 @@ export declare const clarifyProjectConfigSchema: z.ZodObject<{
143
139
  link: z.ZodOptional<z.ZodObject<{
144
140
  label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
145
141
  href: z.ZodString;
146
- external: z.ZodOptional<z.ZodBoolean>;
147
142
  }, z.core.$strict>>;
148
143
  }, z.core.$strict>>;
149
144
  footer: z.ZodOptional<z.ZodObject<{
150
145
  links: z.ZodOptional<z.ZodArray<z.ZodObject<{
151
146
  label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
152
147
  href: z.ZodString;
153
- external: z.ZodOptional<z.ZodBoolean>;
154
148
  }, z.core.$strict>>>;
155
149
  socials: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
156
150
  copyright: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
@@ -158,11 +152,11 @@ export declare const clarifyProjectConfigSchema: z.ZodObject<{
158
152
  locales: z.ZodOptional<z.ZodObject<{
159
153
  default: z.ZodOptional<z.ZodString>;
160
154
  missing: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"fallback">, z.ZodLiteral<"404">, z.ZodLiteral<"hide">]>>;
161
- locales: z.ZodArray<z.ZodObject<{
155
+ locales: z.ZodOptional<z.ZodArray<z.ZodObject<{
162
156
  code: z.ZodString;
163
157
  label: z.ZodString;
164
158
  dir: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"ltr">, z.ZodLiteral<"rtl">]>>;
165
- }, z.core.$strict>>;
159
+ }, z.core.$strict>>>;
166
160
  }, z.core.$strict>>;
167
161
  variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<ClarifyVariableValue, unknown, z.core.$ZodTypeInternals<ClarifyVariableValue, unknown>>>>;
168
162
  features: z.ZodOptional<z.ZodObject<{
@@ -44,6 +44,7 @@ let mdast_util_to_string = require("mdast-util-to-string");
44
44
  let remark = require("remark");
45
45
  let gray_matter = require("gray-matter");
46
46
  gray_matter = __toESM(gray_matter, 1);
47
+ let node_child_process = require("node:child_process");
47
48
  let node_fs = require("node:fs");
48
49
  let vite = require("vite");
49
50
  let zod = require("zod");
@@ -351,6 +352,42 @@ async function compileMarkdownContent(content, options = {}) {
351
352
  }
352
353
  }
353
354
  //#endregion
355
+ //#region source/parsers/routes/git-metadata.ts
356
+ function normalizeDate(value) {
357
+ if (!value) return void 0;
358
+ const date = new Date(value);
359
+ return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
360
+ }
361
+ async function getFileUpdatedAt(filePath, contentRoot) {
362
+ try {
363
+ const result = (0, node_child_process.spawnSync)("git", [
364
+ "log",
365
+ "-1",
366
+ "--format=%cI",
367
+ "--",
368
+ (0, node_path.relative)(contentRoot, filePath)
369
+ ], {
370
+ cwd: contentRoot,
371
+ encoding: "utf8",
372
+ stdio: [
373
+ "ignore",
374
+ "pipe",
375
+ "ignore"
376
+ ]
377
+ });
378
+ const committedAt = normalizeDate(result.status === 0 ? result.stdout.trim() : void 0);
379
+ if (committedAt) return committedAt;
380
+ } catch {}
381
+ try {
382
+ return (await (0, node_fs_promises.stat)(filePath)).mtime.toISOString();
383
+ } catch {
384
+ return;
385
+ }
386
+ }
387
+ function resolveUpdatedAt(frontmatter, detectedAt) {
388
+ return normalizeDate(typeof frontmatter.updatedAt === "string" ? frontmatter.updatedAt : void 0) ?? detectedAt;
389
+ }
390
+ //#endregion
354
391
  //#region source/parsers/routes/routes.ts
355
392
  function kebabToTitle(str) {
356
393
  return str.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
@@ -450,6 +487,7 @@ async function findContentRoutes(dir, base = dir, options = {}) {
450
487
  const cleanPath = ("/" + pathParts.map((p) => p === "index" ? "" : p).filter(Boolean).join("/")).replace(/\/+/g, "/").replace(/\/$/, "") || "/";
451
488
  const source = await (0, node_fs_promises.readFile)(fullPath, "utf-8");
452
489
  const { frontmatter, content } = await (options.contentProcessor ?? createContentProcessor()).processMdx(source, fullPath);
490
+ const updatedAt = resolveUpdatedAt(frontmatter, await getFileUpdatedAt(fullPath, base));
453
491
  const page = {
454
492
  path: cleanPath,
455
493
  filePath: fullPath,
@@ -470,6 +508,9 @@ async function findContentRoutes(dir, base = dir, options = {}) {
470
508
  title,
471
509
  description: typeof page.frontmatter.description === "string" ? page.frontmatter.description : void 0,
472
510
  keywords: frontmatterKeywords(page.frontmatter),
511
+ group: typeof page.frontmatter.group === "string" ? page.frontmatter.group : void 0,
512
+ layout: page.frontmatter.layout === "documentation" || page.frontmatter.layout === "blog" ? page.frontmatter.layout : void 0,
513
+ updatedAt,
473
514
  sections: extractMdxSections(page.content)
474
515
  },
475
516
  module: {
@@ -579,8 +620,15 @@ async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
579
620
  }
580
621
  function buildNavigation(routes) {
581
622
  const root = [];
623
+ const groupedRoutes = /* @__PURE__ */ new Map();
582
624
  for (const route of routes) {
583
625
  if (route.path === "/" || (route.basePath ?? route.path) === "/404") continue;
626
+ if (route.meta.group) {
627
+ const grouped = groupedRoutes.get(route.meta.group) ?? [];
628
+ grouped.push(route);
629
+ groupedRoutes.set(route.meta.group, grouped);
630
+ continue;
631
+ }
584
632
  const parts = route.path.replace(/^\//, "").split("/");
585
633
  let current = root;
586
634
  for (let i = 0; i < parts.length; i++) {
@@ -592,6 +640,7 @@ function buildNavigation(routes) {
592
640
  title: i === parts.length - 1 ? route.meta.title : kebabToTitle(parts[i]),
593
641
  children: []
594
642
  };
643
+ if (i === parts.length - 1 && route.meta.layout) node.layout = route.meta.layout;
595
644
  current.push(node);
596
645
  }
597
646
  if (i === parts.length - 1 && route.meta.sections) node.sections = navigationSections(route.meta.sections);
@@ -601,6 +650,22 @@ function buildNavigation(routes) {
601
650
  }
602
651
  }
603
652
  }
653
+ for (const [title, grouped] of groupedRoutes) {
654
+ const children = buildNavigation(grouped.map((route) => ({
655
+ ...route,
656
+ meta: {
657
+ ...route.meta,
658
+ group: void 0
659
+ }
660
+ })));
661
+ const node = {
662
+ path: children[0]?.path ?? "/",
663
+ title,
664
+ children
665
+ };
666
+ if (grouped[0]?.meta.layout) node.layout = grouped[0].meta.layout;
667
+ root.push(node);
668
+ }
604
669
  return root;
605
670
  }
606
671
  function routeIntentFromPagesItem(item) {
@@ -707,6 +772,7 @@ function buildNavigationFromConfig(routes, config) {
707
772
  path: firstNavigationPath(children),
708
773
  title: resolveLocalizedText(item.group, "", "") ?? "",
709
774
  icon: item.icon,
775
+ layout: item.layout,
710
776
  children
711
777
  };
712
778
  }
@@ -760,6 +826,7 @@ function buildLocalizedNavigationForLocale(routes, config, locale, locales) {
760
826
  path: firstNavigationPath(children),
761
827
  title: resolveLocalizedText(item.group, locale, locales.default) ?? "",
762
828
  icon: item.icon,
829
+ layout: item.layout,
763
830
  children
764
831
  };
765
832
  }
@@ -971,10 +1038,10 @@ var clarifyLocalesConfigSchema = zod.z.object({
971
1038
  zod.z.literal("404"),
972
1039
  zod.z.literal("hide")
973
1040
  ]).optional(),
974
- locales: zod.z.array(clarifyLocaleConfigSchema).min(1)
1041
+ locales: zod.z.array(clarifyLocaleConfigSchema).min(1).optional()
975
1042
  }).strict().superRefine((config, ctx) => {
976
1043
  const localeCodes = /* @__PURE__ */ new Set();
977
- for (const [index, locale] of config.locales.entries()) {
1044
+ for (const [index, locale] of (config.locales ?? []).entries()) {
978
1045
  if (localeCodes.has(locale.code)) ctx.addIssue({
979
1046
  code: zod.z.ZodIssueCode.custom,
980
1047
  message: `Duplicate locale code "${locale.code}"`,
@@ -986,24 +1053,45 @@ var clarifyLocalesConfigSchema = zod.z.object({
986
1053
  });
987
1054
  localeCodes.add(locale.code);
988
1055
  }
989
- if (config.default && !localeCodes.has(config.default)) ctx.addIssue({
1056
+ if (config.default && config.locales && !localeCodes.has(config.default)) ctx.addIssue({
990
1057
  code: zod.z.ZodIssueCode.custom,
991
1058
  message: "default must be one of locales.locales",
992
1059
  path: ["default"]
993
1060
  });
994
1061
  });
995
- var clarifyNavbarLinkSchema = zod.z.object({
1062
+ var clarifyLinkConfigSchema = zod.z.object({
996
1063
  label: clarifyLocalizedTextSchema,
997
- href: zod.z.string(),
998
- external: zod.z.boolean().optional()
1064
+ href: zod.z.string()
999
1065
  }).strict();
1066
+ var clarifyNavbarMenuItemBaseSchema = {
1067
+ label: clarifyLocalizedTextSchema,
1068
+ description: clarifyLocalizedTextSchema.optional(),
1069
+ icon: zod.z.string().optional()
1070
+ };
1071
+ var clarifyNavbarMenuHrefSchema = zod.z.object({
1072
+ ...clarifyNavbarMenuItemBaseSchema,
1073
+ href: zod.z.string()
1074
+ }).strict();
1075
+ var clarifyNavbarMenuPageSchema = zod.z.object({
1076
+ ...clarifyNavbarMenuItemBaseSchema,
1077
+ page: zod.z.string()
1078
+ }).strict();
1079
+ var clarifyNavbarMenuItemsSchema = zod.z.lazy(() => zod.z.object({
1080
+ ...clarifyNavbarMenuItemBaseSchema,
1081
+ items: zod.z.array(clarifyNavbarMenuItemSchema)
1082
+ }).strict());
1083
+ var clarifyNavbarMenuItemSchema = zod.z.lazy(() => zod.z.union([
1084
+ clarifyNavbarMenuHrefSchema,
1085
+ clarifyNavbarMenuPageSchema,
1086
+ clarifyNavbarMenuItemsSchema
1087
+ ]));
1000
1088
  var clarifyBannerConfigOptionsSchema = zod.z.object({
1001
1089
  content: clarifyLocalizedTextSchema,
1002
1090
  dismissible: zod.z.boolean().optional(),
1003
- link: clarifyNavbarLinkSchema.optional()
1091
+ link: clarifyLinkConfigSchema.optional()
1004
1092
  }).strict();
1005
1093
  var clarifyFooterConfigSchema = zod.z.object({
1006
- links: zod.z.array(clarifyNavbarLinkSchema).optional(),
1094
+ links: zod.z.array(clarifyLinkConfigSchema).optional(),
1007
1095
  socials: zod.z.record(zod.z.string(), zod.z.string()).optional(),
1008
1096
  copyright: clarifyLocalizedTextSchema.optional()
1009
1097
  }).strict();
@@ -1056,6 +1144,7 @@ var clarifyPagesItemSchema = zod.z.lazy(() => zod.z.union([
1056
1144
  var clarifyPagesGroupSchema = zod.z.lazy(() => zod.z.object({
1057
1145
  group: clarifyLocalizedTextSchema,
1058
1146
  icon: zod.z.string().optional(),
1147
+ layout: zod.z.enum(["documentation", "blog"]).optional(),
1059
1148
  pages: zod.z.array(clarifyPagesItemSchema)
1060
1149
  }).strict());
1061
1150
  var clarifyPagesConfigSchema = zod.z.union([zod.z.array(clarifyPagesGroupSchema), zod.z.literal("FileTree")]);
@@ -1130,7 +1219,7 @@ var clarifyProjectConfigSchema = zod.z.object({
1130
1219
  theme: clarifyThemeConfigSchema.optional(),
1131
1220
  layout: clarifyLayoutConfigSchema.optional(),
1132
1221
  navigation: zod.z.object({
1133
- links: zod.z.array(clarifyNavbarLinkSchema).optional(),
1222
+ menus: zod.z.array(clarifyNavbarMenuItemSchema).optional(),
1134
1223
  tabs: clarifyTabsConfigSchema.optional()
1135
1224
  }).strict().optional(),
1136
1225
  banner: clarifyBannerConfigOptionsSchema.optional(),
@@ -1161,7 +1250,7 @@ function validateProjectConfig(value) {
1161
1250
  return result.data;
1162
1251
  }
1163
1252
  function resolveLocalesConfig(locales) {
1164
- if (!locales) return void 0;
1253
+ if (!locales?.locales) return void 0;
1165
1254
  const firstLocale = locales.locales[0]?.code;
1166
1255
  const defaultLocale = locales.default ?? firstLocale;
1167
1256
  if (!defaultLocale) return void 0;
@@ -1205,6 +1294,7 @@ function resolveProjectConfig(config = {}) {
1205
1294
  banner: config.banner,
1206
1295
  footer: config.footer,
1207
1296
  locales: resolveLocalesConfig(config.locales),
1297
+ defaultLocale: config.locales?.default,
1208
1298
  variables: config.variables ?? {},
1209
1299
  features: resolveFeaturesConfig(config.features)
1210
1300
  };
@@ -1361,6 +1451,7 @@ function generateConfigModule(projectConfig, version, themeEditor = false) {
1361
1451
  banner: projectConfig.banner,
1362
1452
  footer: projectConfig.footer,
1363
1453
  locales: projectConfig.locales,
1454
+ defaultLocale: projectConfig.defaultLocale,
1364
1455
  variables: projectConfig.variables,
1365
1456
  features: projectConfig.features
1366
1457
  };
@@ -1385,6 +1476,8 @@ function routeToRuntimeManifestEntry(route, component, mode) {
1385
1476
  if (route.alternates) entry.alternates = route.alternates;
1386
1477
  if (route.meta.description) entry.description = route.meta.description;
1387
1478
  if (route.meta.keywords?.length) entry.keywords = route.meta.keywords;
1479
+ if (route.meta.layout) entry.layout = route.meta.layout;
1480
+ if (route.meta.updatedAt) entry.updatedAt = route.meta.updatedAt;
1388
1481
  if (route.artifacts?.contentArtifactUrl) entry.contentArtifactUrl = route.artifacts.contentArtifactUrl;
1389
1482
  if (route.source?.sourceEditUrl) entry.sourceEditUrl = route.source.sourceEditUrl;
1390
1483
  if (route.meta.sections?.length) entry.sections = route.meta.sections.map((section) => ({
@@ -1711,7 +1804,7 @@ function createViteAdapter(engine) {
1711
1804
  }
1712
1805
  var cliPackageVersion = {
1713
1806
  name: "@clarify-labs/cli",
1714
- version: "0.11.8",
1807
+ version: "0.11.10",
1715
1808
  license: "AGPL-3.0-only",
1716
1809
  type: "module",
1717
1810
  repository: {
@@ -2753,6 +2846,7 @@ var OpenAPIPluginState = class {
2753
2846
  const specByFilePath = /* @__PURE__ */ new Map();
2754
2847
  for (const route of routes) {
2755
2848
  if (route.kind !== "openapi") continue;
2849
+ const updatedAt = await getFileUpdatedAt(route.source.filePath, ctx.contentRoot);
2756
2850
  const specFromCache = specByFilePath.get(route.source.filePath);
2757
2851
  const processor = createProjectContentProcessor(ctx.plugins, ctx);
2758
2852
  const result = specFromCache ? {
@@ -2766,6 +2860,13 @@ var OpenAPIPluginState = class {
2766
2860
  continue;
2767
2861
  }
2768
2862
  const spec = normalizeOpenAPISpecSectionIds(result.spec);
2863
+ const specWithMetadata = updatedAt && spec.info ? {
2864
+ ...spec,
2865
+ info: {
2866
+ ...spec.info,
2867
+ "x-clarify-updated-at": updatedAt
2868
+ }
2869
+ } : spec;
2769
2870
  specByFilePath.set(route.source.filePath, spec);
2770
2871
  const sourceSpecId = sourceSpecIdFromPath(route.source.filePath, ctx.generateOptions.projectRoot);
2771
2872
  route.openapi = {
@@ -2774,8 +2875,9 @@ var OpenAPIPluginState = class {
2774
2875
  };
2775
2876
  route.meta.title = spec.info?.title ?? route.meta.title;
2776
2877
  route.meta.description = spec.info?.description ?? route.meta.description;
2878
+ route.meta.updatedAt = updatedAt;
2777
2879
  route.meta.sections = extractOpenAPISections(spec, route.openapi.tagFilter);
2778
- const pageSpec = route.openapi.tagFilter?.length ? filterSpecByTags(spec, route.openapi.tagFilter) : spec;
2880
+ const pageSpec = route.openapi.tagFilter?.length ? filterSpecByTags(specWithMetadata, route.openapi.tagFilter) : specWithMetadata;
2779
2881
  const routeSpecModuleId = routeSpecModuleIdFromSourceSpecId(sourceSpecId, route.openapi.tagFilter);
2780
2882
  route.openapi.routeSpecModuleId = routeSpecModuleId;
2781
2883
  this.specModules.set(routeSpecModuleId, pageSpec);
@@ -4117,4 +4219,4 @@ Object.defineProperty(exports, "searchMcpIndex", {
4117
4219
  }
4118
4220
  });
4119
4221
 
4120
- //# sourceMappingURL=engine-pubnVIwZ.cjs.map
4222
+ //# sourceMappingURL=engine-BuYsLjJN.cjs.map