@farming-labs/next 0.1.70 → 0.1.72

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.
Files changed (2) hide show
  1. package/dist/config.mjs +113 -0
  2. package/package.json +3 -3
package/dist/config.mjs CHANGED
@@ -87,6 +87,7 @@ export const { GET, POST } = createDocsAPI({
87
87
  mcp: docsConfig.mcp,
88
88
  search: docsConfig.search,
89
89
  analytics: docsConfig.analytics,
90
+ observability: docsConfig.observability,
90
91
  ai: docsConfig.ai,
91
92
  });
92
93
 
@@ -104,6 +105,7 @@ export const { GET, POST, DELETE } = createDocsMCPAPI({
104
105
  ordering: docsConfig.ordering,
105
106
  search: docsConfig.search,
106
107
  analytics: docsConfig.analytics,
108
+ observability: docsConfig.observability,
107
109
  mcp: docsConfig.mcp,
108
110
  });
109
111
 
@@ -860,6 +862,106 @@ function dedupeRewrites(rewrites) {
860
862
  }
861
863
  return result;
862
864
  }
865
+ function dedupeRedirects(redirects) {
866
+ const seen = /* @__PURE__ */ new Set();
867
+ const result = [];
868
+ for (const redirect of redirects) {
869
+ const key = redirect.source;
870
+ if (seen.has(key)) continue;
871
+ seen.add(key);
872
+ result.push(redirect);
873
+ }
874
+ return result;
875
+ }
876
+ function resolveDocsPageSourceFile(dir) {
877
+ return ["page.mdx", "page.md"].map((fileName) => join(dir, fileName)).find((candidate) => existsSync(candidate));
878
+ }
879
+ function readDocsPageFrontmatter(filePath) {
880
+ try {
881
+ return matter(readFileSync(filePath, "utf-8")).data;
882
+ } catch {
883
+ return {};
884
+ }
885
+ }
886
+ function resolveDocsPageOrder(dir) {
887
+ const pageSource = resolveDocsPageSourceFile(dir);
888
+ if (!pageSource) return Number.POSITIVE_INFINITY;
889
+ const data = readDocsPageFrontmatter(pageSource);
890
+ return typeof data.order === "number" ? data.order : Number.POSITIVE_INFINITY;
891
+ }
892
+ function resolveDocsPageFolderIndexBehavior(data) {
893
+ const sidebar = data.sidebar;
894
+ if (!sidebar || typeof sidebar !== "object") return void 0;
895
+ const value = sidebar.folderIndexBehavior;
896
+ return value === "link" || value === "toggle" || value === "hidden" ? value : void 0;
897
+ }
898
+ function listSortedDocsChildDirectories(dir) {
899
+ let entries;
900
+ try {
901
+ entries = readdirSync(dir);
902
+ } catch {
903
+ return [];
904
+ }
905
+ return entries.map((name) => ({
906
+ name,
907
+ fullPath: join(dir, name)
908
+ })).filter(({ fullPath }) => {
909
+ try {
910
+ return statSync(fullPath).isDirectory();
911
+ } catch {
912
+ return false;
913
+ }
914
+ }).sort((left, right) => {
915
+ const leftOrder = resolveDocsPageOrder(left.fullPath);
916
+ const rightOrder = resolveDocsPageOrder(right.fullPath);
917
+ if (leftOrder !== rightOrder) return leftOrder - rightOrder;
918
+ return left.name.localeCompare(right.name);
919
+ }).map(({ name }) => name);
920
+ }
921
+ function findFirstVisibleDocsChildSlug(dir, slugParts) {
922
+ for (const name of listSortedDocsChildDirectories(dir)) {
923
+ const childDir = join(dir, name);
924
+ const childSlugParts = [...slugParts, name];
925
+ const pageSource = resolveDocsPageSourceFile(childDir);
926
+ if (!pageSource) {
927
+ const descendant = findFirstVisibleDocsChildSlug(childDir, childSlugParts);
928
+ if (descendant) return descendant;
929
+ continue;
930
+ }
931
+ const data = readDocsPageFrontmatter(pageSource);
932
+ const folderIndexBehavior = resolveDocsPageFolderIndexBehavior(data);
933
+ if (data.hidden === true || folderIndexBehavior === "hidden") {
934
+ const descendant = findFirstVisibleDocsChildSlug(childDir, childSlugParts);
935
+ if (descendant) return descendant;
936
+ continue;
937
+ }
938
+ return childSlugParts;
939
+ }
940
+ }
941
+ function buildHiddenFolderRedirects(docsDir, entry) {
942
+ const redirects = [];
943
+ function scan(dir, slugParts) {
944
+ if (!existsSync(dir)) return;
945
+ const pageSource = resolveDocsPageSourceFile(dir);
946
+ if (pageSource) {
947
+ if (resolveDocsPageFolderIndexBehavior(readDocsPageFrontmatter(pageSource)) === "hidden") {
948
+ const destinationSlug = findFirstVisibleDocsChildSlug(dir, slugParts);
949
+ if (destinationSlug && destinationSlug.join("/") !== slugParts.join("/")) {
950
+ const source = slugParts.length > 0 ? `/${entry}/${slugParts.join("/")}` : `/${entry}`;
951
+ const destination = destinationSlug.length > 0 ? `/${entry}/${destinationSlug.join("/")}` : `/${entry}`;
952
+ redirects.push({
953
+ source,
954
+ destination,
955
+ permanent: false
956
+ });
957
+ }
958
+ }
959
+ }
960
+ for (const name of listSortedDocsChildDirectories(dir)) scan(join(dir, name), [...slugParts, name]);
961
+ }
962
+ scan(docsDir, []);
963
+ return dedupeRedirects(redirects);
964
+ }
863
965
  function mergeDocsMarkdownRewrites(entry, mcp, agentFeedback, result) {
864
966
  const autoRewrites = [
865
967
  ...buildAgentSpecRewrites(),
@@ -880,6 +982,9 @@ function mergeDocsMarkdownRewrites(entry, mcp, agentFeedback, result) {
880
982
  fallback: result.fallback ?? []
881
983
  };
882
984
  }
985
+ function mergeDocsRedirects(autoRedirects, redirects) {
986
+ return dedupeRedirects([...redirects ?? [], ...autoRedirects]);
987
+ }
883
988
  function withDocs(nextConfig = {}) {
884
989
  const root = process.cwd();
885
990
  const workspaceRoot = findDocsWorkspaceRoot(root);
@@ -1053,11 +1158,19 @@ function withDocs(nextConfig = {}) {
1053
1158
  const existingTracingIncludes = nextConfig.outputFileTracingIncludes ?? {};
1054
1159
  const docsTraceGlob = docsContentDir.replace(/\\/g, "/").replace(/^\.?\//, "") + "/**/*";
1055
1160
  const skillTraceFile = "skill.md";
1161
+ const docsContentRoot = isAbsolute(docsContentDir) ? docsContentDir : join(root, docsContentDir);
1056
1162
  if (!isStaticExport) {
1057
1163
  const existingRewrites = nextConfig.rewrites;
1058
1164
  nextConfig.rewrites = async () => {
1059
1165
  return mergeDocsMarkdownRewrites(entry, mcp, agentFeedback, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
1060
1166
  };
1167
+ const autoRedirects = buildHiddenFolderRedirects(docsContentRoot, entry);
1168
+ if (autoRedirects.length > 0) {
1169
+ const existingRedirects = nextConfig.redirects;
1170
+ nextConfig.redirects = async () => {
1171
+ return mergeDocsRedirects(autoRedirects, typeof existingRedirects === "function" ? await existingRedirects() : existingRedirects);
1172
+ };
1173
+ }
1061
1174
  }
1062
1175
  nextConfig.outputFileTracingIncludes = {
1063
1176
  ...existingTracingIncludes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/next",
3
- "version": "0.1.70",
3
+ "version": "0.1.72",
4
4
  "description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
5
5
  "keywords": [
6
6
  "docs",
@@ -95,8 +95,8 @@
95
95
  "tsdown": "^0.20.3",
96
96
  "typescript": "^5.9.3",
97
97
  "vitest": "^3.2.4",
98
- "@farming-labs/docs": "0.1.70",
99
- "@farming-labs/theme": "0.1.70"
98
+ "@farming-labs/theme": "0.1.72",
99
+ "@farming-labs/docs": "0.1.72"
100
100
  },
101
101
  "peerDependencies": {
102
102
  "@farming-labs/docs": ">=0.0.1",