@clarify-labs/cli 0.11.10 → 0.11.13

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.
@@ -742,6 +742,8 @@ function buildNavigationFromConfig(routes, config) {
742
742
  title: resolveLocalizedText(item.group, "", "") ?? "",
743
743
  icon: item.icon,
744
744
  layout: item.layout,
745
+ visible: item.visible,
746
+ searchable: item.searchable,
745
747
  children
746
748
  };
747
749
  }
@@ -771,6 +773,8 @@ function buildNavigationFromConfig(routes, config) {
771
773
  path: children[0]?.path ?? "/",
772
774
  title: resolveLocalizedText(group.group, "", "") ?? "",
773
775
  icon: group.icon,
776
+ visible: group.visible,
777
+ searchable: group.searchable,
774
778
  children
775
779
  };
776
780
  });
@@ -796,6 +800,8 @@ function buildLocalizedNavigationForLocale(routes, config, locale, locales) {
796
800
  title: resolveLocalizedText(item.group, locale, locales.default) ?? "",
797
801
  icon: item.icon,
798
802
  layout: item.layout,
803
+ visible: item.visible,
804
+ searchable: item.searchable,
799
805
  children
800
806
  };
801
807
  }
@@ -816,6 +822,8 @@ function buildLocalizedNavigationForLocale(routes, config, locale, locales) {
816
822
  path: children[0]?.path ?? localizedRoutePath("/", locale, locales),
817
823
  title: resolveLocalizedText(group.group, locale, locales.default) ?? "",
818
824
  icon: group.icon,
825
+ visible: group.visible,
826
+ searchable: group.searchable,
819
827
  children
820
828
  };
821
829
  });
@@ -1442,6 +1450,7 @@ function routeToRuntimeManifestEntry(route, component, mode) {
1442
1450
  if (route.locale) entry.locale = route.locale;
1443
1451
  if (route.isFallback) entry.isFallback = true;
1444
1452
  if (route.isBareAlias) entry.isBareAlias = true;
1453
+ if (route.searchable === false) entry.searchable = false;
1445
1454
  if (route.alternates) entry.alternates = route.alternates;
1446
1455
  if (route.meta.description) entry.description = route.meta.description;
1447
1456
  if (route.meta.keywords?.length) entry.keywords = route.meta.keywords;
@@ -1773,7 +1782,7 @@ function createViteAdapter(engine) {
1773
1782
  }
1774
1783
  var cliPackageVersion = {
1775
1784
  name: "@clarify-labs/cli",
1776
- version: "0.11.10",
1785
+ version: "0.11.13",
1777
1786
  license: "AGPL-3.0-only",
1778
1787
  type: "module",
1779
1788
  repository: {
@@ -1896,6 +1905,49 @@ function readRouteArtifactContent(route) {
1896
1905
  const content = readRouteContent(route);
1897
1906
  return shouldUseUtf8Signature(route) ? withUtf8Signature(content) : content;
1898
1907
  }
1908
+ function mergeOpenAPIRecord(target, source, section, filePath) {
1909
+ if (!source) return;
1910
+ for (const [key, value] of Object.entries(source)) {
1911
+ const existing = target[key];
1912
+ if (existing !== void 0 && JSON.stringify(existing) !== JSON.stringify(value)) throw new Error(`[clarify] Cannot aggregate OpenAPI specs: conflicting ${section} entry "${key}" in ${filePath}.`);
1913
+ target[key] = value;
1914
+ }
1915
+ }
1916
+ function createRootOpenAPISpec(routes, projectConfig) {
1917
+ const paths = {};
1918
+ const webhooks = {};
1919
+ const components = {};
1920
+ const tags = /* @__PURE__ */ new Map();
1921
+ const defaultLocale = projectConfig.locales?.default;
1922
+ for (const route of routes) {
1923
+ if (route.kind !== "openapi" || route.diagnostic || !route.source.content || defaultLocale && route.locale && route.locale !== defaultLocale) continue;
1924
+ const filePath = route.source.filePath;
1925
+ const spec = JSON.parse(route.source.content);
1926
+ mergeOpenAPIRecord(paths, spec.paths, "paths", filePath);
1927
+ mergeOpenAPIRecord(webhooks, "webhooks" in spec ? spec.webhooks : void 0, "webhooks", filePath);
1928
+ for (const [section, entries] of Object.entries(spec.components ?? {})) {
1929
+ components[section] ??= {};
1930
+ mergeOpenAPIRecord(components[section], entries, `components.${section}`, filePath);
1931
+ }
1932
+ for (const tag of spec.tags ?? []) {
1933
+ const existing = tags.get(tag.name);
1934
+ if (existing !== void 0 && JSON.stringify(existing) !== JSON.stringify(tag)) throw new Error(`[clarify] Cannot aggregate OpenAPI specs: conflicting tag "${tag.name}" in ${filePath}.`);
1935
+ tags.set(tag.name, tag);
1936
+ }
1937
+ }
1938
+ return {
1939
+ openapi: "3.1.0",
1940
+ info: {
1941
+ title: projectConfig.title,
1942
+ description: projectConfig.description,
1943
+ version: "1.0.0"
1944
+ },
1945
+ paths,
1946
+ ...Object.keys(webhooks).length > 0 ? { webhooks } : {},
1947
+ ...Object.keys(components).length > 0 ? { components } : {},
1948
+ ...tags.size > 0 ? { tags: [...tags.values()] } : {}
1949
+ };
1950
+ }
1899
1951
  function isLlmsTxtRoute(route) {
1900
1952
  return !route.path.split("/").includes("404");
1901
1953
  }
@@ -1995,6 +2047,14 @@ function serveContentArtifacts(req, res, projectConfig, routes) {
1995
2047
  res.end(createLlmsTxtArtifact(routes, projectConfig), "utf8");
1996
2048
  return true;
1997
2049
  }
2050
+ if (contentPath === "/openapi.json" || contentPath === "/openapi.yml") {
2051
+ const spec = createRootOpenAPISpec(routes, projectConfig);
2052
+ const isJson = contentPath.endsWith(".json");
2053
+ res.statusCode = 200;
2054
+ res.setHeader("Content-Type", isJson ? "application/json; charset=utf-8" : "text/yaml; charset=utf-8");
2055
+ res.end(isJson ? JSON.stringify(spec, null, 2) : stringify(spec, { lineWidth: 0 }), "utf8");
2056
+ return true;
2057
+ }
1998
2058
  if (contentPath.endsWith(".openapi.yaml")) {
1999
2059
  const jsonPath = contentPath.replace(/\.yaml$/, ".json");
2000
2060
  const route = routes.find((route) => route.artifacts?.contentArtifactUrl === jsonPath);
@@ -2054,6 +2114,14 @@ function createContentArtifactsPlugin() {
2054
2114
  fileName: "llms.txt",
2055
2115
  source: createLlmsTxtArtifact(ctx.routes, ctx.projectConfig)
2056
2116
  });
2117
+ const rootOpenAPISpec = createRootOpenAPISpec(ctx.routes, ctx.projectConfig);
2118
+ assets.push({
2119
+ fileName: "openapi.json",
2120
+ source: JSON.stringify(rootOpenAPISpec, null, 2)
2121
+ }, {
2122
+ fileName: "openapi.yml",
2123
+ source: stringify(rootOpenAPISpec, { lineWidth: 0 })
2124
+ });
2057
2125
  return assets;
2058
2126
  }
2059
2127
  }
@@ -2281,7 +2349,7 @@ function routeSearchContent(route) {
2281
2349
  * Convert a `ContentRoute` into the document shape stored in the Orama index.
2282
2350
  */
2283
2351
  function routeToSearchDocument(route, defaultLocale) {
2284
- if (route.isBareAlias) return null;
2352
+ if (route.isBareAlias || route.searchable === false) return null;
2285
2353
  const content = routeSearchContent(route);
2286
2354
  if (!content.trim()) return null;
2287
2355
  return {
@@ -2344,7 +2412,7 @@ function collectIndexedLocales(routes, defaultLocale) {
2344
2412
  const seen = /* @__PURE__ */ new Set();
2345
2413
  const locales = [];
2346
2414
  for (const route of routes) {
2347
- if (route.isBareAlias) continue;
2415
+ if (route.isBareAlias || route.searchable === false) continue;
2348
2416
  const code = route.locale ?? defaultLocale ?? "en";
2349
2417
  if (!seen.has(code)) {
2350
2418
  seen.add(code);
@@ -2797,7 +2865,7 @@ function sourceSpecIdFromPath(filePath, projectRoot) {
2797
2865
  }
2798
2866
  function routeSpecModuleIdFromSourceSpecId(sourceSpecId, tagFilter) {
2799
2867
  if (!tagFilter?.length) return sourceSpecId;
2800
- return `${sourceSpecId}_tags_${tagFilter.map((tag) => tag.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "") || "tag").join("_")}`;
2868
+ return `${sourceSpecId}_tags_${createHash("sha256").update(JSON.stringify(tagFilter)).digest("hex").slice(0, 12)}`;
2801
2869
  }
2802
2870
  function openAPIRegistryKeys(route) {
2803
2871
  const keys = /* @__PURE__ */ new Set();
@@ -2974,7 +3042,7 @@ async function generateDevSearchIndex(ctx, root, pagefind) {
2974
3042
  try {
2975
3043
  let pageCount = 0;
2976
3044
  for (const route of ctx.routes) {
2977
- if (route.isBareAlias) continue;
3045
+ if (route.isBareAlias || route.searchable === false) continue;
2978
3046
  const content = routeSearchContent(route);
2979
3047
  if (!content.trim()) continue;
2980
3048
  const result = await index.addCustomRecord({
@@ -3434,6 +3502,38 @@ function handleRouteConflicts(routes, development) {
3434
3502
  assertNoRouteConflicts(routes);
3435
3503
  return routes;
3436
3504
  }
3505
+ function unsearchablePaths(navigation) {
3506
+ const paths = /* @__PURE__ */ new Set();
3507
+ const visit = (nodes, inherited = true) => {
3508
+ for (const node of nodes) {
3509
+ const searchable = inherited && node.searchable !== false;
3510
+ if (!searchable) paths.add(node.path);
3511
+ visit(node.children ?? [], searchable);
3512
+ }
3513
+ };
3514
+ switch (navigation.kind) {
3515
+ case "flat":
3516
+ visit(navigation.nodes);
3517
+ break;
3518
+ case "tabbed":
3519
+ navigation.tabs.forEach((tab) => visit(tab.children));
3520
+ break;
3521
+ case "localized":
3522
+ Object.values(navigation.locales).forEach((nodes) => visit(nodes));
3523
+ break;
3524
+ case "localized-tabbed":
3525
+ Object.values(navigation.locales).forEach((locale) => locale.tabs.forEach((tab) => visit(tab.children)));
3526
+ break;
3527
+ }
3528
+ return paths;
3529
+ }
3530
+ function applySearchability(routes, navigation) {
3531
+ const excludedPaths = unsearchablePaths(navigation);
3532
+ return routes.map((route) => excludedPaths.has(route.path) ? {
3533
+ ...route,
3534
+ searchable: false
3535
+ } : route);
3536
+ }
3437
3537
  async function resolveRouteState(routes, plugins, ctx, development) {
3438
3538
  const tabs = ctx.projectConfig.navigation?.tabs;
3439
3539
  const configuredRoutes = applyConfiguredPageRoutePaths(routes, tabs, ctx.projectConfig.locales);
@@ -3441,10 +3541,11 @@ async function resolveRouteState(routes, plugins, ctx, development) {
3441
3541
  routes: configuredRoutes,
3442
3542
  navigation: buildNavigationTree(configuredRoutes, ctx)
3443
3543
  }, ctx);
3444
- const finalRoutes = handleRouteConflicts(resolved.routes, development);
3544
+ const conflictRoutes = handleRouteConflicts(resolved.routes, development);
3545
+ const finalNavigation = conflictRoutes === resolved.routes ? resolved.navigation : buildNavigationTree(conflictRoutes, ctx);
3445
3546
  return {
3446
- routes: finalRoutes,
3447
- navigation: finalRoutes === resolved.routes ? resolved.navigation : buildNavigationTree(finalRoutes, ctx)
3547
+ routes: applySearchability(conflictRoutes, finalNavigation),
3548
+ navigation: finalNavigation
3448
3549
  };
3449
3550
  }
3450
3551
  //#endregion
@@ -3556,7 +3657,7 @@ function injectSSRIntoTemplate(template, appHtml, contextOrConfig, route) {
3556
3657
  html = setNamedMeta(html, "description", route?.meta.description ?? projectConfig.description);
3557
3658
  html = setNamedMeta(html, "keywords", route?.meta.keywords?.join(", "));
3558
3659
  html = injectCanonicalUrl(html, contextOrConfig, route);
3559
- const dataPagefindIgnore = route?.isBareAlias ? " data-pagefind-ignore" : "";
3660
+ const dataPagefindIgnore = route?.isBareAlias || route?.searchable === false ? " data-pagefind-ignore" : "";
3560
3661
  html = html.replace(/<div id="root">([\s\S]*?)<\/div>/, `<div id="root"${dataPagefindIgnore}>${appHtml}</div>`);
3561
3662
  return html;
3562
3663
  }
@@ -4065,7 +4166,7 @@ var ClarifyEngine = class {
4065
4166
  assertNoContentDiagnostics(this.routes);
4066
4167
  const outputDir = this.runtime.outputDirectory ?? this.generateOptions.outputDirectory;
4067
4168
  if (!outputDir) throw new Error("[clarify] outputDirectory is required before SSG runs");
4068
- const ssrOutputDir = join(outputDir, ".ssr");
4169
+ const ssrOutputDir = createClarifyTempDir("ssr-output");
4069
4170
  let tempEntryPath;
4070
4171
  try {
4071
4172
  tempEntryPath = createTempEntryFile(SSR_ENTRY_CODE);
@@ -4081,6 +4182,7 @@ var ClarifyEngine = class {
4081
4182
  console.error("[clarify] SSG failed:", err);
4082
4183
  throw err;
4083
4184
  } finally {
4185
+ removeClarifyTempDir(ssrOutputDir);
4084
4186
  if (tempEntryPath) try {
4085
4187
  rmSync(tempEntryPath, { force: true });
4086
4188
  } catch {}
@@ -4123,4 +4225,4 @@ function createClarifyEngine(options = {}) {
4123
4225
  //#endregion
4124
4226
  export { createClarifyTempDir as a, cliPackageVersion as c, defineConfig as d, findRouteConflicts as i, cliPackageVersionWithCaret as l, createClarifyEngine as n, deserializeSearchIndex as o, createClarifyRuntimeAliases as r, searchMcpIndex as s, ClarifyEngine as t, createViteAdapter as u };
4125
4227
 
4126
- //# sourceMappingURL=engine-DisWfZp-.js.map
4228
+ //# sourceMappingURL=engine-CTFNxQRw.js.map