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,170 @@
1
+ import specraConfigJson from "../specra.config.json"
2
+ import { SpecraConfig, defaultConfig } from "./config.types"
3
+
4
+ /**
5
+ * Deep merge two objects
6
+ */
7
+ function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {
8
+ const result = { ...target }
9
+
10
+ for (const key in source) {
11
+ const sourceValue = source[key]
12
+ const targetValue = result[key]
13
+
14
+ if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
15
+ result[key] = deepMerge(
16
+ targetValue && typeof targetValue === "object" ? targetValue : {},
17
+ sourceValue,
18
+ ) as T[Extract<keyof T, string>]
19
+ } else if (sourceValue !== undefined) {
20
+ result[key] = sourceValue as T[Extract<keyof T, string>]
21
+ }
22
+ }
23
+
24
+ return result
25
+ }
26
+
27
+ /**
28
+ * Load and parse the Specra configuration file
29
+ * Falls back to default configuration if file doesn't exist or is invalid
30
+ */
31
+ export function loadConfig(userConfig: Partial<SpecraConfig>): SpecraConfig {
32
+ try {
33
+ // const userConfig = specraConfigJson as unknown as Partial<SpecraConfig>
34
+
35
+ // Merge user config with defaults
36
+ const config = deepMerge(defaultConfig, userConfig)
37
+
38
+ return config
39
+ } catch (error) {
40
+ console.error(`āŒ Error loading configuration:`, error)
41
+ console.warn("Using default configuration.")
42
+ return defaultConfig
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Get a specific configuration value by path (SERVER ONLY)
48
+ * Example: getConfigValue('site.title') or getConfigValue('theme.defaultMode')
49
+ */
50
+ export function getConfigValue<T = any>(path: string, config?: SpecraConfig): T | undefined {
51
+ const cfg = config || loadConfig({})
52
+ const keys = path.split(".")
53
+ let value: any = cfg
54
+
55
+ for (const key of keys) {
56
+ if (value && typeof value === "object" && key in value) {
57
+ value = value[key]
58
+ } else {
59
+ return undefined
60
+ }
61
+ }
62
+
63
+ return value as T
64
+ }
65
+
66
+ /**
67
+ * Replace environment variables in a string (SERVER ONLY)
68
+ * Supports ${ENV_VAR} and {{ENV_VAR}} syntax
69
+ */
70
+ export function replaceEnvVariables(text: string, config?: SpecraConfig): string {
71
+ const cfg = config || loadConfig({})
72
+ const envVars = cfg.env || {}
73
+
74
+ let result = text
75
+
76
+ // Replace ${VAR} syntax
77
+ result = result.replace(/\$\{([^}]+)\}/g, (match, varName) => {
78
+ return envVars[varName] || match
79
+ })
80
+
81
+ // Replace {{VAR}} syntax
82
+ result = result.replace(/\{\{([^}]+)\}\}/g, (match, varName) => {
83
+ return envVars[varName] || match
84
+ })
85
+
86
+ return result
87
+ }
88
+
89
+ /**
90
+ * Process content and replace all environment variables (SERVER ONLY)
91
+ */
92
+ export function processContentWithEnv(content: string, config?: SpecraConfig): string {
93
+ return replaceEnvVariables(content, config)
94
+ }
95
+
96
+ /**
97
+ * Validate configuration (basic validation) (SERVER ONLY)
98
+ */
99
+ export function validateConfig(config: SpecraConfig): { valid: boolean; errors: string[] } {
100
+ const errors: string[] = []
101
+
102
+ // Required fields
103
+ if (!config.site?.title) {
104
+ errors.push("site.title is required")
105
+ }
106
+
107
+ // URL validation
108
+ if (config.site?.url) {
109
+ try {
110
+ new URL(config.site.url)
111
+ } catch {
112
+ errors.push("site.url must be a valid URL")
113
+ }
114
+ }
115
+
116
+ // Social links validation
117
+ if (config.social) {
118
+ const socialKeys = ["github", "twitter", "discord", "linkedin", "youtube"] as const
119
+ for (const key of socialKeys) {
120
+ const url = config.social[key]
121
+ if (url) {
122
+ try {
123
+ new URL(url)
124
+ } catch {
125
+ errors.push(`social.${key} must be a valid URL`)
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ return {
132
+ valid: errors.length === 0,
133
+ errors,
134
+ }
135
+ }
136
+
137
+ // Singleton instance
138
+ let configInstance: SpecraConfig | null = null
139
+
140
+ export function initConfig(userConfig: Partial<SpecraConfig>): SpecraConfig {
141
+ if (configInstance) {
142
+ throw new Error("Specra config has already been initialized")
143
+ }
144
+
145
+ configInstance = loadConfig(userConfig)
146
+ return configInstance
147
+ }
148
+
149
+ /**
150
+ * Get the configuration instance (cached) (SERVER ONLY)
151
+ */
152
+ export function getConfig(): SpecraConfig {
153
+ if (!configInstance) {
154
+ throw new Error("Specra config has not been initialized")
155
+ }
156
+ return configInstance
157
+ }
158
+
159
+ /**
160
+ * Reload the configuration (useful for development) (SERVER ONLY)
161
+ */
162
+ export function reloadConfig(userConfig: Partial<SpecraConfig>): SpecraConfig {
163
+ configInstance = loadConfig(userConfig)
164
+ return configInstance
165
+ }
166
+
167
+ /**
168
+ * Export the loaded config as default (SERVER ONLY)
169
+ */
170
+ // export default getConfig()
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Client-safe config access
3
+ * This file re-exports server functions but is safe to import in client components
4
+ * The actual config loading happens on the server and is passed as props
5
+ */
6
+
7
+ export { defaultConfig } from "./config.types"
8
+ export type { SpecraConfig } from "./config.types"
9
+
10
+ // For client components, config should be passed as props from server components
11
+ // These are re-exported for convenience but will only work on the server
12
+ export {
13
+ getConfig,
14
+ getConfigValue,
15
+ loadConfig,
16
+ processContentWithEnv,
17
+ replaceEnvVariables,
18
+ validateConfig,
19
+ reloadConfig,
20
+ } from "./config.server"
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Configuration schema for Specra documentation system
3
+ */
4
+
5
+ /**
6
+ * Site metadata and branding
7
+ */
8
+ export interface SiteConfig {
9
+ /** The title of the documentation site */
10
+ title: string
11
+ /** Short description of the documentation */
12
+ description?: string
13
+ /** URL where the documentation is hosted */
14
+ url?: string
15
+ /** Base URL path for the documentation (e.g., '/docs') */
16
+ baseUrl?: string
17
+ /** Path to the site logo */
18
+ logo?: string
19
+ /** Path to the favicon */
20
+ favicon?: string
21
+ /** Default language for the documentation */
22
+ language?: string
23
+ /** Organization or author name */
24
+ organizationName?: string
25
+ /** Project name */
26
+ projectName?: string
27
+ /** Active/default version for the documentation */
28
+ activeVersion?: string
29
+ }
30
+
31
+ /**
32
+ * Theme and appearance settings
33
+ */
34
+ export interface ThemeConfig {
35
+ /** Primary color for the theme */
36
+ primaryColor?: string
37
+ /** Default theme mode */
38
+ defaultMode?: "light" | "dark" | "system"
39
+ /** Whether to respect system preferences */
40
+ respectPrefersColorScheme?: boolean
41
+ /** Custom CSS file path */
42
+ customCss?: string
43
+ }
44
+
45
+ /**
46
+ * Tab group for organizing documentation
47
+ */
48
+ export interface TabGroup {
49
+ /** Unique identifier for the tab group */
50
+ id: string
51
+ /** Display label for the tab */
52
+ label: string
53
+ /** Optional icon name (lucide-react icon) */
54
+ icon?: string
55
+ }
56
+
57
+ /**
58
+ * Navigation and sidebar configuration
59
+ */
60
+ export interface NavigationConfig {
61
+ /** Whether to show the sidebar by default */
62
+ showSidebar?: boolean
63
+ /** Whether the sidebar is collapsible */
64
+ collapsibleSidebar?: boolean
65
+ /** Whether to show breadcrumbs */
66
+ showBreadcrumbs?: boolean
67
+ /** Whether to show table of contents */
68
+ showTableOfContents?: boolean
69
+ /** Position of table of contents */
70
+ tocPosition?: "left" | "right"
71
+ /** Maximum depth for table of contents */
72
+ tocMaxDepth?: number
73
+ /** Tab groups for organizing documentation sections */
74
+ tabGroups?: TabGroup[]
75
+ }
76
+
77
+ /**
78
+ * Social and external links
79
+ */
80
+ export interface SocialLinks {
81
+ /** GitHub repository URL */
82
+ github?: string
83
+ /** Twitter/X handle or URL */
84
+ twitter?: string
85
+ /** Discord invite URL */
86
+ discord?: string
87
+ /** LinkedIn profile or company page */
88
+ linkedin?: string
89
+ /** YouTube channel URL */
90
+ youtube?: string
91
+ /** Custom social links */
92
+ custom?: Array<{
93
+ label: string
94
+ url: string
95
+ icon?: string
96
+ }>
97
+ }
98
+
99
+ /**
100
+ * Search configuration
101
+ */
102
+ export interface SearchConfig {
103
+ /** Enable/disable search functionality */
104
+ enabled?: boolean
105
+ /** Placeholder text for search input */
106
+ placeholder?: string
107
+ /** Search provider type */
108
+ provider?: "meilisearch" | "algolia" | "local"
109
+ /** Meilisearch configuration */
110
+ meilisearch?: {
111
+ /** Meilisearch server URL */
112
+ host: string
113
+ /** API key for Meilisearch */
114
+ apiKey?: string
115
+ /** Index name */
116
+ indexName: string
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Analytics configuration
122
+ */
123
+ export interface AnalyticsConfig {
124
+ /** Google Analytics tracking ID */
125
+ googleAnalytics?: string
126
+ /** Google Tag Manager ID */
127
+ googleTagManager?: string
128
+ /** Plausible Analytics domain */
129
+ plausible?: string
130
+ /** Custom analytics scripts */
131
+ custom?: Array<{
132
+ src: string
133
+ async?: boolean
134
+ defer?: boolean
135
+ }>
136
+ }
137
+
138
+ /**
139
+ * Footer configuration
140
+ */
141
+ export interface FooterConfig {
142
+ /** Copyright text */
143
+ copyright?: string
144
+ /** Footer links organized by columns */
145
+ links?: Array<{
146
+ title: string
147
+ items: Array<{
148
+ label: string
149
+ href: string
150
+ }>
151
+ }>
152
+ /** Custom footer content */
153
+ customContent?: string
154
+ }
155
+
156
+ /**
157
+ * Documentation features
158
+ */
159
+ export interface FeaturesConfig {
160
+ /** Enable/disable edit this page links */
161
+ editUrl?: string | false
162
+ /** Show last updated timestamp */
163
+ showLastUpdated?: boolean
164
+ /** Show reading time estimate */
165
+ showReadingTime?: boolean
166
+ /** Show author information */
167
+ showAuthors?: boolean
168
+ /** Show tags */
169
+ showTags?: boolean
170
+ /** Enable version dropdown */
171
+ versioning?: boolean
172
+ /** Enable i18n (internationalization) */
173
+ i18n?: boolean
174
+ }
175
+
176
+ /**
177
+ * Site-wide banner configuration
178
+ */
179
+ export interface BannerConfig {
180
+ /** Whether the banner is enabled */
181
+ enabled?: boolean
182
+ /** Banner message */
183
+ message?: string
184
+ /** Banner type */
185
+ type?: "info" | "warning" | "success" | "error"
186
+ /** Whether the banner can be dismissed */
187
+ dismissible?: boolean
188
+ }
189
+
190
+ /**
191
+ * Environment variables that can be used in documentation
192
+ * These will be replaced at build time or runtime
193
+ */
194
+ export interface EnvironmentVariables {
195
+ /** API base URL */
196
+ API_BASE_URL?: string
197
+ /** API version */
198
+ API_VERSION?: string
199
+ /** CDN URL */
200
+ CDN_URL?: string
201
+ /** Custom environment variables */
202
+ [key: string]: string | undefined
203
+ }
204
+
205
+ /**
206
+ * Deployment configuration for different hosting scenarios
207
+ */
208
+ export interface DeploymentConfig {
209
+ /**
210
+ * Deployment target
211
+ * - 'vercel': For Vercel or similar Node.js hosting (uses 'standalone' output)
212
+ * - 'github-pages': For GitHub Pages static hosting (uses 'export' output)
213
+ * - 'static': For any static hosting like Netlify, Cloudflare Pages, etc.
214
+ * - 'custom-domain-static': For static hosting with custom domain (no basePath needed)
215
+ */
216
+ target?: "vercel" | "github-pages" | "static" | "custom-domain-static"
217
+
218
+ /**
219
+ * Base path for assets when deploying to GitHub Pages without custom domain
220
+ * This should be your repository name (e.g., 'my-repo')
221
+ * Only used when target is 'github-pages' and no custom domain is configured
222
+ */
223
+ basePath?: string
224
+
225
+ /**
226
+ * Whether a custom domain is configured
227
+ * When true, basePath will be ignored even for GitHub Pages
228
+ */
229
+ customDomain?: boolean
230
+ }
231
+
232
+ /**
233
+ * Main configuration interface
234
+ */
235
+ export interface SpecraConfig {
236
+ /** Site metadata and branding */
237
+ site: SiteConfig
238
+ /** Theme and appearance settings */
239
+ theme?: ThemeConfig
240
+ /** Navigation and sidebar configuration */
241
+ navigation?: NavigationConfig
242
+ /** Social and external links */
243
+ social?: SocialLinks
244
+ /** Search configuration */
245
+ search?: SearchConfig
246
+ /** Analytics configuration */
247
+ analytics?: AnalyticsConfig
248
+ /** Footer configuration */
249
+ footer?: FooterConfig
250
+ /** Site-wide banner */
251
+ banner?: BannerConfig
252
+ /** Documentation features */
253
+ features?: FeaturesConfig
254
+ /** Environment variables for use in docs */
255
+ env?: EnvironmentVariables
256
+ /** Deployment configuration */
257
+ deployment?: DeploymentConfig
258
+ }
259
+
260
+ /**
261
+ * Default configuration values
262
+ */
263
+ export const defaultConfig: SpecraConfig = {
264
+ site: {
265
+ title: "Documentation",
266
+ description: "Project documentation",
267
+ baseUrl: "/",
268
+ language: "en",
269
+ },
270
+ theme: {
271
+ defaultMode: "system",
272
+ respectPrefersColorScheme: true,
273
+ },
274
+ navigation: {
275
+ showSidebar: true,
276
+ collapsibleSidebar: true,
277
+ showBreadcrumbs: true,
278
+ showTableOfContents: true,
279
+ tocPosition: "right",
280
+ tocMaxDepth: 3,
281
+ },
282
+ search: {
283
+ enabled: true,
284
+ provider: "local",
285
+ placeholder: "Search documentation...",
286
+ },
287
+ features: {
288
+ showLastUpdated: true,
289
+ showReadingTime: true,
290
+ showAuthors: false,
291
+ showTags: true,
292
+ versioning: true,
293
+ i18n: false,
294
+ },
295
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Development utilities for debugging and performance monitoring
3
+ * Only active in development mode
4
+ */
5
+
6
+ const isDevelopment = process.env.NODE_ENV === 'development'
7
+
8
+ /**
9
+ * Performance timer for measuring operation duration
10
+ */
11
+ export class PerfTimer {
12
+ private startTime: number
13
+ private label: string
14
+
15
+ constructor(label: string) {
16
+ this.label = label
17
+ this.startTime = isDevelopment ? performance.now() : 0
18
+ }
19
+
20
+ end() {
21
+ if (!isDevelopment) return
22
+
23
+ const duration = performance.now() - this.startTime
24
+ const color = duration > 1000 ? '\x1b[31m' : duration > 500 ? '\x1b[33m' : '\x1b[32m'
25
+ const reset = '\x1b[0m'
26
+
27
+ console.log(`${color}ā±ļø ${this.label}: ${duration.toFixed(2)}ms${reset}`)
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Log file system operations
33
+ */
34
+ export function logFsOperation(operation: string, path: string, details?: any) {
35
+ if (!isDevelopment) return
36
+
37
+ console.log(`šŸ“ [FS] ${operation}: ${path}`, details || '')
38
+ }
39
+
40
+ /**
41
+ * Log cache operations
42
+ */
43
+ export function logCacheOperation(operation: 'hit' | 'miss' | 'invalidate', key: string) {
44
+ if (!isDevelopment) return
45
+
46
+ const emoji = operation === 'hit' ? 'āœ…' : operation === 'miss' ? 'āŒ' : 'šŸ”„'
47
+ console.log(`${emoji} [Cache] ${operation}: ${key}`)
48
+ }
49
+
50
+ /**
51
+ * Memory usage reporter
52
+ */
53
+ export function logMemoryUsage(label?: string) {
54
+ if (!isDevelopment) return
55
+
56
+ const used = process.memoryUsage()
57
+ const prefix = label ? `[${label}] ` : ''
58
+
59
+ console.log(`šŸ’¾ ${prefix}Memory Usage:`, {
60
+ rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
61
+ heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
62
+ heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
63
+ })
64
+ }
65
+
66
+ /**
67
+ * Pretty print object for debugging
68
+ */
69
+ export function debugLog(label: string, data: any) {
70
+ if (!isDevelopment) return
71
+
72
+ console.log(`\nšŸ” ${label}:`)
73
+ console.dir(data, { depth: null, colors: true })
74
+ console.log('')
75
+ }
@@ -0,0 +1,27 @@
1
+ // MDX Processing
2
+ export * from './mdx'
3
+ export * from './mdx-cache'
4
+ export * from './toc'
5
+
6
+ // Configuration
7
+ export * from './config.server'
8
+ export * from './config'
9
+ export type * from './config.types'
10
+
11
+ // API Parsers
12
+ export * from './parsers'
13
+ export type * from './api.types'
14
+ export type {
15
+ ApiParam,
16
+ ApiHeader,
17
+ ApiResponse as SpecraApiResponse,
18
+ ApiEndpointSpec,
19
+ SpecraApiSpec
20
+ } from './api-parser.types'
21
+
22
+ // Utilities
23
+ export * from './utils'
24
+ export * from './sidebar-utils'
25
+ export * from './category'
26
+ export * from './redirects'
27
+ export * from './dev-utils'