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
@@ -0,0 +1,1301 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/lib/index.ts
31
+ var lib_exports = {};
32
+ __export(lib_exports, {
33
+ OpenApiParser: () => OpenApiParser,
34
+ PerfTimer: () => PerfTimer,
35
+ PostmanParser: () => PostmanParser,
36
+ SpecraParser: () => SpecraParser,
37
+ buildRedirectMappings: () => buildRedirectMappings,
38
+ buildSidebarStructure: () => buildSidebarStructure,
39
+ clearAllCaches: () => clearAllCaches,
40
+ cn: () => cn,
41
+ debugLog: () => debugLog,
42
+ defaultConfig: () => defaultConfig,
43
+ detectParserType: () => detectParserType,
44
+ extractHeadings: () => extractHeadings,
45
+ extractTableOfContents: () => extractTableOfContents,
46
+ findRedirect: () => findRedirect,
47
+ getAdjacentDocs: () => getAdjacentDocs,
48
+ getAllCategoryConfigs: () => getAllCategoryConfigs,
49
+ getAllDocs: () => getAllDocs,
50
+ getAssetPath: () => getAssetPath,
51
+ getCacheStats: () => getCacheStats,
52
+ getCachedAllDocs: () => getCachedAllDocs,
53
+ getCachedDocBySlug: () => getCachedDocBySlug,
54
+ getCachedVersions: () => getCachedVersions,
55
+ getCategoryConfig: () => getCategoryConfig,
56
+ getConfig: () => getConfig,
57
+ getConfigValue: () => getConfigValue,
58
+ getDocBySlug: () => getDocBySlug,
59
+ getVersions: () => getVersions,
60
+ initConfig: () => initConfig,
61
+ isCategoryPage: () => isCategoryPage,
62
+ loadConfig: () => loadConfig,
63
+ logCacheOperation: () => logCacheOperation,
64
+ logFsOperation: () => logFsOperation,
65
+ logMemoryUsage: () => logMemoryUsage,
66
+ parseApiSpec: () => parseApiSpec,
67
+ processContentWithEnv: () => processContentWithEnv,
68
+ reloadConfig: () => reloadConfig,
69
+ replaceEnvVariables: () => replaceEnvVariables,
70
+ sortSidebarGroups: () => sortSidebarGroups,
71
+ sortSidebarItems: () => sortSidebarItems,
72
+ validateConfig: () => validateConfig
73
+ });
74
+ module.exports = __toCommonJS(lib_exports);
75
+
76
+ // src/lib/mdx.ts
77
+ var import_fs2 = __toESM(require("fs"));
78
+ var import_path2 = __toESM(require("path"));
79
+ var import_gray_matter = __toESM(require("gray-matter"));
80
+
81
+ // src/lib/category.ts
82
+ var import_fs = __toESM(require("fs"));
83
+ var import_path = __toESM(require("path"));
84
+ var DOCS_DIR = import_path.default.join(process.cwd(), "docs");
85
+ function getCategoryConfig(folderPath) {
86
+ try {
87
+ const categoryPath = import_path.default.join(folderPath, "_category_.json");
88
+ if (!import_fs.default.existsSync(categoryPath)) {
89
+ return null;
90
+ }
91
+ const content = import_fs.default.readFileSync(categoryPath, "utf8");
92
+ return JSON.parse(content);
93
+ } catch (error) {
94
+ console.error(`Error reading category config from ${folderPath}:`, error);
95
+ return null;
96
+ }
97
+ }
98
+ function getAllCategoryConfigs(version) {
99
+ const configs = /* @__PURE__ */ new Map();
100
+ const versionDir = import_path.default.join(DOCS_DIR, version);
101
+ if (!import_fs.default.existsSync(versionDir)) {
102
+ return configs;
103
+ }
104
+ function scanDirectory(dir, relativePath = "") {
105
+ const entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
106
+ for (const entry of entries) {
107
+ if (entry.isDirectory()) {
108
+ const fullPath = import_path.default.join(dir, entry.name);
109
+ const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
110
+ const config = getCategoryConfig(fullPath);
111
+ if (config) {
112
+ configs.set(relPath, config);
113
+ }
114
+ scanDirectory(fullPath, relPath);
115
+ }
116
+ }
117
+ }
118
+ scanDirectory(versionDir);
119
+ return configs;
120
+ }
121
+
122
+ // src/lib/sidebar-utils.ts
123
+ function sortSidebarItems(items) {
124
+ return [...items].sort((a, b) => {
125
+ const posA = a.sidebar_position ?? a.meta?.sidebar_position ?? a.meta?.order ?? 999;
126
+ const posB = b.sidebar_position ?? b.meta?.sidebar_position ?? b.meta?.order ?? 999;
127
+ return posA - posB;
128
+ });
129
+ }
130
+ function sortSidebarGroups(groups) {
131
+ return Object.entries(groups).sort(([, a], [, b]) => {
132
+ const posA = a.position ?? 999;
133
+ const posB = b.position ?? 999;
134
+ return posA - posB;
135
+ });
136
+ }
137
+ function buildSidebarStructure(docs) {
138
+ const rootGroups = {};
139
+ const standalone = [];
140
+ const categoryMetadata = /* @__PURE__ */ new Map();
141
+ docs.forEach((doc) => {
142
+ const pathParts = doc.filePath.split("/");
143
+ const folderPath = pathParts.length > 1 ? pathParts.slice(0, -1).join("/") : "";
144
+ if (folderPath && doc.categoryLabel) {
145
+ categoryMetadata.set(folderPath, {
146
+ label: doc.categoryLabel,
147
+ position: doc.categoryPosition,
148
+ icon: doc.categoryIcon,
149
+ collapsible: doc.categoryCollapsible,
150
+ collapsed: doc.categoryCollapsed
151
+ });
152
+ }
153
+ });
154
+ docs.forEach((doc) => {
155
+ const pathParts = doc.filePath.split("/");
156
+ const isIndexFile = doc.filePath.endsWith("/index") || doc.filePath === "index" || pathParts.length > 1 && doc.slug === pathParts.slice(0, -1).join("/");
157
+ const customGroup = doc.meta.sidebar || doc.meta.group;
158
+ if (customGroup) {
159
+ const groupName = customGroup.charAt(0).toUpperCase() + customGroup.slice(1);
160
+ if (!rootGroups[groupName]) {
161
+ rootGroups[groupName] = {
162
+ label: groupName,
163
+ path: customGroup,
164
+ items: [],
165
+ position: 999,
166
+ collapsible: doc.categoryCollapsible ?? true,
167
+ defaultCollapsed: doc.categoryCollapsed ?? false,
168
+ children: {}
169
+ };
170
+ }
171
+ if (isIndexFile) {
172
+ rootGroups[groupName].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? 999;
173
+ rootGroups[groupName].icon = doc.categoryIcon;
174
+ } else {
175
+ rootGroups[groupName].items.push(doc);
176
+ }
177
+ return;
178
+ }
179
+ if (pathParts.length > 1) {
180
+ const folderParts = pathParts.slice(0, -1);
181
+ let currentLevel = rootGroups;
182
+ let currentPath = "";
183
+ for (let i = 0; i < folderParts.length; i++) {
184
+ const folder = folderParts[i];
185
+ currentPath = currentPath ? `${currentPath}/${folder}` : folder;
186
+ const folderLabel = folder.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
187
+ const metadata = categoryMetadata.get(currentPath);
188
+ if (!currentLevel[folder]) {
189
+ currentLevel[folder] = {
190
+ label: metadata?.label ?? folderLabel,
191
+ path: currentPath,
192
+ icon: metadata?.icon,
193
+ items: [],
194
+ position: metadata?.position ?? 999,
195
+ collapsible: metadata?.collapsible ?? true,
196
+ defaultCollapsed: metadata?.collapsed ?? false,
197
+ children: {}
198
+ };
199
+ }
200
+ if (i === folderParts.length - 1) {
201
+ if (isIndexFile) {
202
+ currentLevel[folder].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? currentLevel[folder].position;
203
+ if (doc.categoryLabel) {
204
+ currentLevel[folder].label = doc.categoryLabel;
205
+ }
206
+ if (doc.categoryIcon) {
207
+ currentLevel[folder].icon = doc.categoryIcon;
208
+ }
209
+ if (doc.categoryCollapsible !== void 0) {
210
+ currentLevel[folder].collapsible = doc.categoryCollapsible;
211
+ }
212
+ if (doc.categoryCollapsed !== void 0) {
213
+ currentLevel[folder].defaultCollapsed = doc.categoryCollapsed;
214
+ }
215
+ } else {
216
+ currentLevel[folder].items.push(doc);
217
+ }
218
+ }
219
+ currentLevel = currentLevel[folder].children;
220
+ }
221
+ } else {
222
+ if (!isIndexFile) {
223
+ standalone.push(doc);
224
+ }
225
+ }
226
+ });
227
+ return { rootGroups, standalone };
228
+ }
229
+
230
+ // src/lib/mdx.ts
231
+ var DOCS_DIR2 = import_path2.default.join(process.cwd(), "docs");
232
+ function calculateReadingTime(content) {
233
+ const words = content.trim().split(/\s+/).length;
234
+ const minutes = Math.ceil(words / 200);
235
+ return { minutes, words };
236
+ }
237
+ function getVersions() {
238
+ try {
239
+ const versions = import_fs2.default.readdirSync(DOCS_DIR2);
240
+ return versions.filter((v) => import_fs2.default.statSync(import_path2.default.join(DOCS_DIR2, v)).isDirectory());
241
+ } catch (error) {
242
+ return ["v1.0.0"];
243
+ }
244
+ }
245
+ function findMdxFiles(dir, baseDir = dir) {
246
+ const files = [];
247
+ try {
248
+ const entries = import_fs2.default.readdirSync(dir, { withFileTypes: true });
249
+ for (const entry of entries) {
250
+ const fullPath = import_path2.default.join(dir, entry.name);
251
+ if (entry.isDirectory()) {
252
+ files.push(...findMdxFiles(fullPath, baseDir));
253
+ } else if (entry.isFile() && entry.name.endsWith(".mdx")) {
254
+ const relativePath = import_path2.default.relative(baseDir, fullPath).replace(/\\/g, "/");
255
+ files.push(relativePath);
256
+ }
257
+ }
258
+ } catch (error) {
259
+ console.error(`Error reading directory ${dir}:`, error);
260
+ }
261
+ return files;
262
+ }
263
+ function readDocFromFile(filePath, originalSlug) {
264
+ try {
265
+ if (!import_fs2.default.existsSync(filePath)) {
266
+ return null;
267
+ }
268
+ const fileContents = import_fs2.default.readFileSync(filePath, "utf8");
269
+ const { data, content } = (0, import_gray_matter.default)(fileContents);
270
+ const { minutes, words } = calculateReadingTime(content);
271
+ let finalSlug = originalSlug;
272
+ if (data.slug) {
273
+ const customSlug = data.slug.replace(/^\//, "");
274
+ const parts = originalSlug.split("/");
275
+ if (parts.length > 1) {
276
+ parts[parts.length - 1] = customSlug;
277
+ finalSlug = parts.join("/");
278
+ } else {
279
+ finalSlug = customSlug;
280
+ }
281
+ }
282
+ return {
283
+ slug: finalSlug,
284
+ filePath: originalSlug,
285
+ // Keep original file path for sidebar
286
+ title: data.title || originalSlug,
287
+ meta: {
288
+ ...data,
289
+ content,
290
+ reading_time: minutes,
291
+ word_count: words
292
+ },
293
+ content
294
+ };
295
+ } catch (error) {
296
+ console.error(`Error reading file ${filePath}:`, error);
297
+ return null;
298
+ }
299
+ }
300
+ async function getDocBySlug(slug, version = "v1.0.0") {
301
+ try {
302
+ let filePath = import_path2.default.join(DOCS_DIR2, version, `${slug}.mdx`);
303
+ let doc = readDocFromFile(filePath, slug);
304
+ if (doc) return doc;
305
+ filePath = import_path2.default.join(DOCS_DIR2, version, slug, "index.mdx");
306
+ doc = readDocFromFile(filePath, slug);
307
+ if (doc) return doc;
308
+ const versionDir = import_path2.default.join(DOCS_DIR2, version);
309
+ if (!import_fs2.default.existsSync(versionDir)) {
310
+ return null;
311
+ }
312
+ const mdxFiles = findMdxFiles(versionDir);
313
+ for (const file of mdxFiles) {
314
+ const fileSlug = file.replace(/\.mdx$/, "");
315
+ const testPath = import_path2.default.join(versionDir, file.endsWith("index.mdx") ? file : `${fileSlug}.mdx`);
316
+ const testDoc = readDocFromFile(testPath, fileSlug);
317
+ if (testDoc && testDoc.slug === slug) {
318
+ return testDoc;
319
+ }
320
+ }
321
+ return null;
322
+ } catch (error) {
323
+ console.error(`Error reading doc ${slug}:`, error);
324
+ return null;
325
+ }
326
+ }
327
+ async function getAllDocs(version = "v1.0.0") {
328
+ try {
329
+ const versionDir = import_path2.default.join(DOCS_DIR2, version);
330
+ if (!import_fs2.default.existsSync(versionDir)) {
331
+ return [];
332
+ }
333
+ const mdxFiles = findMdxFiles(versionDir);
334
+ const categoryConfigs = getAllCategoryConfigs(version);
335
+ const docs = await Promise.all(
336
+ mdxFiles.map(async (file) => {
337
+ const originalFilePath = file.replace(/\.mdx$/, "");
338
+ let slug = originalFilePath;
339
+ if (file.endsWith("/index.mdx") || file === "index.mdx") {
340
+ slug = import_path2.default.dirname(file).replace(/\\/g, "/");
341
+ if (slug === ".") slug = "";
342
+ }
343
+ const doc = await getDocBySlug(slug, version);
344
+ if (doc) {
345
+ doc.filePath = originalFilePath;
346
+ const folderPath = import_path2.default.dirname(originalFilePath).replace(/\\/g, "/");
347
+ if (folderPath !== ".") {
348
+ const categoryConfig = categoryConfigs.get(folderPath);
349
+ if (categoryConfig) {
350
+ doc.categoryLabel = categoryConfig.label;
351
+ doc.categoryPosition = categoryConfig.position ?? categoryConfig.sidebar_position;
352
+ doc.categoryCollapsible = categoryConfig.collapsible;
353
+ doc.categoryCollapsed = categoryConfig.collapsed;
354
+ doc.categoryIcon = categoryConfig.icon;
355
+ doc.categoryTabGroup = categoryConfig.tab_group;
356
+ }
357
+ }
358
+ }
359
+ return doc;
360
+ })
361
+ );
362
+ const isDevelopment3 = process.env.NODE_ENV === "development";
363
+ const uniqueDocs = /* @__PURE__ */ new Map();
364
+ docs.filter((doc) => doc !== null).filter((doc) => isDevelopment3 || !doc.meta.draft).forEach((doc) => {
365
+ uniqueDocs.set(doc.slug, doc);
366
+ });
367
+ return Array.from(uniqueDocs.values()).sort((a, b) => {
368
+ const orderA = a.meta.sidebar_position ?? a.meta.order ?? 999;
369
+ const orderB = b.meta.sidebar_position ?? b.meta.order ?? 999;
370
+ return orderA - orderB;
371
+ });
372
+ } catch (error) {
373
+ console.error(`Error getting all docs for version ${version}:`, error);
374
+ return [];
375
+ }
376
+ }
377
+ function flattenSidebarOrder(rootGroups, standalone) {
378
+ const flatDocs = [];
379
+ const flattenGroup = (group) => {
380
+ const sortedChildren = sortSidebarGroups(group.children);
381
+ const sortedItems = sortSidebarItems(group.items);
382
+ const merged = [
383
+ ...sortedChildren.map(([, childGroup]) => ({
384
+ type: "group",
385
+ group: childGroup,
386
+ position: childGroup.position
387
+ })),
388
+ ...sortedItems.map((doc) => ({
389
+ type: "item",
390
+ doc,
391
+ position: doc.meta.sidebar_position ?? doc.meta.order ?? 999
392
+ }))
393
+ ];
394
+ merged.sort((a, b) => a.position - b.position);
395
+ merged.forEach((item) => {
396
+ if (item.type === "group") {
397
+ flattenGroup(item.group);
398
+ } else {
399
+ flatDocs.push(item.doc);
400
+ }
401
+ });
402
+ };
403
+ sortSidebarItems(standalone).forEach((doc) => {
404
+ flatDocs.push(doc);
405
+ });
406
+ const sortedRootGroups = sortSidebarGroups(rootGroups);
407
+ sortedRootGroups.forEach(([, group]) => {
408
+ flattenGroup(group);
409
+ });
410
+ return flatDocs;
411
+ }
412
+ function getAdjacentDocs(currentSlug, allDocs) {
413
+ const { rootGroups, standalone } = buildSidebarStructure(allDocs);
414
+ const orderedDocs = flattenSidebarOrder(rootGroups, standalone);
415
+ const currentIndex = orderedDocs.findIndex((doc) => doc.slug === currentSlug);
416
+ if (currentIndex === -1) {
417
+ return {};
418
+ }
419
+ const currentDoc = orderedDocs[currentIndex];
420
+ const currentTabGroup = currentDoc.meta?.tab_group || currentDoc.categoryTabGroup;
421
+ const filteredDocs = orderedDocs.filter((doc) => {
422
+ const docTabGroup = doc.meta?.tab_group || doc.categoryTabGroup;
423
+ if (currentTabGroup) {
424
+ return docTabGroup === currentTabGroup;
425
+ }
426
+ return !docTabGroup;
427
+ });
428
+ const filteredIndex = filteredDocs.findIndex((doc) => doc.slug === currentSlug);
429
+ if (filteredIndex === -1) {
430
+ return {};
431
+ }
432
+ return {
433
+ previous: filteredIndex > 0 ? filteredDocs[filteredIndex - 1] : void 0,
434
+ next: filteredIndex < filteredDocs.length - 1 ? filteredDocs[filteredIndex + 1] : void 0
435
+ };
436
+ }
437
+ function extractTableOfContents(content) {
438
+ const headingRegex = /^(#{2,3})\s+(.+)$/gm;
439
+ const toc = [];
440
+ let match;
441
+ while ((match = headingRegex.exec(content)) !== null) {
442
+ const level = match[1].length;
443
+ const text = match[2];
444
+ const id = text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-|-$/g, "");
445
+ toc.push({ id, title: text, level });
446
+ }
447
+ return toc;
448
+ }
449
+ function isCategoryPage(slug, allDocs) {
450
+ return allDocs.some((doc) => {
451
+ const parts = doc.slug.split("/");
452
+ const docParent = parts.slice(0, -1).join("/");
453
+ return docParent === slug && doc.slug !== slug;
454
+ });
455
+ }
456
+
457
+ // src/lib/mdx-cache.ts
458
+ var import_fs3 = require("fs");
459
+ var import_path3 = require("path");
460
+
461
+ // src/lib/dev-utils.ts
462
+ var isDevelopment = process.env.NODE_ENV === "development";
463
+ var PerfTimer = class {
464
+ constructor(label) {
465
+ this.label = label;
466
+ this.startTime = isDevelopment ? performance.now() : 0;
467
+ }
468
+ end() {
469
+ if (!isDevelopment) return;
470
+ const duration = performance.now() - this.startTime;
471
+ const color = duration > 1e3 ? "\x1B[31m" : duration > 500 ? "\x1B[33m" : "\x1B[32m";
472
+ const reset = "\x1B[0m";
473
+ console.log(`${color}\u23F1\uFE0F ${this.label}: ${duration.toFixed(2)}ms${reset}`);
474
+ }
475
+ };
476
+ function logFsOperation(operation, path3, details) {
477
+ if (!isDevelopment) return;
478
+ console.log(`\u{1F4C1} [FS] ${operation}: ${path3}`, details || "");
479
+ }
480
+ function logCacheOperation(operation, key) {
481
+ if (!isDevelopment) return;
482
+ const emoji = operation === "hit" ? "\u2705" : operation === "miss" ? "\u274C" : "\u{1F504}";
483
+ console.log(`${emoji} [Cache] ${operation}: ${key}`);
484
+ }
485
+ function logMemoryUsage(label) {
486
+ if (!isDevelopment) return;
487
+ const used = process.memoryUsage();
488
+ const prefix = label ? `[${label}] ` : "";
489
+ console.log(`\u{1F4BE} ${prefix}Memory Usage:`, {
490
+ rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
491
+ heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
492
+ heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`
493
+ });
494
+ }
495
+ function debugLog(label, data) {
496
+ if (!isDevelopment) return;
497
+ console.log(`
498
+ \u{1F50D} ${label}:`);
499
+ console.dir(data, { depth: null, colors: true });
500
+ console.log("");
501
+ }
502
+
503
+ // src/lib/mdx-cache.ts
504
+ var isDevelopment2 = process.env.NODE_ENV === "development";
505
+ var versionsCache = {
506
+ data: null,
507
+ timestamp: 0
508
+ };
509
+ var allDocsCache = /* @__PURE__ */ new Map();
510
+ var docBySlugCache = /* @__PURE__ */ new Map();
511
+ var CACHE_TTL = isDevelopment2 ? 5e3 : 6e4;
512
+ var watchersInitialized = false;
513
+ function initializeWatchers() {
514
+ if (!isDevelopment2 || watchersInitialized) return;
515
+ watchersInitialized = true;
516
+ const docsPath = (0, import_path3.join)(process.cwd(), "docs");
517
+ try {
518
+ (0, import_fs3.watch)(docsPath, { recursive: true }, (eventType, filename) => {
519
+ if (!filename) return;
520
+ if (filename.endsWith(".mdx") || filename.endsWith(".json")) {
521
+ const parts = filename.split(/[/\\]/);
522
+ const version = parts[0];
523
+ allDocsCache.delete(version);
524
+ const cacheKeysToDelete = [];
525
+ docBySlugCache.forEach((_, key) => {
526
+ if (key.startsWith(`${version}:`)) {
527
+ cacheKeysToDelete.push(key);
528
+ }
529
+ });
530
+ cacheKeysToDelete.forEach((key) => docBySlugCache.delete(key));
531
+ if (eventType === "rename") {
532
+ versionsCache.data = null;
533
+ }
534
+ console.log(`[MDX Cache] Invalidated cache for: ${filename}`);
535
+ }
536
+ });
537
+ console.log("[MDX Cache] File watchers initialized");
538
+ } catch (error) {
539
+ console.error("[MDX Cache] Failed to initialize watchers:", error);
540
+ }
541
+ }
542
+ function isCacheValid(timestamp) {
543
+ return Date.now() - timestamp < CACHE_TTL;
544
+ }
545
+ function getCachedVersions() {
546
+ initializeWatchers();
547
+ if (versionsCache.data && isCacheValid(versionsCache.timestamp)) {
548
+ logCacheOperation("hit", "versions");
549
+ return versionsCache.data;
550
+ }
551
+ logCacheOperation("miss", "versions");
552
+ const timer = new PerfTimer("getVersions");
553
+ const versions = getVersions();
554
+ timer.end();
555
+ versionsCache.data = versions;
556
+ versionsCache.timestamp = Date.now();
557
+ return versions;
558
+ }
559
+ async function getCachedAllDocs(version = "v1.0.0") {
560
+ initializeWatchers();
561
+ const cached = allDocsCache.get(version);
562
+ if (cached && isCacheValid(cached.timestamp)) {
563
+ logCacheOperation("hit", `getAllDocs:${version}`);
564
+ return cached.data;
565
+ }
566
+ logCacheOperation("miss", `getAllDocs:${version}`);
567
+ const timer = new PerfTimer(`getAllDocs(${version})`);
568
+ const docs = await getAllDocs(version);
569
+ timer.end();
570
+ allDocsCache.set(version, {
571
+ data: docs,
572
+ timestamp: Date.now()
573
+ });
574
+ return docs;
575
+ }
576
+ async function getCachedDocBySlug(slug, version = "v1.0.0") {
577
+ initializeWatchers();
578
+ const cacheKey = `${version}:${slug}`;
579
+ const cached = docBySlugCache.get(cacheKey);
580
+ if (cached && isCacheValid(cached.timestamp)) {
581
+ logCacheOperation("hit", `getDocBySlug:${cacheKey}`);
582
+ return cached.data;
583
+ }
584
+ logCacheOperation("miss", `getDocBySlug:${cacheKey}`);
585
+ const timer = new PerfTimer(`getDocBySlug(${slug})`);
586
+ const doc = await getDocBySlug(slug, version);
587
+ timer.end();
588
+ docBySlugCache.set(cacheKey, {
589
+ data: doc,
590
+ timestamp: Date.now()
591
+ });
592
+ return doc;
593
+ }
594
+ function clearAllCaches() {
595
+ versionsCache.data = null;
596
+ allDocsCache.clear();
597
+ docBySlugCache.clear();
598
+ console.log("[MDX Cache] All caches cleared");
599
+ }
600
+ function getCacheStats() {
601
+ return {
602
+ versions: {
603
+ cached: versionsCache.data !== null,
604
+ age: versionsCache.timestamp ? Date.now() - versionsCache.timestamp : 0
605
+ },
606
+ allDocs: {
607
+ entries: allDocsCache.size,
608
+ versions: Array.from(allDocsCache.keys())
609
+ },
610
+ docBySlug: {
611
+ entries: docBySlugCache.size
612
+ }
613
+ };
614
+ }
615
+
616
+ // src/lib/toc.ts
617
+ function extractHeadings(html) {
618
+ const headingRegex = /<h([2-3])[^>]*id="([^"]*)"[^>]*>(.*?)<\/h\1>/g;
619
+ const toc = [];
620
+ let match;
621
+ while ((match = headingRegex.exec(html)) !== null) {
622
+ const level = Number.parseInt(match[1]);
623
+ const id = match[2];
624
+ const title = match[3].replace(/<[^>]*>/g, "");
625
+ toc.push({ id, title, level });
626
+ }
627
+ return toc;
628
+ }
629
+
630
+ // src/lib/config.types.ts
631
+ var defaultConfig = {
632
+ site: {
633
+ title: "Documentation",
634
+ description: "Project documentation",
635
+ baseUrl: "/",
636
+ language: "en"
637
+ },
638
+ theme: {
639
+ defaultMode: "system",
640
+ respectPrefersColorScheme: true
641
+ },
642
+ navigation: {
643
+ showSidebar: true,
644
+ collapsibleSidebar: true,
645
+ showBreadcrumbs: true,
646
+ showTableOfContents: true,
647
+ tocPosition: "right",
648
+ tocMaxDepth: 3
649
+ },
650
+ search: {
651
+ enabled: true,
652
+ provider: "local",
653
+ placeholder: "Search documentation..."
654
+ },
655
+ features: {
656
+ showLastUpdated: true,
657
+ showReadingTime: true,
658
+ showAuthors: false,
659
+ showTags: true,
660
+ versioning: true,
661
+ i18n: false
662
+ }
663
+ };
664
+
665
+ // src/lib/config.server.ts
666
+ function deepMerge(target, source) {
667
+ const result = { ...target };
668
+ for (const key in source) {
669
+ const sourceValue = source[key];
670
+ const targetValue = result[key];
671
+ if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
672
+ result[key] = deepMerge(
673
+ targetValue && typeof targetValue === "object" ? targetValue : {},
674
+ sourceValue
675
+ );
676
+ } else if (sourceValue !== void 0) {
677
+ result[key] = sourceValue;
678
+ }
679
+ }
680
+ return result;
681
+ }
682
+ function loadConfig(userConfig) {
683
+ try {
684
+ const config = deepMerge(defaultConfig, userConfig);
685
+ return config;
686
+ } catch (error) {
687
+ console.error(`\u274C Error loading configuration:`, error);
688
+ console.warn("Using default configuration.");
689
+ return defaultConfig;
690
+ }
691
+ }
692
+ function getConfigValue(path3, config) {
693
+ const cfg = config || loadConfig({});
694
+ const keys = path3.split(".");
695
+ let value = cfg;
696
+ for (const key of keys) {
697
+ if (value && typeof value === "object" && key in value) {
698
+ value = value[key];
699
+ } else {
700
+ return void 0;
701
+ }
702
+ }
703
+ return value;
704
+ }
705
+ function replaceEnvVariables(text, config) {
706
+ const cfg = config || loadConfig({});
707
+ const envVars = cfg.env || {};
708
+ let result = text;
709
+ result = result.replace(/\$\{([^}]+)\}/g, (match, varName) => {
710
+ return envVars[varName] || match;
711
+ });
712
+ result = result.replace(/\{\{([^}]+)\}\}/g, (match, varName) => {
713
+ return envVars[varName] || match;
714
+ });
715
+ return result;
716
+ }
717
+ function processContentWithEnv(content, config) {
718
+ return replaceEnvVariables(content, config);
719
+ }
720
+ function validateConfig(config) {
721
+ const errors = [];
722
+ if (!config.site?.title) {
723
+ errors.push("site.title is required");
724
+ }
725
+ if (config.site?.url) {
726
+ try {
727
+ new URL(config.site.url);
728
+ } catch {
729
+ errors.push("site.url must be a valid URL");
730
+ }
731
+ }
732
+ if (config.social) {
733
+ const socialKeys = ["github", "twitter", "discord", "linkedin", "youtube"];
734
+ for (const key of socialKeys) {
735
+ const url = config.social[key];
736
+ if (url) {
737
+ try {
738
+ new URL(url);
739
+ } catch {
740
+ errors.push(`social.${key} must be a valid URL`);
741
+ }
742
+ }
743
+ }
744
+ }
745
+ return {
746
+ valid: errors.length === 0,
747
+ errors
748
+ };
749
+ }
750
+ var configInstance = null;
751
+ function initConfig(userConfig) {
752
+ if (configInstance) {
753
+ throw new Error("Specra config has already been initialized");
754
+ }
755
+ configInstance = loadConfig(userConfig);
756
+ return configInstance;
757
+ }
758
+ function getConfig() {
759
+ if (!configInstance) {
760
+ throw new Error("Specra config has not been initialized");
761
+ }
762
+ return configInstance;
763
+ }
764
+ function reloadConfig(userConfig) {
765
+ configInstance = loadConfig(userConfig);
766
+ return configInstance;
767
+ }
768
+
769
+ // src/lib/parsers/specra-parser.ts
770
+ var SpecraParser = class {
771
+ validate(input) {
772
+ return typeof input === "object" && input !== null && "endpoints" in input && Array.isArray(input.endpoints);
773
+ }
774
+ parse(input) {
775
+ if (!this.validate(input)) {
776
+ throw new Error("Invalid Specra API spec format");
777
+ }
778
+ return input;
779
+ }
780
+ };
781
+
782
+ // src/lib/parsers/openapi-parser.ts
783
+ var OpenApiParser = class {
784
+ validate(input) {
785
+ return typeof input === "object" && input !== null && ("openapi" in input || "swagger" in input) && "paths" in input;
786
+ }
787
+ parse(input) {
788
+ if (!this.validate(input)) {
789
+ throw new Error("Invalid OpenAPI spec format");
790
+ }
791
+ const baseUrl = this.extractBaseUrl(input);
792
+ const endpoints = [];
793
+ for (const [path3, pathItem] of Object.entries(input.paths || {})) {
794
+ const methods = ["get", "post", "put", "patch", "delete"];
795
+ for (const method of methods) {
796
+ const operation = pathItem[method];
797
+ if (!operation) continue;
798
+ const endpoint = this.parseOperation(path3, method.toUpperCase(), operation, input);
799
+ endpoints.push(endpoint);
800
+ }
801
+ }
802
+ return {
803
+ version: input.info?.version,
804
+ title: input.info?.title,
805
+ description: input.info?.description,
806
+ baseUrl,
807
+ auth: this.extractAuth(input),
808
+ endpoints
809
+ };
810
+ }
811
+ extractBaseUrl(spec) {
812
+ if (spec.servers && spec.servers.length > 0) {
813
+ return spec.servers[0].url;
814
+ }
815
+ if (spec.host) {
816
+ const scheme = spec.schemes?.[0] || "https";
817
+ const basePath = spec.basePath || "";
818
+ return `${scheme}://${spec.host}${basePath}`;
819
+ }
820
+ return "";
821
+ }
822
+ extractAuth(spec) {
823
+ const securitySchemes = spec.components?.securitySchemes || spec.securityDefinitions;
824
+ if (!securitySchemes) return void 0;
825
+ const firstScheme = Object.values(securitySchemes)[0];
826
+ if (!firstScheme) return void 0;
827
+ if (firstScheme.type === "http" && firstScheme.scheme === "bearer") {
828
+ return {
829
+ type: "bearer",
830
+ description: firstScheme.description,
831
+ tokenPrefix: "Bearer"
832
+ };
833
+ }
834
+ if (firstScheme.type === "apiKey") {
835
+ return {
836
+ type: "apiKey",
837
+ description: firstScheme.description,
838
+ headerName: firstScheme.name || "X-API-Key"
839
+ };
840
+ }
841
+ if (firstScheme.type === "http" && firstScheme.scheme === "basic") {
842
+ return {
843
+ type: "basic",
844
+ description: firstScheme.description
845
+ };
846
+ }
847
+ return void 0;
848
+ }
849
+ parseOperation(path3, method, operation, spec) {
850
+ const endpoint = {
851
+ title: operation.summary || operation.operationId || `${method} ${path3}`,
852
+ method,
853
+ path: this.convertPathParams(path3),
854
+ description: operation.description
855
+ };
856
+ const params = this.parseParameters(operation.parameters || [], spec);
857
+ if (params.path.length > 0) endpoint.pathParams = params.path;
858
+ if (params.query.length > 0) endpoint.queryParams = params.query;
859
+ if (params.header.length > 0) {
860
+ endpoint.headers = params.header.map((p) => ({
861
+ name: p.name,
862
+ value: p.example || "",
863
+ description: p.description
864
+ }));
865
+ }
866
+ if (operation.requestBody) {
867
+ endpoint.body = this.parseRequestBody(operation.requestBody, spec);
868
+ }
869
+ const responses = this.parseResponses(operation.responses || {}, spec);
870
+ if (responses.success) endpoint.successResponse = responses.success;
871
+ if (responses.errors.length > 0) endpoint.errorResponses = responses.errors;
872
+ return endpoint;
873
+ }
874
+ convertPathParams(path3) {
875
+ return path3.replace(/\{([^}]+)\}/g, ":$1");
876
+ }
877
+ parseParameters(parameters, spec) {
878
+ const result = { path: [], query: [], header: [] };
879
+ for (const param of parameters) {
880
+ const resolved = param.$ref ? this.resolveRef(param.$ref, spec) : param;
881
+ const apiParam = {
882
+ name: resolved.name,
883
+ type: resolved.schema?.type || resolved.type || "string",
884
+ required: resolved.required,
885
+ description: resolved.description,
886
+ example: resolved.example || resolved.schema?.example
887
+ };
888
+ if (resolved.in === "path") result.path.push(apiParam);
889
+ else if (resolved.in === "query") result.query.push(apiParam);
890
+ else if (resolved.in === "header") result.header.push(apiParam);
891
+ }
892
+ return result;
893
+ }
894
+ parseRequestBody(requestBody, spec) {
895
+ const content = requestBody.content?.["application/json"];
896
+ if (!content) return void 0;
897
+ return {
898
+ description: requestBody.description,
899
+ example: content.example || this.generateExample(content.schema, spec),
900
+ schema: content.schema
901
+ };
902
+ }
903
+ parseResponses(responses, spec) {
904
+ const result = { errors: [] };
905
+ for (const [statusCode, response] of Object.entries(responses)) {
906
+ const status = parseInt(statusCode);
907
+ if (isNaN(status)) continue;
908
+ const resolved = response.$ref ? this.resolveRef(response.$ref, spec) : response;
909
+ const content = resolved.content?.["application/json"];
910
+ const apiResponse = {
911
+ status,
912
+ description: resolved.description,
913
+ example: content?.example || this.generateExample(content?.schema, spec),
914
+ schema: content?.schema
915
+ };
916
+ if (status >= 200 && status < 300) {
917
+ result.success = apiResponse;
918
+ } else {
919
+ result.errors.push(apiResponse);
920
+ }
921
+ }
922
+ return result;
923
+ }
924
+ generateExample(schema, spec) {
925
+ if (!schema) return void 0;
926
+ if (schema.$ref) schema = this.resolveRef(schema.$ref, spec);
927
+ if (schema.example) return schema.example;
928
+ if (schema.type === "object" && schema.properties) {
929
+ const example = {};
930
+ for (const [key, prop] of Object.entries(schema.properties)) {
931
+ example[key] = this.generateExample(prop, spec);
932
+ }
933
+ return example;
934
+ }
935
+ if (schema.type === "array" && schema.items) {
936
+ return [this.generateExample(schema.items, spec)];
937
+ }
938
+ const defaults = {
939
+ string: "string",
940
+ number: 0,
941
+ integer: 0,
942
+ boolean: false,
943
+ object: {},
944
+ array: []
945
+ };
946
+ return defaults[schema.type] || null;
947
+ }
948
+ resolveRef(ref, spec) {
949
+ const path3 = ref.replace(/^#\//, "").split("/");
950
+ let current = spec;
951
+ for (const segment of path3) {
952
+ current = current[segment];
953
+ if (!current) return {};
954
+ }
955
+ return current;
956
+ }
957
+ };
958
+
959
+ // src/lib/parsers/postman-parser.ts
960
+ var PostmanParser = class {
961
+ validate(input) {
962
+ return typeof input === "object" && input !== null && "info" in input && input.info?.schema?.includes("v2");
963
+ }
964
+ parse(input) {
965
+ if (!this.validate(input)) {
966
+ throw new Error("Invalid Postman Collection format (requires v2.0 or v2.1)");
967
+ }
968
+ const baseUrl = this.extractBaseUrl(input);
969
+ const endpoints = [];
970
+ this.parseItems(input.item || [], endpoints, baseUrl, input);
971
+ return {
972
+ version: input.info?.version,
973
+ title: input.info?.name,
974
+ description: input.info?.description,
975
+ baseUrl,
976
+ auth: this.extractAuth(input.auth),
977
+ globalHeaders: this.extractGlobalHeaders(input),
978
+ endpoints
979
+ };
980
+ }
981
+ extractBaseUrl(collection) {
982
+ const baseUrlVar = collection.variable?.find(
983
+ (v) => v.key === "baseUrl" || v.key === "base_url" || v.key === "url"
984
+ );
985
+ if (baseUrlVar) return baseUrlVar.value;
986
+ if (collection.item && collection.item.length > 0) {
987
+ const firstRequest = this.findFirstRequest(collection.item);
988
+ if (firstRequest?.request?.url) {
989
+ const url = this.parseUrl(firstRequest.request.url);
990
+ if (url.host) {
991
+ return `${url.protocol}://${url.host.join(".")}`;
992
+ }
993
+ }
994
+ }
995
+ return "";
996
+ }
997
+ findFirstRequest(items) {
998
+ for (const item of items) {
999
+ if (item.request) return item;
1000
+ if (item.item) {
1001
+ const found = this.findFirstRequest(item.item);
1002
+ if (found) return found;
1003
+ }
1004
+ }
1005
+ return null;
1006
+ }
1007
+ extractAuth(auth) {
1008
+ if (!auth) return void 0;
1009
+ if (auth.type === "bearer") {
1010
+ return {
1011
+ type: "bearer",
1012
+ tokenPrefix: "Bearer"
1013
+ };
1014
+ }
1015
+ if (auth.type === "apikey") {
1016
+ const keyData = auth.apikey?.find((a) => a.key === "key");
1017
+ const keyName = keyData?.value || "X-API-Key";
1018
+ return {
1019
+ type: "apiKey",
1020
+ headerName: keyName
1021
+ };
1022
+ }
1023
+ if (auth.type === "basic") {
1024
+ return {
1025
+ type: "basic"
1026
+ };
1027
+ }
1028
+ return void 0;
1029
+ }
1030
+ extractGlobalHeaders(collection) {
1031
+ return [];
1032
+ }
1033
+ parseItems(items, endpoints, baseUrl, collection) {
1034
+ for (const item of items) {
1035
+ if (item.item && Array.isArray(item.item)) {
1036
+ this.parseItems(item.item, endpoints, baseUrl, collection);
1037
+ } else if (item.request) {
1038
+ const endpoint = this.parseRequest(item, baseUrl, collection);
1039
+ endpoints.push(endpoint);
1040
+ }
1041
+ }
1042
+ }
1043
+ parseRequest(item, baseUrl, collection) {
1044
+ const request = item.request;
1045
+ const url = this.parseUrl(request.url);
1046
+ const endpoint = {
1047
+ title: item.name,
1048
+ method: request.method.toUpperCase(),
1049
+ path: this.buildPath(url, baseUrl),
1050
+ description: item.request.description || item.description
1051
+ };
1052
+ const params = this.parseUrlParams(url);
1053
+ if (params.path.length > 0) endpoint.pathParams = params.path;
1054
+ if (params.query.length > 0) endpoint.queryParams = params.query;
1055
+ if (request.header && request.header.length > 0) {
1056
+ endpoint.headers = request.header.filter((h) => !h.disabled).map((h) => ({
1057
+ name: h.key,
1058
+ value: h.value || "",
1059
+ description: h.description
1060
+ }));
1061
+ }
1062
+ if (request.body) {
1063
+ endpoint.body = this.parseBody(request.body);
1064
+ }
1065
+ const responses = this.parseResponses(item.response || []);
1066
+ if (responses.success) endpoint.successResponse = responses.success;
1067
+ if (responses.errors.length > 0) endpoint.errorResponses = responses.errors;
1068
+ return endpoint;
1069
+ }
1070
+ parseUrl(url) {
1071
+ if (typeof url === "string") {
1072
+ const urlObj = new URL(url);
1073
+ return {
1074
+ protocol: urlObj.protocol.replace(":", ""),
1075
+ host: urlObj.hostname.split("."),
1076
+ path: urlObj.pathname.split("/").filter(Boolean),
1077
+ query: [],
1078
+ variable: []
1079
+ };
1080
+ }
1081
+ return {
1082
+ protocol: url.protocol || "https",
1083
+ host: url.host || [],
1084
+ path: url.path || [],
1085
+ query: url.query || [],
1086
+ variable: url.variable || []
1087
+ };
1088
+ }
1089
+ buildPath(url, baseUrl) {
1090
+ let path3 = "/";
1091
+ if (url.path && url.path.length > 0) {
1092
+ path3 += url.path.join("/");
1093
+ }
1094
+ path3 = path3.replace(/\{\{([^}]+)\}\}/g, ":$1");
1095
+ return path3;
1096
+ }
1097
+ parseUrlParams(url) {
1098
+ const result = { path: [], query: [] };
1099
+ if (url.variable && url.variable.length > 0) {
1100
+ for (const v of url.variable) {
1101
+ result.path.push({
1102
+ name: v.key,
1103
+ type: v.type || "string",
1104
+ description: v.description,
1105
+ example: v.value
1106
+ });
1107
+ }
1108
+ }
1109
+ if (url.path && url.path.length > 0) {
1110
+ for (const segment of url.path) {
1111
+ if (segment.startsWith(":")) {
1112
+ const paramName = segment.slice(1);
1113
+ if (!result.path.find((p) => p.name === paramName)) {
1114
+ result.path.push({
1115
+ name: paramName,
1116
+ type: "string"
1117
+ });
1118
+ }
1119
+ }
1120
+ }
1121
+ }
1122
+ if (url.query && url.query.length > 0) {
1123
+ for (const q of url.query) {
1124
+ if (q.disabled) continue;
1125
+ result.query.push({
1126
+ name: q.key,
1127
+ type: "string",
1128
+ description: q.description,
1129
+ example: q.value
1130
+ });
1131
+ }
1132
+ }
1133
+ return result;
1134
+ }
1135
+ parseBody(body) {
1136
+ if (!body) return void 0;
1137
+ let example;
1138
+ let description = body.description;
1139
+ if (body.mode === "raw") {
1140
+ try {
1141
+ example = JSON.parse(body.raw);
1142
+ } catch {
1143
+ example = body.raw;
1144
+ }
1145
+ } else if (body.mode === "formdata" || body.mode === "urlencoded") {
1146
+ example = {};
1147
+ for (const item of body[body.mode] || []) {
1148
+ if (!item.disabled) {
1149
+ example[item.key] = item.value;
1150
+ }
1151
+ }
1152
+ }
1153
+ return {
1154
+ description,
1155
+ example
1156
+ };
1157
+ }
1158
+ parseResponses(responses) {
1159
+ const result = { errors: [] };
1160
+ for (const response of responses) {
1161
+ let example;
1162
+ try {
1163
+ example = JSON.parse(response.body);
1164
+ } catch {
1165
+ example = response.body;
1166
+ }
1167
+ const apiResponse = {
1168
+ status: response.code || 200,
1169
+ description: response.name,
1170
+ example
1171
+ };
1172
+ if (apiResponse.status >= 200 && apiResponse.status < 300) {
1173
+ if (!result.success) result.success = apiResponse;
1174
+ } else {
1175
+ result.errors.push(apiResponse);
1176
+ }
1177
+ }
1178
+ return result;
1179
+ }
1180
+ };
1181
+
1182
+ // src/lib/parsers/index.ts
1183
+ var parsers = /* @__PURE__ */ new Map([
1184
+ ["specra", new SpecraParser()],
1185
+ ["openapi", new OpenApiParser()],
1186
+ ["postman", new PostmanParser()]
1187
+ ]);
1188
+ function detectParserType(input) {
1189
+ if (!input || typeof input !== "object") {
1190
+ throw new Error("Invalid API spec: input must be an object");
1191
+ }
1192
+ if (input.info?.schema?.includes("v2")) {
1193
+ return "postman";
1194
+ }
1195
+ if (input.openapi || input.swagger) {
1196
+ return "openapi";
1197
+ }
1198
+ if (input.endpoints && Array.isArray(input.endpoints)) {
1199
+ return "specra";
1200
+ }
1201
+ throw new Error(
1202
+ "Unable to auto-detect API spec format. Supported formats: Specra, OpenAPI 3.x, Postman Collection v2.x"
1203
+ );
1204
+ }
1205
+ function parseApiSpec(input, parserType = "auto") {
1206
+ const actualType = parserType === "auto" ? detectParserType(input) : parserType;
1207
+ const parser = parsers.get(actualType);
1208
+ if (!parser) {
1209
+ throw new Error(`Unknown parser type: ${actualType}`);
1210
+ }
1211
+ if (!parser.validate(input)) {
1212
+ throw new Error(`Input does not match ${actualType} format`);
1213
+ }
1214
+ return parser.parse(input);
1215
+ }
1216
+
1217
+ // src/lib/utils.ts
1218
+ var import_clsx = require("clsx");
1219
+ var import_tailwind_merge = require("tailwind-merge");
1220
+ function cn(...inputs) {
1221
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
1222
+ }
1223
+ function getAssetPath(path3) {
1224
+ const basePath = process.env.NEXT_PUBLIC_BASE_PATH || process.env.__NEXT_ROUTER_BASEPATH || "";
1225
+ const normalizedPath = path3.startsWith("/") ? path3 : `/${path3}`;
1226
+ if (basePath) {
1227
+ const normalizedBase = basePath.startsWith("/") ? basePath : `/${basePath}`;
1228
+ const cleanBase = normalizedBase.replace(/\/$/, "");
1229
+ return `${cleanBase}${normalizedPath}`;
1230
+ }
1231
+ return normalizedPath;
1232
+ }
1233
+
1234
+ // src/lib/redirects.ts
1235
+ async function buildRedirectMappings() {
1236
+ const versions = getVersions();
1237
+ const redirects = [];
1238
+ for (const version of versions) {
1239
+ const docs = await getAllDocs(version);
1240
+ for (const doc of docs) {
1241
+ if (doc.meta.redirect_from && Array.isArray(doc.meta.redirect_from)) {
1242
+ for (const oldPath of doc.meta.redirect_from) {
1243
+ redirects.push({
1244
+ from: oldPath,
1245
+ to: `/docs/${version}/${doc.slug}`
1246
+ });
1247
+ }
1248
+ }
1249
+ }
1250
+ }
1251
+ return redirects;
1252
+ }
1253
+ async function findRedirect(path3) {
1254
+ const redirects = await buildRedirectMappings();
1255
+ const redirect = redirects.find((r) => r.from === path3);
1256
+ return redirect ? redirect.to : null;
1257
+ }
1258
+ // Annotate the CommonJS export names for ESM import in node:
1259
+ 0 && (module.exports = {
1260
+ OpenApiParser,
1261
+ PerfTimer,
1262
+ PostmanParser,
1263
+ SpecraParser,
1264
+ buildRedirectMappings,
1265
+ buildSidebarStructure,
1266
+ clearAllCaches,
1267
+ cn,
1268
+ debugLog,
1269
+ defaultConfig,
1270
+ detectParserType,
1271
+ extractHeadings,
1272
+ extractTableOfContents,
1273
+ findRedirect,
1274
+ getAdjacentDocs,
1275
+ getAllCategoryConfigs,
1276
+ getAllDocs,
1277
+ getAssetPath,
1278
+ getCacheStats,
1279
+ getCachedAllDocs,
1280
+ getCachedDocBySlug,
1281
+ getCachedVersions,
1282
+ getCategoryConfig,
1283
+ getConfig,
1284
+ getConfigValue,
1285
+ getDocBySlug,
1286
+ getVersions,
1287
+ initConfig,
1288
+ isCategoryPage,
1289
+ loadConfig,
1290
+ logCacheOperation,
1291
+ logFsOperation,
1292
+ logMemoryUsage,
1293
+ parseApiSpec,
1294
+ processContentWithEnv,
1295
+ reloadConfig,
1296
+ replaceEnvVariables,
1297
+ sortSidebarGroups,
1298
+ sortSidebarItems,
1299
+ validateConfig
1300
+ });
1301
+ //# sourceMappingURL=index.js.map