@useavalon/avalon 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -54
- package/mod.ts +302 -302
- package/package.json +49 -26
- package/src/build/integration-bundler-plugin.ts +116 -116
- package/src/build/integration-config.ts +168 -168
- package/src/build/integration-detection-plugin.ts +117 -117
- package/src/build/integration-resolver-plugin.ts +90 -90
- package/src/build/island-manifest.ts +269 -269
- package/src/build/island-types-generator.ts +476 -476
- package/src/build/mdx-island-transform.ts +464 -464
- package/src/build/mdx-plugin.ts +98 -98
- package/src/build/page-island-transform.ts +598 -598
- package/src/build/prop-extractors/index.ts +21 -21
- package/src/build/prop-extractors/lit.ts +140 -140
- package/src/build/prop-extractors/qwik.ts +16 -16
- package/src/build/prop-extractors/solid.ts +125 -125
- package/src/build/prop-extractors/svelte.ts +194 -194
- package/src/build/prop-extractors/vue.ts +111 -111
- package/src/build/sidecar-file-manager.ts +104 -104
- package/src/build/sidecar-renderer.ts +30 -30
- package/src/client/adapters/index.ts +21 -13
- package/src/client/components.ts +35 -35
- package/src/client/css-hmr-handler.ts +344 -344
- package/src/client/framework-adapter.ts +462 -462
- package/src/client/hmr-coordinator.ts +396 -396
- package/src/client/hmr-error-overlay.js +533 -533
- package/src/client/main.js +824 -816
- package/src/client/types/framework-runtime.d.ts +68 -68
- package/src/client/types/vite-hmr.d.ts +46 -46
- package/src/client/types/vite-virtual-modules.d.ts +70 -60
- package/src/components/Image.tsx +123 -123
- package/src/components/IslandErrorBoundary.tsx +145 -145
- package/src/components/LayoutDataErrorBoundary.tsx +141 -141
- package/src/components/LayoutErrorBoundary.tsx +127 -127
- package/src/components/PersistentIsland.tsx +52 -52
- package/src/components/StreamingErrorBoundary.tsx +233 -233
- package/src/components/StreamingLayout.tsx +538 -538
- package/src/core/components/component-analyzer.ts +192 -192
- package/src/core/components/component-detection.ts +508 -508
- package/src/core/components/enhanced-framework-detector.ts +500 -500
- package/src/core/components/framework-registry.ts +563 -563
- package/src/core/content/mdx-processor.ts +46 -46
- package/src/core/integrations/index.ts +19 -19
- package/src/core/integrations/loader.ts +125 -125
- package/src/core/integrations/registry.ts +175 -175
- package/src/core/islands/island-persistence.ts +325 -325
- package/src/core/islands/island-state-serializer.ts +258 -258
- package/src/core/islands/persistent-island-context.tsx +80 -80
- package/src/core/islands/use-persistent-state.ts +68 -68
- package/src/core/layout/enhanced-layout-resolver.ts +322 -322
- package/src/core/layout/layout-cache-manager.ts +485 -485
- package/src/core/layout/layout-composer.ts +357 -357
- package/src/core/layout/layout-data-loader.ts +516 -516
- package/src/core/layout/layout-discovery.ts +243 -243
- package/src/core/layout/layout-matcher.ts +299 -299
- package/src/core/layout/layout-types.ts +110 -110
- package/src/core/modules/framework-module-resolver.ts +273 -273
- package/src/islands/component-analysis.ts +213 -213
- package/src/islands/css-utils.ts +565 -565
- package/src/islands/discovery/index.ts +80 -80
- package/src/islands/discovery/registry.ts +340 -340
- package/src/islands/discovery/resolver.ts +477 -477
- package/src/islands/discovery/scanner.ts +386 -386
- package/src/islands/discovery/types.ts +117 -117
- package/src/islands/discovery/validator.ts +544 -544
- package/src/islands/discovery/watcher.ts +368 -368
- package/src/islands/framework-detection.ts +428 -428
- package/src/islands/integration-loader.ts +490 -490
- package/src/islands/island.tsx +565 -565
- package/src/islands/render-cache.ts +550 -550
- package/src/islands/types.ts +80 -80
- package/src/islands/universal-css-collector.ts +157 -157
- package/src/islands/universal-head-collector.ts +137 -137
- package/src/layout-system.d.ts +592 -592
- package/src/layout-system.ts +218 -218
- package/src/middleware/discovery.ts +268 -268
- package/src/middleware/executor.ts +315 -315
- package/src/middleware/index.ts +76 -76
- package/src/middleware/types.ts +99 -99
- package/src/nitro/build-config.ts +575 -575
- package/src/nitro/config.ts +483 -483
- package/src/nitro/error-handler.ts +636 -636
- package/src/nitro/index.ts +173 -173
- package/src/nitro/island-manifest.ts +584 -584
- package/src/nitro/middleware-adapter.ts +260 -260
- package/src/nitro/renderer.ts +1471 -1471
- package/src/nitro/route-discovery.ts +439 -439
- package/src/nitro/types.ts +321 -321
- package/src/render/collect-css.ts +198 -198
- package/src/render/error-pages.ts +79 -79
- package/src/render/isolated-ssr-renderer.ts +654 -654
- package/src/render/ssr.ts +1030 -1030
- package/src/schemas/api.ts +30 -30
- package/src/schemas/core.ts +64 -64
- package/src/schemas/index.ts +212 -212
- package/src/schemas/layout.ts +279 -279
- package/src/schemas/routing/index.ts +38 -38
- package/src/schemas/routing.ts +376 -376
- package/src/types/as-island.ts +20 -20
- package/src/types/image.d.ts +106 -106
- package/src/types/index.d.ts +22 -22
- package/src/types/island-jsx.d.ts +33 -33
- package/src/types/island-prop.d.ts +20 -20
- package/src/types/layout.ts +285 -285
- package/src/types/mdx.d.ts +6 -6
- package/src/types/routing.ts +555 -555
- package/src/types/types.ts +5 -5
- package/src/types/urlpattern.d.ts +49 -49
- package/src/types/vite-env.d.ts +11 -11
- package/src/utils/dev-logger.ts +299 -299
- package/src/utils/fs.ts +151 -151
- package/src/vite-plugin/auto-discover.ts +551 -551
- package/src/vite-plugin/config.ts +266 -266
- package/src/vite-plugin/errors.ts +127 -127
- package/src/vite-plugin/image-optimization.ts +156 -156
- package/src/vite-plugin/integration-activator.ts +126 -126
- package/src/vite-plugin/island-sidecar-plugin.ts +176 -176
- package/src/vite-plugin/module-discovery.ts +189 -189
- package/src/vite-plugin/nitro-integration.ts +1354 -1354
- package/src/vite-plugin/plugin.ts +403 -409
- package/src/vite-plugin/types.ts +327 -327
- package/src/vite-plugin/validation.ts +228 -228
- package/src/client/adapters/index.js +0 -12
- package/src/client/adapters/lit-adapter.js +0 -467
- package/src/client/adapters/lit-adapter.ts +0 -654
- package/src/client/adapters/preact-adapter.js +0 -223
- package/src/client/adapters/preact-adapter.ts +0 -331
- package/src/client/adapters/qwik-adapter.js +0 -259
- package/src/client/adapters/qwik-adapter.ts +0 -345
- package/src/client/adapters/react-adapter.js +0 -220
- package/src/client/adapters/react-adapter.ts +0 -353
- package/src/client/adapters/solid-adapter.js +0 -295
- package/src/client/adapters/solid-adapter.ts +0 -451
- package/src/client/adapters/svelte-adapter.js +0 -368
- package/src/client/adapters/svelte-adapter.ts +0 -524
- package/src/client/adapters/vue-adapter.js +0 -278
- package/src/client/adapters/vue-adapter.ts +0 -467
- package/src/client/components.js +0 -23
- package/src/client/css-hmr-handler.js +0 -263
- package/src/client/framework-adapter.js +0 -283
- package/src/client/hmr-coordinator.js +0 -274
package/src/schemas/routing.ts
CHANGED
|
@@ -1,376 +1,376 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import type { ComponentType } from 'preact/compat';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Route Type Schema - Defines the different types of routes supported
|
|
6
|
-
*/
|
|
7
|
-
export const RouteTypeSchema = z.enum(['static', 'dynamic', 'catch-all', 'index', 'group']);
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* File System Route Schema - Represents a discovered route from the file system
|
|
11
|
-
*/
|
|
12
|
-
export const FileSystemRouteSchema = z.object({
|
|
13
|
-
/** URL pattern for matching requests */
|
|
14
|
-
pattern: z.any(), // URLPattern object - can't validate with Zod
|
|
15
|
-
/** File path to the page component */
|
|
16
|
-
filePath: z.string().min(1),
|
|
17
|
-
/** Type of route (static, dynamic, etc.) */
|
|
18
|
-
routeType: RouteTypeSchema,
|
|
19
|
-
/** Dynamic segments extracted from the file path */
|
|
20
|
-
dynamicSegments: z.array(z.string()),
|
|
21
|
-
/** Route priority for conflict resolution (lower = higher priority) */
|
|
22
|
-
priority: z.number().int().min(0),
|
|
23
|
-
/** Whether this route is in a private folder */
|
|
24
|
-
isPrivate: z.boolean(),
|
|
25
|
-
/** Route group name if the route is in a group */
|
|
26
|
-
routeGroup: z.string().optional(),
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Route Page Module Schema - Represents the exports from a page file in routing context
|
|
31
|
-
*/
|
|
32
|
-
export const RoutePageModuleSchema = z.object({
|
|
33
|
-
/** Default export - the page component */
|
|
34
|
-
default: z.any(), // ComponentType<PageProps> - can't validate function types with Zod
|
|
35
|
-
/** Optional layout configuration for this page */
|
|
36
|
-
layoutConfig: z.any().optional(), // LayoutConfig from layout system
|
|
37
|
-
/** Optional metadata generator function */
|
|
38
|
-
generateMetadata: z.any().optional(), // (params: RouteParams) => Promise<Metadata>
|
|
39
|
-
/** Optional data loader function */
|
|
40
|
-
loader: z.any().optional(), // (context: LoaderContext) => Promise<any>
|
|
41
|
-
/** Optional frontmatter data from MDX files */
|
|
42
|
-
frontmatter: z.record(z.string(), z.any()).optional(), // Frontmatter metadata from MDX files
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Route Parameters Schema - Parameters extracted from dynamic routes
|
|
47
|
-
*/
|
|
48
|
-
export const RouteParamsSchema = z.record(z.string(), z.string());
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Loader Context Schema - Context passed to page loaders
|
|
52
|
-
*/
|
|
53
|
-
export const LoaderContextSchema = z.object({
|
|
54
|
-
/** HTTP request object */
|
|
55
|
-
request: z.instanceof(Request),
|
|
56
|
-
/** URL object for easy access */
|
|
57
|
-
url: z.instanceof(URL),
|
|
58
|
-
/** Route parameters */
|
|
59
|
-
params: RouteParamsSchema,
|
|
60
|
-
/** Query parameters */
|
|
61
|
-
query: z.instanceof(URLSearchParams),
|
|
62
|
-
/** State from middleware */
|
|
63
|
-
state: z.instanceof(Map),
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Page Props Schema - Props passed to page components
|
|
68
|
-
*/
|
|
69
|
-
export const PagePropsSchema = z.object({
|
|
70
|
-
/** Route parameters */
|
|
71
|
-
params: RouteParamsSchema,
|
|
72
|
-
/** Query parameters */
|
|
73
|
-
query: z.instanceof(URLSearchParams),
|
|
74
|
-
/** Data from loader function */
|
|
75
|
-
data: z.unknown().optional(),
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Metadata Schema - SEO and meta information
|
|
80
|
-
*/
|
|
81
|
-
export const MetadataSchema = z.object({
|
|
82
|
-
/** Page title */
|
|
83
|
-
title: z.string().optional(),
|
|
84
|
-
/** Page description */
|
|
85
|
-
description: z.string().optional(),
|
|
86
|
-
/** Keywords for SEO */
|
|
87
|
-
keywords: z.array(z.string()).optional(),
|
|
88
|
-
/** Open Graph data */
|
|
89
|
-
openGraph: z
|
|
90
|
-
.object({
|
|
91
|
-
title: z.string().optional(),
|
|
92
|
-
description: z.string().optional(),
|
|
93
|
-
image: z.url().optional(),
|
|
94
|
-
url: z.url().optional(),
|
|
95
|
-
type: z.string().optional(),
|
|
96
|
-
siteName: z.string().optional(),
|
|
97
|
-
})
|
|
98
|
-
.optional(),
|
|
99
|
-
/** Twitter Card data */
|
|
100
|
-
twitter: z
|
|
101
|
-
.object({
|
|
102
|
-
card: z.enum(['summary', 'summary_large_image', 'app', 'player']).optional(),
|
|
103
|
-
title: z.string().optional(),
|
|
104
|
-
description: z.string().optional(),
|
|
105
|
-
image: z.url().optional(),
|
|
106
|
-
site: z.string().optional(),
|
|
107
|
-
})
|
|
108
|
-
.optional(),
|
|
109
|
-
/** Schema.org structured data */
|
|
110
|
-
schema: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
111
|
-
/** Canonical URL */
|
|
112
|
-
canonical: z.url().optional(),
|
|
113
|
-
/** Robots meta tag */
|
|
114
|
-
robots: z.string().optional(),
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Resolved Metadata Schema - Final merged metadata for a route
|
|
119
|
-
*/
|
|
120
|
-
export const ResolvedMetadataSchema = MetadataSchema.extend({
|
|
121
|
-
/** Source chain for debugging */
|
|
122
|
-
sources: z.array(z.string()).optional(),
|
|
123
|
-
/** Resolution timestamp */
|
|
124
|
-
resolvedAt: z.number().optional(),
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Metadata Chain Schema - Hierarchical metadata from multiple sources
|
|
129
|
-
*/
|
|
130
|
-
export const MetadataChainSchema = z.object({
|
|
131
|
-
/** Global metadata */
|
|
132
|
-
global: MetadataSchema.optional(),
|
|
133
|
-
/** Section-specific metadata */
|
|
134
|
-
sections: z.array(
|
|
135
|
-
z.object({
|
|
136
|
-
path: z.string(),
|
|
137
|
-
metadata: MetadataSchema,
|
|
138
|
-
})
|
|
139
|
-
),
|
|
140
|
-
/** Page-specific metadata */
|
|
141
|
-
page: MetadataSchema.optional(),
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Route Discovery Options Schema - Configuration for route discovery
|
|
146
|
-
*/
|
|
147
|
-
export const RouteDiscoveryOptionsSchema = z.object({
|
|
148
|
-
/** Base directory to scan for pages */
|
|
149
|
-
pagesDirectory: z.string().min(1).default('src/pages'),
|
|
150
|
-
/** Base directory to scan for API routes */
|
|
151
|
-
apiDirectory: z.string().min(1).default('src/api'),
|
|
152
|
-
/** File extensions to include */
|
|
153
|
-
extensions: z.array(z.string()).default(['.tsx', '.ts', '.jsx', '.js']),
|
|
154
|
-
/** Directories to exclude from scanning */
|
|
155
|
-
excludeDirectories: z.array(z.string()).default(['node_modules', '.git']),
|
|
156
|
-
/** Enable file watching for development */
|
|
157
|
-
enableWatching: z.boolean().default(false),
|
|
158
|
-
/** Development mode features */
|
|
159
|
-
developmentMode: z.boolean().default(false),
|
|
160
|
-
/** Quiet mode - suppress verbose logging */
|
|
161
|
-
quietMode: z.boolean().default(false),
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* File System Router Configuration Schema
|
|
166
|
-
*/
|
|
167
|
-
export const FileSystemRouterConfigSchema = z.object({
|
|
168
|
-
/** Route discovery options */
|
|
169
|
-
discovery: RouteDiscoveryOptionsSchema.optional(),
|
|
170
|
-
/** Enable file-system routing */
|
|
171
|
-
enabled: z.boolean().default(true),
|
|
172
|
-
/** Fallback to manual routes when file-system routes fail */
|
|
173
|
-
fallbackToManual: z.boolean().default(true),
|
|
174
|
-
/** Cache discovered routes */
|
|
175
|
-
enableCaching: z.boolean().default(true),
|
|
176
|
-
/** Cache TTL in milliseconds */
|
|
177
|
-
cacheTTL: z.number().positive().default(300000), // 5 minutes
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Page File Schema - Information about a discovered page file
|
|
182
|
-
*/
|
|
183
|
-
export const PageFileSchema = z.object({
|
|
184
|
-
/** Absolute file path */
|
|
185
|
-
filePath: z.string().min(1),
|
|
186
|
-
/** Relative path from pages directory */
|
|
187
|
-
relativePath: z.string().min(1),
|
|
188
|
-
/** File extension */
|
|
189
|
-
extension: z.string().min(1),
|
|
190
|
-
/** Whether file is in a private folder */
|
|
191
|
-
isPrivate: z.boolean(),
|
|
192
|
-
/** Route group if applicable */
|
|
193
|
-
routeGroup: z.string().optional(),
|
|
194
|
-
/** File modification time */
|
|
195
|
-
mtime: z.number().optional(),
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Route Handler Schema - Complete route handler information
|
|
200
|
-
*/
|
|
201
|
-
export const RouteHandlerSchema = z.object({
|
|
202
|
-
/** Route pattern */
|
|
203
|
-
pattern: z.any(), // URLPattern
|
|
204
|
-
/** Handler function */
|
|
205
|
-
handler: z.any(), // (request: Request, context: LoaderContext) => Promise<Response>
|
|
206
|
-
/** Route metadata */
|
|
207
|
-
metadata: z.object({
|
|
208
|
-
filePath: z.string(),
|
|
209
|
-
routeType: RouteTypeSchema,
|
|
210
|
-
priority: z.number(),
|
|
211
|
-
dynamicSegments: z.array(z.string()),
|
|
212
|
-
}),
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Route Cache Entry Schema - Cached route information
|
|
217
|
-
*/
|
|
218
|
-
export const RouteCacheEntrySchema = z.object({
|
|
219
|
-
/** Cached routes */
|
|
220
|
-
routes: z.array(FileSystemRouteSchema),
|
|
221
|
-
/** Cache timestamp */
|
|
222
|
-
timestamp: z.number(),
|
|
223
|
-
/** File modification times for cache invalidation */
|
|
224
|
-
fileMtimes: z.record(z.string(), z.number()),
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* File System API Route Schema - Represents an API endpoint route discovered from file system
|
|
229
|
-
*/
|
|
230
|
-
export const FileSystemApiRouteSchema = z.object({
|
|
231
|
-
/** URL pattern for the API endpoint */
|
|
232
|
-
pattern: z.any(), // URLPattern
|
|
233
|
-
/** File path to the API handler */
|
|
234
|
-
filePath: z.string().min(1),
|
|
235
|
-
/** HTTP methods supported */
|
|
236
|
-
methods: z.array(z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'])),
|
|
237
|
-
/** Route priority */
|
|
238
|
-
priority: z.number().int().min(0),
|
|
239
|
-
/** Dynamic segments */
|
|
240
|
-
dynamicSegments: z.array(z.string()),
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* File System API Module Schema - Exports from an API route file
|
|
245
|
-
*/
|
|
246
|
-
export const FileSystemApiModuleSchema = z.object({
|
|
247
|
-
/** GET handler */
|
|
248
|
-
GET: z.any().optional(), // (request: Request, context: any) => Promise<Response>
|
|
249
|
-
/** POST handler */
|
|
250
|
-
POST: z.any().optional(),
|
|
251
|
-
/** PUT handler */
|
|
252
|
-
PUT: z.any().optional(),
|
|
253
|
-
/** DELETE handler */
|
|
254
|
-
DELETE: z.any().optional(),
|
|
255
|
-
/** PATCH handler */
|
|
256
|
-
PATCH: z.any().optional(),
|
|
257
|
-
/** HEAD handler */
|
|
258
|
-
HEAD: z.any().optional(),
|
|
259
|
-
/** OPTIONS handler */
|
|
260
|
-
OPTIONS: z.any().optional(),
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// === TypeScript Type Definitions ===
|
|
264
|
-
|
|
265
|
-
export type RouteType = z.infer<typeof RouteTypeSchema>;
|
|
266
|
-
export type FileSystemRoute = z.infer<typeof FileSystemRouteSchema>;
|
|
267
|
-
export type RoutePageModule = z.infer<typeof RoutePageModuleSchema>;
|
|
268
|
-
export type RouteParams = z.infer<typeof RouteParamsSchema>;
|
|
269
|
-
export type LoaderContext = z.infer<typeof LoaderContextSchema>;
|
|
270
|
-
export type PageProps = z.infer<typeof PagePropsSchema>;
|
|
271
|
-
export type Metadata = z.infer<typeof MetadataSchema>;
|
|
272
|
-
export type ResolvedMetadata = z.infer<typeof ResolvedMetadataSchema>;
|
|
273
|
-
export type MetadataChain = z.infer<typeof MetadataChainSchema>;
|
|
274
|
-
export type RouteDiscoveryOptions = z.infer<typeof RouteDiscoveryOptionsSchema>;
|
|
275
|
-
export type FileSystemRouterConfig = z.infer<typeof FileSystemRouterConfigSchema>;
|
|
276
|
-
export type PageFile = z.infer<typeof PageFileSchema>;
|
|
277
|
-
export type RouteHandler = z.infer<typeof RouteHandlerSchema>;
|
|
278
|
-
export type RouteCacheEntry = z.infer<typeof RouteCacheEntrySchema>;
|
|
279
|
-
export type FileSystemApiRoute = z.infer<typeof FileSystemApiRouteSchema>;
|
|
280
|
-
export type FileSystemApiModule = z.infer<typeof FileSystemApiModuleSchema>;
|
|
281
|
-
|
|
282
|
-
// === Function Type Definitions ===
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Page Component Type
|
|
286
|
-
*/
|
|
287
|
-
export type PageComponent<P extends PageProps = PageProps> = ComponentType<P>;
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Metadata Generator Function Type
|
|
291
|
-
*/
|
|
292
|
-
export type MetadataGenerator = (params: RouteParams) => Promise<Metadata>;
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Page Loader Function Type
|
|
296
|
-
*/
|
|
297
|
-
export type PageLoader = (context: LoaderContext) => Promise<unknown>;
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Route Handler Function Type
|
|
301
|
-
*/
|
|
302
|
-
export type RouteHandlerFunction = (request: Request, context: LoaderContext) => Promise<Response>;
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* File System API Handler Function Type
|
|
306
|
-
*/
|
|
307
|
-
export type FileSystemApiHandler = (request: Request, context: LoaderContext) => Promise<Response>;
|
|
308
|
-
|
|
309
|
-
// === Type Guards ===
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Type guard for FileSystemRoute
|
|
313
|
-
*/
|
|
314
|
-
export function isFileSystemRoute(data: unknown): data is FileSystemRoute {
|
|
315
|
-
return FileSystemRouteSchema.safeParse(data).success;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Type guard for RoutePageModule
|
|
320
|
-
*/
|
|
321
|
-
export function isRoutePageModule(data: unknown): data is RoutePageModule {
|
|
322
|
-
return RoutePageModuleSchema.safeParse(data).success;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Type guard for Metadata
|
|
327
|
-
*/
|
|
328
|
-
export function isMetadata(data: unknown): data is Metadata {
|
|
329
|
-
return MetadataSchema.safeParse(data).success;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Type guard for RouteParams
|
|
334
|
-
*/
|
|
335
|
-
export function isRouteParams(data: unknown): data is RouteParams {
|
|
336
|
-
return RouteParamsSchema.safeParse(data).success;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Type guard for FileSystemApiModule
|
|
341
|
-
*/
|
|
342
|
-
export function isFileSystemApiModule(data: unknown): data is FileSystemApiModule {
|
|
343
|
-
return FileSystemApiModuleSchema.safeParse(data).success;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// === Re-exports from types/routing.ts (single source of truth) ===
|
|
347
|
-
|
|
348
|
-
export type {
|
|
349
|
-
ExtractRouteParams,
|
|
350
|
-
ExtractOptionalParams,
|
|
351
|
-
RouteParameters,
|
|
352
|
-
TypedPageComponent,
|
|
353
|
-
TypedPageComponentWithData,
|
|
354
|
-
TypedMetadataGenerator,
|
|
355
|
-
TypedPageLoader,
|
|
356
|
-
TypedApiHandler,
|
|
357
|
-
TypedApiModule,
|
|
358
|
-
HasDynamicSegments,
|
|
359
|
-
HasCatchAllSegments,
|
|
360
|
-
HasOptionalSegments,
|
|
361
|
-
CountDynamicSegments,
|
|
362
|
-
ValidRoutePattern,
|
|
363
|
-
ValidRouteExtension,
|
|
364
|
-
PageComponentProps,
|
|
365
|
-
} from '../types/routing.ts';
|
|
366
|
-
|
|
367
|
-
export {
|
|
368
|
-
isValidRouteParams,
|
|
369
|
-
isValidPageProps,
|
|
370
|
-
isValidRoutePattern,
|
|
371
|
-
validatePageComponent,
|
|
372
|
-
createTypedPageComponent,
|
|
373
|
-
createTypedMetadataGenerator,
|
|
374
|
-
createTypedPageLoader,
|
|
375
|
-
createTypedApiHandler,
|
|
376
|
-
} from '../types/routing.ts';
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ComponentType } from 'preact/compat';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Route Type Schema - Defines the different types of routes supported
|
|
6
|
+
*/
|
|
7
|
+
export const RouteTypeSchema = z.enum(['static', 'dynamic', 'catch-all', 'index', 'group']);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* File System Route Schema - Represents a discovered route from the file system
|
|
11
|
+
*/
|
|
12
|
+
export const FileSystemRouteSchema = z.object({
|
|
13
|
+
/** URL pattern for matching requests */
|
|
14
|
+
pattern: z.any(), // URLPattern object - can't validate with Zod
|
|
15
|
+
/** File path to the page component */
|
|
16
|
+
filePath: z.string().min(1),
|
|
17
|
+
/** Type of route (static, dynamic, etc.) */
|
|
18
|
+
routeType: RouteTypeSchema,
|
|
19
|
+
/** Dynamic segments extracted from the file path */
|
|
20
|
+
dynamicSegments: z.array(z.string()),
|
|
21
|
+
/** Route priority for conflict resolution (lower = higher priority) */
|
|
22
|
+
priority: z.number().int().min(0),
|
|
23
|
+
/** Whether this route is in a private folder */
|
|
24
|
+
isPrivate: z.boolean(),
|
|
25
|
+
/** Route group name if the route is in a group */
|
|
26
|
+
routeGroup: z.string().optional(),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Route Page Module Schema - Represents the exports from a page file in routing context
|
|
31
|
+
*/
|
|
32
|
+
export const RoutePageModuleSchema = z.object({
|
|
33
|
+
/** Default export - the page component */
|
|
34
|
+
default: z.any(), // ComponentType<PageProps> - can't validate function types with Zod
|
|
35
|
+
/** Optional layout configuration for this page */
|
|
36
|
+
layoutConfig: z.any().optional(), // LayoutConfig from layout system
|
|
37
|
+
/** Optional metadata generator function */
|
|
38
|
+
generateMetadata: z.any().optional(), // (params: RouteParams) => Promise<Metadata>
|
|
39
|
+
/** Optional data loader function */
|
|
40
|
+
loader: z.any().optional(), // (context: LoaderContext) => Promise<any>
|
|
41
|
+
/** Optional frontmatter data from MDX files */
|
|
42
|
+
frontmatter: z.record(z.string(), z.any()).optional(), // Frontmatter metadata from MDX files
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Route Parameters Schema - Parameters extracted from dynamic routes
|
|
47
|
+
*/
|
|
48
|
+
export const RouteParamsSchema = z.record(z.string(), z.string());
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Loader Context Schema - Context passed to page loaders
|
|
52
|
+
*/
|
|
53
|
+
export const LoaderContextSchema = z.object({
|
|
54
|
+
/** HTTP request object */
|
|
55
|
+
request: z.instanceof(Request),
|
|
56
|
+
/** URL object for easy access */
|
|
57
|
+
url: z.instanceof(URL),
|
|
58
|
+
/** Route parameters */
|
|
59
|
+
params: RouteParamsSchema,
|
|
60
|
+
/** Query parameters */
|
|
61
|
+
query: z.instanceof(URLSearchParams),
|
|
62
|
+
/** State from middleware */
|
|
63
|
+
state: z.instanceof(Map),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Page Props Schema - Props passed to page components
|
|
68
|
+
*/
|
|
69
|
+
export const PagePropsSchema = z.object({
|
|
70
|
+
/** Route parameters */
|
|
71
|
+
params: RouteParamsSchema,
|
|
72
|
+
/** Query parameters */
|
|
73
|
+
query: z.instanceof(URLSearchParams),
|
|
74
|
+
/** Data from loader function */
|
|
75
|
+
data: z.unknown().optional(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Metadata Schema - SEO and meta information
|
|
80
|
+
*/
|
|
81
|
+
export const MetadataSchema = z.object({
|
|
82
|
+
/** Page title */
|
|
83
|
+
title: z.string().optional(),
|
|
84
|
+
/** Page description */
|
|
85
|
+
description: z.string().optional(),
|
|
86
|
+
/** Keywords for SEO */
|
|
87
|
+
keywords: z.array(z.string()).optional(),
|
|
88
|
+
/** Open Graph data */
|
|
89
|
+
openGraph: z
|
|
90
|
+
.object({
|
|
91
|
+
title: z.string().optional(),
|
|
92
|
+
description: z.string().optional(),
|
|
93
|
+
image: z.url().optional(),
|
|
94
|
+
url: z.url().optional(),
|
|
95
|
+
type: z.string().optional(),
|
|
96
|
+
siteName: z.string().optional(),
|
|
97
|
+
})
|
|
98
|
+
.optional(),
|
|
99
|
+
/** Twitter Card data */
|
|
100
|
+
twitter: z
|
|
101
|
+
.object({
|
|
102
|
+
card: z.enum(['summary', 'summary_large_image', 'app', 'player']).optional(),
|
|
103
|
+
title: z.string().optional(),
|
|
104
|
+
description: z.string().optional(),
|
|
105
|
+
image: z.url().optional(),
|
|
106
|
+
site: z.string().optional(),
|
|
107
|
+
})
|
|
108
|
+
.optional(),
|
|
109
|
+
/** Schema.org structured data */
|
|
110
|
+
schema: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
111
|
+
/** Canonical URL */
|
|
112
|
+
canonical: z.url().optional(),
|
|
113
|
+
/** Robots meta tag */
|
|
114
|
+
robots: z.string().optional(),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Resolved Metadata Schema - Final merged metadata for a route
|
|
119
|
+
*/
|
|
120
|
+
export const ResolvedMetadataSchema = MetadataSchema.extend({
|
|
121
|
+
/** Source chain for debugging */
|
|
122
|
+
sources: z.array(z.string()).optional(),
|
|
123
|
+
/** Resolution timestamp */
|
|
124
|
+
resolvedAt: z.number().optional(),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Metadata Chain Schema - Hierarchical metadata from multiple sources
|
|
129
|
+
*/
|
|
130
|
+
export const MetadataChainSchema = z.object({
|
|
131
|
+
/** Global metadata */
|
|
132
|
+
global: MetadataSchema.optional(),
|
|
133
|
+
/** Section-specific metadata */
|
|
134
|
+
sections: z.array(
|
|
135
|
+
z.object({
|
|
136
|
+
path: z.string(),
|
|
137
|
+
metadata: MetadataSchema,
|
|
138
|
+
})
|
|
139
|
+
),
|
|
140
|
+
/** Page-specific metadata */
|
|
141
|
+
page: MetadataSchema.optional(),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Route Discovery Options Schema - Configuration for route discovery
|
|
146
|
+
*/
|
|
147
|
+
export const RouteDiscoveryOptionsSchema = z.object({
|
|
148
|
+
/** Base directory to scan for pages */
|
|
149
|
+
pagesDirectory: z.string().min(1).default('src/pages'),
|
|
150
|
+
/** Base directory to scan for API routes */
|
|
151
|
+
apiDirectory: z.string().min(1).default('src/api'),
|
|
152
|
+
/** File extensions to include */
|
|
153
|
+
extensions: z.array(z.string()).default(['.tsx', '.ts', '.jsx', '.js']),
|
|
154
|
+
/** Directories to exclude from scanning */
|
|
155
|
+
excludeDirectories: z.array(z.string()).default(['node_modules', '.git']),
|
|
156
|
+
/** Enable file watching for development */
|
|
157
|
+
enableWatching: z.boolean().default(false),
|
|
158
|
+
/** Development mode features */
|
|
159
|
+
developmentMode: z.boolean().default(false),
|
|
160
|
+
/** Quiet mode - suppress verbose logging */
|
|
161
|
+
quietMode: z.boolean().default(false),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* File System Router Configuration Schema
|
|
166
|
+
*/
|
|
167
|
+
export const FileSystemRouterConfigSchema = z.object({
|
|
168
|
+
/** Route discovery options */
|
|
169
|
+
discovery: RouteDiscoveryOptionsSchema.optional(),
|
|
170
|
+
/** Enable file-system routing */
|
|
171
|
+
enabled: z.boolean().default(true),
|
|
172
|
+
/** Fallback to manual routes when file-system routes fail */
|
|
173
|
+
fallbackToManual: z.boolean().default(true),
|
|
174
|
+
/** Cache discovered routes */
|
|
175
|
+
enableCaching: z.boolean().default(true),
|
|
176
|
+
/** Cache TTL in milliseconds */
|
|
177
|
+
cacheTTL: z.number().positive().default(300000), // 5 minutes
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Page File Schema - Information about a discovered page file
|
|
182
|
+
*/
|
|
183
|
+
export const PageFileSchema = z.object({
|
|
184
|
+
/** Absolute file path */
|
|
185
|
+
filePath: z.string().min(1),
|
|
186
|
+
/** Relative path from pages directory */
|
|
187
|
+
relativePath: z.string().min(1),
|
|
188
|
+
/** File extension */
|
|
189
|
+
extension: z.string().min(1),
|
|
190
|
+
/** Whether file is in a private folder */
|
|
191
|
+
isPrivate: z.boolean(),
|
|
192
|
+
/** Route group if applicable */
|
|
193
|
+
routeGroup: z.string().optional(),
|
|
194
|
+
/** File modification time */
|
|
195
|
+
mtime: z.number().optional(),
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Route Handler Schema - Complete route handler information
|
|
200
|
+
*/
|
|
201
|
+
export const RouteHandlerSchema = z.object({
|
|
202
|
+
/** Route pattern */
|
|
203
|
+
pattern: z.any(), // URLPattern
|
|
204
|
+
/** Handler function */
|
|
205
|
+
handler: z.any(), // (request: Request, context: LoaderContext) => Promise<Response>
|
|
206
|
+
/** Route metadata */
|
|
207
|
+
metadata: z.object({
|
|
208
|
+
filePath: z.string(),
|
|
209
|
+
routeType: RouteTypeSchema,
|
|
210
|
+
priority: z.number(),
|
|
211
|
+
dynamicSegments: z.array(z.string()),
|
|
212
|
+
}),
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Route Cache Entry Schema - Cached route information
|
|
217
|
+
*/
|
|
218
|
+
export const RouteCacheEntrySchema = z.object({
|
|
219
|
+
/** Cached routes */
|
|
220
|
+
routes: z.array(FileSystemRouteSchema),
|
|
221
|
+
/** Cache timestamp */
|
|
222
|
+
timestamp: z.number(),
|
|
223
|
+
/** File modification times for cache invalidation */
|
|
224
|
+
fileMtimes: z.record(z.string(), z.number()),
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* File System API Route Schema - Represents an API endpoint route discovered from file system
|
|
229
|
+
*/
|
|
230
|
+
export const FileSystemApiRouteSchema = z.object({
|
|
231
|
+
/** URL pattern for the API endpoint */
|
|
232
|
+
pattern: z.any(), // URLPattern
|
|
233
|
+
/** File path to the API handler */
|
|
234
|
+
filePath: z.string().min(1),
|
|
235
|
+
/** HTTP methods supported */
|
|
236
|
+
methods: z.array(z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'])),
|
|
237
|
+
/** Route priority */
|
|
238
|
+
priority: z.number().int().min(0),
|
|
239
|
+
/** Dynamic segments */
|
|
240
|
+
dynamicSegments: z.array(z.string()),
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* File System API Module Schema - Exports from an API route file
|
|
245
|
+
*/
|
|
246
|
+
export const FileSystemApiModuleSchema = z.object({
|
|
247
|
+
/** GET handler */
|
|
248
|
+
GET: z.any().optional(), // (request: Request, context: any) => Promise<Response>
|
|
249
|
+
/** POST handler */
|
|
250
|
+
POST: z.any().optional(),
|
|
251
|
+
/** PUT handler */
|
|
252
|
+
PUT: z.any().optional(),
|
|
253
|
+
/** DELETE handler */
|
|
254
|
+
DELETE: z.any().optional(),
|
|
255
|
+
/** PATCH handler */
|
|
256
|
+
PATCH: z.any().optional(),
|
|
257
|
+
/** HEAD handler */
|
|
258
|
+
HEAD: z.any().optional(),
|
|
259
|
+
/** OPTIONS handler */
|
|
260
|
+
OPTIONS: z.any().optional(),
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// === TypeScript Type Definitions ===
|
|
264
|
+
|
|
265
|
+
export type RouteType = z.infer<typeof RouteTypeSchema>;
|
|
266
|
+
export type FileSystemRoute = z.infer<typeof FileSystemRouteSchema>;
|
|
267
|
+
export type RoutePageModule = z.infer<typeof RoutePageModuleSchema>;
|
|
268
|
+
export type RouteParams = z.infer<typeof RouteParamsSchema>;
|
|
269
|
+
export type LoaderContext = z.infer<typeof LoaderContextSchema>;
|
|
270
|
+
export type PageProps = z.infer<typeof PagePropsSchema>;
|
|
271
|
+
export type Metadata = z.infer<typeof MetadataSchema>;
|
|
272
|
+
export type ResolvedMetadata = z.infer<typeof ResolvedMetadataSchema>;
|
|
273
|
+
export type MetadataChain = z.infer<typeof MetadataChainSchema>;
|
|
274
|
+
export type RouteDiscoveryOptions = z.infer<typeof RouteDiscoveryOptionsSchema>;
|
|
275
|
+
export type FileSystemRouterConfig = z.infer<typeof FileSystemRouterConfigSchema>;
|
|
276
|
+
export type PageFile = z.infer<typeof PageFileSchema>;
|
|
277
|
+
export type RouteHandler = z.infer<typeof RouteHandlerSchema>;
|
|
278
|
+
export type RouteCacheEntry = z.infer<typeof RouteCacheEntrySchema>;
|
|
279
|
+
export type FileSystemApiRoute = z.infer<typeof FileSystemApiRouteSchema>;
|
|
280
|
+
export type FileSystemApiModule = z.infer<typeof FileSystemApiModuleSchema>;
|
|
281
|
+
|
|
282
|
+
// === Function Type Definitions ===
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Page Component Type
|
|
286
|
+
*/
|
|
287
|
+
export type PageComponent<P extends PageProps = PageProps> = ComponentType<P>;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Metadata Generator Function Type
|
|
291
|
+
*/
|
|
292
|
+
export type MetadataGenerator = (params: RouteParams) => Promise<Metadata>;
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Page Loader Function Type
|
|
296
|
+
*/
|
|
297
|
+
export type PageLoader = (context: LoaderContext) => Promise<unknown>;
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Route Handler Function Type
|
|
301
|
+
*/
|
|
302
|
+
export type RouteHandlerFunction = (request: Request, context: LoaderContext) => Promise<Response>;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* File System API Handler Function Type
|
|
306
|
+
*/
|
|
307
|
+
export type FileSystemApiHandler = (request: Request, context: LoaderContext) => Promise<Response>;
|
|
308
|
+
|
|
309
|
+
// === Type Guards ===
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Type guard for FileSystemRoute
|
|
313
|
+
*/
|
|
314
|
+
export function isFileSystemRoute(data: unknown): data is FileSystemRoute {
|
|
315
|
+
return FileSystemRouteSchema.safeParse(data).success;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Type guard for RoutePageModule
|
|
320
|
+
*/
|
|
321
|
+
export function isRoutePageModule(data: unknown): data is RoutePageModule {
|
|
322
|
+
return RoutePageModuleSchema.safeParse(data).success;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Type guard for Metadata
|
|
327
|
+
*/
|
|
328
|
+
export function isMetadata(data: unknown): data is Metadata {
|
|
329
|
+
return MetadataSchema.safeParse(data).success;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Type guard for RouteParams
|
|
334
|
+
*/
|
|
335
|
+
export function isRouteParams(data: unknown): data is RouteParams {
|
|
336
|
+
return RouteParamsSchema.safeParse(data).success;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Type guard for FileSystemApiModule
|
|
341
|
+
*/
|
|
342
|
+
export function isFileSystemApiModule(data: unknown): data is FileSystemApiModule {
|
|
343
|
+
return FileSystemApiModuleSchema.safeParse(data).success;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// === Re-exports from types/routing.ts (single source of truth) ===
|
|
347
|
+
|
|
348
|
+
export type {
|
|
349
|
+
ExtractRouteParams,
|
|
350
|
+
ExtractOptionalParams,
|
|
351
|
+
RouteParameters,
|
|
352
|
+
TypedPageComponent,
|
|
353
|
+
TypedPageComponentWithData,
|
|
354
|
+
TypedMetadataGenerator,
|
|
355
|
+
TypedPageLoader,
|
|
356
|
+
TypedApiHandler,
|
|
357
|
+
TypedApiModule,
|
|
358
|
+
HasDynamicSegments,
|
|
359
|
+
HasCatchAllSegments,
|
|
360
|
+
HasOptionalSegments,
|
|
361
|
+
CountDynamicSegments,
|
|
362
|
+
ValidRoutePattern,
|
|
363
|
+
ValidRouteExtension,
|
|
364
|
+
PageComponentProps,
|
|
365
|
+
} from '../types/routing.ts';
|
|
366
|
+
|
|
367
|
+
export {
|
|
368
|
+
isValidRouteParams,
|
|
369
|
+
isValidPageProps,
|
|
370
|
+
isValidRoutePattern,
|
|
371
|
+
validatePageComponent,
|
|
372
|
+
createTypedPageComponent,
|
|
373
|
+
createTypedMetadataGenerator,
|
|
374
|
+
createTypedPageLoader,
|
|
375
|
+
createTypedApiHandler,
|
|
376
|
+
} from '../types/routing.ts';
|