@imjp/writenex-astro 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 (141) hide show
  1. package/README.md +539 -0
  2. package/dist/chunk-5PM6EQE5.js +151 -0
  3. package/dist/chunk-5PM6EQE5.js.map +1 -0
  4. package/dist/chunk-7XU5X6CW.js +1331 -0
  5. package/dist/chunk-7XU5X6CW.js.map +1 -0
  6. package/dist/chunk-AAOQHQPU.js +574 -0
  7. package/dist/chunk-AAOQHQPU.js.map +1 -0
  8. package/dist/chunk-CF2XXJFF.js +1410 -0
  9. package/dist/chunk-CF2XXJFF.js.map +1 -0
  10. package/dist/chunk-CRPZUUDU.js +52 -0
  11. package/dist/chunk-CRPZUUDU.js.map +1 -0
  12. package/dist/chunk-CYLDJ3HZ.js +310 -0
  13. package/dist/chunk-CYLDJ3HZ.js.map +1 -0
  14. package/dist/chunk-KIKIPIFA.js +1 -0
  15. package/dist/chunk-KIKIPIFA.js.map +1 -0
  16. package/dist/chunk-XNTQTTJU.js +145 -0
  17. package/dist/chunk-XNTQTTJU.js.map +1 -0
  18. package/dist/client/index.css +2 -0
  19. package/dist/client/index.css.map +1 -0
  20. package/dist/client/index.js +375 -0
  21. package/dist/client/index.js.map +1 -0
  22. package/dist/client/styles.css +584 -0
  23. package/dist/client/variables.css +304 -0
  24. package/dist/config/index.d.ts +54 -0
  25. package/dist/config/index.js +38 -0
  26. package/dist/config/index.js.map +1 -0
  27. package/dist/config-BmEdBDo_.d.ts +220 -0
  28. package/dist/content-BWR52vD-.d.ts +64 -0
  29. package/dist/discovery/index.d.ts +310 -0
  30. package/dist/discovery/index.js +38 -0
  31. package/dist/discovery/index.js.map +1 -0
  32. package/dist/errors-C0iYiDTv.d.ts +107 -0
  33. package/dist/filesystem/index.d.ts +1292 -0
  34. package/dist/filesystem/index.js +203 -0
  35. package/dist/filesystem/index.js.map +1 -0
  36. package/dist/image-FP7w5ZIs.d.ts +47 -0
  37. package/dist/index.d.ts +64 -0
  38. package/dist/index.js +151 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/loader-55LWCXHA.js +12 -0
  41. package/dist/loader-55LWCXHA.js.map +1 -0
  42. package/dist/loader-CrdnaAWR.d.ts +327 -0
  43. package/dist/server/index.d.ts +357 -0
  44. package/dist/server/index.js +37 -0
  45. package/dist/server/index.js.map +1 -0
  46. package/package.json +94 -0
  47. package/src/client/App.tsx +900 -0
  48. package/src/client/components/ConfigPanel/ConfigPanel.css +553 -0
  49. package/src/client/components/ConfigPanel/ConfigPanel.tsx +396 -0
  50. package/src/client/components/ConfigPanel/index.ts +6 -0
  51. package/src/client/components/CreateContentModal/CreateContentModal.css +327 -0
  52. package/src/client/components/CreateContentModal/CreateContentModal.tsx +216 -0
  53. package/src/client/components/CreateContentModal/index.ts +7 -0
  54. package/src/client/components/Editor/Editor.css +885 -0
  55. package/src/client/components/Editor/Editor.tsx +484 -0
  56. package/src/client/components/Editor/ImageDialog.css +344 -0
  57. package/src/client/components/Editor/ImageDialog.tsx +367 -0
  58. package/src/client/components/Editor/LinkDialog.css +326 -0
  59. package/src/client/components/Editor/LinkDialog.tsx +332 -0
  60. package/src/client/components/Editor/index.ts +6 -0
  61. package/src/client/components/FrontmatterForm/FrontmatterForm.css +468 -0
  62. package/src/client/components/FrontmatterForm/FrontmatterForm.tsx +914 -0
  63. package/src/client/components/FrontmatterForm/index.ts +7 -0
  64. package/src/client/components/Header/Header.css +300 -0
  65. package/src/client/components/Header/Header.tsx +300 -0
  66. package/src/client/components/Header/index.ts +7 -0
  67. package/src/client/components/KeyboardShortcuts/KeyboardShortcuts.css +239 -0
  68. package/src/client/components/KeyboardShortcuts/KeyboardShortcuts.tsx +151 -0
  69. package/src/client/components/KeyboardShortcuts/index.ts +6 -0
  70. package/src/client/components/LazyEditor.tsx +75 -0
  71. package/src/client/components/LiveRegion/LiveRegion.css +19 -0
  72. package/src/client/components/LiveRegion/LiveRegion.tsx +60 -0
  73. package/src/client/components/LiveRegion/index.ts +7 -0
  74. package/src/client/components/SearchReplace/SearchReplacePanel.css +300 -0
  75. package/src/client/components/SearchReplace/SearchReplacePanel.tsx +332 -0
  76. package/src/client/components/SearchReplace/index.ts +7 -0
  77. package/src/client/components/SelectCollectionModal/SelectCollectionModal.css +308 -0
  78. package/src/client/components/SelectCollectionModal/SelectCollectionModal.tsx +223 -0
  79. package/src/client/components/SelectCollectionModal/index.ts +7 -0
  80. package/src/client/components/Sidebar/Sidebar.css +570 -0
  81. package/src/client/components/Sidebar/Sidebar.tsx +617 -0
  82. package/src/client/components/Sidebar/index.ts +7 -0
  83. package/src/client/components/SkipLink/SkipLink.css +51 -0
  84. package/src/client/components/SkipLink/SkipLink.tsx +67 -0
  85. package/src/client/components/SkipLink/index.ts +7 -0
  86. package/src/client/components/UnsavedChangesModal/UnsavedChangesModal.css +233 -0
  87. package/src/client/components/UnsavedChangesModal/UnsavedChangesModal.tsx +160 -0
  88. package/src/client/components/UnsavedChangesModal/index.ts +1 -0
  89. package/src/client/components/VersionHistory/DiffViewer.css +430 -0
  90. package/src/client/components/VersionHistory/DiffViewer.tsx +383 -0
  91. package/src/client/components/VersionHistory/VersionActions.css +318 -0
  92. package/src/client/components/VersionHistory/VersionActions.tsx +277 -0
  93. package/src/client/components/VersionHistory/VersionHistoryPanel.css +369 -0
  94. package/src/client/components/VersionHistory/VersionHistoryPanel.tsx +469 -0
  95. package/src/client/components/VersionHistory/index.ts +9 -0
  96. package/src/client/context/ApiContext.tsx +154 -0
  97. package/src/client/context/ThemeContext.tsx +172 -0
  98. package/src/client/hooks/useAnnounce.ts +201 -0
  99. package/src/client/hooks/useApi.ts +374 -0
  100. package/src/client/hooks/useArrowNavigation.ts +286 -0
  101. package/src/client/hooks/useAutosave.ts +241 -0
  102. package/src/client/hooks/useFocusTrap.ts +178 -0
  103. package/src/client/hooks/useKeyboardShortcuts.ts +203 -0
  104. package/src/client/hooks/useSearch.ts +206 -0
  105. package/src/client/hooks/useVersionHistory.ts +451 -0
  106. package/src/client/index.tsx +70 -0
  107. package/src/client/styles.css +584 -0
  108. package/src/client/utils/focus.ts +57 -0
  109. package/src/client/utils/openInEditor.ts +130 -0
  110. package/src/client/variables.css +304 -0
  111. package/src/config/defaults.ts +109 -0
  112. package/src/config/index.ts +32 -0
  113. package/src/config/loader.ts +174 -0
  114. package/src/config/schema.ts +161 -0
  115. package/src/core/constants.ts +39 -0
  116. package/src/core/errors.ts +739 -0
  117. package/src/core/index.ts +11 -0
  118. package/src/discovery/collections.ts +216 -0
  119. package/src/discovery/index.ts +33 -0
  120. package/src/discovery/patterns.ts +702 -0
  121. package/src/discovery/schema.ts +453 -0
  122. package/src/filesystem/images.ts +798 -0
  123. package/src/filesystem/index.ts +107 -0
  124. package/src/filesystem/reader.ts +452 -0
  125. package/src/filesystem/version-config.ts +390 -0
  126. package/src/filesystem/versions.ts +1339 -0
  127. package/src/filesystem/watcher.ts +226 -0
  128. package/src/filesystem/writer.ts +540 -0
  129. package/src/index.ts +61 -0
  130. package/src/integration.ts +228 -0
  131. package/src/server/assets.ts +254 -0
  132. package/src/server/cache.ts +355 -0
  133. package/src/server/index.ts +33 -0
  134. package/src/server/middleware.ts +209 -0
  135. package/src/server/routes.ts +1428 -0
  136. package/src/types/api.ts +61 -0
  137. package/src/types/config.ts +134 -0
  138. package/src/types/content.ts +64 -0
  139. package/src/types/image.ts +48 -0
  140. package/src/types/index.ts +58 -0
  141. package/src/types/version.ts +117 -0
@@ -0,0 +1,327 @@
1
+ import { z } from 'zod';
2
+ import { a as WritenexConfig } from './config-BmEdBDo_.js';
3
+
4
+ /**
5
+ * @fileoverview Configuration schema and validation for @writenex/astro
6
+ *
7
+ * This module provides Zod schemas for validating Writenex configuration
8
+ * and a helper function for defining type-safe configurations.
9
+ *
10
+ * @module @writenex/astro/config/schema
11
+ */
12
+
13
+ /**
14
+ * Main Writenex configuration schema
15
+ */
16
+ declare const writenexConfigSchema: z.ZodObject<{
17
+ collections: z.ZodOptional<z.ZodArray<z.ZodObject<{
18
+ name: z.ZodString;
19
+ path: z.ZodString;
20
+ filePattern: z.ZodOptional<z.ZodString>;
21
+ previewUrl: z.ZodOptional<z.ZodString>;
22
+ schema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
23
+ type: z.ZodEnum<["string", "number", "boolean", "date", "array", "image", "object"]>;
24
+ required: z.ZodOptional<z.ZodBoolean>;
25
+ default: z.ZodOptional<z.ZodUnknown>;
26
+ items: z.ZodOptional<z.ZodString>;
27
+ description: z.ZodOptional<z.ZodString>;
28
+ }, "strip", z.ZodTypeAny, {
29
+ type: "string" | "number" | "boolean" | "object" | "date" | "array" | "image";
30
+ required?: boolean | undefined;
31
+ default?: unknown;
32
+ items?: string | undefined;
33
+ description?: string | undefined;
34
+ }, {
35
+ type: "string" | "number" | "boolean" | "object" | "date" | "array" | "image";
36
+ required?: boolean | undefined;
37
+ default?: unknown;
38
+ items?: string | undefined;
39
+ description?: string | undefined;
40
+ }>>>;
41
+ images: z.ZodOptional<z.ZodObject<{
42
+ strategy: z.ZodEnum<["colocated", "public", "custom"]>;
43
+ publicPath: z.ZodOptional<z.ZodString>;
44
+ storagePath: z.ZodOptional<z.ZodString>;
45
+ }, "strip", z.ZodTypeAny, {
46
+ strategy: "colocated" | "public" | "custom";
47
+ publicPath?: string | undefined;
48
+ storagePath?: string | undefined;
49
+ }, {
50
+ strategy: "colocated" | "public" | "custom";
51
+ publicPath?: string | undefined;
52
+ storagePath?: string | undefined;
53
+ }>>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ name: string;
56
+ path: string;
57
+ images?: {
58
+ strategy: "colocated" | "public" | "custom";
59
+ publicPath?: string | undefined;
60
+ storagePath?: string | undefined;
61
+ } | undefined;
62
+ filePattern?: string | undefined;
63
+ previewUrl?: string | undefined;
64
+ schema?: Record<string, {
65
+ type: "string" | "number" | "boolean" | "object" | "date" | "array" | "image";
66
+ required?: boolean | undefined;
67
+ default?: unknown;
68
+ items?: string | undefined;
69
+ description?: string | undefined;
70
+ }> | undefined;
71
+ }, {
72
+ name: string;
73
+ path: string;
74
+ images?: {
75
+ strategy: "colocated" | "public" | "custom";
76
+ publicPath?: string | undefined;
77
+ storagePath?: string | undefined;
78
+ } | undefined;
79
+ filePattern?: string | undefined;
80
+ previewUrl?: string | undefined;
81
+ schema?: Record<string, {
82
+ type: "string" | "number" | "boolean" | "object" | "date" | "array" | "image";
83
+ required?: boolean | undefined;
84
+ default?: unknown;
85
+ items?: string | undefined;
86
+ description?: string | undefined;
87
+ }> | undefined;
88
+ }>, "many">>;
89
+ images: z.ZodOptional<z.ZodObject<{
90
+ strategy: z.ZodEnum<["colocated", "public", "custom"]>;
91
+ publicPath: z.ZodOptional<z.ZodString>;
92
+ storagePath: z.ZodOptional<z.ZodString>;
93
+ }, "strip", z.ZodTypeAny, {
94
+ strategy: "colocated" | "public" | "custom";
95
+ publicPath?: string | undefined;
96
+ storagePath?: string | undefined;
97
+ }, {
98
+ strategy: "colocated" | "public" | "custom";
99
+ publicPath?: string | undefined;
100
+ storagePath?: string | undefined;
101
+ }>>;
102
+ editor: z.ZodOptional<z.ZodObject<{
103
+ autosave: z.ZodOptional<z.ZodBoolean>;
104
+ autosaveInterval: z.ZodOptional<z.ZodNumber>;
105
+ }, "strip", z.ZodTypeAny, {
106
+ autosave?: boolean | undefined;
107
+ autosaveInterval?: number | undefined;
108
+ }, {
109
+ autosave?: boolean | undefined;
110
+ autosaveInterval?: number | undefined;
111
+ }>>;
112
+ discovery: z.ZodOptional<z.ZodObject<{
113
+ enabled: z.ZodBoolean;
114
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
115
+ }, "strip", z.ZodTypeAny, {
116
+ enabled: boolean;
117
+ ignore?: string[] | undefined;
118
+ }, {
119
+ enabled: boolean;
120
+ ignore?: string[] | undefined;
121
+ }>>;
122
+ versionHistory: z.ZodOptional<z.ZodObject<{
123
+ enabled: z.ZodOptional<z.ZodBoolean>;
124
+ maxVersions: z.ZodOptional<z.ZodNumber>;
125
+ storagePath: z.ZodOptional<z.ZodString>;
126
+ }, "strip", z.ZodTypeAny, {
127
+ storagePath?: string | undefined;
128
+ enabled?: boolean | undefined;
129
+ maxVersions?: number | undefined;
130
+ }, {
131
+ storagePath?: string | undefined;
132
+ enabled?: boolean | undefined;
133
+ maxVersions?: number | undefined;
134
+ }>>;
135
+ }, "strip", z.ZodTypeAny, {
136
+ collections?: {
137
+ name: string;
138
+ path: string;
139
+ images?: {
140
+ strategy: "colocated" | "public" | "custom";
141
+ publicPath?: string | undefined;
142
+ storagePath?: string | undefined;
143
+ } | undefined;
144
+ filePattern?: string | undefined;
145
+ previewUrl?: string | undefined;
146
+ schema?: Record<string, {
147
+ type: "string" | "number" | "boolean" | "object" | "date" | "array" | "image";
148
+ required?: boolean | undefined;
149
+ default?: unknown;
150
+ items?: string | undefined;
151
+ description?: string | undefined;
152
+ }> | undefined;
153
+ }[] | undefined;
154
+ images?: {
155
+ strategy: "colocated" | "public" | "custom";
156
+ publicPath?: string | undefined;
157
+ storagePath?: string | undefined;
158
+ } | undefined;
159
+ editor?: {
160
+ autosave?: boolean | undefined;
161
+ autosaveInterval?: number | undefined;
162
+ } | undefined;
163
+ discovery?: {
164
+ enabled: boolean;
165
+ ignore?: string[] | undefined;
166
+ } | undefined;
167
+ versionHistory?: {
168
+ storagePath?: string | undefined;
169
+ enabled?: boolean | undefined;
170
+ maxVersions?: number | undefined;
171
+ } | undefined;
172
+ }, {
173
+ collections?: {
174
+ name: string;
175
+ path: string;
176
+ images?: {
177
+ strategy: "colocated" | "public" | "custom";
178
+ publicPath?: string | undefined;
179
+ storagePath?: string | undefined;
180
+ } | undefined;
181
+ filePattern?: string | undefined;
182
+ previewUrl?: string | undefined;
183
+ schema?: Record<string, {
184
+ type: "string" | "number" | "boolean" | "object" | "date" | "array" | "image";
185
+ required?: boolean | undefined;
186
+ default?: unknown;
187
+ items?: string | undefined;
188
+ description?: string | undefined;
189
+ }> | undefined;
190
+ }[] | undefined;
191
+ images?: {
192
+ strategy: "colocated" | "public" | "custom";
193
+ publicPath?: string | undefined;
194
+ storagePath?: string | undefined;
195
+ } | undefined;
196
+ editor?: {
197
+ autosave?: boolean | undefined;
198
+ autosaveInterval?: number | undefined;
199
+ } | undefined;
200
+ discovery?: {
201
+ enabled: boolean;
202
+ ignore?: string[] | undefined;
203
+ } | undefined;
204
+ versionHistory?: {
205
+ storagePath?: string | undefined;
206
+ enabled?: boolean | undefined;
207
+ maxVersions?: number | undefined;
208
+ } | undefined;
209
+ }>;
210
+ /**
211
+ * Schema for integration options
212
+ */
213
+ declare const writenexOptionsSchema: z.ZodObject<{
214
+ allowProduction: z.ZodOptional<z.ZodBoolean>;
215
+ }, "strip", z.ZodTypeAny, {
216
+ allowProduction?: boolean | undefined;
217
+ }, {
218
+ allowProduction?: boolean | undefined;
219
+ }>;
220
+ /**
221
+ * Helper function for defining type-safe Writenex configuration.
222
+ *
223
+ * This function provides IDE autocompletion and type checking for
224
+ * the configuration object. It's the recommended way to create
225
+ * a writenex.config.ts file.
226
+ *
227
+ * @param config - The Writenex configuration object
228
+ * @returns The same configuration object (identity function for type safety)
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * // writenex.config.ts
233
+ * import { defineConfig } from '@writenex/astro';
234
+ *
235
+ * export default defineConfig({
236
+ * collections: [
237
+ * {
238
+ * name: 'blog',
239
+ * path: 'src/content/blog',
240
+ * filePattern: '{slug}.md',
241
+ * },
242
+ * ],
243
+ * });
244
+ * ```
245
+ */
246
+ declare function defineConfig(config: WritenexConfig): WritenexConfig;
247
+ /**
248
+ * Validate a Writenex configuration object
249
+ *
250
+ * @param config - The configuration to validate
251
+ * @returns Validation result with success status and parsed data or errors
252
+ */
253
+ declare function validateConfig(config: unknown): z.SafeParseReturnType<unknown, WritenexConfig>;
254
+
255
+ /**
256
+ * @fileoverview Configuration loader for @writenex/astro
257
+ *
258
+ * This module handles loading Writenex configuration from various sources:
259
+ * - writenex.config.ts (TypeScript)
260
+ * - writenex.config.js (JavaScript)
261
+ * - writenex.config.mjs (ES Module)
262
+ *
263
+ * The loader searches for configuration files in the project root and
264
+ * applies default values for any missing options.
265
+ *
266
+ * @module @writenex/astro/config/loader
267
+ */
268
+
269
+ /**
270
+ * Result of loading configuration
271
+ */
272
+ interface LoadConfigResult {
273
+ /** The loaded and validated configuration with defaults applied */
274
+ config: Required<WritenexConfig>;
275
+ /** Path to the configuration file (if found) */
276
+ configPath: string | null;
277
+ /** Whether a configuration file was found */
278
+ hasConfigFile: boolean;
279
+ /** Any warnings generated during loading */
280
+ warnings: string[];
281
+ }
282
+ /**
283
+ * Find the configuration file in the project root
284
+ *
285
+ * @param projectRoot - The root directory of the Astro project
286
+ * @returns Path to the configuration file, or null if not found
287
+ */
288
+ declare function findConfigFile(projectRoot: string): string | null;
289
+ /**
290
+ * Load Writenex configuration from the project root
291
+ *
292
+ * This function:
293
+ * 1. Searches for a configuration file in the project root
294
+ * 2. Loads and validates the configuration if found
295
+ * 3. Applies default values for any missing options
296
+ * 4. Returns the resolved configuration
297
+ *
298
+ * If no configuration file is found, default configuration is returned
299
+ * with auto-discovery enabled.
300
+ *
301
+ * @param projectRoot - The root directory of the Astro project
302
+ * @returns LoadConfigResult with the resolved configuration
303
+ *
304
+ * @example
305
+ * ```typescript
306
+ * const { config, hasConfigFile, warnings } = await loadConfig('/path/to/project');
307
+ *
308
+ * if (!hasConfigFile) {
309
+ * console.log('Using auto-discovery mode');
310
+ * }
311
+ *
312
+ * if (warnings.length > 0) {
313
+ * warnings.forEach(w => console.warn(w));
314
+ * }
315
+ * ```
316
+ */
317
+ declare function loadConfig(projectRoot: string): Promise<LoadConfigResult>;
318
+ /**
319
+ * Check if a content directory exists in the project
320
+ *
321
+ * @param projectRoot - The root directory of the Astro project
322
+ * @param contentPath - Relative path to the content directory
323
+ * @returns True if the content directory exists
324
+ */
325
+ declare function contentDirectoryExists(projectRoot: string, contentPath?: string): boolean;
326
+
327
+ export { type LoadConfigResult as L, writenexOptionsSchema as a, contentDirectoryExists as c, defineConfig as d, findConfigFile as f, loadConfig as l, validateConfig as v, writenexConfigSchema as w };
@@ -0,0 +1,357 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { Connect } from 'vite';
3
+ import { a as WritenexConfig } from '../config-BmEdBDo_.js';
4
+ import { W as WritenexError } from '../errors-C0iYiDTv.js';
5
+ import { D as DiscoveredCollection, a as ContentSummary } from '../content-BWR52vD-.js';
6
+ import { D as DiscoveredImage } from '../image-FP7w5ZIs.js';
7
+
8
+ /**
9
+ * @fileoverview Vite middleware for Writenex routes
10
+ *
11
+ * This module provides the main middleware handler that intercepts requests
12
+ * to Writenex routes (/_writenex/*) and delegates to appropriate handlers.
13
+ *
14
+ * ## Route Structure:
15
+ * - `/_writenex` - Editor UI (HTML page with React app)
16
+ * - `/_writenex/api/*` - API endpoints for CRUD operations
17
+ * - `/_writenex/assets/*` - Static assets (JS, CSS)
18
+ *
19
+ * @module @writenex/astro/server/middleware
20
+ */
21
+
22
+ /**
23
+ * Middleware context passed to handlers
24
+ */
25
+ interface MiddlewareContext {
26
+ /** Base path for Writenex routes */
27
+ basePath: string;
28
+ /** Project root directory */
29
+ projectRoot: string;
30
+ /** Resolved Writenex configuration */
31
+ config: Required<WritenexConfig>;
32
+ /** Astro trailingSlash setting for preview URLs */
33
+ trailingSlash: "always" | "never" | "ignore";
34
+ }
35
+ /**
36
+ * Create the Writenex middleware handler
37
+ *
38
+ * @param context - Middleware context with configuration
39
+ * @returns Connect middleware function
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const middleware = createMiddleware({
44
+ * basePath: '/_writenex',
45
+ * projectRoot: '/path/to/project',
46
+ * config: resolvedConfig,
47
+ * });
48
+ *
49
+ * server.middlewares.use(middleware);
50
+ * ```
51
+ */
52
+ declare function createMiddleware(context: MiddlewareContext): Connect.NextHandleFunction;
53
+ /**
54
+ * Parse URL query parameters
55
+ *
56
+ * @param url - The URL string to parse
57
+ * @returns Object with query parameters
58
+ */
59
+ declare function parseQueryParams(url: string): Record<string, string>;
60
+ /**
61
+ * Parse request body as JSON
62
+ *
63
+ * @param req - The incoming request
64
+ * @returns Parsed JSON body or null
65
+ */
66
+ declare function parseJsonBody(req: IncomingMessage): Promise<unknown | null>;
67
+ /**
68
+ * Send JSON response
69
+ *
70
+ * @param res - The server response
71
+ * @param data - Data to send as JSON
72
+ * @param statusCode - HTTP status code (default: 200)
73
+ */
74
+ declare function sendJson(res: ServerResponse, data: unknown, statusCode?: number): void;
75
+ /**
76
+ * Send error response
77
+ *
78
+ * @param res - The server response
79
+ * @param message - Error message
80
+ * @param statusCode - HTTP status code (default: 400)
81
+ */
82
+ declare function sendError(res: ServerResponse, message: string, statusCode?: number): void;
83
+ /**
84
+ * Send WritenexError response
85
+ *
86
+ * Automatically uses the error's HTTP status code and formats
87
+ * the response using the error's toJSON method.
88
+ *
89
+ * @param res - The server response
90
+ * @param error - WritenexError instance
91
+ */
92
+ declare function sendWritenexError(res: ServerResponse, error: WritenexError): void;
93
+
94
+ /**
95
+ * @fileoverview API route handlers for Writenex
96
+ *
97
+ * This module provides the API router that handles CRUD operations
98
+ * for content collections.
99
+ *
100
+ * ## API Endpoints:
101
+ * - GET /api/collections - List all collections
102
+ * - GET /api/content/:collection - List content in collection
103
+ * - GET /api/content/:collection/:id - Get single content item
104
+ * - POST /api/content/:collection - Create new content
105
+ * - PUT /api/content/:collection/:id - Update content
106
+ * - DELETE /api/content/:collection/:id - Delete content
107
+ * - GET /api/images/:collection/:contentId - Discover images for content
108
+ * - GET /api/images/:collection/:contentId/* - Serve image file
109
+ * - POST /api/images - Upload image
110
+ * - GET /api/versions/:collection/:id - List versions
111
+ * - GET /api/versions/:collection/:id/:versionId - Get version
112
+ * - POST /api/versions/:collection/:id - Create manual version
113
+ * - POST /api/versions/:collection/:id/:versionId/restore - Restore version
114
+ * - GET /api/versions/:collection/:id/:versionId/diff - Get diff data
115
+ * - DELETE /api/versions/:collection/:id/:versionId - Delete version
116
+ * - DELETE /api/versions/:collection/:id - Clear all versions
117
+ *
118
+ * @module @writenex/astro/server/routes
119
+ */
120
+
121
+ /**
122
+ * Create the API router
123
+ *
124
+ * @param context - Middleware context
125
+ * @returns Router function that handles API requests
126
+ */
127
+ declare function createApiRouter(context: MiddlewareContext): (req: IncomingMessage, res: ServerResponse, path: string) => Promise<void>;
128
+
129
+ /**
130
+ * @fileoverview Static asset serving for Writenex editor
131
+ *
132
+ * This module handles serving the editor UI HTML and static assets
133
+ * (JavaScript, CSS) for the Writenex editor interface.
134
+ *
135
+ * ## Asset Strategy:
136
+ * - In development: Serve from source with Vite transform
137
+ * - In production: Serve pre-bundled assets from dist/client
138
+ *
139
+ * @module @writenex/astro/server/assets
140
+ */
141
+
142
+ /**
143
+ * Serve the editor HTML page
144
+ *
145
+ * This generates the HTML shell that loads the React editor application.
146
+ * The actual React components will be loaded via the bundled client assets.
147
+ *
148
+ * @param _req - The incoming request
149
+ * @param res - The server response
150
+ * @param context - Middleware context
151
+ */
152
+ declare function serveEditorHtml(_req: IncomingMessage, res: ServerResponse, context: MiddlewareContext): Promise<void>;
153
+ /**
154
+ * Serve static assets (JS, CSS, etc.)
155
+ *
156
+ * @param _req - The incoming request
157
+ * @param res - The server response
158
+ * @param assetPath - Path to the asset (relative to assets directory)
159
+ * @param _context - Middleware context
160
+ */
161
+ declare function serveAsset(_req: IncomingMessage, res: ServerResponse, assetPath: string, _context: MiddlewareContext): Promise<void>;
162
+ /**
163
+ * Get the path to bundled client assets
164
+ *
165
+ * @returns Path to the client dist directory
166
+ */
167
+ declare function getClientDistPath(): string;
168
+ /**
169
+ * Check if client assets are bundled
170
+ *
171
+ * @returns True if bundled assets exist
172
+ */
173
+ declare function hasClientBundle(): boolean;
174
+
175
+ /**
176
+ * @fileoverview Server-side caching for Writenex
177
+ *
178
+ * Provides in-memory caching for collection discovery and content summaries
179
+ * to improve performance by avoiding repeated filesystem operations.
180
+ *
181
+ * ## Features:
182
+ * - TTL-based cache expiration
183
+ * - Per-collection content caching
184
+ * - Image discovery caching
185
+ * - Manual cache invalidation
186
+ * - Integration with file watcher for automatic invalidation
187
+ *
188
+ * @module @writenex/astro/server/cache
189
+ */
190
+
191
+ /**
192
+ * Server-side cache for collection and content data
193
+ *
194
+ * This cache stores:
195
+ * - Collection discovery results (list of collections with metadata)
196
+ * - Content summaries per collection (list of content items)
197
+ * - Discovered images per content item
198
+ *
199
+ * Cache invalidation happens:
200
+ * - Automatically when TTL expires
201
+ * - Manually via invalidate methods
202
+ * - Via file watcher integration
203
+ */
204
+ declare class ServerCache {
205
+ /** Cache for collection discovery results */
206
+ private collectionsCache;
207
+ /** Cache for content summaries, keyed by collection name */
208
+ private contentCache;
209
+ /** Cache for discovered images, keyed by "collection:contentId" */
210
+ private imagesCache;
211
+ /** Time-to-live for cache entries in milliseconds */
212
+ private ttl;
213
+ /** Whether file watcher is integrated (allows longer TTL) */
214
+ private hasWatcher;
215
+ constructor(options?: {
216
+ ttl?: number;
217
+ hasWatcher?: boolean;
218
+ });
219
+ /**
220
+ * Enable file watcher integration
221
+ *
222
+ * When watcher is enabled, cache can use longer TTL since
223
+ * invalidation happens via watcher events.
224
+ */
225
+ enableWatcher(): void;
226
+ /**
227
+ * Check if a cache entry is still valid
228
+ */
229
+ private isValid;
230
+ /**
231
+ * Get cached collections if valid
232
+ *
233
+ * @returns Cached collections or null if expired/not cached
234
+ */
235
+ getCollections(): DiscoveredCollection[] | null;
236
+ /**
237
+ * Set collections cache
238
+ *
239
+ * @param collections - Collections to cache
240
+ */
241
+ setCollections(collections: DiscoveredCollection[]): void;
242
+ /**
243
+ * Invalidate collections cache
244
+ */
245
+ invalidateCollections(): void;
246
+ /**
247
+ * Get cached content summaries for a collection if valid
248
+ *
249
+ * @param collection - Collection name
250
+ * @returns Cached content summaries or null if expired/not cached
251
+ */
252
+ getContent(collection: string): ContentSummary[] | null;
253
+ /**
254
+ * Set content cache for a collection
255
+ *
256
+ * @param collection - Collection name
257
+ * @param items - Content summaries to cache
258
+ */
259
+ setContent(collection: string, items: ContentSummary[]): void;
260
+ /**
261
+ * Invalidate content cache for a specific collection
262
+ *
263
+ * @param collection - Collection name to invalidate
264
+ */
265
+ invalidateContent(collection: string): void;
266
+ /**
267
+ * Invalidate all content caches
268
+ */
269
+ invalidateAllContent(): void;
270
+ /**
271
+ * Generate cache key for image cache
272
+ *
273
+ * @param collection - Collection name
274
+ * @param contentId - Content ID
275
+ * @returns Cache key string
276
+ */
277
+ private getImagesCacheKey;
278
+ /**
279
+ * Get cached images for a content item if valid
280
+ *
281
+ * @param collection - Collection name
282
+ * @param contentId - Content ID
283
+ * @returns Cached images or null if expired/not cached
284
+ */
285
+ getImages(collection: string, contentId: string): DiscoveredImage[] | null;
286
+ /**
287
+ * Set images cache for a content item
288
+ *
289
+ * @param collection - Collection name
290
+ * @param contentId - Content ID
291
+ * @param images - Discovered images to cache
292
+ */
293
+ setImages(collection: string, contentId: string, images: DiscoveredImage[]): void;
294
+ /**
295
+ * Invalidate image cache for a specific content item
296
+ *
297
+ * @param collection - Collection name
298
+ * @param contentId - Content ID
299
+ */
300
+ invalidateImages(collection: string, contentId: string): void;
301
+ /**
302
+ * Invalidate all image caches for a collection
303
+ *
304
+ * @param collection - Collection name
305
+ */
306
+ invalidateCollectionImages(collection: string): void;
307
+ /**
308
+ * Invalidate all image caches
309
+ */
310
+ invalidateAllImages(): void;
311
+ /**
312
+ * Invalidate all caches
313
+ *
314
+ * Called when a major change occurs that affects everything.
315
+ */
316
+ invalidateAll(): void;
317
+ /**
318
+ * Handle file change event from watcher
319
+ *
320
+ * Intelligently invalidates only the affected caches.
321
+ *
322
+ * @param type - Type of file change (add, change, unlink)
323
+ * @param collection - Collection that was affected
324
+ * @param contentId - Optional content ID for targeted image cache invalidation
325
+ */
326
+ handleFileChange(type: "add" | "change" | "unlink", collection: string, contentId?: string): void;
327
+ /**
328
+ * Get cache statistics for debugging
329
+ *
330
+ * @returns Object with cache stats
331
+ */
332
+ getStats(): {
333
+ collectionsValid: boolean;
334
+ contentCollections: string[];
335
+ cachedImages: string[];
336
+ ttl: number;
337
+ hasWatcher: boolean;
338
+ };
339
+ }
340
+ /**
341
+ * Get or create the global cache instance
342
+ *
343
+ * @param options - Cache options (only used on first call)
344
+ * @returns The global cache instance
345
+ */
346
+ declare function getCache(options?: {
347
+ ttl?: number;
348
+ hasWatcher?: boolean;
349
+ }): ServerCache;
350
+ /**
351
+ * Reset the global cache instance
352
+ *
353
+ * Useful for testing or when configuration changes.
354
+ */
355
+ declare function resetCache(): void;
356
+
357
+ export { type MiddlewareContext, ServerCache, createApiRouter, createMiddleware, getCache, getClientDistPath, hasClientBundle, parseJsonBody, parseQueryParams, resetCache, sendError, sendJson, sendWritenexError, serveAsset, serveEditorHtml };