@flight-framework/core 0.0.1 → 0.0.2
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/dist/actions/index.d.ts +1 -1
- package/dist/actions/index.js +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +1 -1
- package/dist/{chunk-WAGCTWGY.js → chunk-3TPAA52K.js} +2 -2
- package/dist/{chunk-WAGCTWGY.js.map → chunk-3TPAA52K.js.map} +1 -1
- package/dist/{chunk-AFSKXC6V.js → chunk-5KF3QQWZ.js} +2 -2
- package/dist/chunk-5KF3QQWZ.js.map +1 -0
- package/dist/{chunk-Y22KEW2F.js → chunk-6LYV4VQX.js} +3 -3
- package/dist/chunk-6LYV4VQX.js.map +1 -0
- package/dist/{chunk-QEFGUHYD.js → chunk-ABNCAPQB.js} +2 -2
- package/dist/chunk-ABNCAPQB.js.map +1 -0
- package/dist/{chunk-TKXN7KGE.js → chunk-JIW55ZVD.js} +2 -2
- package/dist/chunk-JIW55ZVD.js.map +1 -0
- package/dist/{chunk-Q4C5CCHK.js → chunk-SUILH4ID.js} +2 -2
- package/dist/chunk-SUILH4ID.js.map +1 -0
- package/dist/{chunk-AJ3IBYXT.js → chunk-W6D62JCI.js} +2 -2
- package/dist/chunk-W6D62JCI.js.map +1 -0
- package/dist/{chunk-I5RHYGX6.js → chunk-WOMWIW7D.js} +39 -3
- package/dist/chunk-WOMWIW7D.js.map +1 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +1 -1
- package/dist/file-router/index.d.ts +5 -3
- package/dist/file-router/index.js +1 -1
- package/dist/handlers/index.d.ts +1 -1
- package/dist/handlers/index.js +1 -1
- package/dist/index.d.ts +558 -3
- package/dist/index.js +855 -9
- package/dist/index.js.map +1 -1
- package/dist/rsc/index.d.ts +1 -1
- package/dist/rsc/index.js +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +2 -2
- package/dist/streaming/index.d.ts +1 -1
- package/dist/streaming/index.js +1 -1
- package/package.json +100 -99
- package/LICENSE +0 -21
- package/dist/chunk-AFSKXC6V.js.map +0 -1
- package/dist/chunk-AJ3IBYXT.js.map +0 -1
- package/dist/chunk-I5RHYGX6.js.map +0 -1
- package/dist/chunk-Q4C5CCHK.js.map +0 -1
- package/dist/chunk-QEFGUHYD.js.map +0 -1
- package/dist/chunk-TKXN7KGE.js.map +0 -1
- package/dist/chunk-Y22KEW2F.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAyIO,IAAM,OAAA,GAAU","file":"index.js","sourcesContent":["/**\r\n * Flight Framework - Core\r\n * \r\n * The agnostic full-stack framework primitives.\r\n * Maximum flexibility, zero lock-in.\r\n */\r\n\r\n// Configuration\r\nexport { defineConfig, type FlightConfig, type FlightUserConfig } from './config/index.js';\r\n\r\n// Router\r\nexport {\r\n createRouter,\r\n type Route,\r\n type RouteMatch,\r\n type Router,\r\n type RouteParams,\r\n} from './router/index.js';\r\n\r\n// Server\r\nexport {\r\n createServer,\r\n type FlightServer,\r\n type RouteHandler,\r\n type RouteHandlerContext,\r\n type ServerOptions,\r\n type ServerRoute,\r\n} from './server/index.js';\r\n\r\n// Render\r\nexport {\r\n type RenderMode,\r\n type RenderContext,\r\n type RenderResult,\r\n} from './render/index.js';\r\n\r\n// Cache\r\nexport {\r\n createCache,\r\n type Cache,\r\n type CacheOptions,\r\n} from './cache/index.js';\r\n\r\n// Middleware\r\nexport {\r\n createMiddlewareChain,\r\n type Middleware,\r\n type MiddlewareContext,\r\n type MiddlewareNext,\r\n} from './middleware/index.js';\r\n\r\n// Adapters\r\nexport {\r\n type FlightAdapter,\r\n type AdapterBuilder,\r\n} from './adapters/index.js';\r\n\r\n// File Router\r\nexport {\r\n createFileRouter,\r\n scanRoutes,\r\n loadRoutes,\r\n type FileRoute,\r\n type FileRouter,\r\n type FileRouterOptions,\r\n type ScanResult,\r\n} from './file-router/index.js';\r\n\r\n// Route Handlers (for file-based routing)\r\nexport {\r\n createRouteContext,\r\n json,\r\n redirect,\r\n error,\r\n parseBody,\r\n type RouteHandler as FileRouteHandler,\r\n type RouteHandlerContext as FileRouteHandlerContext,\r\n type HttpMethod as FileHttpMethod,\r\n} from './handlers/index.js';\r\n\r\n// Server Actions\r\nexport {\r\n registerAction,\r\n getAction,\r\n executeAction,\r\n executeFormAction,\r\n handleActionRequest,\r\n cookies,\r\n redirect as actionRedirect,\r\n parseFormData,\r\n RedirectError,\r\n isRedirectError,\r\n type ServerAction,\r\n type ActionResult,\r\n type CookieOptions,\r\n} from './actions/index.js';\r\n\r\n// Streaming SSR\r\nexport {\r\n createStreamingSSR,\r\n createStreamingResponse,\r\n renderWithStreaming,\r\n createLazyContent,\r\n streamParallel,\r\n streamSequential,\r\n type StreamingRenderOptions,\r\n type StreamingRenderResult,\r\n type SuspenseBoundaryConfig,\r\n} from './streaming/index.js';\r\n\r\n// React Server Components (RSC) Primitives\r\nexport {\r\n hasUseClientDirective,\r\n hasUseServerDirective,\r\n detectComponentType,\r\n createRenderContext,\r\n executeServerComponent,\r\n serverFetch,\r\n revalidateTag,\r\n revalidatePath,\r\n serializeProps,\r\n deserializeProps,\r\n createClientBoundary,\r\n createAsyncComponent,\r\n composeComponents,\r\n withErrorBoundary,\r\n notFound,\r\n isNotFoundError,\r\n redirect as rscRedirect,\r\n isRedirectError as isRscRedirectError,\r\n type RenderContext as RSCRenderContext,\r\n type ServerComponent,\r\n type ClientComponent,\r\n type ComponentType as RSCComponentType,\r\n} from './rsc/index.js';\r\n\r\n// Version\r\nexport const VERSION = '0.0.1';\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/route-rules.ts","../src/render/revalidate.ts","../src/build/prerender.ts","../src/render/static.ts","../src/render/metadata.ts","../src/render/devtools.ts","../src/index.ts"],"names":["revalidatePath","error","revalidateTag","fs","createStreamingResponse"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * @flight-framework/core - Route Rules Configuration\r\n * \r\n * Nuxt-inspired route rules for per-route rendering configuration.\r\n * Define SSR, SSG, ISR, SWR, and caching strategies per route pattern.\r\n * \r\n * @example\r\n * ```typescript\r\n * const routeRules: RouteRules = {\r\n * '/': { prerender: true },\r\n * '/blog': { isr: 3600 },\r\n * '/blog/**': { swr: 3600 },\r\n * '/admin/**': { ssr: false },\r\n * '/api/**': { cache: { ttl: 60 } }\r\n * };\r\n * ```\r\n */\r\n\r\nimport type { CacheOptions } from '../cache/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Route rule configuration\r\n */\r\nexport interface RouteRule {\r\n /** Pre-render at build time (SSG) */\r\n prerender?: boolean;\r\n\r\n /** \r\n * Stale-While-Revalidate caching\r\n * - true: use default TTL\r\n * - number: TTL in seconds\r\n */\r\n swr?: number | boolean;\r\n\r\n /** \r\n * Incremental Static Regeneration\r\n * - true: regenerate on next deploy\r\n * - number: revalidate every N seconds\r\n */\r\n isr?: number | boolean;\r\n\r\n /** \r\n * Enable/disable SSR for this route\r\n * - false: client-side only rendering\r\n */\r\n ssr?: boolean;\r\n\r\n /** Custom cache options */\r\n cache?: CacheOptions;\r\n\r\n /** Response headers to add */\r\n headers?: Record<string, string>;\r\n\r\n /** Redirect to another path */\r\n redirect?: string | { to: string; statusCode?: 301 | 302 | 307 | 308 };\r\n\r\n /** CORS headers */\r\n cors?: boolean | {\r\n origin?: string | string[];\r\n methods?: string[];\r\n credentials?: boolean;\r\n };\r\n\r\n /** Cache tags for invalidation */\r\n tags?: string[];\r\n}\r\n\r\n/**\r\n * Route rules map - patterns to rules\r\n * Supports glob patterns: **, *, [param]\r\n */\r\nexport type RouteRules = Record<string, RouteRule>;\r\n\r\n// ============================================================================\r\n// Route Rule Matching\r\n// ============================================================================\r\n\r\n/**\r\n * Match a path against route rules and return the matching rule\r\n */\r\nexport function matchRouteRule(path: string, rules: RouteRules): RouteRule | undefined {\r\n // First, try exact match\r\n if (rules[path]) {\r\n return rules[path];\r\n }\r\n\r\n // Sort patterns by specificity (longer patterns first)\r\n const patterns = Object.keys(rules).sort((a, b) => {\r\n // Exact matches first\r\n if (!a.includes('*') && b.includes('*')) return -1;\r\n if (a.includes('*') && !b.includes('*')) return 1;\r\n // Then by length\r\n return b.length - a.length;\r\n });\r\n\r\n // Try pattern matching\r\n for (const pattern of patterns) {\r\n if (matchPattern(path, pattern)) {\r\n return rules[pattern];\r\n }\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Match a path against a glob pattern\r\n */\r\nfunction matchPattern(path: string, pattern: string): boolean {\r\n // Exact match\r\n if (pattern === path) {\r\n return true;\r\n }\r\n\r\n // Convert glob pattern to regex\r\n const regexPattern = pattern\r\n // Escape special regex chars except * and **\r\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\r\n // ** matches any path segments\r\n .replace(/\\*\\*/g, '.*')\r\n // * matches a single path segment\r\n .replace(/\\*/g, '[^/]*')\r\n // [param] matches a single path segment\r\n .replace(/\\[([^\\]]+)\\]/g, '[^/]+');\r\n\r\n const regex = new RegExp(`^${regexPattern}$`);\r\n return regex.test(path);\r\n}\r\n\r\n/**\r\n * Merge multiple route rules (later rules override earlier)\r\n */\r\nexport function mergeRouteRules(...rules: (RouteRule | undefined)[]): RouteRule {\r\n const result: RouteRule = {};\r\n\r\n for (const rule of rules) {\r\n if (!rule) continue;\r\n\r\n Object.assign(result, rule);\r\n\r\n // Deep merge headers\r\n if (rule.headers) {\r\n result.headers = { ...result.headers, ...rule.headers };\r\n }\r\n\r\n // Deep merge cache options\r\n if (rule.cache) {\r\n result.cache = { ...result.cache, ...rule.cache };\r\n }\r\n\r\n // Merge tags\r\n if (rule.tags) {\r\n result.tags = [...(result.tags || []), ...rule.tags];\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Rule Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Get effective render mode from route rule\r\n */\r\nexport function getRenderModeFromRule(rule: RouteRule): 'ssr' | 'ssg' | 'isr' | 'csr' {\r\n if (rule.ssr === false) {\r\n return 'csr';\r\n }\r\n\r\n if (rule.prerender) {\r\n return 'ssg';\r\n }\r\n\r\n if (rule.isr !== undefined) {\r\n return 'isr';\r\n }\r\n\r\n // Default to SSR\r\n return 'ssr';\r\n}\r\n\r\n/**\r\n * Get revalidation time from rule (in seconds)\r\n */\r\nexport function getRevalidateTime(rule: RouteRule): number | false {\r\n // ISR takes precedence\r\n if (rule.isr !== undefined) {\r\n if (rule.isr === true) {\r\n return false; // Revalidate on deploy only\r\n }\r\n return typeof rule.isr === 'number' ? rule.isr : 60;\r\n }\r\n\r\n // SWR\r\n if (rule.swr !== undefined) {\r\n if (rule.swr === true) {\r\n return 60; // Default 1 minute\r\n }\r\n return typeof rule.swr === 'number' ? rule.swr : 60;\r\n }\r\n\r\n // No revalidation\r\n return false;\r\n}\r\n\r\n/**\r\n * Get cache options from rule\r\n */\r\nexport function getCacheOptionsFromRule(rule: RouteRule): CacheOptions | undefined {\r\n const revalidate = getRevalidateTime(rule);\r\n\r\n if (revalidate === false && !rule.cache) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n ttl: revalidate || rule.cache?.ttl,\r\n swr: rule.swr !== undefined ? (typeof rule.swr === 'number' ? rule.swr : 60) : undefined,\r\n tags: rule.tags || rule.cache?.tags,\r\n };\r\n}\r\n\r\n/**\r\n * Build cache-control header from rule\r\n */\r\nexport function buildCacheControlHeader(rule: RouteRule): string | undefined {\r\n const revalidate = getRevalidateTime(rule);\r\n\r\n if (rule.ssr === false) {\r\n return 'no-store';\r\n }\r\n\r\n if (rule.prerender && revalidate === false) {\r\n return 'public, max-age=31536000, immutable';\r\n }\r\n\r\n if (revalidate !== false) {\r\n const maxAge = revalidate;\r\n const swr = rule.swr !== undefined ? (typeof rule.swr === 'number' ? rule.swr : 60) : 0;\r\n\r\n if (swr > 0) {\r\n return `public, max-age=${maxAge}, stale-while-revalidate=${swr}`;\r\n }\r\n\r\n return `public, max-age=${maxAge}`;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n// ============================================================================\r\n// Default Rules\r\n// ============================================================================\r\n\r\n/**\r\n * Create default route rules\r\n */\r\nexport function createDefaultRouteRules(): RouteRules {\r\n return {\r\n // API routes: no cache by default\r\n '/api/**': { ssr: true, cache: { ttl: 0 } },\r\n // Static assets: cache forever\r\n '/_static/**': { headers: { 'Cache-Control': 'public, max-age=31536000, immutable' } },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - On-Demand Revalidation\r\n * \r\n * APIs for on-demand cache invalidation and page revalidation.\r\n * Similar to Next.js revalidatePath() and revalidateTag().\r\n * \r\n * @example\r\n * ```typescript\r\n * // In an API route\r\n * import { revalidatePath, revalidateTag } from '@flight-framework/core';\r\n * \r\n * app.post('/api/revalidate', async (c) => {\r\n * const { path, tag } = await c.req.json();\r\n * \r\n * if (path) await revalidatePath(path);\r\n * if (tag) await revalidateTag(tag);\r\n * \r\n * return c.json({ revalidated: true });\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { Cache, CacheOptions } from '../cache/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * ISR Cache entry for rendered pages\r\n */\r\nexport interface ISRCacheEntry {\r\n /** Rendered HTML content */\r\n html: string;\r\n /** HTTP status code */\r\n status: number;\r\n /** Response headers */\r\n headers: Record<string, string>;\r\n /** When this entry was generated */\r\n generatedAt: number;\r\n /** When this entry should be revalidated */\r\n revalidateAfter?: number;\r\n /** Cache tags for invalidation */\r\n tags?: string[];\r\n}\r\n\r\n/**\r\n * ISR Cache adapter interface\r\n */\r\nexport interface ISRCacheAdapter {\r\n /** Get cached page */\r\n get(path: string): Promise<ISRCacheEntry | undefined>;\r\n /** Set cached page */\r\n set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void>;\r\n /** Delete cached page */\r\n delete(path: string): Promise<boolean>;\r\n /** Invalidate by tag */\r\n invalidateTag(tag: string): Promise<void>;\r\n /** Get all cached paths */\r\n keys?(): Promise<string[]>;\r\n}\r\n\r\n/**\r\n * Revalidation result\r\n */\r\nexport interface RevalidationResult {\r\n /** Whether revalidation was successful */\r\n success: boolean;\r\n /** Paths that were revalidated */\r\n paths?: string[];\r\n /** Error if failed */\r\n error?: string;\r\n /** Timestamp */\r\n timestamp: number;\r\n}\r\n\r\n// ============================================================================\r\n// Global ISR Cache Instance\r\n// ============================================================================\r\n\r\nlet globalISRCache: ISRCacheAdapter | null = null;\r\n\r\n/**\r\n * Set the global ISR cache adapter\r\n */\r\nexport function setISRCache(cache: ISRCacheAdapter): void {\r\n globalISRCache = cache;\r\n}\r\n\r\n/**\r\n * Get the global ISR cache adapter\r\n */\r\nexport function getISRCache(): ISRCacheAdapter | null {\r\n return globalISRCache;\r\n}\r\n\r\n// ============================================================================\r\n// In-Memory ISR Cache Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Create an in-memory ISR cache\r\n */\r\nexport function createMemoryISRCache(): ISRCacheAdapter {\r\n const store = new Map<string, ISRCacheEntry>();\r\n const tagIndex = new Map<string, Set<string>>();\r\n\r\n return {\r\n async get(path: string): Promise<ISRCacheEntry | undefined> {\r\n const entry = store.get(path);\r\n if (!entry) return undefined;\r\n\r\n // Check if expired\r\n if (entry.revalidateAfter && Date.now() > entry.revalidateAfter) {\r\n // Return stale entry (SWR pattern - caller decides to regenerate)\r\n return entry;\r\n }\r\n\r\n return entry;\r\n },\r\n\r\n async set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void> {\r\n store.set(path, entry);\r\n\r\n // Update tag index\r\n const tags = entry.tags || options?.tags || [];\r\n for (const tag of tags) {\r\n if (!tagIndex.has(tag)) {\r\n tagIndex.set(tag, new Set());\r\n }\r\n tagIndex.get(tag)!.add(path);\r\n }\r\n },\r\n\r\n async delete(path: string): Promise<boolean> {\r\n return store.delete(path);\r\n },\r\n\r\n async invalidateTag(tag: string): Promise<void> {\r\n const paths = tagIndex.get(tag);\r\n if (!paths) return;\r\n\r\n for (const path of paths) {\r\n store.delete(path);\r\n }\r\n tagIndex.delete(tag);\r\n },\r\n\r\n async keys(): Promise<string[]> {\r\n return Array.from(store.keys());\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Revalidation Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Revalidate a specific path\r\n * Removes the cached page so next request regenerates it\r\n */\r\nexport async function revalidatePath(path: string): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n try {\r\n const deleted = await cache.delete(path);\r\n\r\n return {\r\n success: deleted,\r\n paths: deleted ? [path] : [],\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Revalidate all paths associated with a tag\r\n */\r\nexport async function revalidateTag(tag: string): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n try {\r\n await cache.invalidateTag(tag);\r\n\r\n return {\r\n success: true,\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Revalidate multiple paths\r\n */\r\nexport async function revalidatePaths(paths: string[]): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n const revalidated: string[] = [];\r\n\r\n try {\r\n for (const path of paths) {\r\n const deleted = await cache.delete(path);\r\n if (deleted) {\r\n revalidated.push(path);\r\n }\r\n }\r\n\r\n return {\r\n success: true,\r\n paths: revalidated,\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n paths: revalidated,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Revalidation Handler (for API routes)\r\n// ============================================================================\r\n\r\nexport interface RevalidateHandlerOptions {\r\n /** Secret token for authentication */\r\n secret?: string;\r\n /** Header name for the secret */\r\n headerName?: string;\r\n}\r\n\r\n/**\r\n * Create a revalidation handler for API routes\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createRevalidateHandler } from '@flight-framework/core';\r\n * \r\n * const handler = createRevalidateHandler({ \r\n * secret: process.env.REVALIDATE_SECRET \r\n * });\r\n * \r\n * app.post('/api/revalidate', handler);\r\n * ```\r\n */\r\nexport function createRevalidateHandler(options: RevalidateHandlerOptions = {}) {\r\n const { secret, headerName = 'x-revalidate-token' } = options;\r\n\r\n return async (request: Request): Promise<Response> => {\r\n // Verify secret if configured\r\n if (secret) {\r\n const token = request.headers.get(headerName);\r\n if (token !== secret) {\r\n return new Response(\r\n JSON.stringify({ error: 'Invalid revalidation token' }),\r\n { status: 401, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n }\r\n\r\n try {\r\n const body = await request.json() as {\r\n path?: string;\r\n paths?: string[];\r\n tag?: string;\r\n tags?: string[];\r\n };\r\n\r\n const results: RevalidationResult[] = [];\r\n\r\n // Revalidate by path\r\n if (body.path) {\r\n results.push(await revalidatePath(body.path));\r\n }\r\n\r\n // Revalidate by paths\r\n if (body.paths && body.paths.length > 0) {\r\n results.push(await revalidatePaths(body.paths));\r\n }\r\n\r\n // Revalidate by tag\r\n if (body.tag) {\r\n results.push(await revalidateTag(body.tag));\r\n }\r\n\r\n // Revalidate by tags\r\n if (body.tags && body.tags.length > 0) {\r\n for (const tag of body.tags) {\r\n results.push(await revalidateTag(tag));\r\n }\r\n }\r\n\r\n const success = results.every(r => r.success);\r\n\r\n return new Response(\r\n JSON.stringify({\r\n revalidated: success,\r\n results,\r\n timestamp: Date.now(),\r\n }),\r\n {\r\n status: success ? 200 : 500,\r\n headers: { 'Content-Type': 'application/json' }\r\n }\r\n );\r\n } catch (error) {\r\n return new Response(\r\n JSON.stringify({\r\n error: 'Invalid request body',\r\n message: error instanceof Error ? error.message : 'Unknown error',\r\n }),\r\n { status: 400, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Wrap Flight Cache as ISR Cache\r\n// ============================================================================\r\n\r\n/**\r\n * Create an ISR cache adapter from a Flight Cache instance\r\n */\r\nexport function createISRCacheFromFlightCache(cache: Cache): ISRCacheAdapter {\r\n const ISR_PREFIX = 'isr:';\r\n\r\n return {\r\n async get(path: string): Promise<ISRCacheEntry | undefined> {\r\n return cache.get<ISRCacheEntry>(`${ISR_PREFIX}${path}`);\r\n },\r\n\r\n async set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void> {\r\n const ttl = entry.revalidateAfter\r\n ? Math.floor((entry.revalidateAfter - Date.now()) / 1000)\r\n : options?.ttl;\r\n\r\n await cache.set(`${ISR_PREFIX}${path}`, entry, {\r\n ...options,\r\n ttl: ttl && ttl > 0 ? ttl : undefined,\r\n tags: entry.tags || options?.tags,\r\n });\r\n },\r\n\r\n async delete(path: string): Promise<boolean> {\r\n return cache.delete(`${ISR_PREFIX}${path}`);\r\n },\r\n\r\n async invalidateTag(tag: string): Promise<void> {\r\n await cache.invalidateTag(tag);\r\n },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Build-Time Prerender\r\n * \r\n * Static site generation build utilities.\r\n * Pre-renders routes to HTML files at build time.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { prerenderRoutes } from '@flight-framework/core';\r\n * \r\n * await prerenderRoutes({\r\n * routes: ['/','blog/hello', '/about'],\r\n * outDir: './dist',\r\n * renderFn: async (path) => await renderPage(path),\r\n * });\r\n * ```\r\n */\r\n\r\nimport { promises as fs } from 'fs';\r\nimport { join, dirname } from 'path';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Options for prerendering routes\r\n */\r\nexport interface PrerenderOptions {\r\n /** Routes to prerender */\r\n routes: string[] | (() => Promise<string[]>);\r\n /** Output directory */\r\n outDir: string;\r\n /** Render function that generates HTML for a path */\r\n renderFn: (path: string) => Promise<PrerenderResult>;\r\n /** Concurrency limit */\r\n concurrency?: number;\r\n /** Progress callback */\r\n onProgress?: (progress: PrerenderProgress) => void;\r\n /** Error callback */\r\n onError?: (error: PrerenderError) => void;\r\n /** Whether to crawl links from rendered pages */\r\n crawlLinks?: boolean;\r\n}\r\n\r\n/**\r\n * Result from rendering a single page\r\n */\r\nexport interface PrerenderResult {\r\n /** HTML content */\r\n html: string;\r\n /** HTTP status code */\r\n status?: number;\r\n /** Response headers */\r\n headers?: Record<string, string>;\r\n /** Links found in the page (for crawling) */\r\n links?: string[];\r\n}\r\n\r\n/**\r\n * Progress callback data\r\n */\r\nexport interface PrerenderProgress {\r\n /** Current route being processed */\r\n currentRoute: string;\r\n /** Number of routes completed */\r\n completed: number;\r\n /** Total number of routes */\r\n total: number;\r\n /** Percentage complete */\r\n percentage: number;\r\n}\r\n\r\n/**\r\n * Error callback data\r\n */\r\nexport interface PrerenderError {\r\n /** Route that failed */\r\n route: string;\r\n /** Error message */\r\n error: Error;\r\n}\r\n\r\n/**\r\n * Summary of prerender operation\r\n */\r\nexport interface PrerenderSummary {\r\n /** Total routes processed */\r\n total: number;\r\n /** Successfully rendered routes */\r\n success: number;\r\n /** Failed routes */\r\n failed: number;\r\n /** Routes that were discovered via crawling */\r\n discovered?: number;\r\n /** Time taken in milliseconds */\r\n duration: number;\r\n /** List of generated files */\r\n files: string[];\r\n /** List of errors */\r\n errors: PrerenderError[];\r\n}\r\n\r\n// ============================================================================\r\n// Prerender Engine\r\n// ============================================================================\r\n\r\n/**\r\n * Prerender multiple routes to static HTML files\r\n */\r\nexport async function prerenderRoutes(options: PrerenderOptions): Promise<PrerenderSummary> {\r\n const {\r\n routes,\r\n outDir,\r\n renderFn,\r\n concurrency = 10,\r\n onProgress,\r\n onError,\r\n crawlLinks = false,\r\n } = options;\r\n\r\n const startTime = Date.now();\r\n const errors: PrerenderError[] = [];\r\n const files: string[] = [];\r\n const processedRoutes = new Set<string>();\r\n\r\n // Get initial routes\r\n const routeQueue = typeof routes === 'function' ? await routes() : [...routes];\r\n let discoveredCount = 0;\r\n\r\n // Ensure output directory exists\r\n await fs.mkdir(outDir, { recursive: true });\r\n\r\n // Process routes in batches\r\n let completed = 0;\r\n const total = routeQueue.length;\r\n\r\n while (routeQueue.length > 0) {\r\n // Take a batch\r\n const batch = routeQueue.splice(0, concurrency);\r\n\r\n // Process batch concurrently\r\n const results = await Promise.allSettled(\r\n batch.map(async (route) => {\r\n // Skip if already processed\r\n if (processedRoutes.has(route)) {\r\n return null;\r\n }\r\n processedRoutes.add(route);\r\n\r\n // Report progress\r\n if (onProgress) {\r\n onProgress({\r\n currentRoute: route,\r\n completed,\r\n total: total + discoveredCount,\r\n percentage: Math.round((completed / (total + discoveredCount)) * 100),\r\n });\r\n }\r\n\r\n // Render the page\r\n const result = await renderFn(route);\r\n\r\n // Write to file\r\n const filePath = getOutputPath(route, outDir);\r\n await ensureDir(dirname(filePath));\r\n await fs.writeFile(filePath, result.html, 'utf-8');\r\n\r\n files.push(filePath);\r\n completed++;\r\n\r\n // Return links for crawling\r\n return result.links || [];\r\n })\r\n );\r\n\r\n // Handle results\r\n for (let i = 0; i < results.length; i++) {\r\n const result = results[i];\r\n const route = batch[i];\r\n\r\n if (result.status === 'rejected') {\r\n const error = { route, error: result.reason };\r\n errors.push(error);\r\n if (onError) {\r\n onError(error);\r\n }\r\n } else if (crawlLinks && result.value) {\r\n // Add discovered links to process queue\r\n for (const link of result.value) {\r\n if (!processedRoutes.has(link) && !routeQueue.includes(link)) {\r\n routeQueue.push(link);\r\n discoveredCount++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n total: processedRoutes.size,\r\n success: files.length,\r\n failed: errors.length,\r\n discovered: discoveredCount,\r\n duration: Date.now() - startTime,\r\n files,\r\n errors,\r\n };\r\n}\r\n\r\n/**\r\n * Get output file path for a route\r\n */\r\nfunction getOutputPath(route: string, outDir: string): string {\r\n // Normalize route\r\n let normalizedRoute = route;\r\n\r\n if (!normalizedRoute.startsWith('/')) {\r\n normalizedRoute = '/' + normalizedRoute;\r\n }\r\n\r\n // Handle index routes\r\n if (normalizedRoute === '/') {\r\n return join(outDir, 'index.html');\r\n }\r\n\r\n // Handle trailing slashes\r\n if (normalizedRoute.endsWith('/')) {\r\n return join(outDir, normalizedRoute, 'index.html');\r\n }\r\n\r\n // Handle routes without extension\r\n if (!normalizedRoute.includes('.')) {\r\n return join(outDir, normalizedRoute + '.html');\r\n }\r\n\r\n return join(outDir, normalizedRoute);\r\n}\r\n\r\n/**\r\n * Ensure directory exists\r\n */\r\nasync function ensureDir(dir: string): Promise<void> {\r\n try {\r\n await fs.mkdir(dir, { recursive: true });\r\n } catch (error: unknown) {\r\n // Ignore if directory already exists\r\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\r\n throw error;\r\n }\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Link Extraction (for crawling)\r\n// ============================================================================\r\n\r\n/**\r\n * Extract internal links from HTML\r\n */\r\nexport function extractLinks(html: string, baseUrl?: string): string[] {\r\n const links: string[] = [];\r\n const linkRegex = /<a[^>]+href=[\"']([^\"']+)[\"'][^>]*>/gi;\r\n\r\n let match;\r\n while ((match = linkRegex.exec(html)) !== null) {\r\n const href = match[1];\r\n\r\n // Skip external links, anchors, and special protocols\r\n if (\r\n href.startsWith('http://') ||\r\n href.startsWith('https://') ||\r\n href.startsWith('#') ||\r\n href.startsWith('mailto:') ||\r\n href.startsWith('tel:') ||\r\n href.startsWith('javascript:')\r\n ) {\r\n continue;\r\n }\r\n\r\n // Normalize the link\r\n let normalizedLink = href;\r\n\r\n // Handle absolute paths\r\n if (href.startsWith('/')) {\r\n normalizedLink = href;\r\n } else if (baseUrl) {\r\n // Handle relative paths\r\n const base = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';\r\n normalizedLink = new URL(href, base).pathname;\r\n }\r\n\r\n // Remove query strings and fragments\r\n normalizedLink = normalizedLink.split('?')[0].split('#')[0];\r\n\r\n if (normalizedLink && !links.includes(normalizedLink)) {\r\n links.push(normalizedLink);\r\n }\r\n }\r\n\r\n return links;\r\n}\r\n\r\n// ============================================================================\r\n// Generate Static Params Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Expand dynamic routes with static params\r\n */\r\nexport async function expandDynamicRoutes(\r\n routePattern: string,\r\n generateParams: () => Promise<Record<string, string | string[]>[]>\r\n): Promise<string[]> {\r\n const params = await generateParams();\r\n\r\n return params.map((paramSet) => {\r\n let route = routePattern;\r\n\r\n for (const [key, value] of Object.entries(paramSet)) {\r\n const paramValue = Array.isArray(value) ? value.join('/') : value;\r\n\r\n // Replace [param] style\r\n route = route.replace(`[${key}]`, paramValue);\r\n // Replace [...param] style (catch-all)\r\n route = route.replace(`[...${key}]`, paramValue);\r\n }\r\n\r\n return route;\r\n });\r\n}\r\n","/**\r\n * @flight-framework/core - SSR/SSG/ISR Support\r\n * \r\n * Static site generation and incremental static regeneration.\r\n * Similar to Next.js patterns.\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Static params for dynamic routes\r\n */\r\nexport interface StaticParams {\r\n [key: string]: string | string[];\r\n}\r\n\r\n/**\r\n * Generate static params function signature\r\n */\r\nexport type GenerateStaticParamsFunction = () => Promise<StaticParams[]> | StaticParams[];\r\n\r\n/**\r\n * Page metadata\r\n */\r\nexport interface PageMetadata {\r\n title?: string;\r\n description?: string;\r\n keywords?: string[];\r\n openGraph?: {\r\n title?: string;\r\n description?: string;\r\n images?: string[];\r\n };\r\n}\r\n\r\n/**\r\n * Generate metadata function\r\n */\r\nexport type GenerateMetadataFunction = (params: StaticParams) => Promise<PageMetadata> | PageMetadata;\r\n\r\n/**\r\n * Page module exports\r\n */\r\nexport interface PageModule {\r\n default: (props: { params: StaticParams }) => unknown;\r\n generateStaticParams?: GenerateStaticParamsFunction;\r\n generateMetadata?: GenerateMetadataFunction;\r\n revalidate?: number | false;\r\n dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static';\r\n runtime?: 'nodejs' | 'edge';\r\n}\r\n\r\n// ============================================================================\r\n// Static Generation\r\n// ============================================================================\r\n\r\n/**\r\n * Generate all static paths for a page\r\n */\r\nexport async function generateAllStaticPaths(\r\n pageModules: Map<string, PageModule>\r\n): Promise<Map<string, StaticParams[]>> {\r\n const result = new Map<string, StaticParams[]>();\r\n\r\n for (const [path, module] of pageModules) {\r\n if (module.generateStaticParams) {\r\n try {\r\n const params = await module.generateStaticParams();\r\n result.set(path, params);\r\n } catch (error) {\r\n console.error(`[Flight] Failed to generate static params for ${path}:`, error);\r\n result.set(path, []);\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// ISR (Incremental Static Regeneration)\r\n// ============================================================================\r\n\r\ninterface CachedPage {\r\n html: string;\r\n generatedAt: number;\r\n revalidateAfter: number;\r\n}\r\n\r\nconst pageCache = new Map<string, CachedPage>();\r\n\r\n/**\r\n * Get or generate a cached page\r\n */\r\nexport async function getOrGeneratePage(\r\n path: string,\r\n generateFn: () => Promise<string>,\r\n revalidate?: number | false\r\n): Promise<{ html: string; fromCache: boolean }> {\r\n const cached = pageCache.get(path);\r\n const now = Date.now();\r\n\r\n // Check if cached page is valid\r\n if (cached) {\r\n if (revalidate === false) {\r\n // Never revalidate\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n if (now < cached.revalidateAfter) {\r\n // Still valid\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n // Stale-while-revalidate: return cached and regenerate in background\r\n regeneratePageInBackground(path, generateFn, revalidate || 60);\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n // Generate new page\r\n const html = await generateFn();\r\n\r\n // Cache the page\r\n if (revalidate !== false) {\r\n const revalidateMs = (revalidate || 60) * 1000;\r\n pageCache.set(path, {\r\n html,\r\n generatedAt: now,\r\n revalidateAfter: now + revalidateMs,\r\n });\r\n }\r\n\r\n return { html, fromCache: false };\r\n}\r\n\r\n/**\r\n * Regenerate page in background (stale-while-revalidate)\r\n */\r\nasync function regeneratePageInBackground(\r\n path: string,\r\n generateFn: () => Promise<string>,\r\n revalidate: number\r\n): Promise<void> {\r\n try {\r\n const html = await generateFn();\r\n const now = Date.now();\r\n\r\n pageCache.set(path, {\r\n html,\r\n generatedAt: now,\r\n revalidateAfter: now + (revalidate * 1000),\r\n });\r\n } catch (error) {\r\n console.error(`[Flight] Background regeneration failed for ${path}:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Purge cached page\r\n */\r\nexport function purgePage(path: string): boolean {\r\n return pageCache.delete(path);\r\n}\r\n\r\n/**\r\n * Purge all cached pages\r\n */\r\nexport function purgeAllPages(): void {\r\n pageCache.clear();\r\n}\r\n\r\n// ============================================================================\r\n// Dynamic Rendering\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a page should be dynamically rendered\r\n */\r\nexport function shouldDynamicallyRender(\r\n module: PageModule,\r\n hasParams: boolean\r\n): boolean {\r\n // Force dynamic\r\n if (module.dynamic === 'force-dynamic') {\r\n return true;\r\n }\r\n\r\n // Force static\r\n if (module.dynamic === 'force-static') {\r\n return false;\r\n }\r\n\r\n // Error on dynamic (SSG only)\r\n if (module.dynamic === 'error') {\r\n return false;\r\n }\r\n\r\n // Auto: dynamic if no generateStaticParams\r\n if (hasParams && !module.generateStaticParams) {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// ============================================================================\r\n// Streaming SSR\r\n// ============================================================================\r\n\r\n/**\r\n * Create a streaming response\r\n */\r\nexport function createStreamingResponse(\r\n stream: ReadableStream<Uint8Array>\r\n): Response {\r\n return new Response(stream, {\r\n status: 200,\r\n headers: {\r\n 'Content-Type': 'text/html; charset=utf-8',\r\n 'Transfer-Encoding': 'chunked',\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * Create a text encoder stream for HTML\r\n */\r\nexport function createHtmlStream(): {\r\n readable: ReadableStream<Uint8Array>;\r\n write: (html: string) => void;\r\n close: () => void;\r\n} {\r\n const encoder = new TextEncoder();\r\n let controller: ReadableStreamDefaultController<Uint8Array>;\r\n\r\n const readable = new ReadableStream<Uint8Array>({\r\n start(c) {\r\n controller = c;\r\n },\r\n });\r\n\r\n return {\r\n readable,\r\n write(html: string) {\r\n controller.enqueue(encoder.encode(html));\r\n },\r\n close() {\r\n controller.close();\r\n },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Metadata Rendering\r\n * \r\n * Utilities for rendering SEO metadata to HTML head tags.\r\n * Following Next.js Metadata API patterns.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { renderMetadataToHead } from '@flight-framework/core';\r\n * \r\n * const meta = {\r\n * title: 'My Page',\r\n * description: 'Page description',\r\n * openGraph: { title: 'OG Title', images: ['/og.jpg'] }\r\n * };\r\n * \r\n * const headHtml = renderMetadataToHead(meta);\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Complete metadata interface for SEO\r\n */\r\nexport interface Metadata {\r\n /** Page title */\r\n title?: string | { default: string; template?: string };\r\n /** Meta description */\r\n description?: string;\r\n /** Keywords for SEO */\r\n keywords?: string | string[];\r\n /** Canonical URL */\r\n canonical?: string;\r\n /** Robots directives */\r\n robots?: string | {\r\n index?: boolean;\r\n follow?: boolean;\r\n nocache?: boolean;\r\n googleBot?: {\r\n index?: boolean;\r\n follow?: boolean;\r\n noimageindex?: boolean;\r\n };\r\n };\r\n /** Open Graph metadata */\r\n openGraph?: {\r\n title?: string;\r\n description?: string;\r\n url?: string;\r\n siteName?: string;\r\n images?: string[] | Array<{\r\n url: string;\r\n width?: number;\r\n height?: number;\r\n alt?: string;\r\n }>;\r\n locale?: string;\r\n type?: 'website' | 'article' | 'book' | 'profile';\r\n };\r\n /** Twitter Card metadata */\r\n twitter?: {\r\n card?: 'summary' | 'summary_large_image' | 'app' | 'player';\r\n site?: string;\r\n creator?: string;\r\n title?: string;\r\n description?: string;\r\n images?: string[];\r\n };\r\n /** Favicon and icons */\r\n icons?: {\r\n icon?: string | string[];\r\n apple?: string | string[];\r\n shortcut?: string;\r\n };\r\n /** Alternate languages */\r\n alternates?: {\r\n canonical?: string;\r\n languages?: Record<string, string>;\r\n };\r\n /** Verification tokens */\r\n verification?: {\r\n google?: string;\r\n yandex?: string;\r\n bing?: string;\r\n };\r\n /** Additional custom meta tags */\r\n other?: Record<string, string>;\r\n}\r\n\r\n// ============================================================================\r\n// Metadata Rendering\r\n// ============================================================================\r\n\r\n/**\r\n * Render metadata to HTML head tags\r\n */\r\nexport function renderMetadataToHead(meta: Metadata): string {\r\n const tags: string[] = [];\r\n\r\n // Title\r\n if (meta.title) {\r\n const title = typeof meta.title === 'string'\r\n ? meta.title\r\n : meta.title.default;\r\n tags.push(`<title>${escapeHtml(title)}</title>`);\r\n }\r\n\r\n // Description\r\n if (meta.description) {\r\n tags.push(`<meta name=\"description\" content=\"${escapeAttr(meta.description)}\">`);\r\n }\r\n\r\n // Keywords\r\n if (meta.keywords) {\r\n const keywords = Array.isArray(meta.keywords)\r\n ? meta.keywords.join(', ')\r\n : meta.keywords;\r\n tags.push(`<meta name=\"keywords\" content=\"${escapeAttr(keywords)}\">`);\r\n }\r\n\r\n // Canonical\r\n if (meta.canonical) {\r\n tags.push(`<link rel=\"canonical\" href=\"${escapeAttr(meta.canonical)}\">`);\r\n }\r\n\r\n // Robots\r\n if (meta.robots) {\r\n const robotsContent = typeof meta.robots === 'string'\r\n ? meta.robots\r\n : buildRobotsContent(meta.robots);\r\n tags.push(`<meta name=\"robots\" content=\"${escapeAttr(robotsContent)}\">`);\r\n }\r\n\r\n // Open Graph\r\n if (meta.openGraph) {\r\n const og = meta.openGraph;\r\n if (og.title) tags.push(`<meta property=\"og:title\" content=\"${escapeAttr(og.title)}\">`);\r\n if (og.description) tags.push(`<meta property=\"og:description\" content=\"${escapeAttr(og.description)}\">`);\r\n if (og.url) tags.push(`<meta property=\"og:url\" content=\"${escapeAttr(og.url)}\">`);\r\n if (og.siteName) tags.push(`<meta property=\"og:site_name\" content=\"${escapeAttr(og.siteName)}\">`);\r\n if (og.type) tags.push(`<meta property=\"og:type\" content=\"${escapeAttr(og.type)}\">`);\r\n if (og.locale) tags.push(`<meta property=\"og:locale\" content=\"${escapeAttr(og.locale)}\">`);\r\n\r\n if (og.images) {\r\n for (const image of og.images) {\r\n if (typeof image === 'string') {\r\n tags.push(`<meta property=\"og:image\" content=\"${escapeAttr(image)}\">`);\r\n } else {\r\n tags.push(`<meta property=\"og:image\" content=\"${escapeAttr(image.url)}\">`);\r\n if (image.width) tags.push(`<meta property=\"og:image:width\" content=\"${image.width}\">`);\r\n if (image.height) tags.push(`<meta property=\"og:image:height\" content=\"${image.height}\">`);\r\n if (image.alt) tags.push(`<meta property=\"og:image:alt\" content=\"${escapeAttr(image.alt)}\">`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Twitter\r\n if (meta.twitter) {\r\n const tw = meta.twitter;\r\n if (tw.card) tags.push(`<meta name=\"twitter:card\" content=\"${escapeAttr(tw.card)}\">`);\r\n if (tw.site) tags.push(`<meta name=\"twitter:site\" content=\"${escapeAttr(tw.site)}\">`);\r\n if (tw.creator) tags.push(`<meta name=\"twitter:creator\" content=\"${escapeAttr(tw.creator)}\">`);\r\n if (tw.title) tags.push(`<meta name=\"twitter:title\" content=\"${escapeAttr(tw.title)}\">`);\r\n if (tw.description) tags.push(`<meta name=\"twitter:description\" content=\"${escapeAttr(tw.description)}\">`);\r\n\r\n if (tw.images) {\r\n for (const image of tw.images) {\r\n tags.push(`<meta name=\"twitter:image\" content=\"${escapeAttr(image)}\">`);\r\n }\r\n }\r\n }\r\n\r\n // Icons\r\n if (meta.icons) {\r\n const icons = meta.icons;\r\n\r\n if (icons.icon) {\r\n const iconList = Array.isArray(icons.icon) ? icons.icon : [icons.icon];\r\n for (const icon of iconList) {\r\n tags.push(`<link rel=\"icon\" href=\"${escapeAttr(icon)}\">`);\r\n }\r\n }\r\n\r\n if (icons.apple) {\r\n const appleList = Array.isArray(icons.apple) ? icons.apple : [icons.apple];\r\n for (const icon of appleList) {\r\n tags.push(`<link rel=\"apple-touch-icon\" href=\"${escapeAttr(icon)}\">`);\r\n }\r\n }\r\n\r\n if (icons.shortcut) {\r\n tags.push(`<link rel=\"shortcut icon\" href=\"${escapeAttr(icons.shortcut)}\">`);\r\n }\r\n }\r\n\r\n // Alternates\r\n if (meta.alternates) {\r\n if (meta.alternates.canonical) {\r\n tags.push(`<link rel=\"canonical\" href=\"${escapeAttr(meta.alternates.canonical)}\">`);\r\n }\r\n\r\n if (meta.alternates.languages) {\r\n for (const [lang, url] of Object.entries(meta.alternates.languages)) {\r\n tags.push(`<link rel=\"alternate\" hreflang=\"${escapeAttr(lang)}\" href=\"${escapeAttr(url)}\">`);\r\n }\r\n }\r\n }\r\n\r\n // Verification\r\n if (meta.verification) {\r\n if (meta.verification.google) {\r\n tags.push(`<meta name=\"google-site-verification\" content=\"${escapeAttr(meta.verification.google)}\">`);\r\n }\r\n if (meta.verification.bing) {\r\n tags.push(`<meta name=\"msvalidate.01\" content=\"${escapeAttr(meta.verification.bing)}\">`);\r\n }\r\n if (meta.verification.yandex) {\r\n tags.push(`<meta name=\"yandex-verification\" content=\"${escapeAttr(meta.verification.yandex)}\">`);\r\n }\r\n }\r\n\r\n // Custom meta tags\r\n if (meta.other) {\r\n for (const [name, content] of Object.entries(meta.other)) {\r\n tags.push(`<meta name=\"${escapeAttr(name)}\" content=\"${escapeAttr(content)}\">`);\r\n }\r\n }\r\n\r\n return tags.join('\\n ');\r\n}\r\n\r\n/**\r\n * Build robots content string from object\r\n */\r\nfunction buildRobotsContent(robots: Exclude<Metadata['robots'], string | undefined>): string {\r\n const directives: string[] = [];\r\n\r\n if (robots.index === false) directives.push('noindex');\r\n else if (robots.index === true) directives.push('index');\r\n\r\n if (robots.follow === false) directives.push('nofollow');\r\n else if (robots.follow === true) directives.push('follow');\r\n\r\n if (robots.nocache) directives.push('nocache');\r\n\r\n return directives.join(', ') || 'index, follow';\r\n}\r\n\r\n// ============================================================================\r\n// Merge Metadata\r\n// ============================================================================\r\n\r\n/**\r\n * Merge multiple metadata objects (later overrides earlier)\r\n */\r\nexport function mergeMetadata(...metadataList: (Metadata | undefined)[]): Metadata {\r\n const result: Metadata = {};\r\n\r\n for (const meta of metadataList) {\r\n if (!meta) continue;\r\n\r\n // Simple overwrites\r\n if (meta.title !== undefined) result.title = meta.title;\r\n if (meta.description !== undefined) result.description = meta.description;\r\n if (meta.keywords !== undefined) result.keywords = meta.keywords;\r\n if (meta.canonical !== undefined) result.canonical = meta.canonical;\r\n if (meta.robots !== undefined) result.robots = meta.robots;\r\n\r\n // Deep merge objects\r\n if (meta.openGraph) {\r\n result.openGraph = { ...result.openGraph, ...meta.openGraph };\r\n }\r\n if (meta.twitter) {\r\n result.twitter = { ...result.twitter, ...meta.twitter };\r\n }\r\n if (meta.icons) {\r\n result.icons = { ...result.icons, ...meta.icons };\r\n }\r\n if (meta.alternates) {\r\n result.alternates = { ...result.alternates, ...meta.alternates };\r\n }\r\n if (meta.verification) {\r\n result.verification = { ...result.verification, ...meta.verification };\r\n }\r\n if (meta.other) {\r\n result.other = { ...result.other, ...meta.other };\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Generate Metadata Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Type for generateMetadata function\r\n */\r\nexport type GenerateMetadataFn<Params = Record<string, string>> = (\r\n props: { params: Params; searchParams?: Record<string, string> }\r\n) => Metadata | Promise<Metadata>;\r\n\r\n/**\r\n * Resolve metadata from a page module\r\n */\r\nexport async function resolveMetadata<Params = Record<string, string>>(\r\n pageModule: { metadata?: Metadata; generateMetadata?: GenerateMetadataFn<Params> },\r\n props: { params: Params; searchParams?: Record<string, string> }\r\n): Promise<Metadata> {\r\n // Static metadata takes precedence\r\n if (pageModule.metadata) {\r\n return pageModule.metadata;\r\n }\r\n\r\n // Dynamic metadata via generateMetadata\r\n if (pageModule.generateMetadata) {\r\n return await pageModule.generateMetadata(props);\r\n }\r\n\r\n return {};\r\n}\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>');\r\n}\r\n\r\nfunction escapeAttr(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n}\r\n","/**\r\n * @flight-framework/core - Local DevTools\r\n * \r\n * Development-only debugging overlay.\r\n * 100% LOCAL - NO telemetry, NO external requests, NO cloud.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { injectDevTools } from '@flight-framework/core';\r\n * \r\n * const html = renderPage() + injectDevTools({ routes, renderTime });\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface DevToolsOptions {\r\n /** Current route path */\r\n route?: string;\r\n /** Render time in milliseconds */\r\n renderTime?: number;\r\n /** Rendering mode used */\r\n renderMode?: 'ssr' | 'ssg' | 'isr' | 'csr';\r\n /** Whether page is hydrated */\r\n hydrated?: boolean;\r\n /** Route params */\r\n params?: Record<string, string>;\r\n /** Cache status */\r\n cacheStatus?: 'hit' | 'miss' | 'stale';\r\n /** Custom data to display */\r\n customData?: Record<string, unknown>;\r\n}\r\n\r\n// ============================================================================\r\n// DevTools Injection\r\n// ============================================================================\r\n\r\n/**\r\n * Inject DevTools overlay into HTML\r\n * Only works in development mode - returns empty string in production\r\n */\r\nexport function injectDevTools(options: DevToolsOptions = {}): string {\r\n // CRITICAL: Only inject in development\r\n if (process.env.NODE_ENV !== 'development') {\r\n return '';\r\n }\r\n\r\n const data = JSON.stringify(options, null, 2);\r\n\r\n return `\r\n<!-- Flight DevTools - Development Only - NO TELEMETRY -->\r\n<div id=\"flight-devtools\" style=\"display:none;\">\r\n <div id=\"flight-devtools-toggle\" style=\"\r\n position: fixed;\r\n bottom: 16px;\r\n right: 16px;\r\n width: 40px;\r\n height: 40px;\r\n background: #1a1a2e;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 99999;\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\r\n font-size: 20px;\r\n \">✈</div>\r\n <div id=\"flight-devtools-panel\" style=\"\r\n position: fixed;\r\n bottom: 70px;\r\n right: 16px;\r\n width: 320px;\r\n max-height: 400px;\r\n background: #1a1a2e;\r\n color: #e0e0e0;\r\n border-radius: 8px;\r\n padding: 16px;\r\n font-family: ui-monospace, monospace;\r\n font-size: 12px;\r\n z-index: 99998;\r\n overflow-y: auto;\r\n display: none;\r\n box-shadow: 0 8px 24px rgba(0,0,0,0.4);\r\n \">\r\n <div style=\"display:flex;justify-content:space-between;margin-bottom:12px;\">\r\n <strong style=\"color:#60a5fa;\">Flight DevTools</strong>\r\n <span style=\"color:#6b7280;font-size:10px;\">LOCAL ONLY</span>\r\n </div>\r\n <div id=\"flight-devtools-content\"></div>\r\n </div>\r\n</div>\r\n<script>\r\n(function() {\r\n // DevTools data\r\n var data = ${data};\r\n \r\n // Wait for DOM\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', init);\r\n } else {\r\n init();\r\n }\r\n \r\n function init() {\r\n var container = document.getElementById('flight-devtools');\r\n var toggle = document.getElementById('flight-devtools-toggle');\r\n var panel = document.getElementById('flight-devtools-panel');\r\n var content = document.getElementById('flight-devtools-content');\r\n \r\n if (!container || !toggle || !panel || !content) return;\r\n \r\n container.style.display = 'block';\r\n \r\n // Render content\r\n var html = '';\r\n \r\n if (data.route) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Route:</span> <span style=\"color:#34d399;\">' + escapeHtml(data.route) + '</span></div>';\r\n }\r\n \r\n if (data.renderMode) {\r\n var modeColor = {ssr:'#f59e0b',ssg:'#10b981',isr:'#8b5cf6',csr:'#3b82f6'}[data.renderMode] || '#6b7280';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Mode:</span> <span style=\"color:' + modeColor + ';text-transform:uppercase;\">' + data.renderMode + '</span></div>';\r\n }\r\n \r\n if (data.renderTime !== undefined) {\r\n var timeColor = data.renderTime < 50 ? '#10b981' : data.renderTime < 200 ? '#f59e0b' : '#ef4444';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Render:</span> <span style=\"color:' + timeColor + ';\">' + data.renderTime + 'ms</span></div>';\r\n }\r\n \r\n if (data.cacheStatus) {\r\n var cacheColor = {hit:'#10b981',miss:'#ef4444',stale:'#f59e0b'}[data.cacheStatus] || '#6b7280';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Cache:</span> <span style=\"color:' + cacheColor + ';\">' + data.cacheStatus.toUpperCase() + '</span></div>';\r\n }\r\n \r\n if (data.params && Object.keys(data.params).length > 0) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Params:</span></div>';\r\n html += '<pre style=\"background:#0f0f1a;padding:8px;border-radius:4px;margin:0;overflow-x:auto;\">' + escapeHtml(JSON.stringify(data.params, null, 2)) + '</pre>';\r\n }\r\n \r\n if (data.hydrated !== undefined) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Hydrated:</span> <span style=\"color:' + (data.hydrated ? '#10b981' : '#f59e0b') + ';\">' + (data.hydrated ? 'Yes' : 'Pending') + '</span></div>';\r\n }\r\n \r\n if (data.customData) {\r\n html += '<details style=\"margin-top:12px;\"><summary style=\"cursor:pointer;color:#6b7280;\">Custom Data</summary>';\r\n html += '<pre style=\"background:#0f0f1a;padding:8px;border-radius:4px;margin-top:8px;overflow-x:auto;\">' + escapeHtml(JSON.stringify(data.customData, null, 2)) + '</pre></details>';\r\n }\r\n \r\n content.innerHTML = html || '<span style=\"color:#6b7280;\">No data available</span>';\r\n \r\n // Toggle panel\r\n toggle.addEventListener('click', function() {\r\n panel.style.display = panel.style.display === 'none' ? 'block' : 'none';\r\n });\r\n \r\n // Update hydration status\r\n window.addEventListener('load', function() {\r\n setTimeout(function() {\r\n var hydrationEl = content.querySelector('[data-hydration]');\r\n if (hydrationEl) {\r\n hydrationEl.textContent = 'Yes';\r\n hydrationEl.style.color = '#10b981';\r\n }\r\n }, 100);\r\n });\r\n }\r\n \r\n function escapeHtml(str) {\r\n return String(str).replace(/[&<>\"']/g, function(m) {\r\n return {'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[m];\r\n });\r\n }\r\n})();\r\n</script>\r\n`;\r\n}\r\n\r\n/**\r\n * Check if DevTools should be enabled\r\n */\r\nexport function isDevToolsEnabled(): boolean {\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\n/**\r\n * Create DevTools data from request context\r\n */\r\nexport function createDevToolsData(\r\n startTime: number,\r\n options: Partial<DevToolsOptions> = {}\r\n): DevToolsOptions {\r\n return {\r\n renderTime: Date.now() - startTime,\r\n hydrated: false,\r\n ...options,\r\n };\r\n}\r\n","/**\r\n * Flight Framework - Core\r\n * \r\n * The agnostic full-stack framework primitives.\r\n * Maximum flexibility, zero lock-in.\r\n */\r\n\r\n// Configuration\r\nexport { defineConfig, type FlightConfig, type FlightUserConfig } from './config/index.js';\r\n\r\n// Router\r\nexport {\r\n createRouter,\r\n type Route,\r\n type RouteMatch,\r\n type Router,\r\n type RouteParams,\r\n} from './router/index.js';\r\n\r\n// Server\r\nexport {\r\n createServer,\r\n type FlightServer,\r\n type RouteHandler,\r\n type RouteHandlerContext,\r\n type ServerOptions,\r\n type ServerRoute,\r\n} from './server/index.js';\r\n\r\n// Render\r\nexport {\r\n type RenderMode,\r\n type RenderContext,\r\n type RenderResult,\r\n} from './render/index.js';\r\n\r\n// Cache\r\nexport {\r\n createCache,\r\n type Cache,\r\n type CacheOptions,\r\n} from './cache/index.js';\r\n\r\n// Middleware\r\nexport {\r\n createMiddlewareChain,\r\n type Middleware,\r\n type MiddlewareContext,\r\n type MiddlewareNext,\r\n} from './middleware/index.js';\r\n\r\n// Adapters\r\nexport {\r\n type FlightAdapter,\r\n type AdapterBuilder,\r\n} from './adapters/index.js';\r\n\r\n// File Router\r\nexport {\r\n createFileRouter,\r\n scanRoutes,\r\n loadRoutes,\r\n type FileRoute,\r\n type FileRouter,\r\n type FileRouterOptions,\r\n type ScanResult,\r\n} from './file-router/index.js';\r\n\r\n// Route Handlers (for file-based routing)\r\nexport {\r\n createRouteContext,\r\n json,\r\n redirect,\r\n error,\r\n parseBody,\r\n type RouteHandler as FileRouteHandler,\r\n type RouteHandlerContext as FileRouteHandlerContext,\r\n type HttpMethod as FileHttpMethod,\r\n} from './handlers/index.js';\r\n\r\n// Server Actions\r\nexport {\r\n registerAction,\r\n getAction,\r\n executeAction,\r\n executeFormAction,\r\n handleActionRequest,\r\n cookies,\r\n redirect as actionRedirect,\r\n parseFormData,\r\n RedirectError,\r\n isRedirectError,\r\n type ServerAction,\r\n type ActionResult,\r\n type CookieOptions,\r\n} from './actions/index.js';\r\n\r\n// Streaming SSR\r\nexport {\r\n createStreamingSSR,\r\n createStreamingResponse,\r\n renderWithStreaming,\r\n createLazyContent,\r\n streamParallel,\r\n streamSequential,\r\n type StreamingRenderOptions,\r\n type StreamingRenderResult,\r\n type SuspenseBoundaryConfig,\r\n} from './streaming/index.js';\r\n\r\n// React Server Components (RSC) Primitives\r\nexport {\r\n hasUseClientDirective,\r\n hasUseServerDirective,\r\n detectComponentType,\r\n createRenderContext,\r\n executeServerComponent,\r\n serverFetch,\r\n revalidateTag as rscRevalidateTag,\r\n revalidatePath as rscRevalidatePath,\r\n serializeProps,\r\n deserializeProps,\r\n createClientBoundary,\r\n createAsyncComponent,\r\n composeComponents,\r\n withErrorBoundary,\r\n notFound,\r\n isNotFoundError,\r\n redirect as rscRedirect,\r\n isRedirectError as isRscRedirectError,\r\n type RenderContext as RSCRenderContext,\r\n type ServerComponent,\r\n type ClientComponent,\r\n type ComponentType as RSCComponentType,\r\n} from './rsc/index.js';\r\n\r\n// Route Rules (ISR/SSG Configuration)\r\nexport {\r\n matchRouteRule,\r\n mergeRouteRules,\r\n getRenderModeFromRule,\r\n getRevalidateTime,\r\n getCacheOptionsFromRule,\r\n buildCacheControlHeader,\r\n createDefaultRouteRules,\r\n type RouteRule,\r\n type RouteRules,\r\n} from './config/route-rules.js';\r\n\r\n// On-Demand Revalidation\r\nexport {\r\n revalidatePath,\r\n revalidateTag,\r\n revalidatePaths,\r\n createRevalidateHandler,\r\n setISRCache,\r\n getISRCache,\r\n createMemoryISRCache,\r\n createISRCacheFromFlightCache,\r\n type ISRCacheEntry,\r\n type ISRCacheAdapter,\r\n type RevalidationResult,\r\n type RevalidateHandlerOptions,\r\n} from './render/revalidate.js';\r\n\r\n// Build-Time Prerender (SSG)\r\nexport {\r\n prerenderRoutes,\r\n extractLinks,\r\n expandDynamicRoutes,\r\n type PrerenderOptions,\r\n type PrerenderResult,\r\n type PrerenderProgress,\r\n type PrerenderError,\r\n type PrerenderSummary,\r\n} from './build/prerender.js';\r\n\r\n// Static Generation Utilities\r\nexport {\r\n generateAllStaticPaths,\r\n getOrGeneratePage,\r\n purgePage,\r\n purgeAllPages,\r\n shouldDynamicallyRender,\r\n createStreamingResponse as createStaticStreamingResponse,\r\n createHtmlStream,\r\n type StaticParams,\r\n type GenerateStaticParamsFunction,\r\n type PageMetadata,\r\n type GenerateMetadataFunction,\r\n type PageModule,\r\n} from './render/static.js';\r\n\r\n// Metadata API (SEO)\r\nexport {\r\n renderMetadataToHead,\r\n mergeMetadata,\r\n resolveMetadata,\r\n type Metadata,\r\n type GenerateMetadataFn,\r\n} from './render/metadata.js';\r\n\r\n// DevTools (Development only, local, no telemetry)\r\nexport {\r\n injectDevTools,\r\n isDevToolsEnabled,\r\n createDevToolsData,\r\n type DevToolsOptions,\r\n} from './render/devtools.js';\r\n\r\n// Version\r\nexport const VERSION = '0.0.1';\r\n"]}
|
package/dist/rsc/index.d.ts
CHANGED
package/dist/rsc/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { composeComponents, createAsyncComponent, createClientBoundary, createRenderContext, deserializeProps, detectComponentType, executeServerComponent, hasUseClientDirective, hasUseServerDirective, isNotFoundError, isRedirectError, notFound, redirect, revalidatePath, revalidateTag, serializeProps, serverFetch, withErrorBoundary } from '../chunk-
|
|
1
|
+
export { composeComponents, createAsyncComponent, createClientBoundary, createRenderContext, deserializeProps, detectComponentType, executeServerComponent, hasUseClientDirective, hasUseServerDirective, isNotFoundError, isRedirectError, notFound, redirect, revalidatePath, revalidateTag, serializeProps, serverFetch, withErrorBoundary } from '../chunk-5KF3QQWZ.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import '../render/index.js';
|
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
14
|
* ```typescript
|
|
15
|
-
* import { createServer } from '@flight/core';
|
|
15
|
+
* import { createServer } from '@flight-framework/core';
|
|
16
16
|
*
|
|
17
17
|
* const server = createServer();
|
|
18
18
|
*
|
|
@@ -113,7 +113,7 @@ type Runtime = 'node' | 'bun' | 'deno' | 'unknown';
|
|
|
113
113
|
*
|
|
114
114
|
* @example
|
|
115
115
|
* ```typescript
|
|
116
|
-
* import { createServer } from '@flight/core';
|
|
116
|
+
* import { createServer } from '@flight-framework/core';
|
|
117
117
|
*
|
|
118
118
|
* const server = createServer();
|
|
119
119
|
*
|
package/dist/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { createServer, getRuntime, isFlightServer } from '../chunk-
|
|
1
|
+
export { createServer, getRuntime, isFlightServer } from '../chunk-6LYV4VQX.js';
|
|
2
2
|
import '../chunk-GCQZ4FHI.js';
|
|
3
3
|
import '../chunk-KWFX6WHG.js';
|
|
4
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-3TPAA52K.js';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @flight/core - Streaming SSR
|
|
2
|
+
* @flight-framework/core - Streaming SSR
|
|
3
3
|
*
|
|
4
4
|
* Full streaming server-side rendering implementation following React 18+/19 patterns.
|
|
5
5
|
* Supports both Node.js (renderToPipeableStream) and Edge (renderToReadableStream) environments.
|
package/dist/streaming/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { createLazyContent, createStreamingResponse, createStreamingSSR, renderWithStreaming, streamParallel, streamSequential } from '../chunk-
|
|
1
|
+
export { createLazyContent, createStreamingResponse, createStreamingSSR, renderWithStreaming, streamParallel, streamSequential } from '../chunk-ABNCAPQB.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,100 +1,101 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@flight-framework/core",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Core primitives for Flight Framework - routing, rendering, caching",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"flight",
|
|
7
|
+
"framework",
|
|
8
|
+
"core",
|
|
9
|
+
"ssr",
|
|
10
|
+
"routing"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Flight Contributors",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./router": {
|
|
21
|
+
"types": "./dist/router/index.d.ts",
|
|
22
|
+
"import": "./dist/router/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./render": {
|
|
25
|
+
"types": "./dist/render/index.d.ts",
|
|
26
|
+
"import": "./dist/render/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./cache": {
|
|
29
|
+
"types": "./dist/cache/index.d.ts",
|
|
30
|
+
"import": "./dist/cache/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./middleware": {
|
|
33
|
+
"types": "./dist/middleware/index.d.ts",
|
|
34
|
+
"import": "./dist/middleware/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./config": {
|
|
37
|
+
"types": "./dist/config/index.d.ts",
|
|
38
|
+
"import": "./dist/config/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./adapters": {
|
|
41
|
+
"types": "./dist/adapters/index.d.ts",
|
|
42
|
+
"import": "./dist/adapters/index.js"
|
|
43
|
+
},
|
|
44
|
+
"./server": {
|
|
45
|
+
"types": "./dist/server/index.d.ts",
|
|
46
|
+
"import": "./dist/server/index.js"
|
|
47
|
+
},
|
|
48
|
+
"./file-router": {
|
|
49
|
+
"types": "./dist/file-router/index.d.ts",
|
|
50
|
+
"import": "./dist/file-router/index.js"
|
|
51
|
+
},
|
|
52
|
+
"./actions": {
|
|
53
|
+
"types": "./dist/actions/index.d.ts",
|
|
54
|
+
"import": "./dist/actions/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./handlers": {
|
|
57
|
+
"types": "./dist/handlers/index.d.ts",
|
|
58
|
+
"import": "./dist/handlers/index.js"
|
|
59
|
+
},
|
|
60
|
+
"./streaming": {
|
|
61
|
+
"types": "./dist/streaming/index.d.ts",
|
|
62
|
+
"import": "./dist/streaming/index.js"
|
|
63
|
+
},
|
|
64
|
+
"./rsc": {
|
|
65
|
+
"types": "./dist/rsc/index.d.ts",
|
|
66
|
+
"import": "./dist/rsc/index.js"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"main": "./dist/index.js",
|
|
70
|
+
"types": "./dist/index.d.ts",
|
|
71
|
+
"files": [
|
|
72
|
+
"dist"
|
|
73
|
+
],
|
|
74
|
+
"scripts": {
|
|
75
|
+
"build": "tsup",
|
|
76
|
+
"dev": "tsup --watch",
|
|
77
|
+
"test": "vitest run",
|
|
78
|
+
"test:watch": "vitest",
|
|
79
|
+
"lint": "eslint src/",
|
|
80
|
+
"clean": "rimraf dist",
|
|
81
|
+
"typecheck": "tsc --noEmit"
|
|
82
|
+
},
|
|
83
|
+
"dependencies": {
|
|
84
|
+
"radix3": "^1.1.0"
|
|
85
|
+
},
|
|
86
|
+
"devDependencies": {
|
|
87
|
+
"@types/node": "^22.0.0",
|
|
88
|
+
"rimraf": "^6.0.0",
|
|
89
|
+
"tsup": "^8.0.0",
|
|
90
|
+
"typescript": "^5.7.0",
|
|
91
|
+
"vitest": "^2.0.0"
|
|
92
|
+
},
|
|
93
|
+
"peerDependencies": {
|
|
94
|
+
"vite": "^6.0.0 || ^7.0.0"
|
|
95
|
+
},
|
|
96
|
+
"peerDependenciesMeta": {
|
|
97
|
+
"vite": {
|
|
98
|
+
"optional": true
|
|
99
|
+
}
|
|
100
|
+
}
|
|
100
101
|
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024-2026 Flight Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rsc/index.ts"],"names":[],"mappings":"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","file":"chunk-AFSKXC6V.js","sourcesContent":["/**\r\n * @flight/core - React Server Components Support\r\n * \r\n * Framework-agnostic primitives for RSC-like patterns.\r\n * Enables async server components, client/server boundaries, and data fetching.\r\n * \r\n * Best Practices 2025/2026:\r\n * - Async components for server-side data fetching\r\n * - 'use client' / 'use server' directive detection\r\n * - Automatic component serialization\r\n * - Props passing between server and client\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Component rendering context\r\n */\r\nexport interface RenderContext {\r\n /** Current request */\r\n request: Request;\r\n /** Route params */\r\n params: Record<string, string>;\r\n /** Search params */\r\n searchParams: URLSearchParams;\r\n /** Request headers */\r\n headers: Headers;\r\n /** Cookies */\r\n cookies: Map<string, string>;\r\n}\r\n\r\n/**\r\n * Server component definition\r\n */\r\nexport interface ServerComponent<P = unknown> {\r\n (props: P, context: RenderContext): Promise<string> | string;\r\n /** Mark as server component */\r\n __flight_server?: true;\r\n /** Dependencies for hydration */\r\n __flight_deps?: string[];\r\n}\r\n\r\n/**\r\n * Client component definition\r\n */\r\nexport interface ClientComponent<P = unknown> {\r\n (props: P): unknown;\r\n /** Mark as client component */\r\n __flight_client?: true;\r\n /** Client bundle path */\r\n __flight_bundle?: string;\r\n}\r\n\r\n/**\r\n * Component type detection\r\n */\r\nexport type ComponentType = 'server' | 'client' | 'hybrid';\r\n\r\n// ============================================================================\r\n// Directive Detection (Build-time)\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a file has 'use client' directive\r\n */\r\nexport function hasUseClientDirective(source: string): boolean {\r\n const firstLine = source.trim().split('\\n')[0] ?? '';\r\n return /^['\"]use client['\"];?/.test(firstLine);\r\n}\r\n\r\n/**\r\n * Check if a file has 'use server' directive\r\n */\r\nexport function hasUseServerDirective(source: string): boolean {\r\n const firstLine = source.trim().split('\\n')[0] ?? '';\r\n return /^['\"]use server['\"];?/.test(firstLine);\r\n}\r\n\r\n/**\r\n * Detect component type from source\r\n */\r\nexport function detectComponentType(source: string): ComponentType {\r\n if (hasUseClientDirective(source)) return 'client';\r\n if (hasUseServerDirective(source)) return 'server';\r\n return 'hybrid';\r\n}\r\n\r\n// ============================================================================\r\n// Server Component Execution\r\n// ============================================================================\r\n\r\n/**\r\n * Execute an async server component\r\n */\r\nexport async function executeServerComponent<P>(\r\n component: ServerComponent<P>,\r\n props: P,\r\n context: RenderContext\r\n): Promise<string> {\r\n try {\r\n const result = await component(props, context);\r\n return result;\r\n } catch (error) {\r\n console.error('[Flight] Server component error:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Create a render context from a Request\r\n */\r\nexport function createRenderContext(request: Request, params: Record<string, string> = {}): RenderContext {\r\n const url = new URL(request.url);\r\n\r\n // Parse cookies\r\n const cookies = new Map<string, string>();\r\n const cookieHeader = request.headers.get('cookie') || '';\r\n cookieHeader.split(';').forEach(cookie => {\r\n const [key, value] = cookie.trim().split('=');\r\n if (key && value) cookies.set(key, value);\r\n });\r\n\r\n return {\r\n request,\r\n params,\r\n searchParams: url.searchParams,\r\n headers: request.headers,\r\n cookies,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Data Fetching Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Cache for server-side fetch requests\r\n */\r\nconst fetchCache = new Map<string, { data: unknown; timestamp: number }>();\r\n\r\n/**\r\n * Server-side fetch with automatic caching (like Next.js fetch extensions)\r\n */\r\nexport async function serverFetch<T>(\r\n url: string,\r\n options: RequestInit & {\r\n revalidate?: number | false;\r\n tags?: string[];\r\n } = {}\r\n): Promise<T> {\r\n const { revalidate = 60, tags = [], ...fetchOptions } = options;\r\n const cacheKey = `${url}:${JSON.stringify(fetchOptions)}`;\r\n\r\n // Check cache\r\n const cached = fetchCache.get(cacheKey);\r\n if (cached) {\r\n const age = Date.now() - cached.timestamp;\r\n if (revalidate === false || age < (revalidate * 1000)) {\r\n return cached.data as T;\r\n }\r\n }\r\n\r\n // Fetch fresh data\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json();\r\n\r\n // Cache the result\r\n if (revalidate !== false) {\r\n fetchCache.set(cacheKey, {\r\n data,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n\r\n return data as T;\r\n}\r\n\r\n/**\r\n * Invalidate cache by tag\r\n */\r\nexport function revalidateTag(tag: string): void {\r\n // In a real implementation, this would invalidate cache entries by tag\r\n console.log(`[Flight] Revalidating tag: ${tag}`);\r\n}\r\n\r\n/**\r\n * Invalidate cache by path\r\n */\r\nexport function revalidatePath(path: string): void {\r\n // In a real implementation, this would invalidate cache entries by path\r\n console.log(`[Flight] Revalidating path: ${path}`);\r\n}\r\n\r\n// ============================================================================\r\n// Component Serialization (for client boundary crossing)\r\n// ============================================================================\r\n\r\n/**\r\n * Serialize props for transmission to client\r\n */\r\nexport function serializeProps(props: unknown): string {\r\n // Pre-process to handle special types before JSON.stringify\r\n function preProcess(value: unknown): unknown {\r\n if (value instanceof Date) {\r\n return { __type: 'Date', value: value.toISOString() };\r\n }\r\n if (value instanceof Map) {\r\n return { __type: 'Map', value: Array.from(value.entries()).map(([k, v]) => [preProcess(k), preProcess(v)]) };\r\n }\r\n if (value instanceof Set) {\r\n return { __type: 'Set', value: Array.from(value).map(preProcess) };\r\n }\r\n if (typeof value === 'bigint') {\r\n return { __type: 'BigInt', value: value.toString() };\r\n }\r\n if (typeof value === 'function') {\r\n return undefined;\r\n }\r\n if (Array.isArray(value)) {\r\n return value.map(preProcess);\r\n }\r\n if (value && typeof value === 'object') {\r\n const result: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(value)) {\r\n result[k] = preProcess(v);\r\n }\r\n return result;\r\n }\r\n return value;\r\n }\r\n\r\n return JSON.stringify(preProcess(props));\r\n}\r\n\r\n/**\r\n * Deserialize props on client\r\n */\r\nexport function deserializeProps<T>(serialized: string): T {\r\n return JSON.parse(serialized, (_key, value) => {\r\n if (value && typeof value === 'object' && '__type' in value) {\r\n switch (value.__type) {\r\n case 'Date':\r\n return new Date(value.value);\r\n case 'Map':\r\n return new Map(value.value);\r\n case 'Set':\r\n return new Set(value.value);\r\n case 'BigInt':\r\n return BigInt(value.value);\r\n }\r\n }\r\n return value;\r\n });\r\n}\r\n\r\n// ============================================================================\r\n// Client Component Boundary\r\n// ============================================================================\r\n\r\n/**\r\n * Create a client boundary placeholder\r\n */\r\nexport function createClientBoundary(\r\n componentId: string,\r\n props: unknown,\r\n fallback?: string\r\n): string {\r\n const serializedProps = serializeProps(props);\r\n\r\n return `\r\n<!--flight-client:${componentId}-->\r\n<div data-flight-component=\"${componentId}\" data-flight-props='${serializedProps.replace(/'/g, \"'\")}'>\r\n ${fallback || '<div>Loading...</div>'}\r\n</div>\r\n<!--/flight-client-->\r\n<script type=\"module\">\r\n(async function() {\r\n const component = await import('/_flight/components/${componentId}.js');\r\n const props = JSON.parse('${serializedProps.replace(/'/g, \"\\\\'\")}');\r\n const container = document.querySelector('[data-flight-component=\"${componentId}\"]');\r\n if (container && component.default) {\r\n // Hydrate with the framework's hydration method\r\n if (typeof component.hydrate === 'function') {\r\n component.hydrate(container, props);\r\n }\r\n }\r\n})();\r\n</script>`;\r\n}\r\n\r\n// ============================================================================\r\n// Async Component Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Helper to create an async server component\r\n */\r\nexport function createAsyncComponent<P, T>(\r\n fetcher: (props: P, context: RenderContext) => Promise<T>,\r\n renderer: (data: T, props: P) => string\r\n): ServerComponent<P> {\r\n const component: ServerComponent<P> = async (props, context) => {\r\n const data = await fetcher(props, context);\r\n return renderer(data, props);\r\n };\r\n component.__flight_server = true;\r\n return component;\r\n}\r\n\r\n/**\r\n * Compose multiple server components\r\n */\r\nexport function composeComponents(\r\n ...components: Array<() => Promise<string> | string>\r\n): () => Promise<string> {\r\n return async () => {\r\n const results = await Promise.all(\r\n components.map(async (comp) => await comp())\r\n );\r\n return results.join('');\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Error Boundary for Server Components\r\n// ============================================================================\r\n\r\n/**\r\n * Wrap a server component with error handling\r\n */\r\nexport function withErrorBoundary<P>(\r\n component: ServerComponent<P>,\r\n errorFallback: (error: Error) => string\r\n): ServerComponent<P> {\r\n return async (props: P, context: RenderContext) => {\r\n try {\r\n return await component(props, context);\r\n } catch (error) {\r\n console.error('[Flight] Server component error:', error);\r\n return errorFallback(error as Error);\r\n }\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Not Found / Redirect Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Throw a not found error (like Next.js notFound())\r\n */\r\nexport function notFound(): never {\r\n const error = new Error('Not Found');\r\n (error as any).__flight_not_found = true;\r\n throw error;\r\n}\r\n\r\n/**\r\n * Check if error is not found\r\n */\r\nexport function isNotFoundError(error: unknown): boolean {\r\n return error instanceof Error && (error as any).__flight_not_found === true;\r\n}\r\n\r\n/**\r\n * Server-side redirect (like Next.js redirect())\r\n */\r\nexport function redirect(url: string, type: 'replace' | 'push' = 'replace'): never {\r\n const error = new Error(`Redirect: ${url}`);\r\n (error as any).__flight_redirect = { url, type };\r\n throw error;\r\n}\r\n\r\n/**\r\n * Check if error is redirect\r\n */\r\nexport function isRedirectError(error: unknown): { url: string; type: string } | null {\r\n if (error instanceof Error && (error as any).__flight_redirect) {\r\n return (error as any).__flight_redirect;\r\n }\r\n return null;\r\n}\r\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/handlers/index.ts"],"names":[],"mappings":";AAuDO,SAAS,kBAAA,CACZ,OAAA,EACA,MAAA,GAAiC,EAAC,EACf;AACnB,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC/B,EAAA,OAAO;AAAA,IACH,MAAA;AAAA,IACA,cAAc,GAAA,CAAI;AAAA,GACtB;AACJ;AAKO,SAAS,IAAA,CAAQ,MAAS,IAAA,EAA+B;AAC5D,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AACzC,EAAA,OAAA,CAAQ,GAAA,CAAI,gBAAgB,iCAAiC,CAAA;AAE7D,EAAA,OAAO,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,IACtC,GAAG,IAAA;AAAA,IACH;AAAA,GACH,CAAA;AACL;AAKO,SAAS,QAAA,CAAS,GAAA,EAAa,MAAA,GAAsC,GAAA,EAAe;AACvF,EAAA,OAAO,IAAI,SAAS,IAAA,EAAM;AAAA,IACtB,MAAA;AAAA,IACA,OAAA,EAAS,EAAE,QAAA,EAAU,GAAA;AAAI,GAC5B,CAAA;AACL;AAKO,SAAS,KAAA,CAAM,OAAA,EAAiB,MAAA,GAAS,GAAA,EAAe;AAC3D,EAAA,OAAO,IAAI,SAAS,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA,EAAG;AAAA,IACpD,MAAA;AAAA,IACA,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,GACjD,CAAA;AACL;AAKA,eAAsB,UAAa,OAAA,EAA8B;AAC7D,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAE3D,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,kBAAkB,CAAA,EAAG;AAC1C,IAAA,OAAO,MAAM,QAAQ,IAAA,EAAK;AAAA,EAC9B;AAEA,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,mCAAmC,CAAA,EAAG;AAC3D,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAS;AACxC,IAAA,MAAM,MAA8B,EAAC;AACrC,IAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AAC7B,MAAA,GAAA,CAAI,GAAG,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA;AAAA,IAC3B,CAAC,CAAA;AACD,IAAA,OAAO,GAAA;AAAA,EACX;AAEA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,WAAW,CAAA,CAAE,CAAA;AAC9D","file":"chunk-AJ3IBYXT.js","sourcesContent":["/**\r\n * @flight/core - Route Handlers\r\n * \r\n * Types and utilities for route handlers.\r\n * Similar to Next.js Route Handlers pattern.\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * HTTP methods supported by route handlers\r\n */\r\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\r\n\r\n/**\r\n * Context passed to route handlers\r\n */\r\nexport interface RouteHandlerContext {\r\n /** Route parameters (e.g., { id: '123' }) */\r\n params: Record<string, string>;\r\n /** Query string parameters */\r\n searchParams: URLSearchParams;\r\n}\r\n\r\n/**\r\n * Route handler function signature\r\n * \r\n * @example\r\n * ```typescript\r\n * // src/routes/api/users/[id].ts\r\n * export const GET: RouteHandler = async (request, context) => {\r\n * const { id } = context.params;\r\n * return Response.json({ userId: id });\r\n * };\r\n * \r\n * export const PUT: RouteHandler = async (request, context) => {\r\n * const body = await request.json();\r\n * return Response.json({ updated: true, data: body });\r\n * };\r\n * ```\r\n */\r\nexport type RouteHandler = (\r\n request: Request,\r\n context: RouteHandlerContext\r\n) => Response | Promise<Response>;\r\n\r\n// ============================================================================\r\n// Helper Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create a route handler context from request\r\n */\r\nexport function createRouteContext(\r\n request: Request,\r\n params: Record<string, string> = {}\r\n): RouteHandlerContext {\r\n const url = new URL(request.url);\r\n return {\r\n params,\r\n searchParams: url.searchParams,\r\n };\r\n}\r\n\r\n/**\r\n * Helper to create JSON response\r\n */\r\nexport function json<T>(data: T, init?: ResponseInit): Response {\r\n const headers = new Headers(init?.headers);\r\n headers.set('Content-Type', 'application/json; charset=utf-8');\r\n\r\n return new Response(JSON.stringify(data), {\r\n ...init,\r\n headers,\r\n });\r\n}\r\n\r\n/**\r\n * Helper to create redirect response\r\n */\r\nexport function redirect(url: string, status: 301 | 302 | 303 | 307 | 308 = 302): Response {\r\n return new Response(null, {\r\n status,\r\n headers: { Location: url },\r\n });\r\n}\r\n\r\n/**\r\n * Helper to create error response\r\n */\r\nexport function error(message: string, status = 500): Response {\r\n return new Response(JSON.stringify({ error: message }), {\r\n status,\r\n headers: { 'Content-Type': 'application/json' },\r\n });\r\n}\r\n\r\n/**\r\n * Helper to get request body as typed object\r\n */\r\nexport async function parseBody<T>(request: Request): Promise<T> {\r\n const contentType = request.headers.get('content-type') || '';\r\n\r\n if (contentType.includes('application/json')) {\r\n return await request.json() as T;\r\n }\r\n\r\n if (contentType.includes('application/x-www-form-urlencoded')) {\r\n const formData = await request.formData();\r\n const obj: Record<string, string> = {};\r\n formData.forEach((value, key) => {\r\n obj[key] = String(value);\r\n });\r\n return obj as T;\r\n }\r\n\r\n throw new Error(`Unsupported content type: ${contentType}`);\r\n}\r\n"]}
|