@ahmedrowaihi/8n 6.0.41 → 6.0.43

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/dist/index.mjs CHANGED
@@ -3736,7 +3736,7 @@ async function checkSelfUpdate() {
3736
3736
  });
3737
3737
  if (!res.ok) return;
3738
3738
  const { version: latest } = await res.json();
3739
- const current = "6.0.41";
3739
+ const current = "6.0.43";
3740
3740
  if (latest !== current) console.log(pc.yellow("⚠") + pc.dim(` new version available: `) + pc.cyan(latest) + pc.dim(` (current: ${current}) — run `) + pc.cyan("npm i -g @ahmedrowaihi/8n") + pc.dim(" to update"));
3741
3741
  } catch {}
3742
3742
  }
@@ -3849,7 +3849,7 @@ async function dev() {
3849
3849
  async function build({ server = false } = {}) {
3850
3850
  const { config, contentDir } = await resolveProject();
3851
3851
  const projectDir = process.cwd();
3852
- console.log(pc.cyan("8n") + pc.dim(` v6.0.41 build → ${contentDir}`));
3852
+ console.log(pc.cyan("8n") + pc.dim(` v6.0.43 build → ${contentDir}`));
3853
3853
  if (server) await runNextFlat(projectDir, "build", buildEnv({
3854
3854
  config,
3855
3855
  contentDir,
@@ -4167,7 +4167,7 @@ async function mcp() {
4167
4167
  const mcpDir = join(getStarterDir(), "content", "mcp", "en");
4168
4168
  const server = new McpServer({
4169
4169
  name: "8n",
4170
- version: "6.0.41"
4170
+ version: "6.0.43"
4171
4171
  });
4172
4172
  server.registerTool("read_me", {
4173
4173
  description: "Returns how to use the 8n MCP tools. Call this BEFORE documenting anything with 8n.",
@@ -4308,7 +4308,7 @@ Example: get_component({ name: "components" }) returns all available MDX compone
4308
4308
 
4309
4309
  //#endregion
4310
4310
  //#region src/index.ts
4311
- const program = new Command().name("8n").description("Run your 8n docs site").version("6.0.41").addOption(new Option("--debug").hideHelp()).hook("preAction", (cmd) => {
4311
+ const program = new Command().name("8n").description("Run your 8n docs site").version("6.0.43").addOption(new Option("--debug").hideHelp()).hook("preAction", (cmd) => {
4312
4312
  if (cmd.opts().debug) process.env.DEBUG_8N = "1";
4313
4313
  });
4314
4314
  program.command("init").description("Scaffold a new docs project in the current directory").action(init);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahmedrowaihi/8n",
3
- "version": "6.0.41",
3
+ "version": "6.0.43",
4
4
  "description": "8n docs — run your docs site from your content directory",
5
5
  "bin": {
6
6
  "8n": "./dist/index.mjs"
@@ -0,0 +1 @@
1
+ import{createDocsLayout as o}from"../../../../src/lib/create-docs-layout";export default o();
@@ -1 +1 @@
1
- import{createDocsLayout as o}from"../../../src/lib/create-docs-layout";export default o();
1
+ import{jsx as r,Fragment as t}from"react/jsx-runtime";export default function e({children:n}){return r(t,{children:n})}
@@ -1,2 +1 @@
1
- "use client";
2
- import{jsx as r}from"react/jsx-runtime";import{MDXPlayground as o}from"../../../src/features/mdx-playground/components/playground";export default function t(){return r(o,{})}
1
+ import{jsx as r}from"react/jsx-runtime";import{MDXPlayground as n}from"../../../src/features/mdx-playground/components/playground";import{getAllPages as o,getLLMText as t}from"../../../src/lib/source";export default async function e(){let e=(await o()).find(r=>r.url.includes("/mcp/")&&r.url.includes("components"));return r(n,{componentsContent:e?await t(e):""})}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahmedrowaihi/8n-starter",
3
- "version": "6.0.41",
3
+ "version": "6.0.43",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as r}from"react/jsx-runtime";import*as e from"react";import{AIChatContext as o}from"../../ai/chat/provider";import{useAISettings as t}from"../../ai/chat/store";import{usePlaygroundChat as n}from"../hooks/use-playground-chat";import{ProposalCtx as u}from"./proposal-context";import{PlaygroundSidebar as c}from"./playground-sidebar";export function PlaygroundAISidebar({source:o,onPropose:n,onAccept:c,onReject:a,onRejectWithFeedback:m}){let p=t(r=>r.provider),s=e.useRef(c);s.current=c;let f=e.useRef(a);f.current=a;let l=e.useRef(m);return l.current=m,r(u,{value:e.useMemo(()=>({onAccept:()=>s.current(),onReject:()=>f.current(),onRejectWithFeedback:r=>l.current(r)}),[]),children:r(i,{provider:p,source:o,onPropose:n})})}function i({provider:t,source:u,onPropose:a}){let{chat:m,clearMessages:p,sendMessage:s}=n({provider:t,source:u,onPropose:a});return r(o,{value:e.useMemo(()=>({...m,sendMessage:s,clearMessages:p}),[m,s,p]),children:r(c,{})})}
2
+ import{jsx as r}from"react/jsx-runtime";import*as e from"react";import{AIChatContext as o}from"../../ai/chat/provider";import{useAISettings as t}from"../../ai/chat/store";import{usePlaygroundChat as n}from"../hooks/use-playground-chat";import{ProposalCtx as c}from"./proposal-context";import{PlaygroundSidebar as u}from"./playground-sidebar";export function PlaygroundAISidebar({source:o,componentsContent:n,onPropose:u,onAccept:a,onReject:m,onRejectWithFeedback:p}){let s=t(r=>r.provider),f=e.useRef(a);f.current=a;let l=e.useRef(m);l.current=m;let d=e.useRef(p);return d.current=p,r(c,{value:e.useMemo(()=>({onAccept:()=>f.current(),onReject:()=>l.current(),onRejectWithFeedback:r=>d.current(r)}),[]),children:r(i,{provider:s,source:o,componentsContent:n,onPropose:u})})}function i({provider:t,source:c,componentsContent:a,onPropose:m}){let{chat:p,clearMessages:s,sendMessage:f}=n({provider:t,source:c,componentsContent:a,onPropose:m});return r(o,{value:e.useMemo(()=>({...p,sendMessage:f,clearMessages:s}),[p,f,s]),children:r(u,{})})}
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as r from"react";import{getMDXComponents as t}from"../../../components/fumadocs/mdx";import{DocsBody as n}from"../../../components/fumadocs/layout/docs/page";import{Tabs as l,TabsList as s,TabsTrigger as a,TabsContent as d}from"../../../components/ui/tabs";import i from"next/dynamic";let c=i(()=>import("./editor").then(e=>({default:e.CodeMirrorEditor})),{ssr:!1,loading:()=>e("div",{className:"min-h-0 flex-1 animate-pulse bg-muted/20"})});import{PlaygroundAISidebar as m}from"./playground-provider";import{useAISelectionStore as p}from"../../ai/chat/selection-store";import{useMDXCompiler as u}from"../hooks/use-mdx-compiler";import{useCopyButton as h}from"../../../hooks/use-copy-button";import{Button as f}from"../../../components/ui/button";import{Check as v,Copy as x}from"lucide-react";class b extends r.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e){this.props.onError(e.message)}componentDidUpdate(e){e.resetKey!==this.props.resetKey&&this.state.error&&this.setState({error:null})}render(){return this.state.error?null:this.props.children}}let g=t();export function MDXPlayground(){let{source:t,setSource:i,Content:y,error:w,boundaryKey:C,onRenderError:N}=u(),[k,R]=h(()=>navigator.clipboard.writeText(t)),A=p(e=>e.setContextText),[j,D]=r.useState("code"),[E,S]=r.useState(null),M=r.useRef("");r.useEffect(()=>(document.body.style.overflow="hidden",()=>{document.body.style.overflow=""}),[]);let P=r.useCallback((e,o,r)=>{M.current=t,S({content:e,addApprovalResponse:(e,o)=>{r(e,o),e||i(M.current),S(null)}}),D("code")},[t,i]),K=r.useCallback(()=>{E&&(i(E.content),E.addApprovalResponse(!0))},[E,i]),X=r.useCallback(()=>{E&&E.addApprovalResponse(!1)},[E]),z=r.useCallback(e=>{E&&E.addApprovalResponse(!1,e)},[E]),F=r.useCallback(e=>{i(e),E?.addApprovalResponse(!0)},[E,i]);return o(l,{value:j,onValueChange:e=>D(e),className:"flex h-dvh flex-col overflow-hidden",children:[o("div",{className:"flex shrink-0 items-center justify-between border-b border-border bg-background px-4 py-2",children:[o("div",{children:[e("h1",{className:"font-serif text-sm font-semibold text-foreground",children:"MDX Playground"}),e("p",{className:"text-xs text-muted-foreground",children:"Write MDX, see it live, copy when done."})]}),o("div",{className:"flex items-center gap-3",children:[o(s,{children:[e(a,{value:"code",children:"Code"}),e(a,{value:"preview",children:"Preview"})]}),e(f,{type:"button",onClick:R,variant:"secondary",size:"sm",className:"gap-2 [&_svg]:size-3.5",children:k?e(v,{}):e(x,{})})]})]}),o("div",{className:"flex min-h-0 flex-1 overflow-hidden",children:[o("div",{className:"flex min-w-0 flex-1 flex-col overflow-hidden",children:[o(d,{value:"code",className:"flex min-h-0 flex-1 flex-col overflow-hidden data-[state=inactive]:hidden mt-0",children:[e(c,{value:t,onChange:i,proposedContent:E?.content??null,onAllChunksResolved:F,onSelectionChange:A,className:"min-h-0 flex-1 overflow-hidden [&_.cm-editor]:h-full"}),w&&e("div",{className:"shrink-0 border-t border-red-500/30 bg-red-500/10 p-3 font-mono text-xs text-red-500 whitespace-pre-wrap",children:w})]}),e(d,{value:"preview",className:"flex min-h-0 flex-1 flex-col overflow-y-auto data-[state=inactive]:hidden mt-0",children:e(n,{className:"p-6",children:e(b,{resetKey:C,onError:N,children:y&&e(y,{components:g})})})})]}),e(m,{source:t,onPropose:P,onAccept:K,onReject:X,onRejectWithFeedback:z})]})]})}
2
+ import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as r from"react";import{getMDXComponents as t}from"../../../components/fumadocs/mdx";import{DocsBody as n}from"../../../components/fumadocs/layout/docs/page";import{Tabs as l,TabsList as s,TabsTrigger as a,TabsContent as i}from"../../../components/ui/tabs";import d from"next/dynamic";let c=d(()=>import("./editor").then(e=>({default:e.CodeMirrorEditor})),{ssr:!1,loading:()=>e("div",{className:"min-h-0 flex-1 animate-pulse bg-muted/20"})});import{PlaygroundAISidebar as m}from"./playground-provider";import{useAISelectionStore as p}from"../../ai/chat/selection-store";import{useMDXCompiler as u}from"../hooks/use-mdx-compiler";import{compileMDX as h}from"../lib/compile";import{useCopyButton as f}from"../../../hooks/use-copy-button";import{Button as v}from"../../../components/ui/button";import{Check as x,Copy as b}from"lucide-react";class y extends r.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e){this.props.onError(e.message)}componentDidUpdate(e){e.resetKey!==this.props.resetKey&&this.state.error&&this.setState({error:null})}render(){return this.state.error?null:this.props.children}}let g=t();export function MDXPlayground({componentsContent:t}){let{source:d,setSource:w,Content:C,error:N,boundaryKey:k,onRenderError:R}=u(),[A,D]=f(()=>navigator.clipboard.writeText(d)),j=p(e=>e.setContextText),[E,M]=r.useState("code"),[S,P]=r.useState(null),X=r.useRef("");r.useEffect(()=>(document.body.style.overflow="hidden",()=>{document.body.style.overflow=""}),[]);let F=r.useCallback(async(e,o,r)=>{try{await h(e)}catch(e){r(!1,`MDX syntax error: ${e?.message??"compilation failed"}. Fix and retry.`);return}X.current=d,P({content:e,addApprovalResponse:(e,o)=>{r(e,o),e||w(X.current),P(null)}}),M("code")},[d,w]),K=r.useCallback(()=>{S&&(w(S.content),S.addApprovalResponse(!0))},[S,w]),z=r.useCallback(()=>{S&&S.addApprovalResponse(!1)},[S]),T=r.useCallback(e=>{S&&S.addApprovalResponse(!1,e)},[S]),W=r.useCallback(e=>{w(e),S?.addApprovalResponse(!0)},[S,w]);return o(l,{value:E,onValueChange:e=>M(e),className:"flex h-dvh flex-col overflow-hidden",children:[o("div",{className:"flex shrink-0 items-center justify-between border-b border-border bg-background px-4 py-2",children:[o("div",{children:[e("h1",{className:"font-serif text-sm font-semibold text-foreground",children:"MDX Playground"}),e("p",{className:"text-xs text-muted-foreground",children:"Write MDX, see it live, copy when done."})]}),o("div",{className:"flex items-center gap-3",children:[o(s,{children:[e(a,{value:"code",children:"Code"}),e(a,{value:"preview",children:"Preview"})]}),e(v,{type:"button",onClick:D,variant:"secondary",size:"sm",className:"gap-2 [&_svg]:size-3.5",children:A?e(x,{}):e(b,{})})]})]}),o("div",{className:"flex min-h-0 flex-1 overflow-hidden",children:[o("div",{className:"flex min-w-0 flex-1 flex-col overflow-hidden",children:[o(i,{value:"code",className:"flex min-h-0 flex-1 flex-col overflow-hidden data-[state=inactive]:hidden mt-0",children:[e(c,{value:d,onChange:w,proposedContent:S?.content??null,onAllChunksResolved:W,onSelectionChange:j,className:"min-h-0 flex-1 overflow-hidden [&_.cm-editor]:h-full"}),N&&e("div",{className:"shrink-0 border-t border-red-500/30 bg-red-500/10 p-3 font-mono text-xs text-red-500 whitespace-pre-wrap",children:N})]}),e(i,{value:"preview",className:"flex min-h-0 flex-1 flex-col overflow-y-auto data-[state=inactive]:hidden mt-0",children:e(n,{className:"p-6",children:e(y,{resetKey:k,onError:R,children:C&&e(C,{components:g})})})})]}),e(m,{source:d,componentsContent:t,onPropose:F,onAccept:K,onReject:z,onRejectWithFeedback:T})]})]})}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import*as e from"react";import{useChat as t}from"@ai-sdk/react";import{DefaultChatTransport as o,lastAssistantMessageIsCompleteWithToolCalls as l}from"ai";import{useAISettings as s}from"../../ai/chat/store";import{useAISelectionStore as a}from"../../ai/chat/selection-store";import{PROVIDERS as r}from"../../ai/chat/types";import{getComponentDocs as n}from"../lib/components-reference";let u="__playground_messages";export function usePlaygroundChat({provider:d,source:i,onPropose:c}){let f=s(),p=s(e=>e.sourcesEnabled),m=e.useRef(i);m.current=i;let g=e.useRef(c);g.current=c;let y=e.useRef(d);y.current=d;let h=e.useRef(f.keys[d]??"");h.current=f.keys[d]??"";let x=e.useRef(f.models[d]??r[d].defaultModel);x.current=f.models[d]??r[d].defaultModel;let C=e.useRef(p);C.current=p;let I=e.useRef(new Set),v=t({id:"playground",transport:e.useMemo(()=>new o({api:"/api/chat",headers:()=>({"x-agent":"playground","x-provider":y.current,"x-api-key":h.current,"x-model":x.current,"x-research":C.current?"true":"false"})}),[]),sendAutomaticallyWhen:({messages:e})=>l({messages:e})});e.useEffect(()=>{try{let e=localStorage.getItem(u);e&&v.setMessages(JSON.parse(e))}catch{}},[]),e.useEffect(()=>{v.messages.length>0&&localStorage.setItem(u,JSON.stringify(v.messages))},[v.messages]);let R=e.useCallback(()=>{v.setMessages([]),localStorage.removeItem(u)},[v]),S=e.useCallback((e,t)=>{let o=a.getState().contextText;return o&&"object"==typeof e&&"text"in e&&e.text?(a.getState().setContextText(null),v.sendMessage({...e,text:`Selected text:
2
+ import*as e from"react";import{useChat as t}from"@ai-sdk/react";import{DefaultChatTransport as o,lastAssistantMessageIsCompleteWithToolCalls as l}from"ai";import{useAISettings as r}from"../../ai/chat/store";import{useAISelectionStore as s}from"../../ai/chat/selection-store";import{PROVIDERS as a}from"../../ai/chat/types";let n="__playground_messages";export function usePlaygroundChat({provider:u,source:c,componentsContent:d,onPropose:i}){let f=r(),p=r(e=>e.sourcesEnabled),m=e.useRef(c);m.current=c;let g=e.useRef(d);g.current=d;let y=e.useRef(i);y.current=i;let h=e.useRef(u);h.current=u;let x=e.useRef(f.keys[u]??"");x.current=f.keys[u]??"";let C=e.useRef(f.models[u]??a[u].defaultModel);C.current=f.models[u]??a[u].defaultModel;let I=e.useRef(p);I.current=p;let R=e.useRef(new Set),v=e.useRef(!1),S=t({id:"playground",transport:e.useMemo(()=>new o({api:"/api/chat",headers:()=>({"x-agent":"playground","x-provider":h.current,"x-api-key":x.current,"x-model":C.current,"x-research":I.current?"true":"false"})}),[]),sendAutomaticallyWhen:({messages:e})=>v.current?(v.current=!1,!1):l({messages:e})});e.useEffect(()=>{try{let e=localStorage.getItem(n);e&&S.setMessages(JSON.parse(e))}catch{}},[]),e.useEffect(()=>{S.messages.length>0&&localStorage.setItem(n,JSON.stringify(S.messages))},[S.messages]);let M=e.useCallback(()=>{S.setMessages([]),localStorage.removeItem(n)},[S]),T=e.useCallback((e,t)=>{let o=s.getState().contextText;return o&&"object"==typeof e&&"text"in e&&e.text?(s.getState().setContextText(null),S.sendMessage({...e,text:`Selected text:
3
3
  \`\`\`
4
4
  ${o}
5
5
  \`\`\`
6
6
 
7
- ${e.text}`},t)):v.sendMessage(e,t)},[v.sendMessage]);return e.useEffect(()=>{!function(e,t,o,l){for(let s of e)if("assistant"===s.role){for(let e of s.parts??[])if(!("input-available"!==e.state||t.has(e.toolCallId))&&("tool-read"===e.type&&(t.add(e.toolCallId),l({tool:"read",toolCallId:e.toolCallId,output:{content:o()}})),"tool-components"===e.type)){t.add(e.toolCallId);let o=e.input;l({tool:"components",toolCallId:e.toolCallId,output:n(o.names)})}}}(v.messages,I.current,()=>m.current,v.addToolOutput)},[v.messages,v.addToolOutput]),e.useEffect(()=>{!function(e,t,o,l,s){for(let a of e)if("assistant"===a.role)for(let e of a.parts??[]){if("tool-edit"!==e.type&&"tool-write"!==e.type)continue;if("approval-requested"!==e.state||!e.approval||t.has(e.toolCallId))continue;t.add(e.toolCallId);let a=e.approval.id,r=(e,t)=>s({id:a,approved:e,reason:t});if("tool-edit"===e.type){let t=e.input,s=o(),a=[];for(let{oldText:e,newText:o}of t.edits){let t=s.indexOf(e);-1===t?a.push(e.slice(0,60)):s=s.slice(0,t)+o+s.slice(t+e.length)}a.length>0?r(!1,`oldText not found for ${a.length} edit(s): ${a.join(" | ")}. Call read("full") and retry with exact verbatim matches.`):l(s,t.summary,r)}if("tool-write"===e.type){let t=e.input;l(t.content,t.summary,r)}}}(v.messages,I.current,()=>m.current,(...e)=>g.current(...e),v.addToolApprovalResponse)},[v.messages,v.addToolApprovalResponse]),{chat:v,clearMessages:R,sendMessage:S}}
7
+ ${e.text}`},t)):S.sendMessage(e,t)},[S.sendMessage]);return e.useEffect(()=>{!function(e,t,o,l,r){for(let s of e)if("assistant"===s.role)for(let e of s.parts??[])"input-available"!==e.state||t.has(e.toolCallId)||("tool-read"===e.type&&(t.add(e.toolCallId),r({tool:"read",toolCallId:e.toolCallId,output:{content:o()}})),"tool-components"===e.type&&(t.add(e.toolCallId),r({tool:"components",toolCallId:e.toolCallId,output:{content:l()}})))}(S.messages,R.current,()=>m.current,()=>g.current,S.addToolOutput)},[S.messages,S.addToolOutput]),e.useEffect(()=>{!function(e,t,o,l,r){for(let s of e)if("assistant"===s.role)for(let e of s.parts??[]){if("tool-edit"!==e.type&&"tool-write"!==e.type)continue;if("approval-requested"!==e.state||!e.approval||t.has(e.toolCallId))continue;t.add(e.toolCallId);let s=e.approval.id,a=(e,t)=>r({id:s,approved:e,reason:t});if("tool-edit"===e.type){let t=e.input,r=o(),s=[];for(let{oldText:e,newText:o}of t.edits){let t=r.indexOf(e);-1===t?s.push(e.slice(0,60)):r=r.slice(0,t)+o+r.slice(t+e.length)}s.length>0?a(!1,`oldText not found for ${s.length} edit(s): ${s.join(" | ")}. Call read("full") and retry with exact verbatim matches.`):l(r,t.summary,a)}if("tool-write"===e.type){let t=e.input;l(t.content,t.summary,a)}}}(S.messages,R.current,()=>m.current,(e,t,o)=>{y.current(e,t,(e,t)=>{e||t||(v.current=!0),o(e,t)})},S.addToolApprovalResponse)},[S.messages,S.addToolApprovalResponse]),{chat:S,clearMessages:M,sendMessage:T}}
@@ -1 +1 @@
1
- import{jsx as o}from"react/jsx-runtime";import{DocsLayout as r}from"../components/fumadocs/layout/docs";import{docsOptions as t}from"./layout.shared";import{getUnifiedPageTree as a,getNavLinks as e}from"./source";import{SidebarFooter as i}from"../components/fumadocs/layout/sidebar-footer";export function createDocsLayout(){return async function({children:m,params:s}){let{lang:n}=await s,c=await e(n);return o(r,{...t(n),links:c,tree:await a(n),sidebar:{footer:o(i,{})},children:m})}}
1
+ import{jsx as o}from"react/jsx-runtime";import{DocsLayout as r}from"../components/fumadocs/layout/docs";import{docsOptions as t}from"./layout.shared";import{getNavLinks as a,getSectionPageTree as e}from"./source";import{SidebarFooter as i}from"../components/fumadocs/layout/sidebar-footer";export function createDocsLayout(){return async function({children:m,params:s}){let{lang:n,section:c}=await s,u=await a(n),f=await e(c,n);return o(r,{...t(n),links:u,tree:f,sidebar:{footer:o(i,{})},children:m})}}
@@ -1,3 +1,3 @@
1
- import{loader as e}from"fumadocs-core/source";import{lucideIconsPlugin as t}from"fumadocs-core/source/lucide-icons";import{openapiPlugin as r}from"fumadocs-openapi/server";import{createSearchAPI as a}from"fumadocs-core/search/server";import{i18n as o}from"./i18n";import{join as n}from"node:path";import{existsSync as i,watch as c}from"node:fs";import{readFile as s}from"node:fs/promises";import l from"gray-matter";import{env as u,isSectionHidden as f}from"../config";import{createFsSource as m,discoverSections as p}from"./content-source.js";let g=[t(),r()];async function d(){let t=await p(u.CONTENT_DIR),r=Object.fromEntries(await Promise.all(t.map(async t=>{let r=e({source:await m(n(u.CONTENT_DIR,t)),baseUrl:`/${t}`,i18n:o,plugins:g});return[t,r]}))),i=a("simple",{indexes:await Promise.all(Object.entries(r).filter(([e])=>!f(e)).flatMap(([,e])=>e.getLanguages().flatMap(({language:e,pages:t})=>t.map(async t=>{let{content:r}=l(await s(t.data.filePath,"utf-8"));return{id:t.url,url:t.url,locale:e,title:t.data.title,content:r}}))))});return{sections:r,searchServer:i}}let T=null;export function getSources(){return T||(T=d(),"development"===process.env.NODE_ENV&&T.then(()=>{i(u.CONTENT_DIR)&&c(u.CONTENT_DIR,{recursive:!0},()=>{T=null})})),T}export async function getSections(){let{sections:e}=await getSources();return Object.fromEntries(Object.entries(e).filter(([e])=>!f(e)))}export async function getAllPages(){return Object.values(await getSections()).flatMap(e=>e.getPages())}export async function getUnifiedPageTree(e){let t=await getSections(),r=[],a=t.docs;for(let[o,n]of(a&&r.push(...a.getPageTree(e).children),Object.entries(t))){if("docs"===o)continue;let t=n.getPageTree(e);0!==t.children.length&&r.push({type:"folder",name:t.name,children:t.children})}return{name:"",children:r}}export async function getNavLinks(e){return Object.entries(await getSections()).map(([t,r])=>({text:r.getPageTree(e).name??t,url:`/${e}/${t}`,active:"nested-url"}))}export async function getLLMText(e){let{content:t}=l(await s(e.data.filePath,"utf-8"));return`# ${e.data.title}
1
+ import{loader as e}from"fumadocs-core/source";import{lucideIconsPlugin as t}from"fumadocs-core/source/lucide-icons";import{openapiPlugin as r}from"fumadocs-openapi/server";import{createSearchAPI as a}from"fumadocs-core/search/server";import{i18n as n}from"./i18n";import{join as o}from"node:path";import{existsSync as i,watch as c}from"node:fs";import{readFile as s}from"node:fs/promises";import l from"gray-matter";import{env as u,isSectionHidden as f}from"../config";import{createFsSource as m,discoverSections as p}from"./content-source.js";let g=[t(),r()];async function d(){let t=await p(u.CONTENT_DIR),r=Object.fromEntries(await Promise.all(t.map(async t=>{let r=e({source:await m(o(u.CONTENT_DIR,t)),baseUrl:`/${t}`,i18n:n,plugins:g});return[t,r]}))),i=a("simple",{indexes:await Promise.all(Object.entries(r).filter(([e])=>!f(e)).flatMap(([,e])=>e.getLanguages().flatMap(({language:e,pages:t})=>t.map(async t=>{let{content:r}=l(await s(t.data.filePath,"utf-8"));return{id:t.url,url:t.url,locale:e,title:t.data.title,content:r}}))))});return{sections:r,searchServer:i}}let T=null;export function getSources(){return T||(T=d(),"development"===process.env.NODE_ENV&&T.then(()=>{i(u.CONTENT_DIR)&&c(u.CONTENT_DIR,{recursive:!0},()=>{T=null})})),T}export async function getSections(){let{sections:e}=await getSources();return Object.fromEntries(Object.entries(e).filter(([e])=>!f(e)))}export async function getAllPages(){return Object.values(await getSections()).flatMap(e=>e.getPages())}export async function getUnifiedPageTree(e){let t=await getSections(),r=[],a=t.docs;for(let[n,o]of(a&&r.push(...a.getPageTree(e).children),Object.entries(t))){if("docs"===n)continue;let t=o.getPageTree(e);0!==t.children.length&&r.push({type:"folder",name:t.name,children:t.children})}return{name:"",children:r}}export async function getSectionPageTree(e,t){let r=(await getSections())[e];return r?r.getPageTree(t):{name:"",children:[]}}export async function getNavLinks(e){return Object.entries(await getSections()).map(([t,r])=>({text:r.getPageTree(e).name??t,url:`/${e}/${t}`,active:"nested-url"}))}export async function getLLMText(e){let{content:t}=l(await s(e.data.filePath,"utf-8"));return`# ${e.data.title}
2
2
 
3
3
  ${t}`}
@@ -1 +0,0 @@
1
- export const COMPONENTS={Callout:{desc:"Highlighted notice box",props:'type?: "info"|"warn"|"warning"|"error"|"success"|"idea" title?: string children: ReactNode',example:'<Callout type="warn" title="Important">message here</Callout>'},Cards:{desc:"Responsive grid of linked cards. Card title is required; href, icon, and description are optional.",props:"Card: title(string, required) description?(string) href?(string) icon?(Lucide PascalCase name) external?(bool)",constraint:"Use description prop for subtitle text, not children. href is optional.",example:'<Cards>\n <Card title="Start" href="/docs/start" icon="Rocket" description="Get up and running." />\n <Card title="API" description="Browse the reference." />\n</Cards>'},Steps:{desc:"Numbered step sequence",constraint:"Step must be a direct child of Steps — never nest inside divs",example:"<Steps>\n <Step>Install with `npm install`.</Step>\n <Step>Run `npm run dev`.</Step>\n</Steps>"},Tabs:{desc:"Tabbed content panels. items on Tabs is optional — Tab value is auto-detected from index when items is omitted.",constraint:"Tab must be a direct child of Tabs. When items is provided, each Tab value must exactly match an entry in items.",props:"items?: string[] defaultIndex?: number | Tab: value?(string — required when items provided)",example:'<Tabs items={["npm","pnpm"]}>\n <Tab value="npm">```bash\nnpm install\n```</Tab>\n <Tab value="pnpm">```bash\npnpm install\n```</Tab>\n</Tabs>'},Accordions:{desc:"Collapsible sections",constraint:"Accordion must be a direct child of Accordions",props:"Accordion: title(string, required)",example:'<Accordions>\n <Accordion title="What is this?">Explanation here.</Accordion>\n <Accordion title="How does it work?">Details here.</Accordion>\n</Accordions>'},TypeTable:{desc:"Props/options reference table. Use for documenting component APIs or config.",props:"type: Record<string, { type: string (required); description?: string; default?: string; required?: boolean; deprecated?: boolean }>",example:'<TypeTable\n type={{\n name: { type: "string", description: "Display name.", default: \'""\' },\n disabled: { type: "boolean", description: "Disables the button.", default: "false" },\n onChange: { type: "(v: string) => void", description: "Change handler.", required: true },\n }}\n/>'},InlineTOC:{desc:"Inline table of contents. Requires an items array — omitting it crashes the preview.",props:"items: { title: string; url: string; depth: number }[] (required — pass [] if no headings)",constraint:"items is required — always pass at least an empty array: items={[]}",example:'<InlineTOC items={[\n { title: "Introduction", url: "#introduction", depth: 2 },\n { title: "Usage", url: "#usage", depth: 2 },\n]} />'},DynamicCodeBlock:{desc:"Syntax-highlighted code block with a built-in language/theme picker",props:"lang: string (required) code: string (required)",example:'<DynamicCodeBlock lang="ts" code={`const greet = (name: string) => \\`Hello, ${name}!\\`;`} />'},Files:{desc:"Visual directory tree. Always renders LTR regardless of page direction.",props:"Folder: name(string, required) defaultOpen?(bool) File: name(string, required)",example:'<Files>\n <Folder name="src" defaultOpen>\n <Folder name="components">\n <File name="Button.tsx" />\n </Folder>\n <File name="index.ts" />\n </Folder>\n</Files>'},Mermaid:{desc:"Text-based diagrams: flowcharts, sequence, ER, state machines, Gantt",props:"chart: string (required — mermaid DSL)",example:"<Mermaid chart={`\n graph TD\n A[Start] --\x3e B{Decision}\n B --\x3e|Yes| C[Do it]\n B --\x3e|No| D[Skip]\n`} />"},CircuitBoardBlock:{desc:"Animated circuit-board diagram with nodes, directional traces, and electric pulse effects.",props:'nodes: { id, x, y, label?, icon?(see allowed icons below), status?("active"|"inactive"|"processing"|"error"), size?("sm"|"md"|"lg") }[] (required) connections: { from, to, animated?(true), bidirectional?(false), color?, pulseColor? }[] (required) width?: number (default 600) height?: number (default 400) gridSize?: number (default 20) showGrid?: boolean (default true) traceColor?: string pulseColor?: string nodeColor?: string pulseSpeed?: number (default 2, seconds per cycle) traceWidth?: number (default 2) variant?: "light"|"dark"|"auto" (default auto)',constraint:"All node ids referenced in connections must exist in nodes. Positions are absolute pixel coords within width×height. Allowed icon values: Server Database Cloud Globe Cpu Monitor Smartphone Shield Lock Key Settings HardDrive Archive Package Mail MessageSquare Bell User Users Code Terminal Zap RefreshCw CheckCircle XCircle AlertCircle Clock Wifi Radio Network Play Pause LayoutGrid",example:'<CircuitBoardBlock\n width={600} height={300}\n nodes={[\n { id: "client", x: 80, y: 150, label: "Client", status: "active", icon: "Monitor" },\n { id: "api", x: 300, y: 150, label: "API", status: "processing", icon: "Server" },\n { id: "db", x: 520, y: 150, label: "DB", status: "active", icon: "Database" },\n ]}\n connections={[\n { from: "client", to: "api", animated: true },\n { from: "api", to: "db", bidirectional: true },\n ]}\n/>'},DrawioBlock:{desc:"Read-only draw.io diagram embed. Generate raw mxCell XML — the component wraps it automatically.",props:'xml?: string (raw mxCell elements, IDs start at "2", parent="1") height?: number (default 500) variant?: "light"|"dark"|"auto"',constraint:'IDs 0 and 1 are reserved. All vertices need vertex="1", edges need edge="1" with source/target. Use flowAnimation=1 in edge style for animated connectors.',example:'<DrawioBlock height={300} xml={`\n <mxCell id="2" value="Client" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">\n <mxGeometry x="80" y="120" width="120" height="60" as="geometry"/>\n </mxCell>\n <mxCell id="3" value="Server" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">\n <mxGeometry x="360" y="120" width="120" height="60" as="geometry"/>\n </mxCell>\n <mxCell id="4" style="endArrow=classic;html=1;flowAnimation=1;" edge="1" source="2" target="3" parent="1">\n <mxGeometry relative="1" as="geometry"/>\n </mxCell>\n`} />'},ExcalidrawBlock:{desc:"Embedded read-only Excalidraw diagram. All props are optional — renders an empty canvas if initialData is omitted.",props:"initialData?: { elements: ExcalidrawElement[]; appState?: object } height?: number (default 400)",example:'<ExcalidrawBlock height={350} initialData={{\n elements: [\n { id: "1", type: "rectangle", x: 100, y: 60, width: 160, height: 60, strokeColor: "#1971c2", backgroundColor: "#d0ebff", fillStyle: "solid", strokeWidth: 2, roughness: 1, opacity: 100, groupIds: [], isDeleted: false, boundElements: null, updated: 1, version: 1, versionNonce: 1 },\n ],\n appState: { viewBackgroundColor: "transparent" }\n}} />'},FigmaBlock:{desc:"Embed a Figma design file, prototype, or FigJam board. File must be publicly viewable.",props:"url: string (required — Figma share URL, auto-converted to embed URL) height?: number (default 450)",example:'<FigmaBlock url="https://www.figma.com/design/abc123/My-File" />\n<FigmaBlock url="https://www.figma.com/proto/abc123/My-Prototype" height={600} />'},Video:{desc:"Video player supporting direct files, YouTube, Vimeo, HLS, and DASH.",props:"src: string (required) title?: string",example:'<Video src="/media/demo.mp4" />'},Audio:{desc:"Audio player supporting MP3, AAC, OGG, and HLS streams.",props:"src: string (required) title?: string",example:'<Audio src="/media/podcast.mp3" />'},Tweet:{desc:"Embeds a tweet by numeric ID (the number at the end of the tweet URL)",props:"id: string (required)",example:'<Tweet id="1234567890123456789" />'}};export function getComponentDocs(e){return e&&0!==e.length?Object.fromEntries(e.map(e=>[e,COMPONENTS[e]]).filter(([,e])=>void 0!==e)):COMPONENTS}