specra 0.1.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.
Files changed (142) hide show
  1. package/LICENSE.MD +21 -0
  2. package/README.md +157 -0
  3. package/dist/app/api/mdx-watch/route.d.mts +12 -0
  4. package/dist/app/api/mdx-watch/route.d.ts +12 -0
  5. package/dist/app/api/mdx-watch/route.js +98 -0
  6. package/dist/app/api/mdx-watch/route.js.map +1 -0
  7. package/dist/app/api/mdx-watch/route.mjs +71 -0
  8. package/dist/app/api/mdx-watch/route.mjs.map +1 -0
  9. package/dist/app/docs-page.d.mts +32 -0
  10. package/dist/app/docs-page.d.ts +32 -0
  11. package/dist/app/docs-page.js +4072 -0
  12. package/dist/app/docs-page.js.map +1 -0
  13. package/dist/app/docs-page.mjs +14 -0
  14. package/dist/app/docs-page.mjs.map +1 -0
  15. package/dist/app/layout.css +297 -0
  16. package/dist/app/layout.css.map +1 -0
  17. package/dist/app/layout.d.mts +19 -0
  18. package/dist/app/layout.d.ts +19 -0
  19. package/dist/app/layout.js +112 -0
  20. package/dist/app/layout.js.map +1 -0
  21. package/dist/app/layout.mjs +13 -0
  22. package/dist/app/layout.mjs.map +1 -0
  23. package/dist/chunk-DR4EPLMT.mjs +1013 -0
  24. package/dist/chunk-DR4EPLMT.mjs.map +1 -0
  25. package/dist/chunk-INL2EC72.mjs +170 -0
  26. package/dist/chunk-INL2EC72.mjs.map +1 -0
  27. package/dist/chunk-IZFGEAD6.mjs +61 -0
  28. package/dist/chunk-IZFGEAD6.mjs.map +1 -0
  29. package/dist/chunk-KTRWWAGL.mjs +50 -0
  30. package/dist/chunk-KTRWWAGL.mjs.map +1 -0
  31. package/dist/chunk-MZJHJ6BV.mjs +21 -0
  32. package/dist/chunk-MZJHJ6BV.mjs.map +1 -0
  33. package/dist/chunk-NXRIAL7T.mjs +3119 -0
  34. package/dist/chunk-NXRIAL7T.mjs.map +1 -0
  35. package/dist/components/index.d.mts +822 -0
  36. package/dist/components/index.d.ts +822 -0
  37. package/dist/components/index.js +3738 -0
  38. package/dist/components/index.js.map +1 -0
  39. package/dist/components/index.mjs +3627 -0
  40. package/dist/components/index.mjs.map +1 -0
  41. package/dist/index.css +297 -0
  42. package/dist/index.css.map +1 -0
  43. package/dist/index.d.mts +545 -0
  44. package/dist/index.d.ts +545 -0
  45. package/dist/index.js +4648 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/index.mjs +347 -0
  48. package/dist/index.mjs.map +1 -0
  49. package/dist/lib/index.d.mts +798 -0
  50. package/dist/lib/index.d.ts +798 -0
  51. package/dist/lib/index.js +1301 -0
  52. package/dist/lib/index.js.map +1 -0
  53. package/dist/lib/index.mjs +89 -0
  54. package/dist/lib/index.mjs.map +1 -0
  55. package/package.json +119 -0
  56. package/src/app/api/mdx-watch/route.ts +86 -0
  57. package/src/app/docs-page.tsx +212 -0
  58. package/src/app/layout.tsx +74 -0
  59. package/src/components/docs/accordion.tsx +53 -0
  60. package/src/components/docs/api/api-endpoint.tsx +59 -0
  61. package/src/components/docs/api/api-params.tsx +43 -0
  62. package/src/components/docs/api/api-playground.tsx +233 -0
  63. package/src/components/docs/api/api-reference.tsx +291 -0
  64. package/src/components/docs/api/api-response.tsx +48 -0
  65. package/src/components/docs/api/index.ts +5 -0
  66. package/src/components/docs/badge.tsx +22 -0
  67. package/src/components/docs/breadcrumb.tsx +51 -0
  68. package/src/components/docs/callout.tsx +109 -0
  69. package/src/components/docs/card.tsx +84 -0
  70. package/src/components/docs/category-index.tsx +112 -0
  71. package/src/components/docs/code-block.tsx +129 -0
  72. package/src/components/docs/columns.tsx +45 -0
  73. package/src/components/docs/componentTextProps.ts +85 -0
  74. package/src/components/docs/dev-mode-badge.tsx +35 -0
  75. package/src/components/docs/doc-layout-wrapper.tsx +54 -0
  76. package/src/components/docs/doc-layout.tsx +111 -0
  77. package/src/components/docs/doc-loading.tsx +15 -0
  78. package/src/components/docs/doc-metadata.tsx +55 -0
  79. package/src/components/docs/doc-navigation.tsx +62 -0
  80. package/src/components/docs/doc-tags.tsx +25 -0
  81. package/src/components/docs/draft-badge.tsx +10 -0
  82. package/src/components/docs/footer.tsx +47 -0
  83. package/src/components/docs/frame.tsx +22 -0
  84. package/src/components/docs/header.tsx +122 -0
  85. package/src/components/docs/hot-reload-indicator.tsx +77 -0
  86. package/src/components/docs/icon.tsx +70 -0
  87. package/src/components/docs/image-card.tsx +95 -0
  88. package/src/components/docs/image.tsx +73 -0
  89. package/src/components/docs/index.ts +48 -0
  90. package/src/components/docs/math.tsx +46 -0
  91. package/src/components/docs/mdx-components.tsx +166 -0
  92. package/src/components/docs/mdx-hot-reload.tsx +37 -0
  93. package/src/components/docs/mermaid.tsx +77 -0
  94. package/src/components/docs/mobile-doc-layout.tsx +115 -0
  95. package/src/components/docs/not-found-content.tsx +55 -0
  96. package/src/components/docs/search-highlight.tsx +127 -0
  97. package/src/components/docs/search-modal.tsx +223 -0
  98. package/src/components/docs/sidebar-skeleton.tsx +39 -0
  99. package/src/components/docs/sidebar.tsx +323 -0
  100. package/src/components/docs/site-banner.tsx +92 -0
  101. package/src/components/docs/steps.tsx +29 -0
  102. package/src/components/docs/tab-context.tsx +28 -0
  103. package/src/components/docs/tab-groups.tsx +50 -0
  104. package/src/components/docs/table-of-contents.tsx +104 -0
  105. package/src/components/docs/tabs.tsx +63 -0
  106. package/src/components/docs/theme-toggle.tsx +39 -0
  107. package/src/components/docs/tooltip.tsx +37 -0
  108. package/src/components/docs/version-switcher.tsx +52 -0
  109. package/src/components/docs/video.tsx +80 -0
  110. package/src/components/global/index.ts +3 -0
  111. package/src/components/global/version-not-found.tsx +26 -0
  112. package/src/components/index.ts +8 -0
  113. package/src/components/theme-provider.tsx +11 -0
  114. package/src/components/ui/badge.tsx +46 -0
  115. package/src/components/ui/button.tsx +60 -0
  116. package/src/components/ui/dialog.tsx +143 -0
  117. package/src/components/ui/index.ts +6 -0
  118. package/src/components/ui/input.tsx +21 -0
  119. package/src/components/ui/textarea.tsx +18 -0
  120. package/src/index.ts +41 -0
  121. package/src/lib/api-parser.types.ts +78 -0
  122. package/src/lib/api.types.ts +202 -0
  123. package/src/lib/category.ts +71 -0
  124. package/src/lib/config.server.ts +170 -0
  125. package/src/lib/config.ts +20 -0
  126. package/src/lib/config.types.ts +295 -0
  127. package/src/lib/dev-utils.ts +75 -0
  128. package/src/lib/index.ts +27 -0
  129. package/src/lib/mdx-cache.ts +200 -0
  130. package/src/lib/mdx.ts +402 -0
  131. package/src/lib/parsers/base-parser.ts +16 -0
  132. package/src/lib/parsers/index.ts +69 -0
  133. package/src/lib/parsers/openapi-parser.ts +251 -0
  134. package/src/lib/parsers/postman-parser.ts +301 -0
  135. package/src/lib/parsers/specra-parser.ts +24 -0
  136. package/src/lib/redirects.ts +40 -0
  137. package/src/lib/remark-code-meta.ts +23 -0
  138. package/src/lib/sidebar-utils.ts +188 -0
  139. package/src/lib/toc.ts +24 -0
  140. package/src/lib/utils.ts +36 -0
  141. package/src/specra.config.json +124 -0
  142. package/src/styles/globals.css +427 -0
package/LICENSE.MD ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 dalmasonto, arthur-kamau
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # Specra
2
+
3
+ A modern documentation library for Next.js that makes it easy to create beautiful, feature-rich documentation sites.
4
+
5
+ ## Features
6
+
7
+ - 📝 **MDX Support** - Write documentation in Markdown with React components
8
+ - 📚 **Multi-Version Docs** - Support multiple documentation versions seamlessly
9
+ - 🔌 **API Reference Generation** - Auto-generate API docs from OpenAPI, Postman, or Specra formats
10
+ - 🔍 **Full-Text Search** - Integrated MeiliSearch support for fast search
11
+ - 🎯 **Tab Groups** - Organize content into multiple navigation tabs
12
+ - 🌓 **Dark Mode** - Built-in theme switching with system preference detection
13
+ - 🎨 **Customizable** - Highly configurable with Tailwind CSS
14
+ - ⚡ **Fast** - Built on Next.js with optimized performance
15
+ - 📱 **Responsive** - Mobile-friendly design out of the box
16
+ - 🔥 **Hot Reload** - Instant updates during development
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install specra
22
+ # or
23
+ yarn add specra
24
+ # or
25
+ pnpm add specra
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ### 1. Create a new Next.js app (if you don't have one)
31
+
32
+ ```bash
33
+ npx create-next-app@latest my-docs
34
+ cd my-docs
35
+ ```
36
+
37
+ ### 2. Install Specra
38
+
39
+ ```bash
40
+ npm install specra
41
+ ```
42
+
43
+ ### 3. Set up your app structure
44
+
45
+ ```
46
+ my-docs/
47
+ ├── app/
48
+ │ ├── layout.tsx # Re-export from Specra
49
+ │ ├── page.tsx # Your landing page
50
+ │ └── docs/
51
+ │ └── [version]/
52
+ │ └── [...slug]/
53
+ │ └── page.tsx # Re-export from Specra
54
+ ├── docs/ # Your MDX content
55
+ │ └── v1.0.0/
56
+ │ └── getting-started.mdx
57
+ ├── public/
58
+ │ └── logo.png
59
+ └── specra.config.json # Specra configuration
60
+ ```
61
+
62
+ ### 4. Configure app/layout.tsx
63
+
64
+ ```typescript
65
+ // app/layout.tsx
66
+ export { default } from 'specra/app/layout'
67
+ export { generateMetadata } from 'specra/app/layout'
68
+ ```
69
+
70
+ ### 5. Configure app/docs/[version]/[...slug]/page.tsx
71
+
72
+ ```typescript
73
+ // app/docs/[version]/[...slug]/page.tsx
74
+ export { default } from 'specra/app/docs-page'
75
+ export {
76
+ generateStaticParams,
77
+ generateMetadata
78
+ } from 'specra/app/docs-page'
79
+ ```
80
+
81
+ ### 6. Create specra.config.json
82
+
83
+ ```json
84
+ {
85
+ "site": {
86
+ "title": "My Documentation",
87
+ "description": "Awesome docs built with Specra",
88
+ "url": "https://docs.example.com",
89
+ "logo": "/logo.png"
90
+ },
91
+ "theme": {
92
+ "defaultMode": "system",
93
+ "primaryColor": "#0070f3"
94
+ },
95
+ "navigation": {
96
+ "sidebar": true,
97
+ "breadcrumbs": true
98
+ }
99
+ }
100
+ ```
101
+
102
+ ### 7. Create your first doc
103
+
104
+ ```mdx
105
+ ---
106
+ title: Getting Started
107
+ description: Learn how to get started with our platform
108
+ ---
109
+
110
+ # Getting Started
111
+
112
+ Welcome to the documentation!
113
+ ```
114
+
115
+ ### 8. Import globals.css
116
+
117
+ Add to your `app/globals.css`:
118
+
119
+ ```css
120
+ @import 'specra/styles';
121
+
122
+ /* Your custom styles */
123
+ ```
124
+
125
+ ### 9. Run development server
126
+
127
+ ```bash
128
+ npm run dev
129
+ ```
130
+
131
+ Visit `http://localhost:3000/docs/v1.0.0/getting-started` to see your docs!
132
+
133
+ ## Configuration
134
+
135
+ See [Configuration Guide](https://docs.specra.dev/configuration) for full documentation.
136
+
137
+ ## Upgrading
138
+
139
+ Simply update the package to get latest features and bug fixes:
140
+
141
+ ```bash
142
+ npm update specra
143
+ ```
144
+
145
+ Your content and configuration stay the same - only the SDK updates!
146
+
147
+ ## Why Specra?
148
+
149
+ Specra is designed to be the easiest way to create documentation for your projects. It handles all the complex parts (versioning, search, API references) while letting you focus on writing great content.
150
+
151
+ ## License
152
+
153
+ MIT
154
+
155
+ ## Authors
156
+
157
+ dalmasonto, arthur-kamau
@@ -0,0 +1,12 @@
1
+ import { NextRequest } from 'next/server';
2
+
3
+ declare const dynamic = "force-dynamic";
4
+ declare const runtime = "nodejs";
5
+ /**
6
+ * API route for watching MDX file changes in development
7
+ * Provides Server-Sent Events (SSE) stream for hot reloading
8
+ * Only available in development mode
9
+ */
10
+ declare function GET(request: NextRequest): Promise<Response>;
11
+
12
+ export { GET, dynamic, runtime };
@@ -0,0 +1,12 @@
1
+ import { NextRequest } from 'next/server';
2
+
3
+ declare const dynamic = "force-dynamic";
4
+ declare const runtime = "nodejs";
5
+ /**
6
+ * API route for watching MDX file changes in development
7
+ * Provides Server-Sent Events (SSE) stream for hot reloading
8
+ * Only available in development mode
9
+ */
10
+ declare function GET(request: NextRequest): Promise<Response>;
11
+
12
+ export { GET, dynamic, runtime };
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/app/api/mdx-watch/route.ts
21
+ var route_exports = {};
22
+ __export(route_exports, {
23
+ GET: () => GET,
24
+ dynamic: () => dynamic,
25
+ runtime: () => runtime
26
+ });
27
+ module.exports = __toCommonJS(route_exports);
28
+ var import_fs = require("fs");
29
+ var import_path = require("path");
30
+ var dynamic = "force-dynamic";
31
+ var runtime = "nodejs";
32
+ async function GET(request) {
33
+ if (process.env.NODE_ENV !== "development") {
34
+ return new Response("Not available in production", { status: 404 });
35
+ }
36
+ const encoder = new TextEncoder();
37
+ const stream = new ReadableStream({
38
+ start(controller) {
39
+ const connectMsg = `data: ${JSON.stringify({ type: "connected" })}
40
+
41
+ `;
42
+ controller.enqueue(encoder.encode(connectMsg));
43
+ const docsPath = (0, import_path.join)(process.cwd(), "docs");
44
+ const watcher = (0, import_fs.watch)(
45
+ docsPath,
46
+ { recursive: true },
47
+ (eventType, filename) => {
48
+ if (!filename) return;
49
+ if (filename.endsWith(".mdx") || filename.endsWith(".json")) {
50
+ console.log(`[MDX Watch] ${eventType}: ${filename}`);
51
+ const message = `data: ${JSON.stringify({
52
+ type: "change",
53
+ file: filename,
54
+ eventType
55
+ })}
56
+
57
+ `;
58
+ try {
59
+ controller.enqueue(encoder.encode(message));
60
+ } catch (error) {
61
+ console.error("[MDX Watch] Error sending message:", error);
62
+ }
63
+ }
64
+ }
65
+ );
66
+ request.signal.addEventListener("abort", () => {
67
+ console.log("[MDX Watch] Client disconnected");
68
+ watcher.close();
69
+ try {
70
+ controller.close();
71
+ } catch (error) {
72
+ }
73
+ });
74
+ watcher.on("error", (error) => {
75
+ console.error("[MDX Watch] Watcher error:", error);
76
+ watcher.close();
77
+ try {
78
+ controller.close();
79
+ } catch (e) {
80
+ }
81
+ });
82
+ }
83
+ });
84
+ return new Response(stream, {
85
+ headers: {
86
+ "Content-Type": "text/event-stream",
87
+ "Cache-Control": "no-cache, no-transform",
88
+ "Connection": "keep-alive"
89
+ }
90
+ });
91
+ }
92
+ // Annotate the CommonJS export names for ESM import in node:
93
+ 0 && (module.exports = {
94
+ GET,
95
+ dynamic,
96
+ runtime
97
+ });
98
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app/api/mdx-watch/route.ts"],"sourcesContent":["import { NextRequest } from 'next/server'\nimport { watch } from 'fs'\nimport { join } from 'path'\n\nexport const dynamic = 'force-dynamic'\nexport const runtime = 'nodejs'\n\n/**\n * API route for watching MDX file changes in development\n * Provides Server-Sent Events (SSE) stream for hot reloading\n * Only available in development mode\n */\nexport async function GET(request: NextRequest) {\n // Only allow in development mode\n if (process.env.NODE_ENV !== 'development') {\n return new Response('Not available in production', { status: 404 })\n }\n\n const encoder = new TextEncoder()\n\n const stream = new ReadableStream({\n start(controller) {\n // Send initial connection message\n const connectMsg = `data: ${JSON.stringify({ type: 'connected' })}\\n\\n`\n controller.enqueue(encoder.encode(connectMsg))\n\n const docsPath = join(process.cwd(), 'docs')\n\n // Watch the docs directory recursively\n const watcher = watch(\n docsPath,\n { recursive: true },\n (eventType, filename) => {\n if (!filename) return\n\n // Only watch for .mdx and .json files (MDX files and category configs)\n if (filename.endsWith('.mdx') || filename.endsWith('.json')) {\n console.log(`[MDX Watch] ${eventType}: ${filename}`)\n\n const message = `data: ${JSON.stringify({\n type: 'change',\n file: filename,\n eventType\n })}\\n\\n`\n\n try {\n controller.enqueue(encoder.encode(message))\n } catch (error) {\n console.error('[MDX Watch] Error sending message:', error)\n }\n }\n }\n )\n\n // Handle client disconnect\n request.signal.addEventListener('abort', () => {\n console.log('[MDX Watch] Client disconnected')\n watcher.close()\n try {\n controller.close()\n } catch (error) {\n // Controller might already be closed\n }\n })\n\n // Handle errors\n watcher.on('error', (error) => {\n console.error('[MDX Watch] Watcher error:', error)\n watcher.close()\n try {\n controller.close()\n } catch (e) {\n // Controller might already be closed\n }\n })\n }\n })\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n 'Connection': 'keep-alive',\n },\n })\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,gBAAsB;AACtB,kBAAqB;AAEd,IAAM,UAAU;AAChB,IAAM,UAAU;AAOvB,eAAsB,IAAI,SAAsB;AAE9C,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,WAAO,IAAI,SAAS,+BAA+B,EAAE,QAAQ,IAAI,CAAC;AAAA,EACpE;AAEA,QAAM,UAAU,IAAI,YAAY;AAEhC,QAAM,SAAS,IAAI,eAAe;AAAA,IAChC,MAAM,YAAY;AAEhB,YAAM,aAAa,SAAS,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC,CAAC;AAAA;AAAA;AACjE,iBAAW,QAAQ,QAAQ,OAAO,UAAU,CAAC;AAE7C,YAAM,eAAW,kBAAK,QAAQ,IAAI,GAAG,MAAM;AAG3C,YAAM,cAAU;AAAA,QACd;AAAA,QACA,EAAE,WAAW,KAAK;AAAA,QAClB,CAAC,WAAW,aAAa;AACvB,cAAI,CAAC,SAAU;AAGf,cAAI,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,OAAO,GAAG;AAC3D,oBAAQ,IAAI,eAAe,SAAS,KAAK,QAAQ,EAAE;AAEnD,kBAAM,UAAU,SAAS,KAAK,UAAU;AAAA,cACtC,MAAM;AAAA,cACN,MAAM;AAAA,cACN;AAAA,YACF,CAAC,CAAC;AAAA;AAAA;AAEF,gBAAI;AACF,yBAAW,QAAQ,QAAQ,OAAO,OAAO,CAAC;AAAA,YAC5C,SAAS,OAAO;AACd,sBAAQ,MAAM,sCAAsC,KAAK;AAAA,YAC3D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,cAAQ,OAAO,iBAAiB,SAAS,MAAM;AAC7C,gBAAQ,IAAI,iCAAiC;AAC7C,gBAAQ,MAAM;AACd,YAAI;AACF,qBAAW,MAAM;AAAA,QACnB,SAAS,OAAO;AAAA,QAEhB;AAAA,MACF,CAAC;AAGD,cAAQ,GAAG,SAAS,CAAC,UAAU;AAC7B,gBAAQ,MAAM,8BAA8B,KAAK;AACjD,gBAAQ,MAAM;AACd,YAAI;AACF,qBAAW,MAAM;AAAA,QACnB,SAAS,GAAG;AAAA,QAEZ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO,IAAI,SAAS,QAAQ;AAAA,IAC1B,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,cAAc;AAAA,IAChB;AAAA,EACF,CAAC;AACH;","names":[]}
@@ -0,0 +1,71 @@
1
+ // src/app/api/mdx-watch/route.ts
2
+ import { watch } from "fs";
3
+ import { join } from "path";
4
+ var dynamic = "force-dynamic";
5
+ var runtime = "nodejs";
6
+ async function GET(request) {
7
+ if (process.env.NODE_ENV !== "development") {
8
+ return new Response("Not available in production", { status: 404 });
9
+ }
10
+ const encoder = new TextEncoder();
11
+ const stream = new ReadableStream({
12
+ start(controller) {
13
+ const connectMsg = `data: ${JSON.stringify({ type: "connected" })}
14
+
15
+ `;
16
+ controller.enqueue(encoder.encode(connectMsg));
17
+ const docsPath = join(process.cwd(), "docs");
18
+ const watcher = watch(
19
+ docsPath,
20
+ { recursive: true },
21
+ (eventType, filename) => {
22
+ if (!filename) return;
23
+ if (filename.endsWith(".mdx") || filename.endsWith(".json")) {
24
+ console.log(`[MDX Watch] ${eventType}: ${filename}`);
25
+ const message = `data: ${JSON.stringify({
26
+ type: "change",
27
+ file: filename,
28
+ eventType
29
+ })}
30
+
31
+ `;
32
+ try {
33
+ controller.enqueue(encoder.encode(message));
34
+ } catch (error) {
35
+ console.error("[MDX Watch] Error sending message:", error);
36
+ }
37
+ }
38
+ }
39
+ );
40
+ request.signal.addEventListener("abort", () => {
41
+ console.log("[MDX Watch] Client disconnected");
42
+ watcher.close();
43
+ try {
44
+ controller.close();
45
+ } catch (error) {
46
+ }
47
+ });
48
+ watcher.on("error", (error) => {
49
+ console.error("[MDX Watch] Watcher error:", error);
50
+ watcher.close();
51
+ try {
52
+ controller.close();
53
+ } catch (e) {
54
+ }
55
+ });
56
+ }
57
+ });
58
+ return new Response(stream, {
59
+ headers: {
60
+ "Content-Type": "text/event-stream",
61
+ "Cache-Control": "no-cache, no-transform",
62
+ "Connection": "keep-alive"
63
+ }
64
+ });
65
+ }
66
+ export {
67
+ GET,
68
+ dynamic,
69
+ runtime
70
+ };
71
+ //# sourceMappingURL=route.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app/api/mdx-watch/route.ts"],"sourcesContent":["import { NextRequest } from 'next/server'\nimport { watch } from 'fs'\nimport { join } from 'path'\n\nexport const dynamic = 'force-dynamic'\nexport const runtime = 'nodejs'\n\n/**\n * API route for watching MDX file changes in development\n * Provides Server-Sent Events (SSE) stream for hot reloading\n * Only available in development mode\n */\nexport async function GET(request: NextRequest) {\n // Only allow in development mode\n if (process.env.NODE_ENV !== 'development') {\n return new Response('Not available in production', { status: 404 })\n }\n\n const encoder = new TextEncoder()\n\n const stream = new ReadableStream({\n start(controller) {\n // Send initial connection message\n const connectMsg = `data: ${JSON.stringify({ type: 'connected' })}\\n\\n`\n controller.enqueue(encoder.encode(connectMsg))\n\n const docsPath = join(process.cwd(), 'docs')\n\n // Watch the docs directory recursively\n const watcher = watch(\n docsPath,\n { recursive: true },\n (eventType, filename) => {\n if (!filename) return\n\n // Only watch for .mdx and .json files (MDX files and category configs)\n if (filename.endsWith('.mdx') || filename.endsWith('.json')) {\n console.log(`[MDX Watch] ${eventType}: ${filename}`)\n\n const message = `data: ${JSON.stringify({\n type: 'change',\n file: filename,\n eventType\n })}\\n\\n`\n\n try {\n controller.enqueue(encoder.encode(message))\n } catch (error) {\n console.error('[MDX Watch] Error sending message:', error)\n }\n }\n }\n )\n\n // Handle client disconnect\n request.signal.addEventListener('abort', () => {\n console.log('[MDX Watch] Client disconnected')\n watcher.close()\n try {\n controller.close()\n } catch (error) {\n // Controller might already be closed\n }\n })\n\n // Handle errors\n watcher.on('error', (error) => {\n console.error('[MDX Watch] Watcher error:', error)\n watcher.close()\n try {\n controller.close()\n } catch (e) {\n // Controller might already be closed\n }\n })\n }\n })\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n 'Connection': 'keep-alive',\n },\n })\n}"],"mappings":";AACA,SAAS,aAAa;AACtB,SAAS,YAAY;AAEd,IAAM,UAAU;AAChB,IAAM,UAAU;AAOvB,eAAsB,IAAI,SAAsB;AAE9C,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,WAAO,IAAI,SAAS,+BAA+B,EAAE,QAAQ,IAAI,CAAC;AAAA,EACpE;AAEA,QAAM,UAAU,IAAI,YAAY;AAEhC,QAAM,SAAS,IAAI,eAAe;AAAA,IAChC,MAAM,YAAY;AAEhB,YAAM,aAAa,SAAS,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC,CAAC;AAAA;AAAA;AACjE,iBAAW,QAAQ,QAAQ,OAAO,UAAU,CAAC;AAE7C,YAAM,WAAW,KAAK,QAAQ,IAAI,GAAG,MAAM;AAG3C,YAAM,UAAU;AAAA,QACd;AAAA,QACA,EAAE,WAAW,KAAK;AAAA,QAClB,CAAC,WAAW,aAAa;AACvB,cAAI,CAAC,SAAU;AAGf,cAAI,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,OAAO,GAAG;AAC3D,oBAAQ,IAAI,eAAe,SAAS,KAAK,QAAQ,EAAE;AAEnD,kBAAM,UAAU,SAAS,KAAK,UAAU;AAAA,cACtC,MAAM;AAAA,cACN,MAAM;AAAA,cACN;AAAA,YACF,CAAC,CAAC;AAAA;AAAA;AAEF,gBAAI;AACF,yBAAW,QAAQ,QAAQ,OAAO,OAAO,CAAC;AAAA,YAC5C,SAAS,OAAO;AACd,sBAAQ,MAAM,sCAAsC,KAAK;AAAA,YAC3D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,cAAQ,OAAO,iBAAiB,SAAS,MAAM;AAC7C,gBAAQ,IAAI,iCAAiC;AAC7C,gBAAQ,MAAM;AACd,YAAI;AACF,qBAAW,MAAM;AAAA,QACnB,SAAS,OAAO;AAAA,QAEhB;AAAA,MACF,CAAC;AAGD,cAAQ,GAAG,SAAS,CAAC,UAAU;AAC7B,gBAAQ,MAAM,8BAA8B,KAAK;AACjD,gBAAQ,MAAM;AACd,YAAI;AACF,qBAAW,MAAM;AAAA,QACnB,SAAS,GAAG;AAAA,QAEZ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO,IAAI,SAAS,QAAQ;AAAA,IAC1B,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,cAAc;AAAA,IAChB;AAAA,EACF,CAAC;AACH;","names":[]}
@@ -0,0 +1,32 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { Metadata } from 'next';
3
+
4
+ interface PageProps {
5
+ params: Promise<{
6
+ version: string;
7
+ slug: string[];
8
+ }>;
9
+ }
10
+ /**
11
+ * Generate metadata for documentation pages
12
+ * This is exported so users can re-export it from their page.tsx
13
+ */
14
+ declare function generateMetadata({ params }: PageProps): Promise<Metadata>;
15
+ /**
16
+ * Generate static params for all documentation pages
17
+ * This enables static generation at build time
18
+ */
19
+ declare function generateStaticParams(): Promise<{
20
+ version: string;
21
+ slug: string[];
22
+ }[]>;
23
+ /**
24
+ * Documentation page component
25
+ * Handles:
26
+ * - Regular documentation pages
27
+ * - Category index pages (with or without content)
28
+ * - 404 pages (when doc not found)
29
+ */
30
+ declare function DocPage({ params }: PageProps): Promise<react_jsx_runtime.JSX.Element>;
31
+
32
+ export { DocPage as default, generateMetadata, generateStaticParams };
@@ -0,0 +1,32 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { Metadata } from 'next';
3
+
4
+ interface PageProps {
5
+ params: Promise<{
6
+ version: string;
7
+ slug: string[];
8
+ }>;
9
+ }
10
+ /**
11
+ * Generate metadata for documentation pages
12
+ * This is exported so users can re-export it from their page.tsx
13
+ */
14
+ declare function generateMetadata({ params }: PageProps): Promise<Metadata>;
15
+ /**
16
+ * Generate static params for all documentation pages
17
+ * This enables static generation at build time
18
+ */
19
+ declare function generateStaticParams(): Promise<{
20
+ version: string;
21
+ slug: string[];
22
+ }[]>;
23
+ /**
24
+ * Documentation page component
25
+ * Handles:
26
+ * - Regular documentation pages
27
+ * - Category index pages (with or without content)
28
+ * - 404 pages (when doc not found)
29
+ */
30
+ declare function DocPage({ params }: PageProps): Promise<react_jsx_runtime.JSX.Element>;
31
+
32
+ export { DocPage as default, generateMetadata, generateStaticParams };