@flight-framework/core 0.3.0 → 0.3.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/README.md +202 -7
- package/dist/{chunk-UGTETAJ2.js → chunk-4U7CJVNQ.js} +157 -3
- package/dist/chunk-4U7CJVNQ.js.map +1 -0
- package/dist/{chunk-2R23X5Z3.js → chunk-6IG6XIXU.js} +29 -3
- package/dist/chunk-6IG6XIXU.js.map +1 -0
- package/dist/{chunk-UL4Q5CIJ.js → chunk-KDEA64UX.js} +3 -3
- package/dist/{chunk-UL4Q5CIJ.js.map → chunk-KDEA64UX.js.map} +1 -1
- package/dist/{chunk-JFUKVWSO.js → chunk-R7MEVVA4.js} +115 -32
- package/dist/chunk-R7MEVVA4.js.map +1 -0
- package/dist/client.d.ts +25 -0
- package/dist/client.js +16 -0
- package/dist/client.js.map +1 -0
- package/dist/file-router/index.d.ts +95 -1
- package/dist/file-router/index.js +1 -1
- package/dist/index.js +17 -17
- package/dist/middleware/index.d.ts +163 -10
- package/dist/middleware/index.js +1 -1
- package/dist/rsc/index.d.ts +211 -6
- package/dist/rsc/index.js +6 -6
- package/dist/rsc/legacy.d.ts +26 -2
- package/dist/rsc/legacy.js +1 -1
- package/dist/server/index.js +2 -2
- package/package.json +21 -3
- package/dist/chunk-2R23X5Z3.js.map +0 -1
- package/dist/chunk-JFUKVWSO.js.map +0 -1
- package/dist/chunk-UGTETAJ2.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rsc/legacy.ts"],"names":[],"mappings":"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","file":"chunk-2R23X5Z3.js","sourcesContent":["/**\n * @flight-framework/core - Legacy RSC Support\n * \n * Backward compatibility module for the original RSC implementation.\n * Use the new API from './index.js' for new features.\n * \n * @deprecated Use the new RSC API instead\n * @module @flight-framework/core/rsc/legacy\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Component rendering context\n * @deprecated Use ServerContext from './context.js' instead\n */\nexport interface RenderContext {\n /** Current request */\n request: Request;\n /** Route params */\n params: Record<string, string>;\n /** Search params */\n searchParams: URLSearchParams;\n /** Request headers */\n headers: Headers;\n /** Cookies */\n cookies: Map<string, string>;\n}\n\n/**\n * Server component definition\n * @deprecated Use ServerComponentFn from './index.js' instead\n */\nexport interface ServerComponent<P = unknown> {\n (props: P, context: RenderContext): Promise<string> | string;\n /** Mark as server component */\n __flight_server?: true;\n /** Dependencies for hydration */\n __flight_deps?: string[];\n}\n\n/**\n * Client component definition\n * @deprecated Use ClientReference from './boundaries.js' instead\n */\nexport interface ClientComponent<P = unknown> {\n (props: P): unknown;\n /** Mark as client component */\n __flight_client?: true;\n /** Client bundle path */\n __flight_bundle?: string;\n}\n\n/**\n * Component type detection\n */\nexport type ComponentType = 'server' | 'client' | 'hybrid';\n\n// ============================================================================\n// Server Component Execution\n// ============================================================================\n\n/**\n * Execute an async server component\n * @deprecated Use the new rendering pipeline instead\n */\nexport async function executeServerComponent<P>(\n component: ServerComponent<P>,\n props: P,\n context: RenderContext\n): Promise<string> {\n try {\n const result = await component(props, context);\n return result;\n } catch (error) {\n console.error('[Flight] Server component error:', error);\n throw error;\n }\n}\n\n/**\n * Create a render context from a Request\n * @deprecated Use createServerContext from './context.js' instead\n */\nexport function createRenderContext(request: Request, params: Record<string, string> = {}): RenderContext {\n const url = new URL(request.url);\n\n // Parse cookies\n const cookies = new Map<string, string>();\n const cookieHeader = request.headers.get('cookie') || '';\n cookieHeader.split(';').forEach(cookie => {\n const [key, value] = cookie.trim().split('=');\n if (key && value) cookies.set(key, value);\n });\n\n return {\n request,\n params,\n searchParams: url.searchParams,\n headers: request.headers,\n cookies,\n };\n}\n\n// ============================================================================\n// Data Fetching Helpers\n// ============================================================================\n\n/**\n * Cache for server-side fetch requests\n */\nconst fetchCache = new Map<string, { data: unknown; timestamp: number }>();\n\n/**\n * Server-side fetch with automatic caching\n */\nexport async function serverFetch<T>(\n url: string,\n options: RequestInit & {\n revalidate?: number | false;\n tags?: string[];\n } = {}\n): Promise<T> {\n const { revalidate = 60, ...fetchOptions } = options;\n const cacheKey = `${url}:${JSON.stringify(fetchOptions)}`;\n\n // Check cache\n const cached = fetchCache.get(cacheKey);\n if (cached) {\n const age = Date.now() - cached.timestamp;\n if (revalidate === false || age < (revalidate * 1000)) {\n return cached.data as T;\n }\n }\n\n // Fetch fresh data\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n // Cache the result\n if (revalidate !== false) {\n fetchCache.set(cacheKey, {\n data,\n timestamp: Date.now(),\n });\n }\n\n return data as T;\n}\n\n/**\n * Invalidate cache by tag\n */\nexport function revalidateTag(tag: string): void {\n console.log(`[Flight] Revalidating tag: ${tag}`);\n}\n\n/**\n * Invalidate cache by path\n */\nexport function revalidatePath(path: string): void {\n console.log(`[Flight] Revalidating path: ${path}`);\n}\n\n// ============================================================================\n// Component Serialization\n// ============================================================================\n\n/**\n * Serialize props for transmission to client\n * @deprecated Use serialize from './payload.js' instead\n */\nexport function serializeProps(props: unknown): string {\n function preProcess(value: unknown): unknown {\n if (value instanceof Date) {\n return { __type: 'Date', value: value.toISOString() };\n }\n if (value instanceof Map) {\n return { __type: 'Map', value: Array.from(value.entries()).map(([k, v]) => [preProcess(k), preProcess(v)]) };\n }\n if (value instanceof Set) {\n return { __type: 'Set', value: Array.from(value).map(preProcess) };\n }\n if (typeof value === 'bigint') {\n return { __type: 'BigInt', value: value.toString() };\n }\n if (typeof value === 'function') {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map(preProcess);\n }\n if (value && typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n result[k] = preProcess(v);\n }\n return result;\n }\n return value;\n }\n\n return JSON.stringify(preProcess(props));\n}\n\n/**\n * Deserialize props on client\n * @deprecated Use deserialize from './payload.js' instead\n */\nexport function deserializeProps<T>(serialized: string): T {\n return JSON.parse(serialized, (_key, value) => {\n if (value && typeof value === 'object' && '__type' in value) {\n switch (value.__type) {\n case 'Date':\n return new Date(value.value);\n case 'Map':\n return new Map(value.value);\n case 'Set':\n return new Set(value.value);\n case 'BigInt':\n return BigInt(value.value);\n }\n }\n return value;\n });\n}\n\n// ============================================================================\n// Client Component Boundary\n// ============================================================================\n\n/**\n * Create a client boundary placeholder\n * @deprecated Use clientRef from './payload.js' instead\n */\nexport function createClientBoundary(\n componentId: string,\n props: unknown,\n fallback?: string\n): string {\n const serializedProps = serializeProps(props);\n\n return `\n<!--flight-client:${componentId}-->\n<div data-flight-component=\"${componentId}\" data-flight-props='${serializedProps.replace(/'/g, \"'\")}'>\n ${fallback || '<div>Loading...</div>'}\n</div>\n<!--/flight-client-->\n<script type=\"module\">\n(async function() {\n const component = await import('/_flight/components/${componentId}.js');\n const props = JSON.parse('${serializedProps.replace(/'/g, \"\\\\'\")}');\n const container = document.querySelector('[data-flight-component=\"${componentId}\"]');\n if (container && component.default) {\n if (typeof component.hydrate === 'function') {\n component.hydrate(container, props);\n }\n }\n})();\n</script>`;\n}\n\n// ============================================================================\n// Async Component Helpers\n// ============================================================================\n\n/**\n * Helper to create an async server component\n * @deprecated Use async Server Components directly\n */\nexport function createAsyncComponent<P, T>(\n fetcher: (props: P, context: RenderContext) => Promise<T>,\n renderer: (data: T, props: P) => string\n): ServerComponent<P> {\n const component: ServerComponent<P> = async (props, context) => {\n const data = await fetcher(props, context);\n return renderer(data, props);\n };\n component.__flight_server = true;\n return component;\n}\n\n/**\n * Compose multiple server components\n * @deprecated Use Promise.all with async components\n */\nexport function composeComponents(\n ...components: Array<() => Promise<string> | string>\n): () => Promise<string> {\n return async () => {\n const results = await Promise.all(\n components.map(async (comp) => await comp())\n );\n return results.join('');\n };\n}\n\n// ============================================================================\n// Error Boundary for Server Components\n// ============================================================================\n\n/**\n * Wrap a server component with error handling\n * @deprecated Use try/catch in async components\n */\nexport function withErrorBoundary<P>(\n component: ServerComponent<P>,\n errorFallback: (error: Error) => string\n): ServerComponent<P> {\n return async (props: P, context: RenderContext) => {\n try {\n return await component(props, context);\n } catch (error) {\n console.error('[Flight] Server component error:', error);\n return errorFallback(error as Error);\n }\n };\n}\n\n// ============================================================================\n// Not Found / Redirect Helpers\n// ============================================================================\n\n/**\n * Throw a not found error\n * @deprecated Use notFound from './context.js' instead\n */\nexport function notFound(): never {\n const error = new Error('Not Found');\n (error as Error & { __flight_not_found: boolean }).__flight_not_found = true;\n throw error;\n}\n\n/**\n * Check if error is not found\n * @deprecated Use isNotFoundError from './context.js' instead\n */\nexport function isNotFoundError(error: unknown): boolean {\n return error instanceof Error && (error as Error & { __flight_not_found?: boolean }).__flight_not_found === true;\n}\n\n/**\n * Server-side redirect\n * @deprecated Use redirect from './context.js' instead\n */\nexport function redirect(url: string, type: 'replace' | 'push' = 'replace'): never {\n const error = new Error(`Redirect: ${url}`);\n (error as Error & { __flight_redirect: { url: string; type: string } }).__flight_redirect = { url, type };\n throw error;\n}\n\n/**\n * Check if error is redirect\n * @deprecated Use isRedirectError from './context.js' instead\n */\nexport function isRedirectError(error: unknown): { url: string; type: string } | null {\n if (error instanceof Error && (error as Error & { __flight_redirect?: unknown }).__flight_redirect) {\n return (error as Error & { __flight_redirect: { url: string; type: string } }).__flight_redirect;\n }\n return null;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware/index.ts"],"names":[],"mappings":"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","file":"chunk-JFUKVWSO.js","sourcesContent":["/**\n * Flight Middleware - Composable request/response handlers\n * \n * Framework-agnostic middleware system inspired by Koa/Hono.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Request context passed through middleware chain */\nexport interface MiddlewareContext {\n /** Request URL */\n url: URL;\n /** Request method */\n method: string;\n /** Request headers */\n headers: Headers;\n /** URL parameters from routing */\n params: Record<string, string | string[]>;\n /** Query parameters */\n query: URLSearchParams;\n /** Parsed request body (if any) */\n body?: unknown;\n /** Local data shared between middleware */\n locals: Record<string, unknown>;\n /** Original request (platform-specific) */\n request?: Request;\n\n // Response building\n /** Response status code */\n status: number;\n /** Response headers */\n responseHeaders: Headers;\n /** Response body */\n responseBody?: BodyInit | null;\n}\n\n/** Next function to call the next middleware */\nexport type MiddlewareNext = () => Promise<void>;\n\n/** Middleware function signature */\nexport type Middleware = (\n ctx: MiddlewareContext,\n next: MiddlewareNext\n) => Promise<void> | void;\n\n/** Middleware with optional path matching */\nexport interface MiddlewareDefinition {\n /** Path pattern to match (undefined = match all) */\n path?: string | RegExp;\n /** HTTP methods to match (undefined = match all) */\n methods?: string[];\n /** The middleware function */\n handler: Middleware;\n}\n\n// ============================================================================\n// Middleware Chain\n// ============================================================================\n\nexport interface MiddlewareChain {\n /** Add middleware to the chain */\n use(middleware: Middleware): MiddlewareChain;\n use(path: string, middleware: Middleware): MiddlewareChain;\n use(definition: MiddlewareDefinition): MiddlewareChain;\n\n /** Execute the middleware chain */\n execute(ctx: MiddlewareContext): Promise<void>;\n\n /** Get all middleware definitions */\n middlewares(): MiddlewareDefinition[];\n}\n\n/**\n * Create a new middleware chain\n */\nexport function createMiddlewareChain(): MiddlewareChain {\n const stack: MiddlewareDefinition[] = [];\n\n function use(\n pathOrMiddleware: string | Middleware | MiddlewareDefinition,\n maybeMiddleware?: Middleware\n ): MiddlewareChain {\n if (typeof pathOrMiddleware === 'function') {\n // use(middleware)\n stack.push({ handler: pathOrMiddleware });\n } else if (typeof pathOrMiddleware === 'string' && maybeMiddleware) {\n // use(path, middleware)\n stack.push({ path: pathOrMiddleware, handler: maybeMiddleware });\n } else if (typeof pathOrMiddleware === 'object') {\n // use(definition)\n stack.push(pathOrMiddleware);\n }\n return chain;\n }\n\n async function execute(ctx: MiddlewareContext): Promise<void> {\n let index = -1;\n\n async function dispatch(i: number): Promise<void> {\n if (i <= index) {\n throw new Error('next() called multiple times');\n }\n index = i;\n\n if (i >= stack.length) {\n return;\n }\n\n const definition = stack[i];\n if (!definition) {\n return dispatch(i + 1);\n }\n\n // Check if middleware should run\n if (!shouldRun(definition, ctx)) {\n return dispatch(i + 1);\n }\n\n await definition.handler(ctx, () => dispatch(i + 1));\n }\n\n await dispatch(0);\n }\n\n const chain: MiddlewareChain = {\n use: use as MiddlewareChain['use'],\n execute,\n middlewares: () => [...stack],\n };\n\n return chain;\n}\n\n/**\n * Check if a middleware should run for the given context\n */\nfunction shouldRun(def: MiddlewareDefinition, ctx: MiddlewareContext): boolean {\n // Check method\n if (def.methods && !def.methods.includes(ctx.method.toUpperCase())) {\n return false;\n }\n\n // Check path\n if (def.path) {\n const path = ctx.url.pathname;\n\n if (typeof def.path === 'string') {\n // Simple path matching (supports wildcards)\n if (def.path.endsWith('*')) {\n const prefix = def.path.slice(0, -1);\n if (!path.startsWith(prefix)) {\n return false;\n }\n } else if (def.path !== path) {\n return false;\n }\n } else if (def.path instanceof RegExp) {\n if (!def.path.test(path)) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n// ============================================================================\n// Built-in Middleware Factories\n// ============================================================================\n\n/**\n * CORS middleware factory\n */\nexport function cors(options: {\n origin?: string | string[] | ((origin: string) => boolean);\n methods?: string[];\n headers?: string[];\n credentials?: boolean;\n maxAge?: number;\n} = {}): Middleware {\n const {\n origin = '*',\n methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],\n headers = ['Content-Type', 'Authorization'],\n credentials = false,\n maxAge = 86400,\n } = options;\n\n return async (ctx, next) => {\n const requestOrigin = ctx.headers.get('Origin') || '';\n\n // Determine allowed origin\n let allowedOrigin: string | null = null;\n if (origin === '*') {\n allowedOrigin = '*';\n } else if (typeof origin === 'string') {\n allowedOrigin = origin;\n } else if (Array.isArray(origin)) {\n if (origin.includes(requestOrigin)) {\n allowedOrigin = requestOrigin;\n }\n } else if (typeof origin === 'function') {\n if (origin(requestOrigin)) {\n allowedOrigin = requestOrigin;\n }\n }\n\n if (allowedOrigin) {\n ctx.responseHeaders.set('Access-Control-Allow-Origin', allowedOrigin);\n ctx.responseHeaders.set('Access-Control-Allow-Methods', methods.join(', '));\n ctx.responseHeaders.set('Access-Control-Allow-Headers', headers.join(', '));\n\n if (credentials) {\n ctx.responseHeaders.set('Access-Control-Allow-Credentials', 'true');\n }\n\n if (maxAge) {\n ctx.responseHeaders.set('Access-Control-Max-Age', String(maxAge));\n }\n }\n\n // Handle preflight\n if (ctx.method === 'OPTIONS') {\n ctx.status = 204;\n ctx.responseBody = null;\n return;\n }\n\n await next();\n };\n}\n// ============================================================================\n// Logger Types and Constants\n// ============================================================================\n\n/** Log levels in order of verbosity */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\n/** Log format types */\nexport type LogFormat = 'pretty' | 'json' | 'combined' | 'common' | 'short' | 'tiny';\n\n/** Log entry structure for JSON format */\nexport interface LogEntry {\n timestamp: string;\n level: LogLevel;\n method: string;\n path: string;\n status: number;\n duration: number;\n userAgent?: string;\n ip?: string;\n [key: string]: unknown;\n}\n\n/** Custom log writer function */\nexport type LogWriter = (entry: LogEntry, formatted: string) => void;\n\n/** Logger options */\nexport interface LoggerOptions {\n /** Minimum log level (default: 'info') */\n level?: LogLevel;\n /** Output format (default: 'pretty') */\n format?: LogFormat;\n /** Skip logging for certain requests */\n skip?: (ctx: MiddlewareContext) => boolean;\n /** Custom log writer (replaces console output) */\n writer?: LogWriter;\n /** Include request headers in logs */\n includeHeaders?: boolean;\n /** Colorize output (only for 'pretty' format, default: true) */\n colorize?: boolean;\n}\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nconst LOG_LEVEL_COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m', // Cyan\n info: '\\x1b[32m', // Green\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n silent: '',\n};\n\nconst STATUS_COLORS: Record<string, string> = {\n '2': '\\x1b[32m', // Green for 2xx\n '3': '\\x1b[36m', // Cyan for 3xx\n '4': '\\x1b[33m', // Yellow for 4xx\n '5': '\\x1b[31m', // Red for 5xx\n};\n\nconst RESET = '\\x1b[0m';\nconst DIM = '\\x1b[2m';\n\n/**\n * Professional logger middleware with configurable levels\n * \n * @example\n * ```typescript\n * // Basic usage\n * server.use(logger());\n * \n * // With level control\n * server.use(logger({ level: 'warn' })); // Only warn and error\n * \n * // JSON format for production/observability\n * server.use(logger({ format: 'json', level: 'info' }));\n * \n * // Custom writer (e.g., for external logging service)\n * server.use(logger({\n * writer: (entry) => myLoggingService.log(entry)\n * }));\n * \n * // Silent in production\n * server.use(logger({ level: process.env.NODE_ENV === 'production' ? 'error' : 'debug' }));\n * ```\n */\nexport function logger(options: LoggerOptions = {}): Middleware {\n const {\n level = 'info',\n format = 'pretty',\n skip,\n writer,\n includeHeaders = false,\n colorize = true,\n } = options;\n\n return async (ctx, next) => {\n // Skip if configured\n if (skip?.(ctx)) {\n return next();\n }\n\n const start = Date.now();\n const startTime = new Date().toISOString();\n\n await next();\n\n const duration = Date.now() - start;\n const status = ctx.status;\n\n // Determine log level based on status\n let logLevel: LogLevel = 'info';\n if (status >= 500) {\n logLevel = 'error';\n } else if (status >= 400) {\n logLevel = 'warn';\n } else if (status >= 300) {\n logLevel = 'info';\n } else {\n logLevel = 'debug';\n }\n\n // Check if we should log based on level\n if (LOG_LEVEL_PRIORITY[logLevel] < LOG_LEVEL_PRIORITY[level]) {\n return;\n }\n\n // Build log entry\n const entry: LogEntry = {\n timestamp: startTime,\n level: logLevel,\n method: ctx.method,\n path: ctx.url.pathname,\n status,\n duration,\n };\n\n // Add optional fields\n const userAgent = ctx.headers.get('user-agent');\n if (userAgent) entry.userAgent = userAgent;\n\n const forwardedFor = ctx.headers.get('x-forwarded-for');\n const ip = forwardedFor || 'unknown';\n entry.ip = ip;\n\n if (includeHeaders) {\n const headers: Record<string, string> = {};\n ctx.headers.forEach((value, key) => {\n if (!key.toLowerCase().includes('authorization')) {\n headers[key] = value;\n }\n });\n entry.headers = headers;\n }\n\n // Format the log line\n let formatted: string;\n\n switch (format) {\n case 'json':\n formatted = JSON.stringify(entry);\n break;\n\n case 'combined':\n formatted = `${ip} - - [${startTime}] \"${ctx.method} ${ctx.url.pathname}\" ${status} - \"${userAgent || '-'}\"`;\n break;\n\n case 'common':\n formatted = `${ip} - - [${startTime}] \"${ctx.method} ${ctx.url.pathname}\" ${status}`;\n break;\n\n case 'short':\n formatted = `${ctx.method} ${ctx.url.pathname} ${status} ${duration}ms`;\n break;\n\n case 'tiny':\n formatted = `${ctx.method} ${ctx.url.pathname} ${status}`;\n break;\n\n case 'pretty':\n default:\n if (colorize) {\n const statusFirstChar = String(status).charAt(0) || '2';\n const statusColor = STATUS_COLORS[statusFirstChar] ?? '';\n const levelColor = LOG_LEVEL_COLORS[logLevel];\n formatted = `${DIM}${startTime}${RESET} ${levelColor}${logLevel.toUpperCase().padEnd(5)}${RESET} ${ctx.method.padEnd(7)} ${ctx.url.pathname} ${statusColor}${status}${RESET} ${DIM}${duration}ms${RESET}`;\n } else {\n formatted = `${startTime} ${logLevel.toUpperCase().padEnd(5)} ${ctx.method.padEnd(7)} ${ctx.url.pathname} ${status} ${duration}ms`;\n }\n break;\n }\n\n // Output\n if (writer) {\n writer(entry, formatted);\n } else {\n switch (logLevel) {\n case 'error':\n console.error(formatted);\n break;\n case 'warn':\n console.warn(formatted);\n break;\n case 'debug':\n console.debug(formatted);\n break;\n default:\n console.log(formatted);\n }\n }\n };\n}\n\n/**\n * Security headers middleware\n */\nexport function securityHeaders(options: {\n contentSecurityPolicy?: string | false;\n xFrameOptions?: 'DENY' | 'SAMEORIGIN' | false;\n xContentTypeOptions?: boolean;\n referrerPolicy?: string;\n permissionsPolicy?: string;\n} = {}): Middleware {\n const {\n contentSecurityPolicy = \"default-src 'self'\",\n xFrameOptions = 'DENY',\n xContentTypeOptions = true,\n referrerPolicy = 'strict-origin-when-cross-origin',\n permissionsPolicy,\n } = options;\n\n return async (ctx, next) => {\n if (contentSecurityPolicy) {\n ctx.responseHeaders.set('Content-Security-Policy', contentSecurityPolicy);\n }\n if (xFrameOptions) {\n ctx.responseHeaders.set('X-Frame-Options', xFrameOptions);\n }\n if (xContentTypeOptions) {\n ctx.responseHeaders.set('X-Content-Type-Options', 'nosniff');\n }\n if (referrerPolicy) {\n ctx.responseHeaders.set('Referrer-Policy', referrerPolicy);\n }\n if (permissionsPolicy) {\n ctx.responseHeaders.set('Permissions-Policy', permissionsPolicy);\n }\n\n await next();\n };\n}\n\n/**\n * Compression middleware (requires implementation in adapter)\n */\nexport function compress(): Middleware {\n return async (ctx, next) => {\n // Mark that compression is desired\n ctx.locals['flight:compress'] = true;\n await next();\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Create a middleware context from a Web Request\n */\nexport function createContextFromRequest(\n request: Request,\n params: Record<string, string | string[]> = {}\n): MiddlewareContext {\n const url = new URL(request.url);\n\n return {\n url,\n method: request.method,\n headers: request.headers,\n params,\n query: url.searchParams,\n locals: {},\n request,\n status: 200,\n responseHeaders: new Headers(),\n };\n}\n\n/**\n * Create a Web Response from middleware context\n */\nexport function createResponseFromContext(ctx: MiddlewareContext): Response {\n return new Response(ctx.responseBody, {\n status: ctx.status,\n headers: ctx.responseHeaders,\n });\n}\n\n/**\n * Compose multiple middleware into one\n */\nexport function compose(...middlewares: Middleware[]): Middleware {\n return async (ctx, next) => {\n let index = -1;\n\n async function dispatch(i: number): Promise<void> {\n if (i <= index) {\n throw new Error('next() called multiple times');\n }\n index = i;\n\n const fn = i === middlewares.length ? next : middlewares[i];\n\n if (fn) {\n await fn(ctx, () => dispatch(i + 1));\n }\n }\n\n await dispatch(0);\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/file-router/index.ts"],"names":[],"mappings":"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","file":"chunk-UGTETAJ2.js","sourcesContent":["/**\n * @flight-framework/core - File Router\n * \n * Auto-discovery of routes from file system.\n * Similar to Next.js App Router and Nuxt server/api patterns.\n */\n\nimport { readdir } from 'node:fs/promises';\nimport { join, basename, extname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\n\nexport type Handler = (context: unknown) => Response | Promise<Response>;\nexport type Middleware = (context: unknown, next: () => Promise<Response>) => Response | Promise<Response>;\n\nexport interface FileRoute {\n /** HTTP method (GET, POST, etc) or 'ALL' */\n method: HttpMethod | 'ALL';\n /** Route path with params (e.g., /users/:id) */\n path: string;\n /** Original file path */\n filePath: string;\n /** Handler function (for APIs) */\n handler?: Handler;\n /** Route-specific middleware */\n middleware?: Middleware[];\n /** Route type: 'page' for SSR pages, 'api' for API endpoints */\n type: 'page' | 'api';\n /** Component function (for pages) */\n component?: () => unknown;\n /** Page metadata (title, description, etc) */\n meta?: Record<string, unknown>;\n /** Parallel route slot name (for @folder convention) */\n slot?: string;\n /** Intercepting route info (for (.) (..) (...) convention) */\n interceptInfo?: {\n /** Number of levels to intercept: 1 = same, 2 = parent, 3+ = root */\n level: number;\n /** Target route segment to intercept */\n target: string;\n /** Original path that triggers interception */\n interceptPath: string;\n };\n}\n\nexport interface FileRouterOptions {\n /** Root directory to scan (default: src/routes) */\n directory: string;\n /** File extensions to consider (default: ['.ts', '.js']) */\n extensions?: string[];\n /** Whether to watch for changes (default: false in prod) */\n watch?: boolean;\n /** \n * Custom module loader for development with Vite.\n * Pass vite.ssrLoadModule to load TSX files correctly.\n * Falls back to native import() if not provided.\n */\n moduleLoader?: (filePath: string) => Promise<any>;\n}\n\nexport interface ScanResult {\n routes: FileRoute[];\n errors: string[];\n}\n\n// ============================================================================\n// File Scanner\n// ============================================================================\n\n/**\n * Scan a directory for route files\n */\nexport async function scanRoutes(options: FileRouterOptions): Promise<ScanResult> {\n const {\n directory,\n extensions = ['.ts', '.js'],\n } = options;\n\n const routes: FileRoute[] = [];\n const errors: string[] = [];\n\n async function scanDir(dir: string, basePath: string = ''): Promise<void> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Skip hidden directories and node_modules\n if (entry.name.startsWith('.') || entry.name === 'node_modules') {\n continue;\n }\n\n // Detect parallel route slots (@folder convention)\n if (entry.name.startsWith('@')) {\n const slotName = entry.name.slice(1);\n // Scan slot directory and mark routes with slot name\n const slotRoutes = await scanSlotDir(fullPath, basePath, slotName, extensions);\n routes.push(...slotRoutes);\n continue;\n }\n\n // Detect intercepting routes ((.) (..) (...) convention)\n const interceptMatch = entry.name.match(/^\\((\\.+)\\)(.+)$/);\n if (interceptMatch) {\n const level = interceptMatch[1].length;\n const targetSegment = interceptMatch[2];\n // Scan intercept directory and mark routes with interceptInfo\n const interceptRoutes = await scanInterceptDir(\n fullPath,\n basePath,\n level,\n targetSegment,\n extensions\n );\n routes.push(...interceptRoutes);\n continue;\n }\n\n // Recurse into subdirectory\n await scanDir(fullPath, `${basePath}/${entry.name}`);\n } else if (entry.isFile()) {\n const ext = extname(entry.name);\n\n if (!extensions.includes(ext)) {\n continue;\n }\n\n // Parse route from filename\n const routeInfo = parseRouteFile(entry.name, basePath);\n\n if (routeInfo && routeInfo.method && routeInfo.path) {\n routes.push({\n method: routeInfo.method,\n path: routeInfo.path,\n filePath: fullPath,\n type: routeInfo.type,\n });\n }\n }\n }\n } catch (error) {\n errors.push(`Failed to scan ${dir}: ${error}`);\n }\n }\n\n await scanDir(directory);\n\n return { routes, errors };\n}\n\n/**\n * Scan a parallel route slot directory\n */\nasync function scanSlotDir(\n dir: string,\n basePath: string,\n slotName: string,\n extensions: string[] = ['.ts', '.js', '.tsx', '.jsx']\n): Promise<FileRoute[]> {\n const routes: FileRoute[] = [];\n\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isFile()) {\n const ext = extname(entry.name);\n\n if (!extensions.includes(ext)) {\n continue;\n }\n\n const routeInfo = parseRouteFile(entry.name, basePath);\n\n if (routeInfo && routeInfo.method && routeInfo.path) {\n routes.push({\n method: routeInfo.method,\n path: routeInfo.path,\n filePath: fullPath,\n type: routeInfo.type,\n slot: slotName,\n });\n }\n }\n }\n } catch (error) {\n console.error(`[Flight] Failed to scan slot @${slotName}:`, error);\n }\n\n return routes;\n}\n\n/**\n * Scan an intercepting route directory\n * Uses (.) (..) (...) convention similar to Next.js\n * - (.)segment - intercepts from same level\n * - (..)segment - intercepts from parent level\n * - (...)segment - intercepts from root\n */\nasync function scanInterceptDir(\n dir: string,\n basePath: string,\n level: number,\n targetSegment: string,\n extensions: string[] = ['.ts', '.js', '.tsx', '.jsx']\n): Promise<FileRoute[]> {\n const routes: FileRoute[] = [];\n\n // Calculate the intercept path based on level\n const pathParts = basePath.split('/').filter(Boolean);\n let interceptPath: string;\n\n if (level === 1) {\n // (.) - Same level, intercepts sibling route\n interceptPath = `${basePath}/${targetSegment}`;\n } else if (level === 2) {\n // (..) - Parent level\n pathParts.pop();\n interceptPath = `/${pathParts.join('/')}/${targetSegment}`;\n } else {\n // (...) - Root level (3 or more dots)\n interceptPath = `/${targetSegment}`;\n }\n\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isFile()) {\n const ext = extname(entry.name);\n\n if (!extensions.includes(ext)) {\n continue;\n }\n\n const routeInfo = parseRouteFile(entry.name, basePath);\n\n if (routeInfo && routeInfo.method && routeInfo.path) {\n routes.push({\n method: routeInfo.method,\n path: routeInfo.path,\n filePath: fullPath,\n type: routeInfo.type,\n interceptInfo: {\n level,\n target: targetSegment,\n interceptPath: interceptPath.replace(/\\/+/g, '/') || '/',\n },\n });\n }\n } else if (entry.isDirectory()) {\n // Recurse into subdirectories within intercept folder\n const subRoutes = await scanInterceptDir(\n fullPath,\n `${basePath}/${entry.name}`,\n level,\n targetSegment,\n extensions\n );\n routes.push(...subRoutes);\n }\n }\n } catch (error) {\n console.error(`[Flight] Failed to scan intercept (${'.'.repeat(level)})${targetSegment}:`, error);\n }\n\n return routes;\n}\n\n// ============================================================================\n// Route Parser\n// ============================================================================\n\ninterface ParsedRoute {\n method: HttpMethod | 'ALL';\n path: string;\n type: 'page' | 'api';\n}\n\n/**\n * Parse route information from filename and path\n * \n * Patterns:\n * - index.ts → /\n * - users.ts → /users\n * - users.get.ts → GET /users (API)\n * - users.post.ts → POST /users (API)\n * - about.page.tsx → GET /about (Page)\n * - blog/[slug].page.tsx → GET /blog/:slug (Page)\n * - [id].ts → /:id\n * - [...slug].ts → /* (catch-all)\n * - [[...slug]].ts → /* (optional catch-all)\n */\nfunction parseRouteFile(filename: string, basePath: string): ParsedRoute | null {\n const ext = extname(filename);\n const nameWithoutExt = basename(filename, ext);\n\n // Skip files starting with underscore (private)\n if (nameWithoutExt.startsWith('_')) {\n return null;\n }\n\n // Detect route type\n let type: 'page' | 'api' = 'api';\n let routeName = nameWithoutExt;\n let method: HttpMethod | 'ALL' = 'ALL';\n\n // Check for page suffix (e.g., about.page.tsx, index.page.tsx)\n const pageMatch = nameWithoutExt.match(/^(.+)?\\.page$/i);\n if (pageMatch) {\n type = 'page';\n method = 'GET'; // Pages are always GET\n routeName = pageMatch[1] || 'index';\n } else {\n // Check for method suffix (e.g., users.get.ts)\n const methodMatch = nameWithoutExt.match(/^(.+)\\.(get|post|put|delete|patch|head|options)$/i);\n if (methodMatch) {\n routeName = methodMatch[1] || nameWithoutExt;\n method = (methodMatch[2] || 'ALL').toUpperCase() as HttpMethod;\n }\n }\n\n // Also check if file is in /api/ directory\n if (basePath.startsWith('/api') || basePath.includes('/api/')) {\n type = 'api';\n }\n\n // Build route path\n let path = basePath;\n\n if (routeName !== 'index') {\n path = `${basePath}/${convertToRoutePath(routeName)}`;\n }\n\n // Ensure path starts with /\n if (!path.startsWith('/')) {\n path = '/' + path;\n }\n\n // Remove trailing slash (except for root)\n if (path !== '/' && path.endsWith('/')) {\n path = path.slice(0, -1);\n }\n\n return { method, path, type };\n}\n\n/**\n * Convert filename segment to route path segment\n * \n * - [id] → :id\n * - [...slug] → *\n * - [[...slug]] → *?\n */\nfunction convertToRoutePath(name: string): string {\n // Optional catch-all: [[...slug]]\n if (name.startsWith('[[...') && name.endsWith(']]')) {\n const paramName = name.slice(5, -2);\n return `:${paramName}*`;\n }\n\n // Catch-all: [...slug]\n if (name.startsWith('[...') && name.endsWith(']')) {\n const paramName = name.slice(4, -1);\n return `:${paramName}+`;\n }\n\n // Dynamic param: [id]\n if (name.startsWith('[') && name.endsWith(']')) {\n const paramName = name.slice(1, -1);\n return `:${paramName}`;\n }\n\n return name;\n}\n\n// ============================================================================\n// Route Loader\n// ============================================================================\n\n/**\n * Load routes with their handlers or components\n * @param scanResult - Result from scanRoutes\n * @param moduleLoader - Optional custom loader (use vite.ssrLoadModule for dev)\n */\nexport async function loadRoutes(\n scanResult: ScanResult,\n moduleLoader?: (filePath: string) => Promise<any>\n): Promise<FileRoute[]> {\n const loadedRoutes: FileRoute[] = [];\n\n for (const route of scanResult.routes) {\n try {\n // Use custom loader if provided (Vite ssrLoadModule for TSX)\n // Otherwise fall back to native import() for production\n let module: any;\n if (moduleLoader) {\n module = await moduleLoader(route.filePath);\n } else {\n // Convert to file:// URL for Windows ESM compatibility\n const fileUrl = pathToFileURL(route.filePath).href;\n module = await import(fileUrl);\n }\n\n // Handle PAGE routes\n if (route.type === 'page') {\n // Pages export default component\n const component = module.default;\n const meta = module.meta || module.metadata || {};\n\n if (component) {\n loadedRoutes.push({\n ...route,\n component,\n meta,\n });\n }\n continue;\n }\n\n // Handle API routes\n if (route.method === 'ALL') {\n // Look for named exports: GET, POST, PUT, DELETE, etc\n const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];\n\n for (const method of methods) {\n if (typeof module[method] === 'function') {\n loadedRoutes.push({\n ...route,\n method,\n handler: module[method],\n });\n }\n }\n\n // Also check for default export as handler\n if (typeof module.default === 'function') {\n loadedRoutes.push({\n ...route,\n method: 'ALL',\n handler: module.default,\n });\n }\n } else {\n // Specific method from filename suffix\n const handler = module[route.method] || module.default;\n\n if (typeof handler === 'function') {\n loadedRoutes.push({\n ...route,\n handler,\n });\n }\n }\n } catch (error) {\n console.error(`[Flight] Failed to load route ${route.filePath}:`, error);\n }\n }\n\n return loadedRoutes;\n}\n\n// ============================================================================\n// File Router Factory\n// ============================================================================\n\nexport interface FileRouter {\n routes: FileRoute[];\n refresh: () => Promise<void>;\n}\n\n/**\n * Create a file-based router\n * \n * @example\n * ```typescript\n * import { createFileRouter } from '@flight-framework/core/file-router';\n * import { createServer } from '@flight-framework/http';\n * \n * const router = await createFileRouter({ directory: './src/routes' });\n * const app = createServer();\n * \n * // Register all discovered routes\n * for (const route of router.routes) {\n * app[route.method.toLowerCase()](route.path, route.handler);\n * }\n * ```\n */\nexport async function createFileRouter(options: FileRouterOptions): Promise<FileRouter> {\n let routes: FileRoute[] = [];\n const { moduleLoader } = options;\n\n async function refresh(): Promise<void> {\n const scanResult = await scanRoutes(options);\n\n if (scanResult.errors.length > 0) {\n console.warn('[Flight] Route scan errors:', scanResult.errors);\n }\n\n routes = await loadRoutes(scanResult, moduleLoader);\n\n console.log(`[Flight] Loaded ${routes.length} routes from ${options.directory}`);\n }\n\n // Initial load\n await refresh();\n\n return {\n get routes() {\n return routes;\n },\n refresh,\n };\n}\n"]}
|