@flight-framework/core 0.1.0 → 0.2.1
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/LICENSE +21 -0
- package/dist/{chunk-5KF3QQWZ.js → chunk-3ZSSRE6M.js} +5 -19
- package/dist/chunk-3ZSSRE6M.js.map +1 -0
- package/dist/chunk-4S5JWTGN.js +218 -0
- package/dist/chunk-4S5JWTGN.js.map +1 -0
- package/dist/chunk-62C7LX2E.js +205 -0
- package/dist/chunk-62C7LX2E.js.map +1 -0
- package/dist/chunk-63SCEXD7.js +3 -0
- package/dist/chunk-63SCEXD7.js.map +1 -0
- package/dist/{chunk-YIOQC3DC.js → chunk-6BDCTUQY.js} +3 -3
- package/dist/{chunk-YIOQC3DC.js.map → chunk-6BDCTUQY.js.map} +1 -1
- package/dist/chunk-6Z2RYHEU.js +212 -0
- package/dist/chunk-6Z2RYHEU.js.map +1 -0
- package/dist/chunk-HAX5OAB6.js +324 -0
- package/dist/chunk-HAX5OAB6.js.map +1 -0
- package/dist/chunk-K2CQZPCG.js +257 -0
- package/dist/chunk-K2CQZPCG.js.map +1 -0
- package/dist/chunk-N3TUOEV4.js +213 -0
- package/dist/chunk-N3TUOEV4.js.map +1 -0
- package/dist/chunk-NWMJYTMB.js +300 -0
- package/dist/chunk-NWMJYTMB.js.map +1 -0
- package/dist/chunk-OCVLNLTI.js +252 -0
- package/dist/chunk-OCVLNLTI.js.map +1 -0
- package/dist/chunk-PDW5WCMW.js +258 -0
- package/dist/chunk-PDW5WCMW.js.map +1 -0
- package/dist/chunk-PVUMB632.js +256 -0
- package/dist/chunk-PVUMB632.js.map +1 -0
- package/dist/{chunk-6WSPUG5L.js → chunk-RSVA2EYO.js} +2 -2
- package/dist/chunk-RSVA2EYO.js.map +1 -0
- package/dist/chunk-T4Z4HM4W.js +285 -0
- package/dist/chunk-T4Z4HM4W.js.map +1 -0
- package/dist/{chunk-OBNYNJB5.js → chunk-WOEIJWGJ.js} +6 -8
- package/dist/chunk-WOEIJWGJ.js.map +1 -0
- package/dist/{chunk-I2B4WSHC.js → chunk-XSY5AAXT.js} +3 -4
- package/dist/chunk-XSY5AAXT.js.map +1 -0
- package/dist/chunk-Y22AMGTM.js +3 -0
- package/dist/chunk-Y22AMGTM.js.map +1 -0
- package/dist/chunk-ZIE56LCA.js +341 -0
- package/dist/chunk-ZIE56LCA.js.map +1 -0
- package/dist/file-router/streaming-hints.d.ts +1 -1
- package/dist/file-router/streaming-hints.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +19 -7
- package/dist/index.js.map +1 -1
- package/dist/rsc/adapters/index.d.ts +8 -0
- package/dist/rsc/adapters/index.js +7 -0
- package/dist/rsc/adapters/index.js.map +1 -0
- package/dist/rsc/adapters/preact.d.ts +97 -0
- package/dist/rsc/adapters/preact.js +3 -0
- package/dist/rsc/adapters/preact.js.map +1 -0
- package/dist/rsc/adapters/react.d.ts +82 -0
- package/dist/rsc/adapters/react.js +3 -0
- package/dist/rsc/adapters/react.js.map +1 -0
- package/dist/rsc/adapters/solid.d.ts +84 -0
- package/dist/rsc/adapters/solid.js +3 -0
- package/dist/rsc/adapters/solid.js.map +1 -0
- package/dist/rsc/adapters/vue.d.ts +80 -0
- package/dist/rsc/adapters/vue.js +3 -0
- package/dist/rsc/adapters/vue.js.map +1 -0
- package/dist/rsc/boundaries.d.ts +182 -0
- package/dist/rsc/boundaries.js +3 -0
- package/dist/rsc/boundaries.js.map +1 -0
- package/dist/rsc/context.d.ts +201 -0
- package/dist/rsc/context.js +3 -0
- package/dist/rsc/context.js.map +1 -0
- package/dist/rsc/index.d.ts +20 -124
- package/dist/rsc/index.js +13 -1
- package/dist/rsc/legacy.d.ts +131 -0
- package/dist/rsc/legacy.js +3 -0
- package/dist/rsc/legacy.js.map +1 -0
- package/dist/rsc/payload.d.ts +262 -0
- package/dist/rsc/payload.js +3 -0
- package/dist/rsc/payload.js.map +1 -0
- package/dist/rsc/plugins/esbuild.d.ts +124 -0
- package/dist/rsc/plugins/esbuild.js +4 -0
- package/dist/rsc/plugins/esbuild.js.map +1 -0
- package/dist/rsc/plugins/index.d.ts +4 -0
- package/dist/rsc/plugins/index.js +6 -0
- package/dist/rsc/plugins/index.js.map +1 -0
- package/dist/rsc/plugins/rollup.d.ts +103 -0
- package/dist/rsc/plugins/rollup.js +4 -0
- package/dist/rsc/plugins/rollup.js.map +1 -0
- package/dist/rsc/renderer.d.ts +160 -0
- package/dist/rsc/renderer.js +5 -0
- package/dist/rsc/renderer.js.map +1 -0
- package/dist/rsc/stream.d.ts +129 -0
- package/dist/rsc/stream.js +3 -0
- package/dist/rsc/stream.js.map +1 -0
- package/dist/rsc/vite-plugin.d.ts +78 -0
- package/dist/rsc/vite-plugin.js +4 -0
- package/dist/rsc/vite-plugin.js.map +1 -0
- package/dist/streaming/index.js +1 -1
- package/dist/streaming/observability.js +2 -2
- package/dist/streaming/priority.js +1 -1
- package/package.json +180 -124
- package/dist/chunk-5KF3QQWZ.js.map +0 -1
- package/dist/chunk-6WSPUG5L.js.map +0 -1
- package/dist/chunk-I2B4WSHC.js.map +0 -1
- package/dist/chunk-OBNYNJB5.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createStreamingSSR } from './chunk-
|
|
1
|
+
import { createStreamingSSR } from './chunk-RSVA2EYO.js';
|
|
2
2
|
|
|
3
3
|
// src/streaming/observability.ts
|
|
4
4
|
function generateStreamId() {
|
|
@@ -278,5 +278,5 @@ function createHttpObserver(endpoint, options) {
|
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
export { MetricsAggregator, createHttpObserver, createInstrumentedStream, createLoggerObserver };
|
|
281
|
-
//# sourceMappingURL=chunk-
|
|
282
|
-
//# sourceMappingURL=chunk-
|
|
281
|
+
//# sourceMappingURL=chunk-6BDCTUQY.js.map
|
|
282
|
+
//# sourceMappingURL=chunk-6BDCTUQY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/streaming/observability.ts"],"names":[],"mappings":"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","file":"chunk-YIOQC3DC.js","sourcesContent":["/**\r\n * @flight-framework/core - Streaming Observability\r\n * \r\n * Zero-telemetry metrics and instrumentation for streaming SSR.\r\n * All data stays on YOUR infrastructure - never sent anywhere.\r\n * \r\n * Best Practices 2026:\r\n * - Comprehensive timing metrics for each boundary\r\n * - Hook-based observability for custom integrations\r\n * - Performance insights without vendor lock-in\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createInstrumentedStream } from '@flight-framework/core/streaming';\r\n * \r\n * const { stream, metrics } = await createInstrumentedStream({\r\n * shell: '<html>...',\r\n * boundaries: [...],\r\n * onMetrics: (m) => myAnalytics.track(m), // YOUR system\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { StreamingRenderOptions, SuspenseBoundaryConfig } from './index.js';\r\nimport { createStreamingSSR } from './index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Timing information for a single boundary\r\n */\r\nexport interface BoundaryTiming {\r\n /** Boundary identifier */\r\n id: string;\r\n /** When the boundary started resolving (ms since stream start) */\r\n startTime: number;\r\n /** When the boundary finished resolving */\r\n endTime: number;\r\n /** Total duration in milliseconds */\r\n duration: number;\r\n /** Whether it resolved successfully */\r\n success: boolean;\r\n /** Size of content in bytes (if successful) */\r\n contentSize?: number;\r\n /** Error message if failed */\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Overall streaming metrics\r\n */\r\nexport interface StreamingMetrics {\r\n /** Unique ID for this stream session */\r\n streamId: string;\r\n /** When streaming started */\r\n startTime: number;\r\n /** Time to shell ready (TTFB improvement) */\r\n shellTime: number;\r\n /** Time until all boundaries resolved */\r\n totalStreamTime: number;\r\n /** Individual boundary timings */\r\n boundaries: BoundaryTiming[];\r\n /** Number of boundaries that resolved successfully */\r\n successCount: number;\r\n /** Number of boundaries that failed */\r\n errorCount: number;\r\n /** Total bytes streamed */\r\n totalBytes: number;\r\n /** Strategy used (if priority streaming) */\r\n strategy?: string;\r\n /** Custom metadata you can add */\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Observability hooks for streaming events\r\n */\r\nexport interface StreamingObserver {\r\n /** Called when streaming starts */\r\n onStreamStart?: (streamId: string) => void;\r\n /** Called when shell is sent */\r\n onShellReady?: (timing: { streamId: string; duration: number }) => void;\r\n /** Called when a boundary starts resolving */\r\n onBoundaryStart?: (info: { streamId: string; boundaryId: string; startTime: number }) => void;\r\n /** Called when a boundary finishes */\r\n onBoundaryEnd?: (timing: BoundaryTiming & { streamId: string }) => void;\r\n /** Called when streaming completes */\r\n onStreamEnd?: (metrics: StreamingMetrics) => void;\r\n /** Called on any error */\r\n onError?: (error: { streamId: string; boundaryId?: string; error: Error }) => void;\r\n}\r\n\r\n/**\r\n * Configuration for instrumented streaming\r\n */\r\nexport interface InstrumentedStreamConfig {\r\n /** Initial HTML shell */\r\n shell: string;\r\n /** Closing HTML */\r\n shellEnd: string;\r\n /** Suspense boundaries */\r\n suspenseBoundaries: SuspenseBoundaryConfig[];\r\n /** Streaming options */\r\n options?: StreamingRenderOptions;\r\n /** Observer hooks */\r\n observer?: StreamingObserver;\r\n /** Callback when all metrics are ready */\r\n onMetrics?: (metrics: StreamingMetrics) => void;\r\n /** Custom metadata to include in metrics */\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Result of instrumented streaming\r\n */\r\nexport interface InstrumentedStreamResult {\r\n /** The readable stream */\r\n stream: ReadableStream<Uint8Array>;\r\n /** Abort the stream */\r\n abort: () => void;\r\n /** Shell ready promise */\r\n shellReady: Promise<void>;\r\n /** All content ready promise */\r\n allReady: Promise<void>;\r\n /** Final metrics (resolves when stream completes) */\r\n metrics: Promise<StreamingMetrics>;\r\n /** Stream ID for correlation */\r\n streamId: string;\r\n}\r\n\r\n// ============================================================================\r\n// Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Generate a unique stream ID\r\n */\r\nfunction generateStreamId(): string {\r\n return `stream_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Create an instrumented streaming SSR response with full observability\r\n */\r\nexport async function createInstrumentedStream(\r\n config: InstrumentedStreamConfig\r\n): Promise<InstrumentedStreamResult> {\r\n const {\r\n shell,\r\n shellEnd,\r\n suspenseBoundaries,\r\n options = {},\r\n observer,\r\n onMetrics,\r\n meta,\r\n } = config;\r\n\r\n const streamId = generateStreamId();\r\n const startTime = Date.now();\r\n const boundaryTimings: BoundaryTiming[] = [];\r\n const boundaryStarts = new Map<string, number>();\r\n let shellTime = 0;\r\n let totalBytes = 0;\r\n\r\n // Metrics promise\r\n let resolveMetrics: (m: StreamingMetrics) => void;\r\n const metricsPromise = new Promise<StreamingMetrics>((r) => { resolveMetrics = r; });\r\n\r\n // Notify stream start\r\n observer?.onStreamStart?.(streamId);\r\n\r\n // Wrap boundaries with instrumentation\r\n const instrumentedBoundaries: SuspenseBoundaryConfig[] = suspenseBoundaries.map(boundary => {\r\n const boundaryStart = Date.now();\r\n boundaryStarts.set(boundary.id, boundaryStart);\r\n\r\n observer?.onBoundaryStart?.({\r\n streamId,\r\n boundaryId: boundary.id,\r\n startTime: boundaryStart - startTime,\r\n });\r\n\r\n return {\r\n ...boundary,\r\n contentPromise: boundary.contentPromise.then(\r\n (content) => {\r\n const endTime = Date.now();\r\n const timing: BoundaryTiming = {\r\n id: boundary.id,\r\n startTime: boundaryStarts.get(boundary.id)! - startTime,\r\n endTime: endTime - startTime,\r\n duration: endTime - boundaryStarts.get(boundary.id)!,\r\n success: true,\r\n contentSize: new TextEncoder().encode(content).length,\r\n };\r\n boundaryTimings.push(timing);\r\n observer?.onBoundaryEnd?.({ ...timing, streamId });\r\n return content;\r\n },\r\n (error) => {\r\n const endTime = Date.now();\r\n const timing: BoundaryTiming = {\r\n id: boundary.id,\r\n startTime: boundaryStarts.get(boundary.id)! - startTime,\r\n endTime: endTime - startTime,\r\n duration: endTime - boundaryStarts.get(boundary.id)!,\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n };\r\n boundaryTimings.push(timing);\r\n observer?.onBoundaryEnd?.({ ...timing, streamId });\r\n observer?.onError?.({ streamId, boundaryId: boundary.id, error: error as Error });\r\n throw error;\r\n }\r\n ),\r\n };\r\n });\r\n\r\n // Create the underlying stream with instrumented callbacks\r\n const result = await createStreamingSSR({\r\n shell,\r\n shellEnd,\r\n suspenseBoundaries: instrumentedBoundaries,\r\n options: {\r\n ...options,\r\n onShellReady: () => {\r\n shellTime = Date.now() - startTime;\r\n observer?.onShellReady?.({ streamId, duration: shellTime });\r\n options.onShellReady?.();\r\n },\r\n onAllReady: () => {\r\n const totalStreamTime = Date.now() - startTime;\r\n\r\n const metrics: StreamingMetrics = {\r\n streamId,\r\n startTime,\r\n shellTime,\r\n totalStreamTime,\r\n boundaries: boundaryTimings,\r\n successCount: boundaryTimings.filter(b => b.success).length,\r\n errorCount: boundaryTimings.filter(b => !b.success).length,\r\n totalBytes,\r\n meta,\r\n };\r\n\r\n observer?.onStreamEnd?.(metrics);\r\n onMetrics?.(metrics);\r\n resolveMetrics!(metrics);\r\n options.onAllReady?.();\r\n },\r\n onError: (error) => {\r\n observer?.onError?.({ streamId, error });\r\n options.onError?.(error);\r\n },\r\n },\r\n });\r\n\r\n // Wrap stream to count bytes\r\n const countingStream = result.stream.pipeThrough(\r\n new TransformStream<Uint8Array, Uint8Array>({\r\n transform(chunk, controller) {\r\n totalBytes += chunk.length;\r\n controller.enqueue(chunk);\r\n },\r\n })\r\n );\r\n\r\n return {\r\n stream: countingStream,\r\n abort: result.abort,\r\n shellReady: result.shellReady,\r\n allReady: result.allReady,\r\n metrics: metricsPromise,\r\n streamId,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Metrics Aggregator\r\n// ============================================================================\r\n\r\n/**\r\n * Aggregate metrics from multiple streams for analysis\r\n */\r\nexport class MetricsAggregator {\r\n private metrics: StreamingMetrics[] = [];\r\n private maxSamples: number;\r\n\r\n constructor(maxSamples = 1000) {\r\n this.maxSamples = maxSamples;\r\n }\r\n\r\n /**\r\n * Add metrics from a stream\r\n */\r\n add(metrics: StreamingMetrics): void {\r\n this.metrics.push(metrics);\r\n if (this.metrics.length > this.maxSamples) {\r\n this.metrics.shift();\r\n }\r\n }\r\n\r\n /**\r\n * Get average shell time\r\n */\r\n getAverageShellTime(): number {\r\n if (this.metrics.length === 0) return 0;\r\n return this.metrics.reduce((sum, m) => sum + m.shellTime, 0) / this.metrics.length;\r\n }\r\n\r\n /**\r\n * Get average total stream time\r\n */\r\n getAverageTotalTime(): number {\r\n if (this.metrics.length === 0) return 0;\r\n return this.metrics.reduce((sum, m) => sum + m.totalStreamTime, 0) / this.metrics.length;\r\n }\r\n\r\n /**\r\n * Get slowest boundaries (by average duration)\r\n */\r\n getSlowestBoundaries(limit = 5): { id: string; avgDuration: number; errorRate: number }[] {\r\n const boundaryStats = new Map<string, { totalDuration: number; count: number; errors: number }>();\r\n\r\n for (const m of this.metrics) {\r\n for (const b of m.boundaries) {\r\n const stats = boundaryStats.get(b.id) || { totalDuration: 0, count: 0, errors: 0 };\r\n stats.totalDuration += b.duration;\r\n stats.count++;\r\n if (!b.success) stats.errors++;\r\n boundaryStats.set(b.id, stats);\r\n }\r\n }\r\n\r\n return [...boundaryStats.entries()]\r\n .map(([id, stats]) => ({\r\n id,\r\n avgDuration: stats.totalDuration / stats.count,\r\n errorRate: stats.errors / stats.count,\r\n }))\r\n .sort((a, b) => b.avgDuration - a.avgDuration)\r\n .slice(0, limit);\r\n }\r\n\r\n /**\r\n * Get overall error rate\r\n */\r\n getErrorRate(): number {\r\n const total = this.metrics.reduce((sum, m) => sum + m.boundaries.length, 0);\r\n const errors = this.metrics.reduce((sum, m) => sum + m.errorCount, 0);\r\n return total > 0 ? errors / total : 0;\r\n }\r\n\r\n /**\r\n * Get percentiles for shell time\r\n */\r\n getShellTimePercentiles(): { p50: number; p90: number; p99: number } {\r\n const sorted = [...this.metrics].map(m => m.shellTime).sort((a, b) => a - b);\r\n const len = sorted.length;\r\n if (len === 0) return { p50: 0, p90: 0, p99: 0 };\r\n\r\n return {\r\n p50: sorted[Math.floor(len * 0.5)] ?? 0,\r\n p90: sorted[Math.floor(len * 0.9)] ?? 0,\r\n p99: sorted[Math.floor(len * 0.99)] ?? 0,\r\n };\r\n }\r\n\r\n /**\r\n * Export all metrics for external analysis\r\n */\r\n export(): StreamingMetrics[] {\r\n return [...this.metrics];\r\n }\r\n\r\n /**\r\n * Clear all metrics\r\n */\r\n clear(): void {\r\n this.metrics = [];\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Create Observer from Logger\r\n// ============================================================================\r\n\r\n/**\r\n * Create a streaming observer from a simple logger function\r\n */\r\nexport function createLoggerObserver(\r\n log: (message: string, data?: Record<string, unknown>) => void\r\n): StreamingObserver {\r\n return {\r\n onStreamStart: (streamId) => {\r\n log('[Flight] Stream started', { streamId });\r\n },\r\n onShellReady: ({ streamId, duration }) => {\r\n log('[Flight] Shell ready', { streamId, duration: `${duration}ms` });\r\n },\r\n onBoundaryStart: ({ streamId, boundaryId, startTime }) => {\r\n log('[Flight] Boundary started', { streamId, boundaryId, startTime: `${startTime}ms` });\r\n },\r\n onBoundaryEnd: (timing) => {\r\n log('[Flight] Boundary completed', {\r\n streamId: (timing as any).streamId,\r\n boundaryId: timing.id,\r\n duration: `${timing.duration}ms`,\r\n success: timing.success,\r\n size: timing.contentSize ? `${timing.contentSize}b` : undefined,\r\n });\r\n },\r\n onStreamEnd: (metrics) => {\r\n log('[Flight] Stream completed', {\r\n streamId: metrics.streamId,\r\n totalTime: `${metrics.totalStreamTime}ms`,\r\n shellTime: `${metrics.shellTime}ms`,\r\n boundaries: metrics.boundaries.length,\r\n errors: metrics.errorCount,\r\n });\r\n },\r\n onError: ({ streamId, boundaryId, error }) => {\r\n log('[Flight] Stream error', { streamId, boundaryId, error: error.message });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Create observer that sends metrics to a custom endpoint (YOUR infrastructure)\r\n */\r\nexport function createHttpObserver(endpoint: string, options?: {\r\n headers?: Record<string, string>;\r\n batchSize?: number;\r\n flushInterval?: number;\r\n}): StreamingObserver {\r\n const { headers = {}, batchSize = 10, flushInterval = 5000 } = options || {};\r\n const buffer: StreamingMetrics[] = [];\r\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n const flush = async () => {\r\n if (buffer.length === 0) return;\r\n const batch = buffer.splice(0, buffer.length);\r\n\r\n try {\r\n await fetch(endpoint, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...headers,\r\n },\r\n body: JSON.stringify({ metrics: batch, timestamp: Date.now() }),\r\n });\r\n } catch (error) {\r\n console.error('[Flight] Failed to send metrics:', error);\r\n // Re-add to buffer for retry\r\n buffer.unshift(...batch);\r\n }\r\n };\r\n\r\n const scheduleFlush = () => {\r\n if (flushTimer) return;\r\n flushTimer = setTimeout(() => {\r\n flushTimer = null;\r\n flush();\r\n }, flushInterval);\r\n };\r\n\r\n return {\r\n onStreamEnd: (metrics) => {\r\n buffer.push(metrics);\r\n if (buffer.length >= batchSize) {\r\n flush();\r\n } else {\r\n scheduleFlush();\r\n }\r\n },\r\n };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/streaming/observability.ts"],"names":[],"mappings":"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","file":"chunk-6BDCTUQY.js","sourcesContent":["/**\r\n * @flight-framework/core - Streaming Observability\r\n * \r\n * Zero-telemetry metrics and instrumentation for streaming SSR.\r\n * All data stays on YOUR infrastructure - never sent anywhere.\r\n * \r\n * Best Practices 2026:\r\n * - Comprehensive timing metrics for each boundary\r\n * - Hook-based observability for custom integrations\r\n * - Performance insights without vendor lock-in\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createInstrumentedStream } from '@flight-framework/core/streaming';\r\n * \r\n * const { stream, metrics } = await createInstrumentedStream({\r\n * shell: '<html>...',\r\n * boundaries: [...],\r\n * onMetrics: (m) => myAnalytics.track(m), // YOUR system\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { StreamingRenderOptions, SuspenseBoundaryConfig } from './index.js';\r\nimport { createStreamingSSR } from './index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Timing information for a single boundary\r\n */\r\nexport interface BoundaryTiming {\r\n /** Boundary identifier */\r\n id: string;\r\n /** When the boundary started resolving (ms since stream start) */\r\n startTime: number;\r\n /** When the boundary finished resolving */\r\n endTime: number;\r\n /** Total duration in milliseconds */\r\n duration: number;\r\n /** Whether it resolved successfully */\r\n success: boolean;\r\n /** Size of content in bytes (if successful) */\r\n contentSize?: number;\r\n /** Error message if failed */\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Overall streaming metrics\r\n */\r\nexport interface StreamingMetrics {\r\n /** Unique ID for this stream session */\r\n streamId: string;\r\n /** When streaming started */\r\n startTime: number;\r\n /** Time to shell ready (TTFB improvement) */\r\n shellTime: number;\r\n /** Time until all boundaries resolved */\r\n totalStreamTime: number;\r\n /** Individual boundary timings */\r\n boundaries: BoundaryTiming[];\r\n /** Number of boundaries that resolved successfully */\r\n successCount: number;\r\n /** Number of boundaries that failed */\r\n errorCount: number;\r\n /** Total bytes streamed */\r\n totalBytes: number;\r\n /** Strategy used (if priority streaming) */\r\n strategy?: string;\r\n /** Custom metadata you can add */\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Observability hooks for streaming events\r\n */\r\nexport interface StreamingObserver {\r\n /** Called when streaming starts */\r\n onStreamStart?: (streamId: string) => void;\r\n /** Called when shell is sent */\r\n onShellReady?: (timing: { streamId: string; duration: number }) => void;\r\n /** Called when a boundary starts resolving */\r\n onBoundaryStart?: (info: { streamId: string; boundaryId: string; startTime: number }) => void;\r\n /** Called when a boundary finishes */\r\n onBoundaryEnd?: (timing: BoundaryTiming & { streamId: string }) => void;\r\n /** Called when streaming completes */\r\n onStreamEnd?: (metrics: StreamingMetrics) => void;\r\n /** Called on any error */\r\n onError?: (error: { streamId: string; boundaryId?: string; error: Error }) => void;\r\n}\r\n\r\n/**\r\n * Configuration for instrumented streaming\r\n */\r\nexport interface InstrumentedStreamConfig {\r\n /** Initial HTML shell */\r\n shell: string;\r\n /** Closing HTML */\r\n shellEnd: string;\r\n /** Suspense boundaries */\r\n suspenseBoundaries: SuspenseBoundaryConfig[];\r\n /** Streaming options */\r\n options?: StreamingRenderOptions;\r\n /** Observer hooks */\r\n observer?: StreamingObserver;\r\n /** Callback when all metrics are ready */\r\n onMetrics?: (metrics: StreamingMetrics) => void;\r\n /** Custom metadata to include in metrics */\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Result of instrumented streaming\r\n */\r\nexport interface InstrumentedStreamResult {\r\n /** The readable stream */\r\n stream: ReadableStream<Uint8Array>;\r\n /** Abort the stream */\r\n abort: () => void;\r\n /** Shell ready promise */\r\n shellReady: Promise<void>;\r\n /** All content ready promise */\r\n allReady: Promise<void>;\r\n /** Final metrics (resolves when stream completes) */\r\n metrics: Promise<StreamingMetrics>;\r\n /** Stream ID for correlation */\r\n streamId: string;\r\n}\r\n\r\n// ============================================================================\r\n// Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Generate a unique stream ID\r\n */\r\nfunction generateStreamId(): string {\r\n return `stream_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Create an instrumented streaming SSR response with full observability\r\n */\r\nexport async function createInstrumentedStream(\r\n config: InstrumentedStreamConfig\r\n): Promise<InstrumentedStreamResult> {\r\n const {\r\n shell,\r\n shellEnd,\r\n suspenseBoundaries,\r\n options = {},\r\n observer,\r\n onMetrics,\r\n meta,\r\n } = config;\r\n\r\n const streamId = generateStreamId();\r\n const startTime = Date.now();\r\n const boundaryTimings: BoundaryTiming[] = [];\r\n const boundaryStarts = new Map<string, number>();\r\n let shellTime = 0;\r\n let totalBytes = 0;\r\n\r\n // Metrics promise\r\n let resolveMetrics: (m: StreamingMetrics) => void;\r\n const metricsPromise = new Promise<StreamingMetrics>((r) => { resolveMetrics = r; });\r\n\r\n // Notify stream start\r\n observer?.onStreamStart?.(streamId);\r\n\r\n // Wrap boundaries with instrumentation\r\n const instrumentedBoundaries: SuspenseBoundaryConfig[] = suspenseBoundaries.map(boundary => {\r\n const boundaryStart = Date.now();\r\n boundaryStarts.set(boundary.id, boundaryStart);\r\n\r\n observer?.onBoundaryStart?.({\r\n streamId,\r\n boundaryId: boundary.id,\r\n startTime: boundaryStart - startTime,\r\n });\r\n\r\n return {\r\n ...boundary,\r\n contentPromise: boundary.contentPromise.then(\r\n (content) => {\r\n const endTime = Date.now();\r\n const timing: BoundaryTiming = {\r\n id: boundary.id,\r\n startTime: boundaryStarts.get(boundary.id)! - startTime,\r\n endTime: endTime - startTime,\r\n duration: endTime - boundaryStarts.get(boundary.id)!,\r\n success: true,\r\n contentSize: new TextEncoder().encode(content).length,\r\n };\r\n boundaryTimings.push(timing);\r\n observer?.onBoundaryEnd?.({ ...timing, streamId });\r\n return content;\r\n },\r\n (error) => {\r\n const endTime = Date.now();\r\n const timing: BoundaryTiming = {\r\n id: boundary.id,\r\n startTime: boundaryStarts.get(boundary.id)! - startTime,\r\n endTime: endTime - startTime,\r\n duration: endTime - boundaryStarts.get(boundary.id)!,\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n };\r\n boundaryTimings.push(timing);\r\n observer?.onBoundaryEnd?.({ ...timing, streamId });\r\n observer?.onError?.({ streamId, boundaryId: boundary.id, error: error as Error });\r\n throw error;\r\n }\r\n ),\r\n };\r\n });\r\n\r\n // Create the underlying stream with instrumented callbacks\r\n const result = await createStreamingSSR({\r\n shell,\r\n shellEnd,\r\n suspenseBoundaries: instrumentedBoundaries,\r\n options: {\r\n ...options,\r\n onShellReady: () => {\r\n shellTime = Date.now() - startTime;\r\n observer?.onShellReady?.({ streamId, duration: shellTime });\r\n options.onShellReady?.();\r\n },\r\n onAllReady: () => {\r\n const totalStreamTime = Date.now() - startTime;\r\n\r\n const metrics: StreamingMetrics = {\r\n streamId,\r\n startTime,\r\n shellTime,\r\n totalStreamTime,\r\n boundaries: boundaryTimings,\r\n successCount: boundaryTimings.filter(b => b.success).length,\r\n errorCount: boundaryTimings.filter(b => !b.success).length,\r\n totalBytes,\r\n meta,\r\n };\r\n\r\n observer?.onStreamEnd?.(metrics);\r\n onMetrics?.(metrics);\r\n resolveMetrics!(metrics);\r\n options.onAllReady?.();\r\n },\r\n onError: (error) => {\r\n observer?.onError?.({ streamId, error });\r\n options.onError?.(error);\r\n },\r\n },\r\n });\r\n\r\n // Wrap stream to count bytes\r\n const countingStream = result.stream.pipeThrough(\r\n new TransformStream<Uint8Array, Uint8Array>({\r\n transform(chunk, controller) {\r\n totalBytes += chunk.length;\r\n controller.enqueue(chunk);\r\n },\r\n })\r\n );\r\n\r\n return {\r\n stream: countingStream,\r\n abort: result.abort,\r\n shellReady: result.shellReady,\r\n allReady: result.allReady,\r\n metrics: metricsPromise,\r\n streamId,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Metrics Aggregator\r\n// ============================================================================\r\n\r\n/**\r\n * Aggregate metrics from multiple streams for analysis\r\n */\r\nexport class MetricsAggregator {\r\n private metrics: StreamingMetrics[] = [];\r\n private maxSamples: number;\r\n\r\n constructor(maxSamples = 1000) {\r\n this.maxSamples = maxSamples;\r\n }\r\n\r\n /**\r\n * Add metrics from a stream\r\n */\r\n add(metrics: StreamingMetrics): void {\r\n this.metrics.push(metrics);\r\n if (this.metrics.length > this.maxSamples) {\r\n this.metrics.shift();\r\n }\r\n }\r\n\r\n /**\r\n * Get average shell time\r\n */\r\n getAverageShellTime(): number {\r\n if (this.metrics.length === 0) return 0;\r\n return this.metrics.reduce((sum, m) => sum + m.shellTime, 0) / this.metrics.length;\r\n }\r\n\r\n /**\r\n * Get average total stream time\r\n */\r\n getAverageTotalTime(): number {\r\n if (this.metrics.length === 0) return 0;\r\n return this.metrics.reduce((sum, m) => sum + m.totalStreamTime, 0) / this.metrics.length;\r\n }\r\n\r\n /**\r\n * Get slowest boundaries (by average duration)\r\n */\r\n getSlowestBoundaries(limit = 5): { id: string; avgDuration: number; errorRate: number }[] {\r\n const boundaryStats = new Map<string, { totalDuration: number; count: number; errors: number }>();\r\n\r\n for (const m of this.metrics) {\r\n for (const b of m.boundaries) {\r\n const stats = boundaryStats.get(b.id) || { totalDuration: 0, count: 0, errors: 0 };\r\n stats.totalDuration += b.duration;\r\n stats.count++;\r\n if (!b.success) stats.errors++;\r\n boundaryStats.set(b.id, stats);\r\n }\r\n }\r\n\r\n return [...boundaryStats.entries()]\r\n .map(([id, stats]) => ({\r\n id,\r\n avgDuration: stats.totalDuration / stats.count,\r\n errorRate: stats.errors / stats.count,\r\n }))\r\n .sort((a, b) => b.avgDuration - a.avgDuration)\r\n .slice(0, limit);\r\n }\r\n\r\n /**\r\n * Get overall error rate\r\n */\r\n getErrorRate(): number {\r\n const total = this.metrics.reduce((sum, m) => sum + m.boundaries.length, 0);\r\n const errors = this.metrics.reduce((sum, m) => sum + m.errorCount, 0);\r\n return total > 0 ? errors / total : 0;\r\n }\r\n\r\n /**\r\n * Get percentiles for shell time\r\n */\r\n getShellTimePercentiles(): { p50: number; p90: number; p99: number } {\r\n const sorted = [...this.metrics].map(m => m.shellTime).sort((a, b) => a - b);\r\n const len = sorted.length;\r\n if (len === 0) return { p50: 0, p90: 0, p99: 0 };\r\n\r\n return {\r\n p50: sorted[Math.floor(len * 0.5)] ?? 0,\r\n p90: sorted[Math.floor(len * 0.9)] ?? 0,\r\n p99: sorted[Math.floor(len * 0.99)] ?? 0,\r\n };\r\n }\r\n\r\n /**\r\n * Export all metrics for external analysis\r\n */\r\n export(): StreamingMetrics[] {\r\n return [...this.metrics];\r\n }\r\n\r\n /**\r\n * Clear all metrics\r\n */\r\n clear(): void {\r\n this.metrics = [];\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Create Observer from Logger\r\n// ============================================================================\r\n\r\n/**\r\n * Create a streaming observer from a simple logger function\r\n */\r\nexport function createLoggerObserver(\r\n log: (message: string, data?: Record<string, unknown>) => void\r\n): StreamingObserver {\r\n return {\r\n onStreamStart: (streamId) => {\r\n log('[Flight] Stream started', { streamId });\r\n },\r\n onShellReady: ({ streamId, duration }) => {\r\n log('[Flight] Shell ready', { streamId, duration: `${duration}ms` });\r\n },\r\n onBoundaryStart: ({ streamId, boundaryId, startTime }) => {\r\n log('[Flight] Boundary started', { streamId, boundaryId, startTime: `${startTime}ms` });\r\n },\r\n onBoundaryEnd: (timing) => {\r\n log('[Flight] Boundary completed', {\r\n streamId: (timing as any).streamId,\r\n boundaryId: timing.id,\r\n duration: `${timing.duration}ms`,\r\n success: timing.success,\r\n size: timing.contentSize ? `${timing.contentSize}b` : undefined,\r\n });\r\n },\r\n onStreamEnd: (metrics) => {\r\n log('[Flight] Stream completed', {\r\n streamId: metrics.streamId,\r\n totalTime: `${metrics.totalStreamTime}ms`,\r\n shellTime: `${metrics.shellTime}ms`,\r\n boundaries: metrics.boundaries.length,\r\n errors: metrics.errorCount,\r\n });\r\n },\r\n onError: ({ streamId, boundaryId, error }) => {\r\n log('[Flight] Stream error', { streamId, boundaryId, error: error.message });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Create observer that sends metrics to a custom endpoint (YOUR infrastructure)\r\n */\r\nexport function createHttpObserver(endpoint: string, options?: {\r\n headers?: Record<string, string>;\r\n batchSize?: number;\r\n flushInterval?: number;\r\n}): StreamingObserver {\r\n const { headers = {}, batchSize = 10, flushInterval = 5000 } = options || {};\r\n const buffer: StreamingMetrics[] = [];\r\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n const flush = async () => {\r\n if (buffer.length === 0) return;\r\n const batch = buffer.splice(0, buffer.length);\r\n\r\n try {\r\n await fetch(endpoint, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...headers,\r\n },\r\n body: JSON.stringify({ metrics: batch, timestamp: Date.now() }),\r\n });\r\n } catch (error) {\r\n console.error('[Flight] Failed to send metrics:', error);\r\n // Re-add to buffer for retry\r\n buffer.unshift(...batch);\r\n }\r\n };\r\n\r\n const scheduleFlush = () => {\r\n if (flushTimer) return;\r\n flushTimer = setTimeout(() => {\r\n flushTimer = null;\r\n flush();\r\n }, flushInterval);\r\n };\r\n\r\n return {\r\n onStreamEnd: (metrics) => {\r\n buffer.push(metrics);\r\n if (buffer.length >= batchSize) {\r\n flush();\r\n } else {\r\n scheduleFlush();\r\n }\r\n },\r\n };\r\n}\r\n"]}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// src/rsc/adapters/react.ts
|
|
2
|
+
var REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.element");
|
|
3
|
+
var REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment");
|
|
4
|
+
var REACT_PROVIDER_TYPE = /* @__PURE__ */ Symbol.for("react.provider");
|
|
5
|
+
var REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context");
|
|
6
|
+
var REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
7
|
+
var REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense");
|
|
8
|
+
var REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo");
|
|
9
|
+
var REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
|
|
10
|
+
var CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("flight.client.reference");
|
|
11
|
+
function createReactAdapter(deps) {
|
|
12
|
+
const { React, renderToString } = deps || {};
|
|
13
|
+
return {
|
|
14
|
+
name: "react",
|
|
15
|
+
isElement(value) {
|
|
16
|
+
if (React) {
|
|
17
|
+
return React.isValidElement(value);
|
|
18
|
+
}
|
|
19
|
+
return typeof value === "object" && value !== null && "$$typeof" in value && value.$$typeof === REACT_ELEMENT_TYPE;
|
|
20
|
+
},
|
|
21
|
+
getElementType(element) {
|
|
22
|
+
const el = element;
|
|
23
|
+
const type = el.type;
|
|
24
|
+
if (typeof type === "string") {
|
|
25
|
+
return { kind: "host", tag: type };
|
|
26
|
+
}
|
|
27
|
+
if (typeof type === "symbol") {
|
|
28
|
+
if (type === REACT_FRAGMENT_TYPE || type === React?.Fragment) {
|
|
29
|
+
return { kind: "fragment" };
|
|
30
|
+
}
|
|
31
|
+
if (type === REACT_SUSPENSE_TYPE || React?.Suspense && type === React.Suspense) {
|
|
32
|
+
return {
|
|
33
|
+
kind: "suspense",
|
|
34
|
+
fallback: el.props.fallback
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (type === REACT_PROVIDER_TYPE) {
|
|
38
|
+
return { kind: "provider", value: el.props.value };
|
|
39
|
+
}
|
|
40
|
+
if (type === REACT_CONTEXT_TYPE) {
|
|
41
|
+
return { kind: "context" };
|
|
42
|
+
}
|
|
43
|
+
return { kind: "null" };
|
|
44
|
+
}
|
|
45
|
+
if (typeof type === "object" && type !== null) {
|
|
46
|
+
const typeObj = type;
|
|
47
|
+
if (typeObj.$$typeof === REACT_MEMO_TYPE) {
|
|
48
|
+
return this.getElementType({ ...el, type: typeObj.type });
|
|
49
|
+
}
|
|
50
|
+
if (typeObj.$$typeof === REACT_LAZY_TYPE) {
|
|
51
|
+
return { kind: "component", fn: () => null, name: "Lazy" };
|
|
52
|
+
}
|
|
53
|
+
if (typeObj.$$typeof === REACT_FORWARD_REF_TYPE && typeObj.render) {
|
|
54
|
+
return {
|
|
55
|
+
kind: "component",
|
|
56
|
+
fn: typeObj.render,
|
|
57
|
+
name: "ForwardRef"
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if ("$$typeof" in typeObj && typeObj.$$typeof === REACT_SUSPENSE_TYPE) {
|
|
61
|
+
return { kind: "suspense", fallback: el.props.fallback };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (typeof type === "function") {
|
|
65
|
+
const fn = type;
|
|
66
|
+
return {
|
|
67
|
+
kind: "component",
|
|
68
|
+
fn,
|
|
69
|
+
name: fn.displayName || fn.name || "Component"
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return { kind: "null" };
|
|
73
|
+
},
|
|
74
|
+
getProps(element) {
|
|
75
|
+
return element.props || {};
|
|
76
|
+
},
|
|
77
|
+
getChildren(element) {
|
|
78
|
+
const props = element.props;
|
|
79
|
+
const children = props?.children;
|
|
80
|
+
if (children === void 0 || children === null) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
if (React?.Children) {
|
|
84
|
+
return React.Children.toArray(children);
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(children)) {
|
|
87
|
+
return children.flat();
|
|
88
|
+
}
|
|
89
|
+
return [children];
|
|
90
|
+
},
|
|
91
|
+
getKey(element) {
|
|
92
|
+
const key = element.key;
|
|
93
|
+
return key !== null ? key : void 0;
|
|
94
|
+
},
|
|
95
|
+
isClientBoundary(component) {
|
|
96
|
+
if (typeof component !== "function") return false;
|
|
97
|
+
const comp = component;
|
|
98
|
+
if (comp.__flight_client === true) return true;
|
|
99
|
+
if (comp.$$typeof === CLIENT_REFERENCE) return true;
|
|
100
|
+
return false;
|
|
101
|
+
},
|
|
102
|
+
async renderToString(element) {
|
|
103
|
+
if (renderToString) {
|
|
104
|
+
return renderToString(element);
|
|
105
|
+
}
|
|
106
|
+
throw new Error(
|
|
107
|
+
"renderToString not provided. Pass it when creating the adapter: createReactAdapter({ renderToString })"
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function createReactConsumer(deps, options = {}) {
|
|
113
|
+
const { React } = deps;
|
|
114
|
+
const { registry = /* @__PURE__ */ new Map() } = options;
|
|
115
|
+
return {
|
|
116
|
+
/**
|
|
117
|
+
* Register a client component
|
|
118
|
+
*/
|
|
119
|
+
register(id, loader) {
|
|
120
|
+
registry.set(id, loader);
|
|
121
|
+
},
|
|
122
|
+
/**
|
|
123
|
+
* Convert Flight elements to React elements
|
|
124
|
+
*/
|
|
125
|
+
toReactElement(element) {
|
|
126
|
+
switch (element.$$type) {
|
|
127
|
+
case "null":
|
|
128
|
+
return null;
|
|
129
|
+
case "text":
|
|
130
|
+
return element.value;
|
|
131
|
+
case "host": {
|
|
132
|
+
const children = element.children.map((c) => this.toReactElement(c));
|
|
133
|
+
return React.createElement(
|
|
134
|
+
element.tag,
|
|
135
|
+
{ ...element.props, key: element.key },
|
|
136
|
+
...children
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
case "fragment": {
|
|
140
|
+
const children = element.children.map((c) => this.toReactElement(c));
|
|
141
|
+
return React.createElement(React.Fragment, null, ...children);
|
|
142
|
+
}
|
|
143
|
+
case "suspense": {
|
|
144
|
+
const fallback = this.toReactElement(element.fallback);
|
|
145
|
+
const children = element.children.map((c) => this.toReactElement(c));
|
|
146
|
+
return React.createElement(
|
|
147
|
+
React.Suspense,
|
|
148
|
+
{ fallback },
|
|
149
|
+
...children
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
case "client": {
|
|
153
|
+
const loader = registry.get(element.ref);
|
|
154
|
+
if (!loader) {
|
|
155
|
+
console.warn(`[Flight] Client component not registered: ${element.ref}`);
|
|
156
|
+
if (element.ssr) {
|
|
157
|
+
return React.createElement("div", {
|
|
158
|
+
dangerouslySetInnerHTML: { __html: element.ssr }
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const LazyComponent = React.lazy(async () => {
|
|
164
|
+
const mod = await loader();
|
|
165
|
+
return { default: mod.default ?? mod };
|
|
166
|
+
});
|
|
167
|
+
return React.createElement(LazyComponent);
|
|
168
|
+
}
|
|
169
|
+
case "lazy": {
|
|
170
|
+
if (element.fallback) {
|
|
171
|
+
return this.toReactElement(element.fallback);
|
|
172
|
+
}
|
|
173
|
+
return React.createElement("div", { "data-flight-pending": element.id });
|
|
174
|
+
}
|
|
175
|
+
default:
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
/**
|
|
180
|
+
* Process Flight chunks and build React tree
|
|
181
|
+
*/
|
|
182
|
+
processChunks(chunks) {
|
|
183
|
+
const rootChunk = chunks.find((c) => c.type === "S" && c.id === "root");
|
|
184
|
+
if (!rootChunk || rootChunk.type !== "S") {
|
|
185
|
+
throw new Error("[Flight] No root chunk found in payload");
|
|
186
|
+
}
|
|
187
|
+
for (const chunk of chunks) {
|
|
188
|
+
if (chunk.type === "C") {
|
|
189
|
+
if (!registry.has(chunk.id)) {
|
|
190
|
+
registry.set(chunk.id, () => import(
|
|
191
|
+
/* webpackIgnore: true */
|
|
192
|
+
chunk.module
|
|
193
|
+
));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return this.toReactElement(rootChunk.tree);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function markAsClientComponent(component, moduleId, exportName = "default") {
|
|
202
|
+
const marked = component;
|
|
203
|
+
marked.$$typeof = CLIENT_REFERENCE;
|
|
204
|
+
marked.__flight_client = true;
|
|
205
|
+
marked.__flight_module = moduleId;
|
|
206
|
+
marked.__flight_export = exportName;
|
|
207
|
+
return marked;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export { createReactAdapter, createReactConsumer, markAsClientComponent };
|
|
211
|
+
//# sourceMappingURL=chunk-6Z2RYHEU.js.map
|
|
212
|
+
//# sourceMappingURL=chunk-6Z2RYHEU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/rsc/adapters/react.ts"],"names":[],"mappings":"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","file":"chunk-6Z2RYHEU.js","sourcesContent":["/**\r\n * @flight-framework/core - React UI Adapter\r\n * \r\n * Adapter for using React with Flight Server Components.\r\n * Enables Flight to render React elements without tight coupling.\r\n * \r\n * @module @flight-framework/core/rsc/adapters/react\r\n */\r\n\r\nimport type { UIAdapter, ElementTypeInfo } from '../renderer.js';\r\n\r\n// ============================================================================\r\n// React Symbols\r\n// ============================================================================\r\n\r\n// React internal symbols (stable across versions)\r\nconst REACT_ELEMENT_TYPE = Symbol.for('react.element');\r\nconst REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');\r\nconst REACT_PROVIDER_TYPE = Symbol.for('react.provider');\r\nconst REACT_CONTEXT_TYPE = Symbol.for('react.context');\r\nconst REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');\r\nconst REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');\r\nconst REACT_MEMO_TYPE = Symbol.for('react.memo');\r\nconst REACT_LAZY_TYPE = Symbol.for('react.lazy');\r\n\r\n// Flight reference symbols\r\nconst CLIENT_REFERENCE = Symbol.for('flight.client.reference');\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * React element shape (minimal interface)\r\n */\r\ninterface ReactElement {\r\n $$typeof: symbol;\r\n type: unknown;\r\n key: string | number | null;\r\n ref: unknown;\r\n props: Record<string, unknown>;\r\n _owner: unknown;\r\n}\r\n\r\n// ============================================================================\r\n// Adapter Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Create React UI Adapter\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createReactAdapter } from '@flight-framework/core/rsc/adapters/react';\r\n * import { renderToString } from 'react-dom/server';\r\n * import * as React from 'react';\r\n * \r\n * const adapter = createReactAdapter({\r\n * React,\r\n * renderToString,\r\n * });\r\n * \r\n * const renderer = createRenderer(adapter);\r\n * ```\r\n */\r\nexport function createReactAdapter(deps?: {\r\n /** React module (optional - for SSR) */\r\n React?: {\r\n isValidElement: (value: unknown) => boolean;\r\n Children: { toArray: (children: unknown) => unknown[] };\r\n Fragment: symbol;\r\n Suspense: unknown;\r\n };\r\n /** renderToString function (optional - for SSR fallbacks) */\r\n renderToString?: (element: unknown) => string;\r\n}): UIAdapter {\r\n const { React, renderToString } = deps || {};\r\n\r\n return {\r\n name: 'react',\r\n\r\n isElement(value: unknown): boolean {\r\n if (React) {\r\n return React.isValidElement(value);\r\n }\r\n // Fallback: check for $$typeof\r\n return (\r\n typeof value === 'object' &&\r\n value !== null &&\r\n '$$typeof' in value &&\r\n (value as ReactElement).$$typeof === REACT_ELEMENT_TYPE\r\n );\r\n },\r\n\r\n getElementType(element: unknown): ElementTypeInfo {\r\n const el = element as ReactElement;\r\n const type = el.type;\r\n\r\n // String = host element (div, span, etc.)\r\n if (typeof type === 'string') {\r\n return { kind: 'host', tag: type };\r\n }\r\n\r\n // Symbol types\r\n if (typeof type === 'symbol') {\r\n if (type === REACT_FRAGMENT_TYPE || type === (React?.Fragment as symbol)) {\r\n return { kind: 'fragment' };\r\n }\r\n if (type === REACT_SUSPENSE_TYPE || (React?.Suspense && type === (React.Suspense as unknown as symbol))) {\r\n return {\r\n kind: 'suspense',\r\n fallback: el.props.fallback\r\n };\r\n }\r\n if (type === REACT_PROVIDER_TYPE) {\r\n return { kind: 'provider', value: el.props.value };\r\n }\r\n if (type === REACT_CONTEXT_TYPE) {\r\n return { kind: 'context' };\r\n }\r\n return { kind: 'null' };\r\n }\r\n\r\n // Object types (memo, lazy, forwardRef)\r\n if (typeof type === 'object' && type !== null) {\r\n const typeObj = type as { $$typeof?: symbol; type?: unknown; render?: unknown };\r\n\r\n if (typeObj.$$typeof === REACT_MEMO_TYPE) {\r\n // Unwrap memo\r\n return this.getElementType({ ...el, type: typeObj.type });\r\n }\r\n\r\n if (typeObj.$$typeof === REACT_LAZY_TYPE) {\r\n return { kind: 'component', fn: () => null, name: 'Lazy' };\r\n }\r\n\r\n if (typeObj.$$typeof === REACT_FORWARD_REF_TYPE && typeObj.render) {\r\n return {\r\n kind: 'component',\r\n fn: typeObj.render as (props: Record<string, unknown>) => unknown,\r\n name: 'ForwardRef'\r\n };\r\n }\r\n\r\n // Check for Suspense object\r\n if ('$$typeof' in typeObj &&\r\n (typeObj.$$typeof === REACT_SUSPENSE_TYPE)) {\r\n return { kind: 'suspense', fallback: el.props.fallback };\r\n }\r\n }\r\n\r\n // Function component\r\n if (typeof type === 'function') {\r\n const fn = type as ((props: Record<string, unknown>) => unknown) & {\r\n displayName?: string;\r\n name?: string;\r\n };\r\n return {\r\n kind: 'component',\r\n fn,\r\n name: fn.displayName || fn.name || 'Component'\r\n };\r\n }\r\n\r\n return { kind: 'null' };\r\n },\r\n\r\n getProps(element: unknown): Record<string, unknown> {\r\n return (element as ReactElement).props || {};\r\n },\r\n\r\n getChildren(element: unknown): unknown[] {\r\n const props = (element as ReactElement).props;\r\n const children = props?.children;\r\n\r\n if (children === undefined || children === null) {\r\n return [];\r\n }\r\n\r\n if (React?.Children) {\r\n return React.Children.toArray(children);\r\n }\r\n\r\n // Fallback array handling\r\n if (Array.isArray(children)) {\r\n return children.flat();\r\n }\r\n\r\n return [children];\r\n },\r\n\r\n getKey(element: unknown): string | number | undefined {\r\n const key = (element as ReactElement).key;\r\n return key !== null ? key : undefined;\r\n },\r\n\r\n isClientBoundary(component: unknown): boolean {\r\n if (typeof component !== 'function') return false;\r\n\r\n const comp = component as {\r\n $$typeof?: symbol;\r\n __flight_client?: boolean;\r\n };\r\n\r\n // Check for Flight client marker\r\n if (comp.__flight_client === true) return true;\r\n\r\n // Check for client reference symbol\r\n if (comp.$$typeof === CLIENT_REFERENCE) return true;\r\n\r\n return false;\r\n },\r\n\r\n async renderToString(element: unknown): Promise<string> {\r\n if (renderToString) {\r\n return renderToString(element);\r\n }\r\n throw new Error(\r\n 'renderToString not provided. Pass it when creating the adapter: ' +\r\n 'createReactAdapter({ renderToString })'\r\n );\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// React Client Consumer\r\n// ============================================================================\r\n\r\n/**\r\n * Opciones para el consumer de React\r\n */\r\nexport interface ReactConsumerOptions {\r\n /** Registry de client components */\r\n registry?: Map<string, () => Promise<unknown>>;\r\n /** Callback when hydration completes */\r\n onHydrate?: (id: string) => void;\r\n}\r\n\r\n/**\r\n * Create a React client-side consumer for Flight payloads\r\n * \r\n * This reconstructs React elements from Flight chunks on the client.\r\n */\r\nexport function createReactConsumer(deps: {\r\n React: {\r\n createElement: (type: unknown, props?: unknown, ...children: unknown[]) => unknown;\r\n Suspense: unknown;\r\n Fragment: unknown;\r\n lazy: (factory: () => Promise<{ default: unknown }>) => unknown;\r\n };\r\n}, options: ReactConsumerOptions = {}) {\r\n const { React } = deps;\r\n const { registry = new Map() } = options;\r\n\r\n return {\r\n /**\r\n * Register a client component\r\n */\r\n register(id: string, loader: () => Promise<unknown>): void {\r\n registry.set(id, loader);\r\n },\r\n\r\n /**\r\n * Convert Flight elements to React elements\r\n */\r\n toReactElement(element: import('../payload.js').FlightElement): unknown {\r\n switch (element.$$type) {\r\n case 'null':\r\n return null;\r\n\r\n case 'text':\r\n return element.value;\r\n\r\n case 'host': {\r\n const children = element.children.map(c => this.toReactElement(c));\r\n return React.createElement(\r\n element.tag,\r\n { ...element.props, key: element.key },\r\n ...children\r\n );\r\n }\r\n\r\n case 'fragment': {\r\n const children = element.children.map(c => this.toReactElement(c));\r\n return React.createElement(React.Fragment, null, ...children);\r\n }\r\n\r\n case 'suspense': {\r\n const fallback = this.toReactElement(element.fallback);\r\n const children = element.children.map(c => this.toReactElement(c));\r\n return React.createElement(\r\n React.Suspense,\r\n { fallback },\r\n ...children\r\n );\r\n }\r\n\r\n case 'client': {\r\n // Get loader from registry\r\n const loader = registry.get(element.ref);\r\n if (!loader) {\r\n console.warn(`[Flight] Client component not registered: ${element.ref}`);\r\n // Return SSR fallback if available\r\n if (element.ssr) {\r\n return React.createElement('div', {\r\n dangerouslySetInnerHTML: { __html: element.ssr }\r\n });\r\n }\r\n return null;\r\n }\r\n\r\n // Create lazy component\r\n const LazyComponent = React.lazy(async () => {\r\n const mod = await loader() as { default?: unknown };\r\n return { default: mod.default ?? mod };\r\n });\r\n\r\n return React.createElement(LazyComponent);\r\n }\r\n\r\n case 'lazy': {\r\n // This is a pending chunk - render fallback\r\n if (element.fallback) {\r\n return this.toReactElement(element.fallback);\r\n }\r\n return React.createElement('div', { 'data-flight-pending': element.id });\r\n }\r\n\r\n default:\r\n return null;\r\n }\r\n },\r\n\r\n /**\r\n * Process Flight chunks and build React tree\r\n */\r\n processChunks(chunks: import('../payload.js').FlightChunk[]): unknown {\r\n // Find root chunk\r\n const rootChunk = chunks.find(c => c.type === 'S' && c.id === 'root');\r\n if (!rootChunk || rootChunk.type !== 'S') {\r\n throw new Error('[Flight] No root chunk found in payload');\r\n }\r\n\r\n // Register all client references\r\n for (const chunk of chunks) {\r\n if (chunk.type === 'C') {\r\n // Default registry - lazy load via dynamic import\r\n if (!registry.has(chunk.id)) {\r\n registry.set(chunk.id, () => import(/* webpackIgnore: true */ chunk.module));\r\n }\r\n }\r\n }\r\n\r\n return this.toReactElement(rootChunk.tree);\r\n }\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Utility Types\r\n// ============================================================================\r\n\r\n/**\r\n * Type helper for React Server Component\r\n */\r\nexport type ReactServerComponent<P = Record<string, unknown>> = (\r\n props: P,\r\n ctx: import('../context.js').ServerContext\r\n) => Promise<ReturnType<typeof import('react').createElement>> | ReturnType<typeof import('react').createElement>;\r\n\r\n/**\r\n * Mark a component as a client component (for use without bundler transform)\r\n */\r\nexport function markAsClientComponent<T extends (...args: unknown[]) => unknown>(\r\n component: T,\r\n moduleId: string,\r\n exportName = 'default'\r\n): T {\r\n const marked = component as T & {\r\n $$typeof: symbol;\r\n __flight_client: boolean;\r\n __flight_module: string;\r\n __flight_export: string;\r\n };\r\n\r\n marked.$$typeof = CLIENT_REFERENCE;\r\n marked.__flight_client = true;\r\n marked.__flight_module = moduleId;\r\n marked.__flight_export = exportName;\r\n\r\n return marked;\r\n}\r\n"]}
|