@flight-framework/core 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +308 -1
- package/dist/index.js +236 -1
- package/dist/index.js.map +1 -1
- package/package.json +18 -1
package/dist/index.d.ts
CHANGED
|
@@ -574,6 +574,313 @@ declare function isDevToolsEnabled(): boolean;
|
|
|
574
574
|
*/
|
|
575
575
|
declare function createDevToolsData(startTime: number, options?: Partial<DevToolsOptions>): DevToolsOptions;
|
|
576
576
|
|
|
577
|
+
/**
|
|
578
|
+
* @flight-framework/core - Error Handling
|
|
579
|
+
*
|
|
580
|
+
* Comprehensive error handling utilities for Flight applications.
|
|
581
|
+
* All utilities are OPTIONAL - developers can use their own error handling.
|
|
582
|
+
*
|
|
583
|
+
* Philosophy: Flight OFFERS these utilities, but never IMPOSES them.
|
|
584
|
+
* Using throw new Error() works perfectly fine - this is your choice.
|
|
585
|
+
*/
|
|
586
|
+
/**
|
|
587
|
+
* Options for creating a Flight error
|
|
588
|
+
*/
|
|
589
|
+
interface FlightErrorOptions {
|
|
590
|
+
/** HTTP status code */
|
|
591
|
+
statusCode: number;
|
|
592
|
+
/** Short status message (e.g., "Not Found") */
|
|
593
|
+
statusMessage?: string;
|
|
594
|
+
/** Detailed error message */
|
|
595
|
+
message?: string;
|
|
596
|
+
/** Additional data to include with the error */
|
|
597
|
+
data?: Record<string, unknown>;
|
|
598
|
+
/** If true, shows full-screen error page instead of error boundary */
|
|
599
|
+
fatal?: boolean;
|
|
600
|
+
/** Original error that caused this error */
|
|
601
|
+
cause?: Error;
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Extended error props with digest for production error correlation
|
|
605
|
+
*/
|
|
606
|
+
interface FlightErrorProps {
|
|
607
|
+
/** The error object */
|
|
608
|
+
error: Error & {
|
|
609
|
+
digest?: string;
|
|
610
|
+
};
|
|
611
|
+
/** Function to attempt recovery by re-rendering */
|
|
612
|
+
reset: () => void;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Reset details provided to onReset callback
|
|
616
|
+
*/
|
|
617
|
+
interface ResetDetails {
|
|
618
|
+
/** Reason for the reset */
|
|
619
|
+
reason: 'imperative-api' | 'keys';
|
|
620
|
+
/** Arguments passed to resetErrorBoundary (if imperative) */
|
|
621
|
+
args?: unknown[];
|
|
622
|
+
/** Previous resetKeys values (if keys changed) */
|
|
623
|
+
prev?: unknown[];
|
|
624
|
+
/** New resetKeys values (if keys changed) */
|
|
625
|
+
next?: unknown[];
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Options for error boundary behavior
|
|
629
|
+
*/
|
|
630
|
+
interface ErrorBoundaryOptions {
|
|
631
|
+
/** Keys that trigger automatic reset when changed */
|
|
632
|
+
resetKeys?: unknown[];
|
|
633
|
+
/** Callback when error boundary resets */
|
|
634
|
+
onReset?: (details: ResetDetails) => void;
|
|
635
|
+
/** Callback when error is caught */
|
|
636
|
+
onError?: (error: Error, info: {
|
|
637
|
+
componentStack?: string;
|
|
638
|
+
}) => void;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Custom error class with status code and metadata support.
|
|
642
|
+
*
|
|
643
|
+
* You can use this class or regular Error - Flight handles both.
|
|
644
|
+
*
|
|
645
|
+
* @example
|
|
646
|
+
* ```typescript
|
|
647
|
+
* throw new FlightError({
|
|
648
|
+
* statusCode: 404,
|
|
649
|
+
* message: 'User not found',
|
|
650
|
+
* data: { userId: '123' }
|
|
651
|
+
* });
|
|
652
|
+
* ```
|
|
653
|
+
*/
|
|
654
|
+
declare class FlightError extends Error {
|
|
655
|
+
/** HTTP status code */
|
|
656
|
+
readonly statusCode: number;
|
|
657
|
+
/** Short status message */
|
|
658
|
+
readonly statusMessage: string;
|
|
659
|
+
/** Additional error data */
|
|
660
|
+
readonly data?: Record<string, unknown>;
|
|
661
|
+
/** Whether this is a fatal error (shows full-screen) */
|
|
662
|
+
readonly fatal: boolean;
|
|
663
|
+
/** Unique digest for production error correlation */
|
|
664
|
+
readonly digest?: string;
|
|
665
|
+
constructor(options: FlightErrorOptions);
|
|
666
|
+
/**
|
|
667
|
+
* Convert to plain object for serialization
|
|
668
|
+
*/
|
|
669
|
+
toJSON(): Record<string, unknown>;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* 400 Bad Request error
|
|
673
|
+
*/
|
|
674
|
+
declare class BadRequestError extends FlightError {
|
|
675
|
+
constructor(message?: string, data?: Record<string, unknown>);
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* 401 Unauthorized error
|
|
679
|
+
*/
|
|
680
|
+
declare class UnauthorizedError extends FlightError {
|
|
681
|
+
constructor(message?: string, data?: Record<string, unknown>);
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* 403 Forbidden error
|
|
685
|
+
*/
|
|
686
|
+
declare class ForbiddenError extends FlightError {
|
|
687
|
+
constructor(message?: string, data?: Record<string, unknown>);
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* 404 Not Found error
|
|
691
|
+
*/
|
|
692
|
+
declare class NotFoundError extends FlightError {
|
|
693
|
+
constructor(message?: string, data?: Record<string, unknown>);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* 500 Internal Server Error
|
|
697
|
+
*/
|
|
698
|
+
declare class InternalError extends FlightError {
|
|
699
|
+
constructor(message?: string, data?: Record<string, unknown>);
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Create a FlightError with the specified options.
|
|
703
|
+
*
|
|
704
|
+
* This is a convenience function - you can also use `new FlightError()` directly
|
|
705
|
+
* or just `throw new Error()` - Flight handles all cases.
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* ```typescript
|
|
709
|
+
* // With full options
|
|
710
|
+
* throw createError({
|
|
711
|
+
* statusCode: 404,
|
|
712
|
+
* message: 'Product not found',
|
|
713
|
+
* data: { productId: 'abc123' }
|
|
714
|
+
* });
|
|
715
|
+
*
|
|
716
|
+
* // Simple string shorthand (becomes 500 error)
|
|
717
|
+
* throw createError('Something went wrong');
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
720
|
+
declare function createError(options: FlightErrorOptions | string): FlightError;
|
|
721
|
+
/**
|
|
722
|
+
* Create a 404 Not Found error.
|
|
723
|
+
* Convenience function equivalent to `createError({ statusCode: 404, ... })`.
|
|
724
|
+
*
|
|
725
|
+
* @example
|
|
726
|
+
* ```typescript
|
|
727
|
+
* if (!user) {
|
|
728
|
+
* throw notFound('User not found');
|
|
729
|
+
* }
|
|
730
|
+
* ```
|
|
731
|
+
*/
|
|
732
|
+
declare function notFound(message?: string, data?: Record<string, unknown>): never;
|
|
733
|
+
/**
|
|
734
|
+
* Create a 403 Forbidden error.
|
|
735
|
+
*
|
|
736
|
+
* @example
|
|
737
|
+
* ```typescript
|
|
738
|
+
* if (!user.isAdmin) {
|
|
739
|
+
* throw forbidden('Admin access required');
|
|
740
|
+
* }
|
|
741
|
+
* ```
|
|
742
|
+
*/
|
|
743
|
+
declare function forbidden(message?: string, data?: Record<string, unknown>): never;
|
|
744
|
+
/**
|
|
745
|
+
* Create a 401 Unauthorized error.
|
|
746
|
+
*
|
|
747
|
+
* @example
|
|
748
|
+
* ```typescript
|
|
749
|
+
* if (!session) {
|
|
750
|
+
* throw unauthorized('Please log in to continue');
|
|
751
|
+
* }
|
|
752
|
+
* ```
|
|
753
|
+
*/
|
|
754
|
+
declare function unauthorized(message?: string, data?: Record<string, unknown>): never;
|
|
755
|
+
declare global {
|
|
756
|
+
interface Window {
|
|
757
|
+
__FLIGHT_ERROR__?: FlightError | null;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Programmatically show an error page.
|
|
762
|
+
*
|
|
763
|
+
* This triggers the nearest error boundary or navigates to the error page.
|
|
764
|
+
* Only works on the client side.
|
|
765
|
+
*
|
|
766
|
+
* @example
|
|
767
|
+
* ```typescript
|
|
768
|
+
* // Show error with full options
|
|
769
|
+
* showError({
|
|
770
|
+
* statusCode: 500,
|
|
771
|
+
* message: 'Connection lost'
|
|
772
|
+
* });
|
|
773
|
+
*
|
|
774
|
+
* // Simple string shorthand
|
|
775
|
+
* showError('Something went wrong');
|
|
776
|
+
* ```
|
|
777
|
+
*/
|
|
778
|
+
declare function showError(error: FlightErrorOptions | FlightError | string): void;
|
|
779
|
+
/**
|
|
780
|
+
* Clear the current error state and optionally redirect.
|
|
781
|
+
*
|
|
782
|
+
* Use this to dismiss an error and return to normal state.
|
|
783
|
+
*
|
|
784
|
+
* @example
|
|
785
|
+
* ```typescript
|
|
786
|
+
* // Just clear the error
|
|
787
|
+
* clearError();
|
|
788
|
+
*
|
|
789
|
+
* // Clear and redirect to home
|
|
790
|
+
* clearError({ redirect: '/' });
|
|
791
|
+
* ```
|
|
792
|
+
*/
|
|
793
|
+
declare function clearError(options?: {
|
|
794
|
+
redirect?: string;
|
|
795
|
+
}): void;
|
|
796
|
+
/**
|
|
797
|
+
* Get the current error from global state.
|
|
798
|
+
* Returns null if no error is active.
|
|
799
|
+
*/
|
|
800
|
+
declare function getError(): FlightError | null;
|
|
801
|
+
/**
|
|
802
|
+
* Check if an error is a FlightError
|
|
803
|
+
*/
|
|
804
|
+
declare function isFlightError(error: unknown): error is FlightError;
|
|
805
|
+
/**
|
|
806
|
+
* Check if an error is a NotFoundError (404)
|
|
807
|
+
*/
|
|
808
|
+
declare function isNotFoundError(error: unknown): error is NotFoundError;
|
|
809
|
+
/**
|
|
810
|
+
* Check if an error is a ForbiddenError (403)
|
|
811
|
+
*/
|
|
812
|
+
declare function isForbiddenError(error: unknown): error is ForbiddenError;
|
|
813
|
+
/**
|
|
814
|
+
* Check if an error is an UnauthorizedError (401)
|
|
815
|
+
*/
|
|
816
|
+
declare function isUnauthorizedError(error: unknown): error is UnauthorizedError;
|
|
817
|
+
/**
|
|
818
|
+
* Get the status code from any error.
|
|
819
|
+
* Returns 500 for non-FlightError errors.
|
|
820
|
+
*/
|
|
821
|
+
declare function getErrorStatusCode(error: unknown): number;
|
|
822
|
+
/**
|
|
823
|
+
* Create an error Response from a FlightError.
|
|
824
|
+
*
|
|
825
|
+
* @example
|
|
826
|
+
* ```typescript
|
|
827
|
+
* try {
|
|
828
|
+
* // ... some operation
|
|
829
|
+
* } catch (error) {
|
|
830
|
+
* return createErrorResponse(error);
|
|
831
|
+
* }
|
|
832
|
+
* ```
|
|
833
|
+
*/
|
|
834
|
+
declare function createErrorResponse(error: unknown): Response;
|
|
835
|
+
/**
|
|
836
|
+
* Wrap an error with a digest if it doesn't have one.
|
|
837
|
+
* Useful for adding correlation IDs to third-party errors.
|
|
838
|
+
*/
|
|
839
|
+
declare function wrapWithDigest<T extends Error>(error: T): T & {
|
|
840
|
+
digest: string;
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* @flight-framework/core - Environment Utilities
|
|
845
|
+
*
|
|
846
|
+
* Environment detection utilities that work across Node.js, browsers, and edge runtimes.
|
|
847
|
+
* No hardcoded values - detects environment dynamically.
|
|
848
|
+
*/
|
|
849
|
+
/**
|
|
850
|
+
* Check if running in production environment.
|
|
851
|
+
*
|
|
852
|
+
* Detection order:
|
|
853
|
+
* 1. Node.js process.env.NODE_ENV
|
|
854
|
+
* 2. Vite/modern bundlers import.meta.env.MODE or import.meta.env.PROD
|
|
855
|
+
* 3. Default: false (not production)
|
|
856
|
+
*/
|
|
857
|
+
declare function isProduction(): boolean;
|
|
858
|
+
/**
|
|
859
|
+
* Check if running in development environment.
|
|
860
|
+
*
|
|
861
|
+
* Detection order:
|
|
862
|
+
* 1. Node.js process.env.NODE_ENV
|
|
863
|
+
* 2. Vite/modern bundlers import.meta.env.MODE or import.meta.env.DEV
|
|
864
|
+
* 3. Default: true (assume development if unknown)
|
|
865
|
+
*/
|
|
866
|
+
declare function isDevelopment(): boolean;
|
|
867
|
+
/**
|
|
868
|
+
* Check if running in test environment.
|
|
869
|
+
*/
|
|
870
|
+
declare function isTest(): boolean;
|
|
871
|
+
/**
|
|
872
|
+
* Check if running on the server (not browser).
|
|
873
|
+
*/
|
|
874
|
+
declare function isServer(): boolean;
|
|
875
|
+
/**
|
|
876
|
+
* Check if running in the browser.
|
|
877
|
+
*/
|
|
878
|
+
declare function isBrowser(): boolean;
|
|
879
|
+
/**
|
|
880
|
+
* Get the current environment name.
|
|
881
|
+
*/
|
|
882
|
+
declare function getEnvironment(): 'production' | 'development' | 'test' | 'unknown';
|
|
883
|
+
|
|
577
884
|
/**
|
|
578
885
|
* Flight Framework - Core
|
|
579
886
|
*
|
|
@@ -583,4 +890,4 @@ declare function createDevToolsData(startTime: number, options?: Partial<DevTool
|
|
|
583
890
|
|
|
584
891
|
declare const VERSION = "0.0.1";
|
|
585
892
|
|
|
586
|
-
export { Cache, CacheOptions, type DevToolsOptions, type GenerateMetadataFn, type GenerateMetadataFunction, type GenerateStaticParamsFunction, type ISRCacheAdapter, type ISRCacheEntry, type Metadata, type PageMetadata, type PageModule, type PrerenderError, type PrerenderOptions, type PrerenderProgress, type PrerenderResult, type PrerenderSummary, type RevalidateHandlerOptions, type RevalidationResult, type RouteRule, type RouteRules, type StaticParams, VERSION, buildCacheControlHeader, createDefaultRouteRules, createDevToolsData, createHtmlStream, createISRCacheFromFlightCache, createMemoryISRCache, createRevalidateHandler, createStreamingResponse as createStaticStreamingResponse, expandDynamicRoutes, extractLinks, generateAllStaticPaths, getCacheOptionsFromRule, getISRCache, getOrGeneratePage, getRenderModeFromRule, getRevalidateTime, injectDevTools, isDevToolsEnabled, matchRouteRule, mergeMetadata, mergeRouteRules, prerenderRoutes, purgeAllPages, purgePage, renderMetadataToHead, resolveMetadata, revalidatePath, revalidatePaths, revalidateTag, setISRCache, shouldDynamicallyRender };
|
|
893
|
+
export { BadRequestError, Cache, CacheOptions, type DevToolsOptions, type ErrorBoundaryOptions, FlightError, type FlightErrorOptions, type FlightErrorProps, ForbiddenError, type GenerateMetadataFn, type GenerateMetadataFunction, type GenerateStaticParamsFunction, type ISRCacheAdapter, type ISRCacheEntry, InternalError, type Metadata, NotFoundError, type PageMetadata, type PageModule, type PrerenderError, type PrerenderOptions, type PrerenderProgress, type PrerenderResult, type PrerenderSummary, type ResetDetails, type RevalidateHandlerOptions, type RevalidationResult, type RouteRule, type RouteRules, type StaticParams, UnauthorizedError, VERSION, buildCacheControlHeader, clearError, createDefaultRouteRules, createDevToolsData, createError, createErrorResponse, forbidden as createForbidden, createHtmlStream, createISRCacheFromFlightCache, createMemoryISRCache, notFound as createNotFound, createRevalidateHandler, createStreamingResponse as createStaticStreamingResponse, unauthorized as createUnauthorized, expandDynamicRoutes, extractLinks, generateAllStaticPaths, getCacheOptionsFromRule, getEnvironment, getError, getErrorStatusCode, getISRCache, getOrGeneratePage, getRenderModeFromRule, getRevalidateTime, injectDevTools, isBrowser, isDevToolsEnabled, isDevelopment, isFlightError, isForbiddenError as isForbidden, isNotFoundError as isNotFound, isProduction, isServer, isTest, isUnauthorizedError as isUnauthorized, matchRouteRule, mergeMetadata, mergeRouteRules, prerenderRoutes, purgeAllPages, purgePage, renderMetadataToHead, resolveMetadata, revalidatePath, revalidatePaths, revalidateTag, setISRCache, shouldDynamicallyRender, showError, wrapWithDigest };
|
package/dist/index.js
CHANGED
|
@@ -875,9 +875,244 @@ function createDevToolsData(startTime, options = {}) {
|
|
|
875
875
|
};
|
|
876
876
|
}
|
|
877
877
|
|
|
878
|
+
// src/utils/env.ts
|
|
879
|
+
function isProduction() {
|
|
880
|
+
if (typeof globalThis !== "undefined" && "process" in globalThis) {
|
|
881
|
+
const proc = globalThis.process;
|
|
882
|
+
return proc?.env?.NODE_ENV === "production";
|
|
883
|
+
}
|
|
884
|
+
if (typeof import.meta !== "undefined" && "env" in import.meta) {
|
|
885
|
+
const env = import.meta.env;
|
|
886
|
+
return env?.MODE === "production" || env?.PROD === true;
|
|
887
|
+
}
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
function isDevelopment() {
|
|
891
|
+
if (typeof globalThis !== "undefined" && "process" in globalThis) {
|
|
892
|
+
const proc = globalThis.process;
|
|
893
|
+
return proc?.env?.NODE_ENV === "development";
|
|
894
|
+
}
|
|
895
|
+
if (typeof import.meta !== "undefined" && "env" in import.meta) {
|
|
896
|
+
const env = import.meta.env;
|
|
897
|
+
return env?.MODE === "development" || env?.DEV === true;
|
|
898
|
+
}
|
|
899
|
+
return true;
|
|
900
|
+
}
|
|
901
|
+
function isTest() {
|
|
902
|
+
if (typeof globalThis !== "undefined" && "process" in globalThis) {
|
|
903
|
+
const proc = globalThis.process;
|
|
904
|
+
return proc?.env?.NODE_ENV === "test";
|
|
905
|
+
}
|
|
906
|
+
return false;
|
|
907
|
+
}
|
|
908
|
+
function isServer() {
|
|
909
|
+
return typeof window === "undefined";
|
|
910
|
+
}
|
|
911
|
+
function isBrowser() {
|
|
912
|
+
return typeof window !== "undefined";
|
|
913
|
+
}
|
|
914
|
+
function getEnvironment() {
|
|
915
|
+
if (isProduction()) return "production";
|
|
916
|
+
if (isDevelopment()) return "development";
|
|
917
|
+
if (isTest()) return "test";
|
|
918
|
+
return "unknown";
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/errors/index.ts
|
|
922
|
+
var FlightError = class extends Error {
|
|
923
|
+
/** HTTP status code */
|
|
924
|
+
statusCode;
|
|
925
|
+
/** Short status message */
|
|
926
|
+
statusMessage;
|
|
927
|
+
/** Additional error data */
|
|
928
|
+
data;
|
|
929
|
+
/** Whether this is a fatal error (shows full-screen) */
|
|
930
|
+
fatal;
|
|
931
|
+
/** Unique digest for production error correlation */
|
|
932
|
+
digest;
|
|
933
|
+
constructor(options) {
|
|
934
|
+
super(options.message || options.statusMessage || "An error occurred");
|
|
935
|
+
this.name = "FlightError";
|
|
936
|
+
this.statusCode = options.statusCode;
|
|
937
|
+
this.statusMessage = options.statusMessage || getDefaultStatusMessage(options.statusCode);
|
|
938
|
+
this.data = options.data;
|
|
939
|
+
this.fatal = options.fatal ?? false;
|
|
940
|
+
if (isProduction()) {
|
|
941
|
+
this.digest = generateDigest();
|
|
942
|
+
}
|
|
943
|
+
if (options.cause) {
|
|
944
|
+
this.cause = options.cause;
|
|
945
|
+
if (options.cause.stack) {
|
|
946
|
+
this.stack = `${this.stack}
|
|
947
|
+
Caused by: ${options.cause.stack}`;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Convert to plain object for serialization
|
|
953
|
+
*/
|
|
954
|
+
toJSON() {
|
|
955
|
+
return {
|
|
956
|
+
name: this.name,
|
|
957
|
+
message: this.message,
|
|
958
|
+
statusCode: this.statusCode,
|
|
959
|
+
statusMessage: this.statusMessage,
|
|
960
|
+
data: this.data,
|
|
961
|
+
fatal: this.fatal,
|
|
962
|
+
digest: this.digest
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
var BadRequestError = class extends FlightError {
|
|
967
|
+
constructor(message, data) {
|
|
968
|
+
super({ statusCode: 400, message, data });
|
|
969
|
+
this.name = "BadRequestError";
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
var UnauthorizedError = class extends FlightError {
|
|
973
|
+
constructor(message, data) {
|
|
974
|
+
super({ statusCode: 401, message: message || "Unauthorized", data });
|
|
975
|
+
this.name = "UnauthorizedError";
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
var ForbiddenError = class extends FlightError {
|
|
979
|
+
constructor(message, data) {
|
|
980
|
+
super({ statusCode: 403, message: message || "Forbidden", data });
|
|
981
|
+
this.name = "ForbiddenError";
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
var NotFoundError = class extends FlightError {
|
|
985
|
+
constructor(message, data) {
|
|
986
|
+
super({ statusCode: 404, message: message || "Not Found", data });
|
|
987
|
+
this.name = "NotFoundError";
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
var InternalError = class extends FlightError {
|
|
991
|
+
constructor(message, data) {
|
|
992
|
+
super({ statusCode: 500, message: message || "Internal Server Error", data });
|
|
993
|
+
this.name = "InternalError";
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
function createError(options) {
|
|
997
|
+
if (typeof options === "string") {
|
|
998
|
+
return new FlightError({ statusCode: 500, message: options });
|
|
999
|
+
}
|
|
1000
|
+
return new FlightError(options);
|
|
1001
|
+
}
|
|
1002
|
+
function notFound2(message, data) {
|
|
1003
|
+
throw new NotFoundError(message, data);
|
|
1004
|
+
}
|
|
1005
|
+
function forbidden(message, data) {
|
|
1006
|
+
throw new ForbiddenError(message, data);
|
|
1007
|
+
}
|
|
1008
|
+
function unauthorized(message, data) {
|
|
1009
|
+
throw new UnauthorizedError(message, data);
|
|
1010
|
+
}
|
|
1011
|
+
function showError(error2) {
|
|
1012
|
+
let flightError;
|
|
1013
|
+
if (typeof error2 === "string") {
|
|
1014
|
+
flightError = new FlightError({ statusCode: 500, message: error2 });
|
|
1015
|
+
} else if (error2 instanceof FlightError) {
|
|
1016
|
+
flightError = error2;
|
|
1017
|
+
} else {
|
|
1018
|
+
flightError = new FlightError(error2);
|
|
1019
|
+
}
|
|
1020
|
+
if (typeof window !== "undefined") {
|
|
1021
|
+
window.__FLIGHT_ERROR__ = flightError;
|
|
1022
|
+
window.dispatchEvent(new CustomEvent("flight:error", {
|
|
1023
|
+
detail: flightError,
|
|
1024
|
+
bubbles: true
|
|
1025
|
+
}));
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
function clearError(options) {
|
|
1029
|
+
if (typeof window !== "undefined") {
|
|
1030
|
+
window.__FLIGHT_ERROR__ = null;
|
|
1031
|
+
window.dispatchEvent(new CustomEvent("flight:error-clear", { bubbles: true }));
|
|
1032
|
+
if (options?.redirect) {
|
|
1033
|
+
window.location.href = options.redirect;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
function getError() {
|
|
1038
|
+
if (typeof window !== "undefined") {
|
|
1039
|
+
return window.__FLIGHT_ERROR__ ?? null;
|
|
1040
|
+
}
|
|
1041
|
+
return null;
|
|
1042
|
+
}
|
|
1043
|
+
function isFlightError(error2) {
|
|
1044
|
+
return error2 instanceof FlightError;
|
|
1045
|
+
}
|
|
1046
|
+
function isNotFoundError2(error2) {
|
|
1047
|
+
return error2 instanceof NotFoundError || isFlightError(error2) && error2.statusCode === 404;
|
|
1048
|
+
}
|
|
1049
|
+
function isForbiddenError(error2) {
|
|
1050
|
+
return error2 instanceof ForbiddenError || isFlightError(error2) && error2.statusCode === 403;
|
|
1051
|
+
}
|
|
1052
|
+
function isUnauthorizedError(error2) {
|
|
1053
|
+
return error2 instanceof UnauthorizedError || isFlightError(error2) && error2.statusCode === 401;
|
|
1054
|
+
}
|
|
1055
|
+
function getErrorStatusCode(error2) {
|
|
1056
|
+
if (isFlightError(error2)) {
|
|
1057
|
+
return error2.statusCode;
|
|
1058
|
+
}
|
|
1059
|
+
return 500;
|
|
1060
|
+
}
|
|
1061
|
+
function createErrorResponse(error2) {
|
|
1062
|
+
const flightError = isFlightError(error2) ? error2 : new InternalError(error2 instanceof Error ? error2.message : "Unknown error");
|
|
1063
|
+
return new Response(
|
|
1064
|
+
JSON.stringify({
|
|
1065
|
+
error: flightError.statusMessage,
|
|
1066
|
+
message: flightError.message,
|
|
1067
|
+
statusCode: flightError.statusCode,
|
|
1068
|
+
digest: flightError.digest,
|
|
1069
|
+
...isDevelopment() && flightError.data ? { data: flightError.data } : {}
|
|
1070
|
+
}),
|
|
1071
|
+
{
|
|
1072
|
+
status: flightError.statusCode,
|
|
1073
|
+
headers: {
|
|
1074
|
+
"Content-Type": "application/json"
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
function getDefaultStatusMessage(statusCode) {
|
|
1080
|
+
const messages = {
|
|
1081
|
+
400: "Bad Request",
|
|
1082
|
+
401: "Unauthorized",
|
|
1083
|
+
403: "Forbidden",
|
|
1084
|
+
404: "Not Found",
|
|
1085
|
+
405: "Method Not Allowed",
|
|
1086
|
+
408: "Request Timeout",
|
|
1087
|
+
409: "Conflict",
|
|
1088
|
+
410: "Gone",
|
|
1089
|
+
422: "Unprocessable Entity",
|
|
1090
|
+
429: "Too Many Requests",
|
|
1091
|
+
500: "Internal Server Error",
|
|
1092
|
+
501: "Not Implemented",
|
|
1093
|
+
502: "Bad Gateway",
|
|
1094
|
+
503: "Service Unavailable",
|
|
1095
|
+
504: "Gateway Timeout"
|
|
1096
|
+
};
|
|
1097
|
+
return messages[statusCode] || "Error";
|
|
1098
|
+
}
|
|
1099
|
+
function generateDigest() {
|
|
1100
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
1101
|
+
return crypto.randomUUID().slice(0, 8);
|
|
1102
|
+
}
|
|
1103
|
+
return Math.random().toString(36).slice(2, 10);
|
|
1104
|
+
}
|
|
1105
|
+
function wrapWithDigest(error2) {
|
|
1106
|
+
const wrapped = error2;
|
|
1107
|
+
if (!wrapped.digest) {
|
|
1108
|
+
wrapped.digest = generateDigest();
|
|
1109
|
+
}
|
|
1110
|
+
return wrapped;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
878
1113
|
// src/index.ts
|
|
879
1114
|
var VERSION = "0.0.1";
|
|
880
1115
|
|
|
881
|
-
export { VERSION, buildCacheControlHeader, createDefaultRouteRules, createDevToolsData, createHtmlStream, createISRCacheFromFlightCache, createMemoryISRCache, createRevalidateHandler, createStreamingResponse3 as createStaticStreamingResponse, expandDynamicRoutes, extractLinks, generateAllStaticPaths, getCacheOptionsFromRule, getISRCache, getOrGeneratePage, getRenderModeFromRule, getRevalidateTime, injectDevTools, isDevToolsEnabled, matchRouteRule, mergeMetadata, mergeRouteRules, prerenderRoutes, purgeAllPages, purgePage, renderMetadataToHead, resolveMetadata, revalidatePath2 as revalidatePath, revalidatePaths, revalidateTag2 as revalidateTag, setISRCache, shouldDynamicallyRender };
|
|
1116
|
+
export { BadRequestError, FlightError, ForbiddenError, InternalError, NotFoundError, UnauthorizedError, VERSION, buildCacheControlHeader, clearError, createDefaultRouteRules, createDevToolsData, createError, createErrorResponse, forbidden as createForbidden, createHtmlStream, createISRCacheFromFlightCache, createMemoryISRCache, notFound2 as createNotFound, createRevalidateHandler, createStreamingResponse3 as createStaticStreamingResponse, unauthorized as createUnauthorized, expandDynamicRoutes, extractLinks, generateAllStaticPaths, getCacheOptionsFromRule, getEnvironment, getError, getErrorStatusCode, getISRCache, getOrGeneratePage, getRenderModeFromRule, getRevalidateTime, injectDevTools, isBrowser, isDevToolsEnabled, isDevelopment, isFlightError, isForbiddenError as isForbidden, isNotFoundError2 as isNotFound, isProduction, isServer, isTest, isUnauthorizedError as isUnauthorized, matchRouteRule, mergeMetadata, mergeRouteRules, prerenderRoutes, purgeAllPages, purgePage, renderMetadataToHead, resolveMetadata, revalidatePath2 as revalidatePath, revalidatePaths, revalidateTag2 as revalidateTag, setISRCache, shouldDynamicallyRender, showError, wrapWithDigest };
|
|
882
1117
|
//# sourceMappingURL=index.js.map
|
|
883
1118
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/route-rules.ts","../src/render/revalidate.ts","../src/build/prerender.ts","../src/render/static.ts","../src/render/metadata.ts","../src/render/devtools.ts","../src/index.ts"],"names":["revalidatePath","error","revalidateTag","fs","cached","createStreamingResponse"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * @flight-framework/core - Route Rules Configuration\r\n * \r\n * Nuxt-inspired route rules for per-route rendering configuration.\r\n * Define SSR, SSG, ISR, SWR, and caching strategies per route pattern.\r\n * \r\n * @example\r\n * ```typescript\r\n * const routeRules: RouteRules = {\r\n * '/': { prerender: true },\r\n * '/blog': { isr: 3600 },\r\n * '/blog/**': { swr: 3600 },\r\n * '/admin/**': { ssr: false },\r\n * '/api/**': { cache: { ttl: 60 } }\r\n * };\r\n * ```\r\n */\r\n\r\nimport type { CacheOptions } from '../cache/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Route rule configuration\r\n */\r\nexport interface RouteRule {\r\n /** Pre-render at build time (SSG) */\r\n prerender?: boolean;\r\n\r\n /** \r\n * Stale-While-Revalidate caching\r\n * - true: use default TTL\r\n * - number: TTL in seconds\r\n */\r\n swr?: number | boolean;\r\n\r\n /** \r\n * Incremental Static Regeneration\r\n * - true: regenerate on next deploy\r\n * - number: revalidate every N seconds\r\n */\r\n isr?: number | boolean;\r\n\r\n /** \r\n * Enable/disable SSR for this route\r\n * - false: client-side only rendering\r\n */\r\n ssr?: boolean;\r\n\r\n /** Custom cache options */\r\n cache?: CacheOptions;\r\n\r\n /** Response headers to add */\r\n headers?: Record<string, string>;\r\n\r\n /** Redirect to another path */\r\n redirect?: string | { to: string; statusCode?: 301 | 302 | 307 | 308 };\r\n\r\n /** CORS headers */\r\n cors?: boolean | {\r\n origin?: string | string[];\r\n methods?: string[];\r\n credentials?: boolean;\r\n };\r\n\r\n /** Cache tags for invalidation */\r\n tags?: string[];\r\n}\r\n\r\n/**\r\n * Route rules map - patterns to rules\r\n * Supports glob patterns: **, *, [param]\r\n */\r\nexport type RouteRules = Record<string, RouteRule>;\r\n\r\n// ============================================================================\r\n// Route Rule Matching\r\n// ============================================================================\r\n\r\n/**\r\n * Match a path against route rules and return the matching rule\r\n */\r\nexport function matchRouteRule(path: string, rules: RouteRules): RouteRule | undefined {\r\n // First, try exact match\r\n if (rules[path]) {\r\n return rules[path];\r\n }\r\n\r\n // Sort patterns by specificity (longer patterns first)\r\n const patterns = Object.keys(rules).sort((a, b) => {\r\n // Exact matches first\r\n if (!a.includes('*') && b.includes('*')) return -1;\r\n if (a.includes('*') && !b.includes('*')) return 1;\r\n // Then by length\r\n return b.length - a.length;\r\n });\r\n\r\n // Try pattern matching\r\n for (const pattern of patterns) {\r\n if (matchPattern(path, pattern)) {\r\n return rules[pattern];\r\n }\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Match a path against a glob pattern\r\n */\r\nfunction matchPattern(path: string, pattern: string): boolean {\r\n // Exact match\r\n if (pattern === path) {\r\n return true;\r\n }\r\n\r\n // Convert glob pattern to regex\r\n const regexPattern = pattern\r\n // Escape special regex chars except * and **\r\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\r\n // ** matches any path segments\r\n .replace(/\\*\\*/g, '.*')\r\n // * matches a single path segment\r\n .replace(/\\*/g, '[^/]*')\r\n // [param] matches a single path segment\r\n .replace(/\\[([^\\]]+)\\]/g, '[^/]+');\r\n\r\n const regex = new RegExp(`^${regexPattern}$`);\r\n return regex.test(path);\r\n}\r\n\r\n/**\r\n * Merge multiple route rules (later rules override earlier)\r\n */\r\nexport function mergeRouteRules(...rules: (RouteRule | undefined)[]): RouteRule {\r\n const result: RouteRule = {};\r\n\r\n for (const rule of rules) {\r\n if (!rule) continue;\r\n\r\n Object.assign(result, rule);\r\n\r\n // Deep merge headers\r\n if (rule.headers) {\r\n result.headers = { ...result.headers, ...rule.headers };\r\n }\r\n\r\n // Deep merge cache options\r\n if (rule.cache) {\r\n result.cache = { ...result.cache, ...rule.cache };\r\n }\r\n\r\n // Merge tags\r\n if (rule.tags) {\r\n result.tags = [...(result.tags || []), ...rule.tags];\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Rule Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Get effective render mode from route rule\r\n */\r\nexport function getRenderModeFromRule(rule: RouteRule): 'ssr' | 'ssg' | 'isr' | 'csr' {\r\n if (rule.ssr === false) {\r\n return 'csr';\r\n }\r\n\r\n if (rule.prerender) {\r\n return 'ssg';\r\n }\r\n\r\n if (rule.isr !== undefined) {\r\n return 'isr';\r\n }\r\n\r\n // Default to SSR\r\n return 'ssr';\r\n}\r\n\r\n/**\r\n * Get revalidation time from rule (in seconds)\r\n */\r\nexport function getRevalidateTime(rule: RouteRule): number | false {\r\n // ISR takes precedence\r\n if (rule.isr !== undefined) {\r\n if (rule.isr === true) {\r\n return false; // Revalidate on deploy only\r\n }\r\n return typeof rule.isr === 'number' ? rule.isr : 60;\r\n }\r\n\r\n // SWR\r\n if (rule.swr !== undefined) {\r\n if (rule.swr === true) {\r\n return 60; // Default 1 minute\r\n }\r\n return typeof rule.swr === 'number' ? rule.swr : 60;\r\n }\r\n\r\n // No revalidation\r\n return false;\r\n}\r\n\r\n/**\r\n * Get cache options from rule\r\n */\r\nexport function getCacheOptionsFromRule(rule: RouteRule): CacheOptions | undefined {\r\n const revalidate = getRevalidateTime(rule);\r\n\r\n if (revalidate === false && !rule.cache) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n ttl: revalidate || rule.cache?.ttl,\r\n swr: rule.swr !== undefined ? (typeof rule.swr === 'number' ? rule.swr : 60) : undefined,\r\n tags: rule.tags || rule.cache?.tags,\r\n };\r\n}\r\n\r\n/**\r\n * Build cache-control header from rule\r\n */\r\nexport function buildCacheControlHeader(rule: RouteRule): string | undefined {\r\n const revalidate = getRevalidateTime(rule);\r\n\r\n if (rule.ssr === false) {\r\n return 'no-store';\r\n }\r\n\r\n if (rule.prerender && revalidate === false) {\r\n return 'public, max-age=31536000, immutable';\r\n }\r\n\r\n if (revalidate !== false) {\r\n const maxAge = revalidate;\r\n const swr = rule.swr !== undefined ? (typeof rule.swr === 'number' ? rule.swr : 60) : 0;\r\n\r\n if (swr > 0) {\r\n return `public, max-age=${maxAge}, stale-while-revalidate=${swr}`;\r\n }\r\n\r\n return `public, max-age=${maxAge}`;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n// ============================================================================\r\n// Default Rules\r\n// ============================================================================\r\n\r\n/**\r\n * Create default route rules\r\n */\r\nexport function createDefaultRouteRules(): RouteRules {\r\n return {\r\n // API routes: no cache by default\r\n '/api/**': { ssr: true, cache: { ttl: 0 } },\r\n // Static assets: cache forever\r\n '/_static/**': { headers: { 'Cache-Control': 'public, max-age=31536000, immutable' } },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - On-Demand Revalidation\r\n * \r\n * APIs for on-demand cache invalidation and page revalidation.\r\n * Similar to Next.js revalidatePath() and revalidateTag().\r\n * \r\n * @example\r\n * ```typescript\r\n * // In an API route\r\n * import { revalidatePath, revalidateTag } from '@flight-framework/core';\r\n * \r\n * app.post('/api/revalidate', async (c) => {\r\n * const { path, tag } = await c.req.json();\r\n * \r\n * if (path) await revalidatePath(path);\r\n * if (tag) await revalidateTag(tag);\r\n * \r\n * return c.json({ revalidated: true });\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { Cache, CacheOptions } from '../cache/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * ISR Cache entry for rendered pages\r\n */\r\nexport interface ISRCacheEntry {\r\n /** Rendered HTML content */\r\n html: string;\r\n /** HTTP status code */\r\n status: number;\r\n /** Response headers */\r\n headers: Record<string, string>;\r\n /** When this entry was generated */\r\n generatedAt: number;\r\n /** When this entry should be revalidated */\r\n revalidateAfter?: number;\r\n /** Cache tags for invalidation */\r\n tags?: string[];\r\n}\r\n\r\n/**\r\n * ISR Cache adapter interface\r\n */\r\nexport interface ISRCacheAdapter {\r\n /** Get cached page */\r\n get(path: string): Promise<ISRCacheEntry | undefined>;\r\n /** Set cached page */\r\n set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void>;\r\n /** Delete cached page */\r\n delete(path: string): Promise<boolean>;\r\n /** Invalidate by tag */\r\n invalidateTag(tag: string): Promise<void>;\r\n /** Get all cached paths */\r\n keys?(): Promise<string[]>;\r\n}\r\n\r\n/**\r\n * Revalidation result\r\n */\r\nexport interface RevalidationResult {\r\n /** Whether revalidation was successful */\r\n success: boolean;\r\n /** Paths that were revalidated */\r\n paths?: string[];\r\n /** Error if failed */\r\n error?: string;\r\n /** Timestamp */\r\n timestamp: number;\r\n}\r\n\r\n// ============================================================================\r\n// Global ISR Cache Instance\r\n// ============================================================================\r\n\r\nlet globalISRCache: ISRCacheAdapter | null = null;\r\n\r\n/**\r\n * Set the global ISR cache adapter\r\n */\r\nexport function setISRCache(cache: ISRCacheAdapter): void {\r\n globalISRCache = cache;\r\n}\r\n\r\n/**\r\n * Get the global ISR cache adapter\r\n */\r\nexport function getISRCache(): ISRCacheAdapter | null {\r\n return globalISRCache;\r\n}\r\n\r\n// ============================================================================\r\n// In-Memory ISR Cache Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Create an in-memory ISR cache\r\n */\r\nexport function createMemoryISRCache(): ISRCacheAdapter {\r\n const store = new Map<string, ISRCacheEntry>();\r\n const tagIndex = new Map<string, Set<string>>();\r\n\r\n return {\r\n async get(path: string): Promise<ISRCacheEntry | undefined> {\r\n const entry = store.get(path);\r\n if (!entry) return undefined;\r\n\r\n // Check if expired\r\n if (entry.revalidateAfter && Date.now() > entry.revalidateAfter) {\r\n // Return stale entry (SWR pattern - caller decides to regenerate)\r\n return entry;\r\n }\r\n\r\n return entry;\r\n },\r\n\r\n async set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void> {\r\n store.set(path, entry);\r\n\r\n // Update tag index\r\n const tags = entry.tags || options?.tags || [];\r\n for (const tag of tags) {\r\n if (!tagIndex.has(tag)) {\r\n tagIndex.set(tag, new Set());\r\n }\r\n tagIndex.get(tag)!.add(path);\r\n }\r\n },\r\n\r\n async delete(path: string): Promise<boolean> {\r\n return store.delete(path);\r\n },\r\n\r\n async invalidateTag(tag: string): Promise<void> {\r\n const paths = tagIndex.get(tag);\r\n if (!paths) return;\r\n\r\n for (const path of paths) {\r\n store.delete(path);\r\n }\r\n tagIndex.delete(tag);\r\n },\r\n\r\n async keys(): Promise<string[]> {\r\n return Array.from(store.keys());\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Revalidation Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Revalidate a specific path\r\n * Removes the cached page so next request regenerates it\r\n */\r\nexport async function revalidatePath(path: string): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n try {\r\n const deleted = await cache.delete(path);\r\n\r\n return {\r\n success: deleted,\r\n paths: deleted ? [path] : [],\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Revalidate all paths associated with a tag\r\n */\r\nexport async function revalidateTag(tag: string): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n try {\r\n await cache.invalidateTag(tag);\r\n\r\n return {\r\n success: true,\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Revalidate multiple paths\r\n */\r\nexport async function revalidatePaths(paths: string[]): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n const revalidated: string[] = [];\r\n\r\n try {\r\n for (const path of paths) {\r\n const deleted = await cache.delete(path);\r\n if (deleted) {\r\n revalidated.push(path);\r\n }\r\n }\r\n\r\n return {\r\n success: true,\r\n paths: revalidated,\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n paths: revalidated,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Revalidation Handler (for API routes)\r\n// ============================================================================\r\n\r\nexport interface RevalidateHandlerOptions {\r\n /** Secret token for authentication */\r\n secret?: string;\r\n /** Header name for the secret */\r\n headerName?: string;\r\n}\r\n\r\n/**\r\n * Create a revalidation handler for API routes\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createRevalidateHandler } from '@flight-framework/core';\r\n * \r\n * const handler = createRevalidateHandler({ \r\n * secret: process.env.REVALIDATE_SECRET \r\n * });\r\n * \r\n * app.post('/api/revalidate', handler);\r\n * ```\r\n */\r\nexport function createRevalidateHandler(options: RevalidateHandlerOptions = {}) {\r\n const { secret, headerName = 'x-revalidate-token' } = options;\r\n\r\n return async (request: Request): Promise<Response> => {\r\n // Verify secret if configured\r\n if (secret) {\r\n const token = request.headers.get(headerName);\r\n if (token !== secret) {\r\n return new Response(\r\n JSON.stringify({ error: 'Invalid revalidation token' }),\r\n { status: 401, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n }\r\n\r\n try {\r\n const body = await request.json() as {\r\n path?: string;\r\n paths?: string[];\r\n tag?: string;\r\n tags?: string[];\r\n };\r\n\r\n const results: RevalidationResult[] = [];\r\n\r\n // Revalidate by path\r\n if (body.path) {\r\n results.push(await revalidatePath(body.path));\r\n }\r\n\r\n // Revalidate by paths\r\n if (body.paths && body.paths.length > 0) {\r\n results.push(await revalidatePaths(body.paths));\r\n }\r\n\r\n // Revalidate by tag\r\n if (body.tag) {\r\n results.push(await revalidateTag(body.tag));\r\n }\r\n\r\n // Revalidate by tags\r\n if (body.tags && body.tags.length > 0) {\r\n for (const tag of body.tags) {\r\n results.push(await revalidateTag(tag));\r\n }\r\n }\r\n\r\n const success = results.every(r => r.success);\r\n\r\n return new Response(\r\n JSON.stringify({\r\n revalidated: success,\r\n results,\r\n timestamp: Date.now(),\r\n }),\r\n {\r\n status: success ? 200 : 500,\r\n headers: { 'Content-Type': 'application/json' }\r\n }\r\n );\r\n } catch (error) {\r\n return new Response(\r\n JSON.stringify({\r\n error: 'Invalid request body',\r\n message: error instanceof Error ? error.message : 'Unknown error',\r\n }),\r\n { status: 400, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Wrap Flight Cache as ISR Cache\r\n// ============================================================================\r\n\r\n/**\r\n * Create an ISR cache adapter from a Flight Cache instance\r\n */\r\nexport function createISRCacheFromFlightCache(cache: Cache): ISRCacheAdapter {\r\n const ISR_PREFIX = 'isr:';\r\n\r\n return {\r\n async get(path: string): Promise<ISRCacheEntry | undefined> {\r\n return cache.get<ISRCacheEntry>(`${ISR_PREFIX}${path}`);\r\n },\r\n\r\n async set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void> {\r\n const ttl = entry.revalidateAfter\r\n ? Math.floor((entry.revalidateAfter - Date.now()) / 1000)\r\n : options?.ttl;\r\n\r\n await cache.set(`${ISR_PREFIX}${path}`, entry, {\r\n ...options,\r\n ttl: ttl && ttl > 0 ? ttl : undefined,\r\n tags: entry.tags || options?.tags,\r\n });\r\n },\r\n\r\n async delete(path: string): Promise<boolean> {\r\n return cache.delete(`${ISR_PREFIX}${path}`);\r\n },\r\n\r\n async invalidateTag(tag: string): Promise<void> {\r\n await cache.invalidateTag(tag);\r\n },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Build-Time Prerender\r\n * \r\n * Static site generation build utilities.\r\n * Pre-renders routes to HTML files at build time.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { prerenderRoutes } from '@flight-framework/core';\r\n * \r\n * await prerenderRoutes({\r\n * routes: ['/','blog/hello', '/about'],\r\n * outDir: './dist',\r\n * renderFn: async (path) => await renderPage(path),\r\n * });\r\n * ```\r\n */\r\n\r\nimport { promises as fs } from 'fs';\r\nimport { join, dirname } from 'path';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Options for prerendering routes\r\n */\r\nexport interface PrerenderOptions {\r\n /** Routes to prerender */\r\n routes: string[] | (() => Promise<string[]>);\r\n /** Output directory */\r\n outDir: string;\r\n /** Render function that generates HTML for a path */\r\n renderFn: (path: string) => Promise<PrerenderResult>;\r\n /** Concurrency limit */\r\n concurrency?: number;\r\n /** Progress callback */\r\n onProgress?: (progress: PrerenderProgress) => void;\r\n /** Error callback */\r\n onError?: (error: PrerenderError) => void;\r\n /** Whether to crawl links from rendered pages */\r\n crawlLinks?: boolean;\r\n}\r\n\r\n/**\r\n * Result from rendering a single page\r\n */\r\nexport interface PrerenderResult {\r\n /** HTML content */\r\n html: string;\r\n /** HTTP status code */\r\n status?: number;\r\n /** Response headers */\r\n headers?: Record<string, string>;\r\n /** Links found in the page (for crawling) */\r\n links?: string[];\r\n}\r\n\r\n/**\r\n * Progress callback data\r\n */\r\nexport interface PrerenderProgress {\r\n /** Current route being processed */\r\n currentRoute: string;\r\n /** Number of routes completed */\r\n completed: number;\r\n /** Total number of routes */\r\n total: number;\r\n /** Percentage complete */\r\n percentage: number;\r\n}\r\n\r\n/**\r\n * Error callback data\r\n */\r\nexport interface PrerenderError {\r\n /** Route that failed */\r\n route: string;\r\n /** Error message */\r\n error: Error;\r\n}\r\n\r\n/**\r\n * Summary of prerender operation\r\n */\r\nexport interface PrerenderSummary {\r\n /** Total routes processed */\r\n total: number;\r\n /** Successfully rendered routes */\r\n success: number;\r\n /** Failed routes */\r\n failed: number;\r\n /** Routes that were discovered via crawling */\r\n discovered?: number;\r\n /** Time taken in milliseconds */\r\n duration: number;\r\n /** List of generated files */\r\n files: string[];\r\n /** List of errors */\r\n errors: PrerenderError[];\r\n}\r\n\r\n// ============================================================================\r\n// Prerender Engine\r\n// ============================================================================\r\n\r\n/**\r\n * Prerender multiple routes to static HTML files\r\n */\r\nexport async function prerenderRoutes(options: PrerenderOptions): Promise<PrerenderSummary> {\r\n const {\r\n routes,\r\n outDir,\r\n renderFn,\r\n concurrency = 10,\r\n onProgress,\r\n onError,\r\n crawlLinks = false,\r\n } = options;\r\n\r\n const startTime = Date.now();\r\n const errors: PrerenderError[] = [];\r\n const files: string[] = [];\r\n const processedRoutes = new Set<string>();\r\n\r\n // Get initial routes\r\n const routeQueue = typeof routes === 'function' ? await routes() : [...routes];\r\n let discoveredCount = 0;\r\n\r\n // Ensure output directory exists\r\n await fs.mkdir(outDir, { recursive: true });\r\n\r\n // Process routes in batches\r\n let completed = 0;\r\n const total = routeQueue.length;\r\n\r\n while (routeQueue.length > 0) {\r\n // Take a batch\r\n const batch = routeQueue.splice(0, concurrency);\r\n\r\n // Process batch concurrently\r\n const results = await Promise.allSettled(\r\n batch.map(async (route) => {\r\n // Skip if already processed\r\n if (processedRoutes.has(route)) {\r\n return null;\r\n }\r\n processedRoutes.add(route);\r\n\r\n // Report progress\r\n if (onProgress) {\r\n onProgress({\r\n currentRoute: route,\r\n completed,\r\n total: total + discoveredCount,\r\n percentage: Math.round((completed / (total + discoveredCount)) * 100),\r\n });\r\n }\r\n\r\n // Render the page\r\n const result = await renderFn(route);\r\n\r\n // Write to file\r\n const filePath = getOutputPath(route, outDir);\r\n await ensureDir(dirname(filePath));\r\n await fs.writeFile(filePath, result.html, 'utf-8');\r\n\r\n files.push(filePath);\r\n completed++;\r\n\r\n // Return links for crawling\r\n return result.links || [];\r\n })\r\n );\r\n\r\n // Handle results\r\n for (let i = 0; i < results.length; i++) {\r\n const result = results[i];\r\n const route = batch[i];\r\n\r\n if (result.status === 'rejected') {\r\n const error = { route, error: result.reason };\r\n errors.push(error);\r\n if (onError) {\r\n onError(error);\r\n }\r\n } else if (crawlLinks && result.value) {\r\n // Add discovered links to process queue\r\n for (const link of result.value) {\r\n if (!processedRoutes.has(link) && !routeQueue.includes(link)) {\r\n routeQueue.push(link);\r\n discoveredCount++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n total: processedRoutes.size,\r\n success: files.length,\r\n failed: errors.length,\r\n discovered: discoveredCount,\r\n duration: Date.now() - startTime,\r\n files,\r\n errors,\r\n };\r\n}\r\n\r\n/**\r\n * Get output file path for a route\r\n */\r\nfunction getOutputPath(route: string, outDir: string): string {\r\n // Normalize route\r\n let normalizedRoute = route;\r\n\r\n if (!normalizedRoute.startsWith('/')) {\r\n normalizedRoute = '/' + normalizedRoute;\r\n }\r\n\r\n // Handle index routes\r\n if (normalizedRoute === '/') {\r\n return join(outDir, 'index.html');\r\n }\r\n\r\n // Handle trailing slashes\r\n if (normalizedRoute.endsWith('/')) {\r\n return join(outDir, normalizedRoute, 'index.html');\r\n }\r\n\r\n // Handle routes without extension\r\n if (!normalizedRoute.includes('.')) {\r\n return join(outDir, normalizedRoute + '.html');\r\n }\r\n\r\n return join(outDir, normalizedRoute);\r\n}\r\n\r\n/**\r\n * Ensure directory exists\r\n */\r\nasync function ensureDir(dir: string): Promise<void> {\r\n try {\r\n await fs.mkdir(dir, { recursive: true });\r\n } catch (error: unknown) {\r\n // Ignore if directory already exists\r\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\r\n throw error;\r\n }\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Link Extraction (for crawling)\r\n// ============================================================================\r\n\r\n/**\r\n * Extract internal links from HTML\r\n */\r\nexport function extractLinks(html: string, baseUrl?: string): string[] {\r\n const links: string[] = [];\r\n const linkRegex = /<a[^>]+href=[\"']([^\"']+)[\"'][^>]*>/gi;\r\n\r\n let match;\r\n while ((match = linkRegex.exec(html)) !== null) {\r\n const href = match[1];\r\n\r\n // Skip external links, anchors, and special protocols\r\n if (\r\n href.startsWith('http://') ||\r\n href.startsWith('https://') ||\r\n href.startsWith('#') ||\r\n href.startsWith('mailto:') ||\r\n href.startsWith('tel:') ||\r\n href.startsWith('javascript:')\r\n ) {\r\n continue;\r\n }\r\n\r\n // Normalize the link\r\n let normalizedLink = href;\r\n\r\n // Handle absolute paths\r\n if (href.startsWith('/')) {\r\n normalizedLink = href;\r\n } else if (baseUrl) {\r\n // Handle relative paths\r\n const base = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';\r\n normalizedLink = new URL(href, base).pathname;\r\n }\r\n\r\n // Remove query strings and fragments\r\n normalizedLink = normalizedLink.split('?')[0].split('#')[0];\r\n\r\n if (normalizedLink && !links.includes(normalizedLink)) {\r\n links.push(normalizedLink);\r\n }\r\n }\r\n\r\n return links;\r\n}\r\n\r\n// ============================================================================\r\n// Generate Static Params Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Expand dynamic routes with static params\r\n */\r\nexport async function expandDynamicRoutes(\r\n routePattern: string,\r\n generateParams: () => Promise<Record<string, string | string[]>[]>\r\n): Promise<string[]> {\r\n const params = await generateParams();\r\n\r\n return params.map((paramSet) => {\r\n let route = routePattern;\r\n\r\n for (const [key, value] of Object.entries(paramSet)) {\r\n const paramValue = Array.isArray(value) ? value.join('/') : value;\r\n\r\n // Replace [param] style\r\n route = route.replace(`[${key}]`, paramValue);\r\n // Replace [...param] style (catch-all)\r\n route = route.replace(`[...${key}]`, paramValue);\r\n }\r\n\r\n return route;\r\n });\r\n}\r\n","/**\r\n * @flight-framework/core - SSR/SSG/ISR Support\r\n * \r\n * Static site generation and incremental static regeneration.\r\n * Similar to Next.js patterns.\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Static params for dynamic routes\r\n */\r\nexport interface StaticParams {\r\n [key: string]: string | string[];\r\n}\r\n\r\n/**\r\n * Generate static params function signature\r\n */\r\nexport type GenerateStaticParamsFunction = () => Promise<StaticParams[]> | StaticParams[];\r\n\r\n/**\r\n * Page metadata\r\n */\r\nexport interface PageMetadata {\r\n title?: string;\r\n description?: string;\r\n keywords?: string[];\r\n openGraph?: {\r\n title?: string;\r\n description?: string;\r\n images?: string[];\r\n };\r\n}\r\n\r\n/**\r\n * Generate metadata function\r\n */\r\nexport type GenerateMetadataFunction = (params: StaticParams) => Promise<PageMetadata> | PageMetadata;\r\n\r\n/**\r\n * Page module exports\r\n */\r\nexport interface PageModule {\r\n default: (props: { params: StaticParams }) => unknown;\r\n generateStaticParams?: GenerateStaticParamsFunction;\r\n generateMetadata?: GenerateMetadataFunction;\r\n revalidate?: number | false;\r\n dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static';\r\n runtime?: 'nodejs' | 'edge';\r\n}\r\n\r\n// ============================================================================\r\n// Static Generation\r\n// ============================================================================\r\n\r\n/**\r\n * Generate all static paths for a page\r\n */\r\nexport async function generateAllStaticPaths(\r\n pageModules: Map<string, PageModule>\r\n): Promise<Map<string, StaticParams[]>> {\r\n const result = new Map<string, StaticParams[]>();\r\n\r\n for (const [path, module] of pageModules) {\r\n if (module.generateStaticParams) {\r\n try {\r\n const params = await module.generateStaticParams();\r\n result.set(path, params);\r\n } catch (error) {\r\n console.error(`[Flight] Failed to generate static params for ${path}:`, error);\r\n result.set(path, []);\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// ISR (Incremental Static Regeneration)\r\n// ============================================================================\r\n\r\ninterface CachedPage {\r\n html: string;\r\n generatedAt: number;\r\n revalidateAfter: number;\r\n}\r\n\r\nconst pageCache = new Map<string, CachedPage>();\r\n\r\n/**\r\n * Get or generate a cached page\r\n */\r\nexport async function getOrGeneratePage(\r\n path: string,\r\n generateFn: () => Promise<string>,\r\n revalidate?: number | false\r\n): Promise<{ html: string; fromCache: boolean }> {\r\n const cached = pageCache.get(path);\r\n const now = Date.now();\r\n\r\n // Check if cached page is valid\r\n if (cached) {\r\n if (revalidate === false) {\r\n // Never revalidate\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n if (now < cached.revalidateAfter) {\r\n // Still valid\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n // Stale-while-revalidate: return cached and regenerate in background\r\n regeneratePageInBackground(path, generateFn, revalidate || 60);\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n // Generate new page\r\n const html = await generateFn();\r\n\r\n // Cache the page\r\n if (revalidate !== false) {\r\n const revalidateMs = (revalidate || 60) * 1000;\r\n pageCache.set(path, {\r\n html,\r\n generatedAt: now,\r\n revalidateAfter: now + revalidateMs,\r\n });\r\n }\r\n\r\n return { html, fromCache: false };\r\n}\r\n\r\n/**\r\n * Regenerate page in background (stale-while-revalidate)\r\n */\r\nasync function regeneratePageInBackground(\r\n path: string,\r\n generateFn: () => Promise<string>,\r\n revalidate: number\r\n): Promise<void> {\r\n try {\r\n const html = await generateFn();\r\n const now = Date.now();\r\n\r\n pageCache.set(path, {\r\n html,\r\n generatedAt: now,\r\n revalidateAfter: now + (revalidate * 1000),\r\n });\r\n } catch (error) {\r\n console.error(`[Flight] Background regeneration failed for ${path}:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Purge cached page\r\n */\r\nexport function purgePage(path: string): boolean {\r\n return pageCache.delete(path);\r\n}\r\n\r\n/**\r\n * Purge all cached pages\r\n */\r\nexport function purgeAllPages(): void {\r\n pageCache.clear();\r\n}\r\n\r\n// ============================================================================\r\n// Dynamic Rendering\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a page should be dynamically rendered\r\n */\r\nexport function shouldDynamicallyRender(\r\n module: PageModule,\r\n hasParams: boolean\r\n): boolean {\r\n // Force dynamic\r\n if (module.dynamic === 'force-dynamic') {\r\n return true;\r\n }\r\n\r\n // Force static\r\n if (module.dynamic === 'force-static') {\r\n return false;\r\n }\r\n\r\n // Error on dynamic (SSG only)\r\n if (module.dynamic === 'error') {\r\n return false;\r\n }\r\n\r\n // Auto: dynamic if no generateStaticParams\r\n if (hasParams && !module.generateStaticParams) {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// ============================================================================\r\n// Streaming SSR\r\n// ============================================================================\r\n\r\n/**\r\n * Create a streaming response\r\n */\r\nexport function createStreamingResponse(\r\n stream: ReadableStream<Uint8Array>\r\n): Response {\r\n return new Response(stream, {\r\n status: 200,\r\n headers: {\r\n 'Content-Type': 'text/html; charset=utf-8',\r\n 'Transfer-Encoding': 'chunked',\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * Create a text encoder stream for HTML\r\n */\r\nexport function createHtmlStream(): {\r\n readable: ReadableStream<Uint8Array>;\r\n write: (html: string) => void;\r\n close: () => void;\r\n} {\r\n const encoder = new TextEncoder();\r\n let controller: ReadableStreamDefaultController<Uint8Array>;\r\n\r\n const readable = new ReadableStream<Uint8Array>({\r\n start(c) {\r\n controller = c;\r\n },\r\n });\r\n\r\n return {\r\n readable,\r\n write(html: string) {\r\n controller.enqueue(encoder.encode(html));\r\n },\r\n close() {\r\n controller.close();\r\n },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Metadata Rendering\r\n * \r\n * Utilities for rendering SEO metadata to HTML head tags.\r\n * Following Next.js Metadata API patterns.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { renderMetadataToHead } from '@flight-framework/core';\r\n * \r\n * const meta = {\r\n * title: 'My Page',\r\n * description: 'Page description',\r\n * openGraph: { title: 'OG Title', images: ['/og.jpg'] }\r\n * };\r\n * \r\n * const headHtml = renderMetadataToHead(meta);\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Complete metadata interface for SEO\r\n */\r\nexport interface Metadata {\r\n /** Page title */\r\n title?: string | { default: string; template?: string };\r\n /** Meta description */\r\n description?: string;\r\n /** Keywords for SEO */\r\n keywords?: string | string[];\r\n /** Canonical URL */\r\n canonical?: string;\r\n /** Robots directives */\r\n robots?: string | {\r\n index?: boolean;\r\n follow?: boolean;\r\n nocache?: boolean;\r\n googleBot?: {\r\n index?: boolean;\r\n follow?: boolean;\r\n noimageindex?: boolean;\r\n };\r\n };\r\n /** Open Graph metadata */\r\n openGraph?: {\r\n title?: string;\r\n description?: string;\r\n url?: string;\r\n siteName?: string;\r\n images?: string[] | Array<{\r\n url: string;\r\n width?: number;\r\n height?: number;\r\n alt?: string;\r\n }>;\r\n locale?: string;\r\n type?: 'website' | 'article' | 'book' | 'profile';\r\n };\r\n /** Twitter Card metadata */\r\n twitter?: {\r\n card?: 'summary' | 'summary_large_image' | 'app' | 'player';\r\n site?: string;\r\n creator?: string;\r\n title?: string;\r\n description?: string;\r\n images?: string[];\r\n };\r\n /** Favicon and icons */\r\n icons?: {\r\n icon?: string | string[];\r\n apple?: string | string[];\r\n shortcut?: string;\r\n };\r\n /** Alternate languages */\r\n alternates?: {\r\n canonical?: string;\r\n languages?: Record<string, string>;\r\n };\r\n /** Verification tokens */\r\n verification?: {\r\n google?: string;\r\n yandex?: string;\r\n bing?: string;\r\n };\r\n /** Additional custom meta tags */\r\n other?: Record<string, string>;\r\n}\r\n\r\n// ============================================================================\r\n// Metadata Rendering\r\n// ============================================================================\r\n\r\n/**\r\n * Render metadata to HTML head tags\r\n */\r\nexport function renderMetadataToHead(meta: Metadata): string {\r\n const tags: string[] = [];\r\n\r\n // Title\r\n if (meta.title) {\r\n const title = typeof meta.title === 'string'\r\n ? meta.title\r\n : meta.title.default;\r\n tags.push(`<title>${escapeHtml(title)}</title>`);\r\n }\r\n\r\n // Description\r\n if (meta.description) {\r\n tags.push(`<meta name=\"description\" content=\"${escapeAttr(meta.description)}\">`);\r\n }\r\n\r\n // Keywords\r\n if (meta.keywords) {\r\n const keywords = Array.isArray(meta.keywords)\r\n ? meta.keywords.join(', ')\r\n : meta.keywords;\r\n tags.push(`<meta name=\"keywords\" content=\"${escapeAttr(keywords)}\">`);\r\n }\r\n\r\n // Canonical\r\n if (meta.canonical) {\r\n tags.push(`<link rel=\"canonical\" href=\"${escapeAttr(meta.canonical)}\">`);\r\n }\r\n\r\n // Robots\r\n if (meta.robots) {\r\n const robotsContent = typeof meta.robots === 'string'\r\n ? meta.robots\r\n : buildRobotsContent(meta.robots);\r\n tags.push(`<meta name=\"robots\" content=\"${escapeAttr(robotsContent)}\">`);\r\n }\r\n\r\n // Open Graph\r\n if (meta.openGraph) {\r\n const og = meta.openGraph;\r\n if (og.title) tags.push(`<meta property=\"og:title\" content=\"${escapeAttr(og.title)}\">`);\r\n if (og.description) tags.push(`<meta property=\"og:description\" content=\"${escapeAttr(og.description)}\">`);\r\n if (og.url) tags.push(`<meta property=\"og:url\" content=\"${escapeAttr(og.url)}\">`);\r\n if (og.siteName) tags.push(`<meta property=\"og:site_name\" content=\"${escapeAttr(og.siteName)}\">`);\r\n if (og.type) tags.push(`<meta property=\"og:type\" content=\"${escapeAttr(og.type)}\">`);\r\n if (og.locale) tags.push(`<meta property=\"og:locale\" content=\"${escapeAttr(og.locale)}\">`);\r\n\r\n if (og.images) {\r\n for (const image of og.images) {\r\n if (typeof image === 'string') {\r\n tags.push(`<meta property=\"og:image\" content=\"${escapeAttr(image)}\">`);\r\n } else {\r\n tags.push(`<meta property=\"og:image\" content=\"${escapeAttr(image.url)}\">`);\r\n if (image.width) tags.push(`<meta property=\"og:image:width\" content=\"${image.width}\">`);\r\n if (image.height) tags.push(`<meta property=\"og:image:height\" content=\"${image.height}\">`);\r\n if (image.alt) tags.push(`<meta property=\"og:image:alt\" content=\"${escapeAttr(image.alt)}\">`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Twitter\r\n if (meta.twitter) {\r\n const tw = meta.twitter;\r\n if (tw.card) tags.push(`<meta name=\"twitter:card\" content=\"${escapeAttr(tw.card)}\">`);\r\n if (tw.site) tags.push(`<meta name=\"twitter:site\" content=\"${escapeAttr(tw.site)}\">`);\r\n if (tw.creator) tags.push(`<meta name=\"twitter:creator\" content=\"${escapeAttr(tw.creator)}\">`);\r\n if (tw.title) tags.push(`<meta name=\"twitter:title\" content=\"${escapeAttr(tw.title)}\">`);\r\n if (tw.description) tags.push(`<meta name=\"twitter:description\" content=\"${escapeAttr(tw.description)}\">`);\r\n\r\n if (tw.images) {\r\n for (const image of tw.images) {\r\n tags.push(`<meta name=\"twitter:image\" content=\"${escapeAttr(image)}\">`);\r\n }\r\n }\r\n }\r\n\r\n // Icons\r\n if (meta.icons) {\r\n const icons = meta.icons;\r\n\r\n if (icons.icon) {\r\n const iconList = Array.isArray(icons.icon) ? icons.icon : [icons.icon];\r\n for (const icon of iconList) {\r\n tags.push(`<link rel=\"icon\" href=\"${escapeAttr(icon)}\">`);\r\n }\r\n }\r\n\r\n if (icons.apple) {\r\n const appleList = Array.isArray(icons.apple) ? icons.apple : [icons.apple];\r\n for (const icon of appleList) {\r\n tags.push(`<link rel=\"apple-touch-icon\" href=\"${escapeAttr(icon)}\">`);\r\n }\r\n }\r\n\r\n if (icons.shortcut) {\r\n tags.push(`<link rel=\"shortcut icon\" href=\"${escapeAttr(icons.shortcut)}\">`);\r\n }\r\n }\r\n\r\n // Alternates\r\n if (meta.alternates) {\r\n if (meta.alternates.canonical) {\r\n tags.push(`<link rel=\"canonical\" href=\"${escapeAttr(meta.alternates.canonical)}\">`);\r\n }\r\n\r\n if (meta.alternates.languages) {\r\n for (const [lang, url] of Object.entries(meta.alternates.languages)) {\r\n tags.push(`<link rel=\"alternate\" hreflang=\"${escapeAttr(lang)}\" href=\"${escapeAttr(url)}\">`);\r\n }\r\n }\r\n }\r\n\r\n // Verification\r\n if (meta.verification) {\r\n if (meta.verification.google) {\r\n tags.push(`<meta name=\"google-site-verification\" content=\"${escapeAttr(meta.verification.google)}\">`);\r\n }\r\n if (meta.verification.bing) {\r\n tags.push(`<meta name=\"msvalidate.01\" content=\"${escapeAttr(meta.verification.bing)}\">`);\r\n }\r\n if (meta.verification.yandex) {\r\n tags.push(`<meta name=\"yandex-verification\" content=\"${escapeAttr(meta.verification.yandex)}\">`);\r\n }\r\n }\r\n\r\n // Custom meta tags\r\n if (meta.other) {\r\n for (const [name, content] of Object.entries(meta.other)) {\r\n tags.push(`<meta name=\"${escapeAttr(name)}\" content=\"${escapeAttr(content)}\">`);\r\n }\r\n }\r\n\r\n return tags.join('\\n ');\r\n}\r\n\r\n/**\r\n * Build robots content string from object\r\n */\r\nfunction buildRobotsContent(robots: Exclude<Metadata['robots'], string | undefined>): string {\r\n const directives: string[] = [];\r\n\r\n if (robots.index === false) directives.push('noindex');\r\n else if (robots.index === true) directives.push('index');\r\n\r\n if (robots.follow === false) directives.push('nofollow');\r\n else if (robots.follow === true) directives.push('follow');\r\n\r\n if (robots.nocache) directives.push('nocache');\r\n\r\n return directives.join(', ') || 'index, follow';\r\n}\r\n\r\n// ============================================================================\r\n// Merge Metadata\r\n// ============================================================================\r\n\r\n/**\r\n * Merge multiple metadata objects (later overrides earlier)\r\n */\r\nexport function mergeMetadata(...metadataList: (Metadata | undefined)[]): Metadata {\r\n const result: Metadata = {};\r\n\r\n for (const meta of metadataList) {\r\n if (!meta) continue;\r\n\r\n // Simple overwrites\r\n if (meta.title !== undefined) result.title = meta.title;\r\n if (meta.description !== undefined) result.description = meta.description;\r\n if (meta.keywords !== undefined) result.keywords = meta.keywords;\r\n if (meta.canonical !== undefined) result.canonical = meta.canonical;\r\n if (meta.robots !== undefined) result.robots = meta.robots;\r\n\r\n // Deep merge objects\r\n if (meta.openGraph) {\r\n result.openGraph = { ...result.openGraph, ...meta.openGraph };\r\n }\r\n if (meta.twitter) {\r\n result.twitter = { ...result.twitter, ...meta.twitter };\r\n }\r\n if (meta.icons) {\r\n result.icons = { ...result.icons, ...meta.icons };\r\n }\r\n if (meta.alternates) {\r\n result.alternates = { ...result.alternates, ...meta.alternates };\r\n }\r\n if (meta.verification) {\r\n result.verification = { ...result.verification, ...meta.verification };\r\n }\r\n if (meta.other) {\r\n result.other = { ...result.other, ...meta.other };\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Generate Metadata Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Type for generateMetadata function\r\n */\r\nexport type GenerateMetadataFn<Params = Record<string, string>> = (\r\n props: { params: Params; searchParams?: Record<string, string> }\r\n) => Metadata | Promise<Metadata>;\r\n\r\n/**\r\n * Resolve metadata from a page module\r\n */\r\nexport async function resolveMetadata<Params = Record<string, string>>(\r\n pageModule: { metadata?: Metadata; generateMetadata?: GenerateMetadataFn<Params> },\r\n props: { params: Params; searchParams?: Record<string, string> }\r\n): Promise<Metadata> {\r\n // Static metadata takes precedence\r\n if (pageModule.metadata) {\r\n return pageModule.metadata;\r\n }\r\n\r\n // Dynamic metadata via generateMetadata\r\n if (pageModule.generateMetadata) {\r\n return await pageModule.generateMetadata(props);\r\n }\r\n\r\n return {};\r\n}\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>');\r\n}\r\n\r\nfunction escapeAttr(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n}\r\n","/**\r\n * @flight-framework/core - Local DevTools\r\n * \r\n * Development-only debugging overlay.\r\n * 100% LOCAL - NO telemetry, NO external requests, NO cloud.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { injectDevTools } from '@flight-framework/core';\r\n * \r\n * const html = renderPage() + injectDevTools({ routes, renderTime });\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface DevToolsOptions {\r\n /** Current route path */\r\n route?: string;\r\n /** Render time in milliseconds */\r\n renderTime?: number;\r\n /** Rendering mode used */\r\n renderMode?: 'ssr' | 'ssg' | 'isr' | 'csr';\r\n /** Whether page is hydrated */\r\n hydrated?: boolean;\r\n /** Route params */\r\n params?: Record<string, string>;\r\n /** Cache status */\r\n cacheStatus?: 'hit' | 'miss' | 'stale';\r\n /** Custom data to display */\r\n customData?: Record<string, unknown>;\r\n}\r\n\r\n// ============================================================================\r\n// DevTools Injection\r\n// ============================================================================\r\n\r\n/**\r\n * Inject DevTools overlay into HTML\r\n * Only works in development mode - returns empty string in production\r\n */\r\nexport function injectDevTools(options: DevToolsOptions = {}): string {\r\n // CRITICAL: Only inject in development\r\n if (process.env.NODE_ENV !== 'development') {\r\n return '';\r\n }\r\n\r\n const data = JSON.stringify(options, null, 2);\r\n\r\n return `\r\n<!-- Flight DevTools - Development Only - NO TELEMETRY -->\r\n<div id=\"flight-devtools\" style=\"display:none;\">\r\n <div id=\"flight-devtools-toggle\" style=\"\r\n position: fixed;\r\n bottom: 16px;\r\n right: 16px;\r\n width: 40px;\r\n height: 40px;\r\n background: #1a1a2e;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 99999;\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\r\n font-size: 20px;\r\n \">✈</div>\r\n <div id=\"flight-devtools-panel\" style=\"\r\n position: fixed;\r\n bottom: 70px;\r\n right: 16px;\r\n width: 320px;\r\n max-height: 400px;\r\n background: #1a1a2e;\r\n color: #e0e0e0;\r\n border-radius: 8px;\r\n padding: 16px;\r\n font-family: ui-monospace, monospace;\r\n font-size: 12px;\r\n z-index: 99998;\r\n overflow-y: auto;\r\n display: none;\r\n box-shadow: 0 8px 24px rgba(0,0,0,0.4);\r\n \">\r\n <div style=\"display:flex;justify-content:space-between;margin-bottom:12px;\">\r\n <strong style=\"color:#60a5fa;\">Flight DevTools</strong>\r\n <span style=\"color:#6b7280;font-size:10px;\">LOCAL ONLY</span>\r\n </div>\r\n <div id=\"flight-devtools-content\"></div>\r\n </div>\r\n</div>\r\n<script>\r\n(function() {\r\n // DevTools data\r\n var data = ${data};\r\n \r\n // Wait for DOM\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', init);\r\n } else {\r\n init();\r\n }\r\n \r\n function init() {\r\n var container = document.getElementById('flight-devtools');\r\n var toggle = document.getElementById('flight-devtools-toggle');\r\n var panel = document.getElementById('flight-devtools-panel');\r\n var content = document.getElementById('flight-devtools-content');\r\n \r\n if (!container || !toggle || !panel || !content) return;\r\n \r\n container.style.display = 'block';\r\n \r\n // Render content\r\n var html = '';\r\n \r\n if (data.route) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Route:</span> <span style=\"color:#34d399;\">' + escapeHtml(data.route) + '</span></div>';\r\n }\r\n \r\n if (data.renderMode) {\r\n var modeColor = {ssr:'#f59e0b',ssg:'#10b981',isr:'#8b5cf6',csr:'#3b82f6'}[data.renderMode] || '#6b7280';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Mode:</span> <span style=\"color:' + modeColor + ';text-transform:uppercase;\">' + data.renderMode + '</span></div>';\r\n }\r\n \r\n if (data.renderTime !== undefined) {\r\n var timeColor = data.renderTime < 50 ? '#10b981' : data.renderTime < 200 ? '#f59e0b' : '#ef4444';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Render:</span> <span style=\"color:' + timeColor + ';\">' + data.renderTime + 'ms</span></div>';\r\n }\r\n \r\n if (data.cacheStatus) {\r\n var cacheColor = {hit:'#10b981',miss:'#ef4444',stale:'#f59e0b'}[data.cacheStatus] || '#6b7280';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Cache:</span> <span style=\"color:' + cacheColor + ';\">' + data.cacheStatus.toUpperCase() + '</span></div>';\r\n }\r\n \r\n if (data.params && Object.keys(data.params).length > 0) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Params:</span></div>';\r\n html += '<pre style=\"background:#0f0f1a;padding:8px;border-radius:4px;margin:0;overflow-x:auto;\">' + escapeHtml(JSON.stringify(data.params, null, 2)) + '</pre>';\r\n }\r\n \r\n if (data.hydrated !== undefined) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Hydrated:</span> <span style=\"color:' + (data.hydrated ? '#10b981' : '#f59e0b') + ';\">' + (data.hydrated ? 'Yes' : 'Pending') + '</span></div>';\r\n }\r\n \r\n if (data.customData) {\r\n html += '<details style=\"margin-top:12px;\"><summary style=\"cursor:pointer;color:#6b7280;\">Custom Data</summary>';\r\n html += '<pre style=\"background:#0f0f1a;padding:8px;border-radius:4px;margin-top:8px;overflow-x:auto;\">' + escapeHtml(JSON.stringify(data.customData, null, 2)) + '</pre></details>';\r\n }\r\n \r\n content.innerHTML = html || '<span style=\"color:#6b7280;\">No data available</span>';\r\n \r\n // Toggle panel\r\n toggle.addEventListener('click', function() {\r\n panel.style.display = panel.style.display === 'none' ? 'block' : 'none';\r\n });\r\n \r\n // Update hydration status\r\n window.addEventListener('load', function() {\r\n setTimeout(function() {\r\n var hydrationEl = content.querySelector('[data-hydration]');\r\n if (hydrationEl) {\r\n hydrationEl.textContent = 'Yes';\r\n hydrationEl.style.color = '#10b981';\r\n }\r\n }, 100);\r\n });\r\n }\r\n \r\n function escapeHtml(str) {\r\n return String(str).replace(/[&<>\"']/g, function(m) {\r\n return {'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[m];\r\n });\r\n }\r\n})();\r\n</script>\r\n`;\r\n}\r\n\r\n/**\r\n * Check if DevTools should be enabled\r\n */\r\nexport function isDevToolsEnabled(): boolean {\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\n/**\r\n * Create DevTools data from request context\r\n */\r\nexport function createDevToolsData(\r\n startTime: number,\r\n options: Partial<DevToolsOptions> = {}\r\n): DevToolsOptions {\r\n return {\r\n renderTime: Date.now() - startTime,\r\n hydrated: false,\r\n ...options,\r\n };\r\n}\r\n","/**\r\n * Flight Framework - Core\r\n * \r\n * The agnostic full-stack framework primitives.\r\n * Maximum flexibility, zero lock-in.\r\n */\r\n\r\n// Configuration\r\nexport { defineConfig, type FlightConfig, type FlightUserConfig } from './config/index.js';\r\n\r\n// Router\r\nexport {\r\n createRouter,\r\n type Route,\r\n type RouteMatch,\r\n type Router,\r\n type RouteParams,\r\n} from './router/index.js';\r\n\r\n// Server\r\nexport {\r\n createServer,\r\n type FlightServer,\r\n type RouteHandler,\r\n type RouteHandlerContext,\r\n type ServerOptions,\r\n type ServerRoute,\r\n} from './server/index.js';\r\n\r\n// Render\r\nexport {\r\n type RenderMode,\r\n type RenderContext,\r\n type RenderResult,\r\n} from './render/index.js';\r\n\r\n// Cache\r\nexport {\r\n createCache,\r\n memory,\r\n cacheKey,\r\n cached,\r\n dedupe,\r\n jsonSerializer,\r\n type Cache,\r\n type CacheOptions,\r\n type CacheEntry,\r\n type CacheAdapter,\r\n type CacheStats,\r\n type Serializer,\r\n type CreateCacheOptions,\r\n} from './cache/index.js';\r\n\r\n// Middleware\r\nexport {\r\n createMiddlewareChain,\r\n type Middleware,\r\n type MiddlewareContext,\r\n type MiddlewareNext,\r\n} from './middleware/index.js';\r\n\r\n// Adapters\r\nexport {\r\n type FlightAdapter,\r\n type AdapterBuilder,\r\n} from './adapters/index.js';\r\n\r\n// File Router\r\nexport {\r\n createFileRouter,\r\n scanRoutes,\r\n loadRoutes,\r\n type FileRoute,\r\n type FileRouter,\r\n type FileRouterOptions,\r\n type ScanResult,\r\n} from './file-router/index.js';\r\n\r\n// Route Handlers (for file-based routing)\r\nexport {\r\n createRouteContext,\r\n json,\r\n redirect,\r\n error,\r\n parseBody,\r\n type RouteHandler as FileRouteHandler,\r\n type RouteHandlerContext as FileRouteHandlerContext,\r\n type HttpMethod as FileHttpMethod,\r\n} from './handlers/index.js';\r\n\r\n// Server Actions\r\nexport {\r\n registerAction,\r\n getAction,\r\n executeAction,\r\n executeFormAction,\r\n handleActionRequest,\r\n cookies,\r\n redirect as actionRedirect,\r\n parseFormData,\r\n RedirectError,\r\n isRedirectError,\r\n type ServerAction,\r\n type ActionResult,\r\n type CookieOptions,\r\n} from './actions/index.js';\r\n\r\n// Streaming SSR\r\nexport {\r\n createStreamingSSR,\r\n createStreamingResponse,\r\n renderWithStreaming,\r\n createLazyContent,\r\n streamParallel,\r\n streamSequential,\r\n type StreamingRenderOptions,\r\n type StreamingRenderResult,\r\n type SuspenseBoundaryConfig,\r\n} from './streaming/index.js';\r\n\r\n// Priority Streaming (Out-of-Order with Control)\r\nexport {\r\n streamWithPriority,\r\n validateDependencies,\r\n type PriorityBoundary,\r\n type StreamingStrategy,\r\n type BoundaryResolution,\r\n type PriorityStreamConfig,\r\n type PriorityStreamResult,\r\n} from './streaming/priority.js';\r\n\r\n// Streaming Observability (Zero Telemetry)\r\nexport {\r\n createInstrumentedStream,\r\n MetricsAggregator,\r\n createLoggerObserver,\r\n createHttpObserver,\r\n type BoundaryTiming,\r\n type StreamingMetrics,\r\n type StreamingObserver,\r\n type InstrumentedStreamConfig,\r\n type InstrumentedStreamResult,\r\n} from './streaming/observability.js';\r\n\r\n// Conditional Streaming\r\nexport {\r\n streamIf,\r\n isBot,\r\n prefersNoStream,\r\n isSlowConnection,\r\n supportsStreaming,\r\n createConditionalStreamer,\r\n addStreamingHeaders,\r\n createStreamingResponse as createConditionalStreamingResponse,\r\n createStaticResponse,\r\n DEFAULT_BOT_PATTERNS,\r\n type StreamingCondition,\r\n type BuiltInCondition,\r\n type StreamIfConfig,\r\n} from './streaming/conditional.js';\r\n\r\n// Multi-Framework Streaming Adapters\r\nexport {\r\n createReactStreamAdapter,\r\n createVueStreamAdapter,\r\n createSolidStreamAdapter,\r\n createSvelteStreamAdapter,\r\n createHTMXStreamAdapter,\r\n createStreamAdapter,\r\n type StreamingAdapter,\r\n type AdapterOptions,\r\n type ReactAdapterOptions,\r\n type VueAdapterOptions,\r\n type SolidAdapterOptions,\r\n type SvelteAdapterOptions,\r\n type HTMXAdapterOptions,\r\n type FrameworkType,\r\n} from './streaming/adapters/index.js';\r\n\r\n// Islands Architecture\r\nexport {\r\n defineIsland,\r\n renderIsland,\r\n renderIslands,\r\n setIslandAdapter,\r\n createIslandRegistry,\r\n registerIsland,\r\n hydrateIslands,\r\n registerFlightIslandElement,\r\n createReactIslandAdapter,\r\n createPreactIslandAdapter,\r\n createVueIslandAdapter,\r\n createSolidIslandAdapter,\r\n type HydrationTrigger,\r\n type CustomHydrationTrigger,\r\n type IslandConfig,\r\n type Island,\r\n type RenderedIsland,\r\n type IslandRegistry,\r\n type HydrateOptions,\r\n type IslandRenderAdapter,\r\n} from './islands/index.js';\r\n\r\n// File Router Streaming Hints\r\nexport {\r\n resolveStreamingConfig,\r\n loadRouteWithStreaming,\r\n shouldStream,\r\n createStreamingController,\r\n generateCacheKey,\r\n getStreamingCacheHeaders,\r\n hasStreamingConfig,\r\n isValidStreamingHints,\r\n DEFAULT_STREAMING_HINTS,\r\n type StreamingHints,\r\n type GetStreamingConfig,\r\n type StreamingRouteModule,\r\n type ResolvedStreamingConfig,\r\n} from './file-router/streaming-hints.js';\r\n// React Server Components (RSC) Primitives\r\nexport {\r\n hasUseClientDirective,\r\n hasUseServerDirective,\r\n detectBoundaryType,\r\n createServerContext,\r\n notFound,\r\n isNotFoundError,\r\n redirect as rscRedirect,\r\n isRedirectError as isRscRedirectError,\r\n type ServerContext as RSCServerContext,\r\n type BoundaryType as RSCBoundaryType,\r\n} from './rsc/index.js';\r\n\r\n// RSC Legacy exports (backward compatibility)\r\nexport {\r\n createRenderContext,\r\n executeServerComponent,\r\n serverFetch,\r\n revalidateTag as rscRevalidateTag,\r\n revalidatePath as rscRevalidatePath,\r\n serializeProps,\r\n deserializeProps,\r\n createClientBoundary,\r\n createAsyncComponent,\r\n composeComponents,\r\n withErrorBoundary,\r\n type RenderContext as RSCRenderContext,\r\n type ServerComponent,\r\n type ClientComponent,\r\n type ComponentType as RSCComponentType,\r\n} from './rsc/legacy.js';\r\n\r\n// Route Rules (ISR/SSG Configuration)\r\nexport {\r\n matchRouteRule,\r\n mergeRouteRules,\r\n getRenderModeFromRule,\r\n getRevalidateTime,\r\n getCacheOptionsFromRule,\r\n buildCacheControlHeader,\r\n createDefaultRouteRules,\r\n type RouteRule,\r\n type RouteRules,\r\n} from './config/route-rules.js';\r\n\r\n// On-Demand Revalidation\r\nexport {\r\n revalidatePath,\r\n revalidateTag,\r\n revalidatePaths,\r\n createRevalidateHandler,\r\n setISRCache,\r\n getISRCache,\r\n createMemoryISRCache,\r\n createISRCacheFromFlightCache,\r\n type ISRCacheEntry,\r\n type ISRCacheAdapter,\r\n type RevalidationResult,\r\n type RevalidateHandlerOptions,\r\n} from './render/revalidate.js';\r\n\r\n// Build-Time Prerender (SSG)\r\nexport {\r\n prerenderRoutes,\r\n extractLinks,\r\n expandDynamicRoutes,\r\n type PrerenderOptions,\r\n type PrerenderResult,\r\n type PrerenderProgress,\r\n type PrerenderError,\r\n type PrerenderSummary,\r\n} from './build/prerender.js';\r\n\r\n// Static Generation Utilities\r\nexport {\r\n generateAllStaticPaths,\r\n getOrGeneratePage,\r\n purgePage,\r\n purgeAllPages,\r\n shouldDynamicallyRender,\r\n createStreamingResponse as createStaticStreamingResponse,\r\n createHtmlStream,\r\n type StaticParams,\r\n type GenerateStaticParamsFunction,\r\n type PageMetadata,\r\n type GenerateMetadataFunction,\r\n type PageModule,\r\n} from './render/static.js';\r\n\r\n// Metadata API (SEO)\r\nexport {\r\n renderMetadataToHead,\r\n mergeMetadata,\r\n resolveMetadata,\r\n type Metadata,\r\n type GenerateMetadataFn,\r\n} from './render/metadata.js';\r\n\r\n// DevTools (Development only, local, no telemetry)\r\nexport {\r\n injectDevTools,\r\n isDevToolsEnabled,\r\n createDevToolsData,\r\n type DevToolsOptions,\r\n} from './render/devtools.js';\r\n\r\n// Version\r\nexport const VERSION = '0.0.1';\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/route-rules.ts","../src/render/revalidate.ts","../src/build/prerender.ts","../src/render/static.ts","../src/render/metadata.ts","../src/render/devtools.ts","../src/utils/env.ts","../src/errors/index.ts","../src/index.ts"],"names":["revalidatePath","error","revalidateTag","fs","cached","createStreamingResponse","notFound","isNotFoundError"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * @flight-framework/core - Route Rules Configuration\r\n * \r\n * Nuxt-inspired route rules for per-route rendering configuration.\r\n * Define SSR, SSG, ISR, SWR, and caching strategies per route pattern.\r\n * \r\n * @example\r\n * ```typescript\r\n * const routeRules: RouteRules = {\r\n * '/': { prerender: true },\r\n * '/blog': { isr: 3600 },\r\n * '/blog/**': { swr: 3600 },\r\n * '/admin/**': { ssr: false },\r\n * '/api/**': { cache: { ttl: 60 } }\r\n * };\r\n * ```\r\n */\r\n\r\nimport type { CacheOptions } from '../cache/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Route rule configuration\r\n */\r\nexport interface RouteRule {\r\n /** Pre-render at build time (SSG) */\r\n prerender?: boolean;\r\n\r\n /** \r\n * Stale-While-Revalidate caching\r\n * - true: use default TTL\r\n * - number: TTL in seconds\r\n */\r\n swr?: number | boolean;\r\n\r\n /** \r\n * Incremental Static Regeneration\r\n * - true: regenerate on next deploy\r\n * - number: revalidate every N seconds\r\n */\r\n isr?: number | boolean;\r\n\r\n /** \r\n * Enable/disable SSR for this route\r\n * - false: client-side only rendering\r\n */\r\n ssr?: boolean;\r\n\r\n /** Custom cache options */\r\n cache?: CacheOptions;\r\n\r\n /** Response headers to add */\r\n headers?: Record<string, string>;\r\n\r\n /** Redirect to another path */\r\n redirect?: string | { to: string; statusCode?: 301 | 302 | 307 | 308 };\r\n\r\n /** CORS headers */\r\n cors?: boolean | {\r\n origin?: string | string[];\r\n methods?: string[];\r\n credentials?: boolean;\r\n };\r\n\r\n /** Cache tags for invalidation */\r\n tags?: string[];\r\n}\r\n\r\n/**\r\n * Route rules map - patterns to rules\r\n * Supports glob patterns: **, *, [param]\r\n */\r\nexport type RouteRules = Record<string, RouteRule>;\r\n\r\n// ============================================================================\r\n// Route Rule Matching\r\n// ============================================================================\r\n\r\n/**\r\n * Match a path against route rules and return the matching rule\r\n */\r\nexport function matchRouteRule(path: string, rules: RouteRules): RouteRule | undefined {\r\n // First, try exact match\r\n if (rules[path]) {\r\n return rules[path];\r\n }\r\n\r\n // Sort patterns by specificity (longer patterns first)\r\n const patterns = Object.keys(rules).sort((a, b) => {\r\n // Exact matches first\r\n if (!a.includes('*') && b.includes('*')) return -1;\r\n if (a.includes('*') && !b.includes('*')) return 1;\r\n // Then by length\r\n return b.length - a.length;\r\n });\r\n\r\n // Try pattern matching\r\n for (const pattern of patterns) {\r\n if (matchPattern(path, pattern)) {\r\n return rules[pattern];\r\n }\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Match a path against a glob pattern\r\n */\r\nfunction matchPattern(path: string, pattern: string): boolean {\r\n // Exact match\r\n if (pattern === path) {\r\n return true;\r\n }\r\n\r\n // Convert glob pattern to regex\r\n const regexPattern = pattern\r\n // Escape special regex chars except * and **\r\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\r\n // ** matches any path segments\r\n .replace(/\\*\\*/g, '.*')\r\n // * matches a single path segment\r\n .replace(/\\*/g, '[^/]*')\r\n // [param] matches a single path segment\r\n .replace(/\\[([^\\]]+)\\]/g, '[^/]+');\r\n\r\n const regex = new RegExp(`^${regexPattern}$`);\r\n return regex.test(path);\r\n}\r\n\r\n/**\r\n * Merge multiple route rules (later rules override earlier)\r\n */\r\nexport function mergeRouteRules(...rules: (RouteRule | undefined)[]): RouteRule {\r\n const result: RouteRule = {};\r\n\r\n for (const rule of rules) {\r\n if (!rule) continue;\r\n\r\n Object.assign(result, rule);\r\n\r\n // Deep merge headers\r\n if (rule.headers) {\r\n result.headers = { ...result.headers, ...rule.headers };\r\n }\r\n\r\n // Deep merge cache options\r\n if (rule.cache) {\r\n result.cache = { ...result.cache, ...rule.cache };\r\n }\r\n\r\n // Merge tags\r\n if (rule.tags) {\r\n result.tags = [...(result.tags || []), ...rule.tags];\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Rule Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Get effective render mode from route rule\r\n */\r\nexport function getRenderModeFromRule(rule: RouteRule): 'ssr' | 'ssg' | 'isr' | 'csr' {\r\n if (rule.ssr === false) {\r\n return 'csr';\r\n }\r\n\r\n if (rule.prerender) {\r\n return 'ssg';\r\n }\r\n\r\n if (rule.isr !== undefined) {\r\n return 'isr';\r\n }\r\n\r\n // Default to SSR\r\n return 'ssr';\r\n}\r\n\r\n/**\r\n * Get revalidation time from rule (in seconds)\r\n */\r\nexport function getRevalidateTime(rule: RouteRule): number | false {\r\n // ISR takes precedence\r\n if (rule.isr !== undefined) {\r\n if (rule.isr === true) {\r\n return false; // Revalidate on deploy only\r\n }\r\n return typeof rule.isr === 'number' ? rule.isr : 60;\r\n }\r\n\r\n // SWR\r\n if (rule.swr !== undefined) {\r\n if (rule.swr === true) {\r\n return 60; // Default 1 minute\r\n }\r\n return typeof rule.swr === 'number' ? rule.swr : 60;\r\n }\r\n\r\n // No revalidation\r\n return false;\r\n}\r\n\r\n/**\r\n * Get cache options from rule\r\n */\r\nexport function getCacheOptionsFromRule(rule: RouteRule): CacheOptions | undefined {\r\n const revalidate = getRevalidateTime(rule);\r\n\r\n if (revalidate === false && !rule.cache) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n ttl: revalidate || rule.cache?.ttl,\r\n swr: rule.swr !== undefined ? (typeof rule.swr === 'number' ? rule.swr : 60) : undefined,\r\n tags: rule.tags || rule.cache?.tags,\r\n };\r\n}\r\n\r\n/**\r\n * Build cache-control header from rule\r\n */\r\nexport function buildCacheControlHeader(rule: RouteRule): string | undefined {\r\n const revalidate = getRevalidateTime(rule);\r\n\r\n if (rule.ssr === false) {\r\n return 'no-store';\r\n }\r\n\r\n if (rule.prerender && revalidate === false) {\r\n return 'public, max-age=31536000, immutable';\r\n }\r\n\r\n if (revalidate !== false) {\r\n const maxAge = revalidate;\r\n const swr = rule.swr !== undefined ? (typeof rule.swr === 'number' ? rule.swr : 60) : 0;\r\n\r\n if (swr > 0) {\r\n return `public, max-age=${maxAge}, stale-while-revalidate=${swr}`;\r\n }\r\n\r\n return `public, max-age=${maxAge}`;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n// ============================================================================\r\n// Default Rules\r\n// ============================================================================\r\n\r\n/**\r\n * Create default route rules\r\n */\r\nexport function createDefaultRouteRules(): RouteRules {\r\n return {\r\n // API routes: no cache by default\r\n '/api/**': { ssr: true, cache: { ttl: 0 } },\r\n // Static assets: cache forever\r\n '/_static/**': { headers: { 'Cache-Control': 'public, max-age=31536000, immutable' } },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - On-Demand Revalidation\r\n * \r\n * APIs for on-demand cache invalidation and page revalidation.\r\n * Similar to Next.js revalidatePath() and revalidateTag().\r\n * \r\n * @example\r\n * ```typescript\r\n * // In an API route\r\n * import { revalidatePath, revalidateTag } from '@flight-framework/core';\r\n * \r\n * app.post('/api/revalidate', async (c) => {\r\n * const { path, tag } = await c.req.json();\r\n * \r\n * if (path) await revalidatePath(path);\r\n * if (tag) await revalidateTag(tag);\r\n * \r\n * return c.json({ revalidated: true });\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { Cache, CacheOptions } from '../cache/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * ISR Cache entry for rendered pages\r\n */\r\nexport interface ISRCacheEntry {\r\n /** Rendered HTML content */\r\n html: string;\r\n /** HTTP status code */\r\n status: number;\r\n /** Response headers */\r\n headers: Record<string, string>;\r\n /** When this entry was generated */\r\n generatedAt: number;\r\n /** When this entry should be revalidated */\r\n revalidateAfter?: number;\r\n /** Cache tags for invalidation */\r\n tags?: string[];\r\n}\r\n\r\n/**\r\n * ISR Cache adapter interface\r\n */\r\nexport interface ISRCacheAdapter {\r\n /** Get cached page */\r\n get(path: string): Promise<ISRCacheEntry | undefined>;\r\n /** Set cached page */\r\n set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void>;\r\n /** Delete cached page */\r\n delete(path: string): Promise<boolean>;\r\n /** Invalidate by tag */\r\n invalidateTag(tag: string): Promise<void>;\r\n /** Get all cached paths */\r\n keys?(): Promise<string[]>;\r\n}\r\n\r\n/**\r\n * Revalidation result\r\n */\r\nexport interface RevalidationResult {\r\n /** Whether revalidation was successful */\r\n success: boolean;\r\n /** Paths that were revalidated */\r\n paths?: string[];\r\n /** Error if failed */\r\n error?: string;\r\n /** Timestamp */\r\n timestamp: number;\r\n}\r\n\r\n// ============================================================================\r\n// Global ISR Cache Instance\r\n// ============================================================================\r\n\r\nlet globalISRCache: ISRCacheAdapter | null = null;\r\n\r\n/**\r\n * Set the global ISR cache adapter\r\n */\r\nexport function setISRCache(cache: ISRCacheAdapter): void {\r\n globalISRCache = cache;\r\n}\r\n\r\n/**\r\n * Get the global ISR cache adapter\r\n */\r\nexport function getISRCache(): ISRCacheAdapter | null {\r\n return globalISRCache;\r\n}\r\n\r\n// ============================================================================\r\n// In-Memory ISR Cache Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Create an in-memory ISR cache\r\n */\r\nexport function createMemoryISRCache(): ISRCacheAdapter {\r\n const store = new Map<string, ISRCacheEntry>();\r\n const tagIndex = new Map<string, Set<string>>();\r\n\r\n return {\r\n async get(path: string): Promise<ISRCacheEntry | undefined> {\r\n const entry = store.get(path);\r\n if (!entry) return undefined;\r\n\r\n // Check if expired\r\n if (entry.revalidateAfter && Date.now() > entry.revalidateAfter) {\r\n // Return stale entry (SWR pattern - caller decides to regenerate)\r\n return entry;\r\n }\r\n\r\n return entry;\r\n },\r\n\r\n async set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void> {\r\n store.set(path, entry);\r\n\r\n // Update tag index\r\n const tags = entry.tags || options?.tags || [];\r\n for (const tag of tags) {\r\n if (!tagIndex.has(tag)) {\r\n tagIndex.set(tag, new Set());\r\n }\r\n tagIndex.get(tag)!.add(path);\r\n }\r\n },\r\n\r\n async delete(path: string): Promise<boolean> {\r\n return store.delete(path);\r\n },\r\n\r\n async invalidateTag(tag: string): Promise<void> {\r\n const paths = tagIndex.get(tag);\r\n if (!paths) return;\r\n\r\n for (const path of paths) {\r\n store.delete(path);\r\n }\r\n tagIndex.delete(tag);\r\n },\r\n\r\n async keys(): Promise<string[]> {\r\n return Array.from(store.keys());\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Revalidation Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Revalidate a specific path\r\n * Removes the cached page so next request regenerates it\r\n */\r\nexport async function revalidatePath(path: string): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n try {\r\n const deleted = await cache.delete(path);\r\n\r\n return {\r\n success: deleted,\r\n paths: deleted ? [path] : [],\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Revalidate all paths associated with a tag\r\n */\r\nexport async function revalidateTag(tag: string): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n try {\r\n await cache.invalidateTag(tag);\r\n\r\n return {\r\n success: true,\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Revalidate multiple paths\r\n */\r\nexport async function revalidatePaths(paths: string[]): Promise<RevalidationResult> {\r\n const cache = getISRCache();\r\n\r\n if (!cache) {\r\n return {\r\n success: false,\r\n error: 'ISR cache not configured',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n const revalidated: string[] = [];\r\n\r\n try {\r\n for (const path of paths) {\r\n const deleted = await cache.delete(path);\r\n if (deleted) {\r\n revalidated.push(path);\r\n }\r\n }\r\n\r\n return {\r\n success: true,\r\n paths: revalidated,\r\n timestamp: Date.now(),\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n paths: revalidated,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n timestamp: Date.now(),\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Revalidation Handler (for API routes)\r\n// ============================================================================\r\n\r\nexport interface RevalidateHandlerOptions {\r\n /** Secret token for authentication */\r\n secret?: string;\r\n /** Header name for the secret */\r\n headerName?: string;\r\n}\r\n\r\n/**\r\n * Create a revalidation handler for API routes\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createRevalidateHandler } from '@flight-framework/core';\r\n * \r\n * const handler = createRevalidateHandler({ \r\n * secret: process.env.REVALIDATE_SECRET \r\n * });\r\n * \r\n * app.post('/api/revalidate', handler);\r\n * ```\r\n */\r\nexport function createRevalidateHandler(options: RevalidateHandlerOptions = {}) {\r\n const { secret, headerName = 'x-revalidate-token' } = options;\r\n\r\n return async (request: Request): Promise<Response> => {\r\n // Verify secret if configured\r\n if (secret) {\r\n const token = request.headers.get(headerName);\r\n if (token !== secret) {\r\n return new Response(\r\n JSON.stringify({ error: 'Invalid revalidation token' }),\r\n { status: 401, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n }\r\n\r\n try {\r\n const body = await request.json() as {\r\n path?: string;\r\n paths?: string[];\r\n tag?: string;\r\n tags?: string[];\r\n };\r\n\r\n const results: RevalidationResult[] = [];\r\n\r\n // Revalidate by path\r\n if (body.path) {\r\n results.push(await revalidatePath(body.path));\r\n }\r\n\r\n // Revalidate by paths\r\n if (body.paths && body.paths.length > 0) {\r\n results.push(await revalidatePaths(body.paths));\r\n }\r\n\r\n // Revalidate by tag\r\n if (body.tag) {\r\n results.push(await revalidateTag(body.tag));\r\n }\r\n\r\n // Revalidate by tags\r\n if (body.tags && body.tags.length > 0) {\r\n for (const tag of body.tags) {\r\n results.push(await revalidateTag(tag));\r\n }\r\n }\r\n\r\n const success = results.every(r => r.success);\r\n\r\n return new Response(\r\n JSON.stringify({\r\n revalidated: success,\r\n results,\r\n timestamp: Date.now(),\r\n }),\r\n {\r\n status: success ? 200 : 500,\r\n headers: { 'Content-Type': 'application/json' }\r\n }\r\n );\r\n } catch (error) {\r\n return new Response(\r\n JSON.stringify({\r\n error: 'Invalid request body',\r\n message: error instanceof Error ? error.message : 'Unknown error',\r\n }),\r\n { status: 400, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Wrap Flight Cache as ISR Cache\r\n// ============================================================================\r\n\r\n/**\r\n * Create an ISR cache adapter from a Flight Cache instance\r\n */\r\nexport function createISRCacheFromFlightCache(cache: Cache): ISRCacheAdapter {\r\n const ISR_PREFIX = 'isr:';\r\n\r\n return {\r\n async get(path: string): Promise<ISRCacheEntry | undefined> {\r\n return cache.get<ISRCacheEntry>(`${ISR_PREFIX}${path}`);\r\n },\r\n\r\n async set(path: string, entry: ISRCacheEntry, options?: CacheOptions): Promise<void> {\r\n const ttl = entry.revalidateAfter\r\n ? Math.floor((entry.revalidateAfter - Date.now()) / 1000)\r\n : options?.ttl;\r\n\r\n await cache.set(`${ISR_PREFIX}${path}`, entry, {\r\n ...options,\r\n ttl: ttl && ttl > 0 ? ttl : undefined,\r\n tags: entry.tags || options?.tags,\r\n });\r\n },\r\n\r\n async delete(path: string): Promise<boolean> {\r\n return cache.delete(`${ISR_PREFIX}${path}`);\r\n },\r\n\r\n async invalidateTag(tag: string): Promise<void> {\r\n await cache.invalidateTag(tag);\r\n },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Build-Time Prerender\r\n * \r\n * Static site generation build utilities.\r\n * Pre-renders routes to HTML files at build time.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { prerenderRoutes } from '@flight-framework/core';\r\n * \r\n * await prerenderRoutes({\r\n * routes: ['/','blog/hello', '/about'],\r\n * outDir: './dist',\r\n * renderFn: async (path) => await renderPage(path),\r\n * });\r\n * ```\r\n */\r\n\r\nimport { promises as fs } from 'fs';\r\nimport { join, dirname } from 'path';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Options for prerendering routes\r\n */\r\nexport interface PrerenderOptions {\r\n /** Routes to prerender */\r\n routes: string[] | (() => Promise<string[]>);\r\n /** Output directory */\r\n outDir: string;\r\n /** Render function that generates HTML for a path */\r\n renderFn: (path: string) => Promise<PrerenderResult>;\r\n /** Concurrency limit */\r\n concurrency?: number;\r\n /** Progress callback */\r\n onProgress?: (progress: PrerenderProgress) => void;\r\n /** Error callback */\r\n onError?: (error: PrerenderError) => void;\r\n /** Whether to crawl links from rendered pages */\r\n crawlLinks?: boolean;\r\n}\r\n\r\n/**\r\n * Result from rendering a single page\r\n */\r\nexport interface PrerenderResult {\r\n /** HTML content */\r\n html: string;\r\n /** HTTP status code */\r\n status?: number;\r\n /** Response headers */\r\n headers?: Record<string, string>;\r\n /** Links found in the page (for crawling) */\r\n links?: string[];\r\n}\r\n\r\n/**\r\n * Progress callback data\r\n */\r\nexport interface PrerenderProgress {\r\n /** Current route being processed */\r\n currentRoute: string;\r\n /** Number of routes completed */\r\n completed: number;\r\n /** Total number of routes */\r\n total: number;\r\n /** Percentage complete */\r\n percentage: number;\r\n}\r\n\r\n/**\r\n * Error callback data\r\n */\r\nexport interface PrerenderError {\r\n /** Route that failed */\r\n route: string;\r\n /** Error message */\r\n error: Error;\r\n}\r\n\r\n/**\r\n * Summary of prerender operation\r\n */\r\nexport interface PrerenderSummary {\r\n /** Total routes processed */\r\n total: number;\r\n /** Successfully rendered routes */\r\n success: number;\r\n /** Failed routes */\r\n failed: number;\r\n /** Routes that were discovered via crawling */\r\n discovered?: number;\r\n /** Time taken in milliseconds */\r\n duration: number;\r\n /** List of generated files */\r\n files: string[];\r\n /** List of errors */\r\n errors: PrerenderError[];\r\n}\r\n\r\n// ============================================================================\r\n// Prerender Engine\r\n// ============================================================================\r\n\r\n/**\r\n * Prerender multiple routes to static HTML files\r\n */\r\nexport async function prerenderRoutes(options: PrerenderOptions): Promise<PrerenderSummary> {\r\n const {\r\n routes,\r\n outDir,\r\n renderFn,\r\n concurrency = 10,\r\n onProgress,\r\n onError,\r\n crawlLinks = false,\r\n } = options;\r\n\r\n const startTime = Date.now();\r\n const errors: PrerenderError[] = [];\r\n const files: string[] = [];\r\n const processedRoutes = new Set<string>();\r\n\r\n // Get initial routes\r\n const routeQueue = typeof routes === 'function' ? await routes() : [...routes];\r\n let discoveredCount = 0;\r\n\r\n // Ensure output directory exists\r\n await fs.mkdir(outDir, { recursive: true });\r\n\r\n // Process routes in batches\r\n let completed = 0;\r\n const total = routeQueue.length;\r\n\r\n while (routeQueue.length > 0) {\r\n // Take a batch\r\n const batch = routeQueue.splice(0, concurrency);\r\n\r\n // Process batch concurrently\r\n const results = await Promise.allSettled(\r\n batch.map(async (route) => {\r\n // Skip if already processed\r\n if (processedRoutes.has(route)) {\r\n return null;\r\n }\r\n processedRoutes.add(route);\r\n\r\n // Report progress\r\n if (onProgress) {\r\n onProgress({\r\n currentRoute: route,\r\n completed,\r\n total: total + discoveredCount,\r\n percentage: Math.round((completed / (total + discoveredCount)) * 100),\r\n });\r\n }\r\n\r\n // Render the page\r\n const result = await renderFn(route);\r\n\r\n // Write to file\r\n const filePath = getOutputPath(route, outDir);\r\n await ensureDir(dirname(filePath));\r\n await fs.writeFile(filePath, result.html, 'utf-8');\r\n\r\n files.push(filePath);\r\n completed++;\r\n\r\n // Return links for crawling\r\n return result.links || [];\r\n })\r\n );\r\n\r\n // Handle results\r\n for (let i = 0; i < results.length; i++) {\r\n const result = results[i];\r\n const route = batch[i];\r\n\r\n if (result.status === 'rejected') {\r\n const error = { route, error: result.reason };\r\n errors.push(error);\r\n if (onError) {\r\n onError(error);\r\n }\r\n } else if (crawlLinks && result.value) {\r\n // Add discovered links to process queue\r\n for (const link of result.value) {\r\n if (!processedRoutes.has(link) && !routeQueue.includes(link)) {\r\n routeQueue.push(link);\r\n discoveredCount++;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n total: processedRoutes.size,\r\n success: files.length,\r\n failed: errors.length,\r\n discovered: discoveredCount,\r\n duration: Date.now() - startTime,\r\n files,\r\n errors,\r\n };\r\n}\r\n\r\n/**\r\n * Get output file path for a route\r\n */\r\nfunction getOutputPath(route: string, outDir: string): string {\r\n // Normalize route\r\n let normalizedRoute = route;\r\n\r\n if (!normalizedRoute.startsWith('/')) {\r\n normalizedRoute = '/' + normalizedRoute;\r\n }\r\n\r\n // Handle index routes\r\n if (normalizedRoute === '/') {\r\n return join(outDir, 'index.html');\r\n }\r\n\r\n // Handle trailing slashes\r\n if (normalizedRoute.endsWith('/')) {\r\n return join(outDir, normalizedRoute, 'index.html');\r\n }\r\n\r\n // Handle routes without extension\r\n if (!normalizedRoute.includes('.')) {\r\n return join(outDir, normalizedRoute + '.html');\r\n }\r\n\r\n return join(outDir, normalizedRoute);\r\n}\r\n\r\n/**\r\n * Ensure directory exists\r\n */\r\nasync function ensureDir(dir: string): Promise<void> {\r\n try {\r\n await fs.mkdir(dir, { recursive: true });\r\n } catch (error: unknown) {\r\n // Ignore if directory already exists\r\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\r\n throw error;\r\n }\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Link Extraction (for crawling)\r\n// ============================================================================\r\n\r\n/**\r\n * Extract internal links from HTML\r\n */\r\nexport function extractLinks(html: string, baseUrl?: string): string[] {\r\n const links: string[] = [];\r\n const linkRegex = /<a[^>]+href=[\"']([^\"']+)[\"'][^>]*>/gi;\r\n\r\n let match;\r\n while ((match = linkRegex.exec(html)) !== null) {\r\n const href = match[1];\r\n\r\n // Skip external links, anchors, and special protocols\r\n if (\r\n href.startsWith('http://') ||\r\n href.startsWith('https://') ||\r\n href.startsWith('#') ||\r\n href.startsWith('mailto:') ||\r\n href.startsWith('tel:') ||\r\n href.startsWith('javascript:')\r\n ) {\r\n continue;\r\n }\r\n\r\n // Normalize the link\r\n let normalizedLink = href;\r\n\r\n // Handle absolute paths\r\n if (href.startsWith('/')) {\r\n normalizedLink = href;\r\n } else if (baseUrl) {\r\n // Handle relative paths\r\n const base = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';\r\n normalizedLink = new URL(href, base).pathname;\r\n }\r\n\r\n // Remove query strings and fragments\r\n normalizedLink = normalizedLink.split('?')[0].split('#')[0];\r\n\r\n if (normalizedLink && !links.includes(normalizedLink)) {\r\n links.push(normalizedLink);\r\n }\r\n }\r\n\r\n return links;\r\n}\r\n\r\n// ============================================================================\r\n// Generate Static Params Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Expand dynamic routes with static params\r\n */\r\nexport async function expandDynamicRoutes(\r\n routePattern: string,\r\n generateParams: () => Promise<Record<string, string | string[]>[]>\r\n): Promise<string[]> {\r\n const params = await generateParams();\r\n\r\n return params.map((paramSet) => {\r\n let route = routePattern;\r\n\r\n for (const [key, value] of Object.entries(paramSet)) {\r\n const paramValue = Array.isArray(value) ? value.join('/') : value;\r\n\r\n // Replace [param] style\r\n route = route.replace(`[${key}]`, paramValue);\r\n // Replace [...param] style (catch-all)\r\n route = route.replace(`[...${key}]`, paramValue);\r\n }\r\n\r\n return route;\r\n });\r\n}\r\n","/**\r\n * @flight-framework/core - SSR/SSG/ISR Support\r\n * \r\n * Static site generation and incremental static regeneration.\r\n * Similar to Next.js patterns.\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Static params for dynamic routes\r\n */\r\nexport interface StaticParams {\r\n [key: string]: string | string[];\r\n}\r\n\r\n/**\r\n * Generate static params function signature\r\n */\r\nexport type GenerateStaticParamsFunction = () => Promise<StaticParams[]> | StaticParams[];\r\n\r\n/**\r\n * Page metadata\r\n */\r\nexport interface PageMetadata {\r\n title?: string;\r\n description?: string;\r\n keywords?: string[];\r\n openGraph?: {\r\n title?: string;\r\n description?: string;\r\n images?: string[];\r\n };\r\n}\r\n\r\n/**\r\n * Generate metadata function\r\n */\r\nexport type GenerateMetadataFunction = (params: StaticParams) => Promise<PageMetadata> | PageMetadata;\r\n\r\n/**\r\n * Page module exports\r\n */\r\nexport interface PageModule {\r\n default: (props: { params: StaticParams }) => unknown;\r\n generateStaticParams?: GenerateStaticParamsFunction;\r\n generateMetadata?: GenerateMetadataFunction;\r\n revalidate?: number | false;\r\n dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static';\r\n runtime?: 'nodejs' | 'edge';\r\n}\r\n\r\n// ============================================================================\r\n// Static Generation\r\n// ============================================================================\r\n\r\n/**\r\n * Generate all static paths for a page\r\n */\r\nexport async function generateAllStaticPaths(\r\n pageModules: Map<string, PageModule>\r\n): Promise<Map<string, StaticParams[]>> {\r\n const result = new Map<string, StaticParams[]>();\r\n\r\n for (const [path, module] of pageModules) {\r\n if (module.generateStaticParams) {\r\n try {\r\n const params = await module.generateStaticParams();\r\n result.set(path, params);\r\n } catch (error) {\r\n console.error(`[Flight] Failed to generate static params for ${path}:`, error);\r\n result.set(path, []);\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// ISR (Incremental Static Regeneration)\r\n// ============================================================================\r\n\r\ninterface CachedPage {\r\n html: string;\r\n generatedAt: number;\r\n revalidateAfter: number;\r\n}\r\n\r\nconst pageCache = new Map<string, CachedPage>();\r\n\r\n/**\r\n * Get or generate a cached page\r\n */\r\nexport async function getOrGeneratePage(\r\n path: string,\r\n generateFn: () => Promise<string>,\r\n revalidate?: number | false\r\n): Promise<{ html: string; fromCache: boolean }> {\r\n const cached = pageCache.get(path);\r\n const now = Date.now();\r\n\r\n // Check if cached page is valid\r\n if (cached) {\r\n if (revalidate === false) {\r\n // Never revalidate\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n if (now < cached.revalidateAfter) {\r\n // Still valid\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n // Stale-while-revalidate: return cached and regenerate in background\r\n regeneratePageInBackground(path, generateFn, revalidate || 60);\r\n return { html: cached.html, fromCache: true };\r\n }\r\n\r\n // Generate new page\r\n const html = await generateFn();\r\n\r\n // Cache the page\r\n if (revalidate !== false) {\r\n const revalidateMs = (revalidate || 60) * 1000;\r\n pageCache.set(path, {\r\n html,\r\n generatedAt: now,\r\n revalidateAfter: now + revalidateMs,\r\n });\r\n }\r\n\r\n return { html, fromCache: false };\r\n}\r\n\r\n/**\r\n * Regenerate page in background (stale-while-revalidate)\r\n */\r\nasync function regeneratePageInBackground(\r\n path: string,\r\n generateFn: () => Promise<string>,\r\n revalidate: number\r\n): Promise<void> {\r\n try {\r\n const html = await generateFn();\r\n const now = Date.now();\r\n\r\n pageCache.set(path, {\r\n html,\r\n generatedAt: now,\r\n revalidateAfter: now + (revalidate * 1000),\r\n });\r\n } catch (error) {\r\n console.error(`[Flight] Background regeneration failed for ${path}:`, error);\r\n }\r\n}\r\n\r\n/**\r\n * Purge cached page\r\n */\r\nexport function purgePage(path: string): boolean {\r\n return pageCache.delete(path);\r\n}\r\n\r\n/**\r\n * Purge all cached pages\r\n */\r\nexport function purgeAllPages(): void {\r\n pageCache.clear();\r\n}\r\n\r\n// ============================================================================\r\n// Dynamic Rendering\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a page should be dynamically rendered\r\n */\r\nexport function shouldDynamicallyRender(\r\n module: PageModule,\r\n hasParams: boolean\r\n): boolean {\r\n // Force dynamic\r\n if (module.dynamic === 'force-dynamic') {\r\n return true;\r\n }\r\n\r\n // Force static\r\n if (module.dynamic === 'force-static') {\r\n return false;\r\n }\r\n\r\n // Error on dynamic (SSG only)\r\n if (module.dynamic === 'error') {\r\n return false;\r\n }\r\n\r\n // Auto: dynamic if no generateStaticParams\r\n if (hasParams && !module.generateStaticParams) {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// ============================================================================\r\n// Streaming SSR\r\n// ============================================================================\r\n\r\n/**\r\n * Create a streaming response\r\n */\r\nexport function createStreamingResponse(\r\n stream: ReadableStream<Uint8Array>\r\n): Response {\r\n return new Response(stream, {\r\n status: 200,\r\n headers: {\r\n 'Content-Type': 'text/html; charset=utf-8',\r\n 'Transfer-Encoding': 'chunked',\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * Create a text encoder stream for HTML\r\n */\r\nexport function createHtmlStream(): {\r\n readable: ReadableStream<Uint8Array>;\r\n write: (html: string) => void;\r\n close: () => void;\r\n} {\r\n const encoder = new TextEncoder();\r\n let controller: ReadableStreamDefaultController<Uint8Array>;\r\n\r\n const readable = new ReadableStream<Uint8Array>({\r\n start(c) {\r\n controller = c;\r\n },\r\n });\r\n\r\n return {\r\n readable,\r\n write(html: string) {\r\n controller.enqueue(encoder.encode(html));\r\n },\r\n close() {\r\n controller.close();\r\n },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Metadata Rendering\r\n * \r\n * Utilities for rendering SEO metadata to HTML head tags.\r\n * Following Next.js Metadata API patterns.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { renderMetadataToHead } from '@flight-framework/core';\r\n * \r\n * const meta = {\r\n * title: 'My Page',\r\n * description: 'Page description',\r\n * openGraph: { title: 'OG Title', images: ['/og.jpg'] }\r\n * };\r\n * \r\n * const headHtml = renderMetadataToHead(meta);\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Complete metadata interface for SEO\r\n */\r\nexport interface Metadata {\r\n /** Page title */\r\n title?: string | { default: string; template?: string };\r\n /** Meta description */\r\n description?: string;\r\n /** Keywords for SEO */\r\n keywords?: string | string[];\r\n /** Canonical URL */\r\n canonical?: string;\r\n /** Robots directives */\r\n robots?: string | {\r\n index?: boolean;\r\n follow?: boolean;\r\n nocache?: boolean;\r\n googleBot?: {\r\n index?: boolean;\r\n follow?: boolean;\r\n noimageindex?: boolean;\r\n };\r\n };\r\n /** Open Graph metadata */\r\n openGraph?: {\r\n title?: string;\r\n description?: string;\r\n url?: string;\r\n siteName?: string;\r\n images?: string[] | Array<{\r\n url: string;\r\n width?: number;\r\n height?: number;\r\n alt?: string;\r\n }>;\r\n locale?: string;\r\n type?: 'website' | 'article' | 'book' | 'profile';\r\n };\r\n /** Twitter Card metadata */\r\n twitter?: {\r\n card?: 'summary' | 'summary_large_image' | 'app' | 'player';\r\n site?: string;\r\n creator?: string;\r\n title?: string;\r\n description?: string;\r\n images?: string[];\r\n };\r\n /** Favicon and icons */\r\n icons?: {\r\n icon?: string | string[];\r\n apple?: string | string[];\r\n shortcut?: string;\r\n };\r\n /** Alternate languages */\r\n alternates?: {\r\n canonical?: string;\r\n languages?: Record<string, string>;\r\n };\r\n /** Verification tokens */\r\n verification?: {\r\n google?: string;\r\n yandex?: string;\r\n bing?: string;\r\n };\r\n /** Additional custom meta tags */\r\n other?: Record<string, string>;\r\n}\r\n\r\n// ============================================================================\r\n// Metadata Rendering\r\n// ============================================================================\r\n\r\n/**\r\n * Render metadata to HTML head tags\r\n */\r\nexport function renderMetadataToHead(meta: Metadata): string {\r\n const tags: string[] = [];\r\n\r\n // Title\r\n if (meta.title) {\r\n const title = typeof meta.title === 'string'\r\n ? meta.title\r\n : meta.title.default;\r\n tags.push(`<title>${escapeHtml(title)}</title>`);\r\n }\r\n\r\n // Description\r\n if (meta.description) {\r\n tags.push(`<meta name=\"description\" content=\"${escapeAttr(meta.description)}\">`);\r\n }\r\n\r\n // Keywords\r\n if (meta.keywords) {\r\n const keywords = Array.isArray(meta.keywords)\r\n ? meta.keywords.join(', ')\r\n : meta.keywords;\r\n tags.push(`<meta name=\"keywords\" content=\"${escapeAttr(keywords)}\">`);\r\n }\r\n\r\n // Canonical\r\n if (meta.canonical) {\r\n tags.push(`<link rel=\"canonical\" href=\"${escapeAttr(meta.canonical)}\">`);\r\n }\r\n\r\n // Robots\r\n if (meta.robots) {\r\n const robotsContent = typeof meta.robots === 'string'\r\n ? meta.robots\r\n : buildRobotsContent(meta.robots);\r\n tags.push(`<meta name=\"robots\" content=\"${escapeAttr(robotsContent)}\">`);\r\n }\r\n\r\n // Open Graph\r\n if (meta.openGraph) {\r\n const og = meta.openGraph;\r\n if (og.title) tags.push(`<meta property=\"og:title\" content=\"${escapeAttr(og.title)}\">`);\r\n if (og.description) tags.push(`<meta property=\"og:description\" content=\"${escapeAttr(og.description)}\">`);\r\n if (og.url) tags.push(`<meta property=\"og:url\" content=\"${escapeAttr(og.url)}\">`);\r\n if (og.siteName) tags.push(`<meta property=\"og:site_name\" content=\"${escapeAttr(og.siteName)}\">`);\r\n if (og.type) tags.push(`<meta property=\"og:type\" content=\"${escapeAttr(og.type)}\">`);\r\n if (og.locale) tags.push(`<meta property=\"og:locale\" content=\"${escapeAttr(og.locale)}\">`);\r\n\r\n if (og.images) {\r\n for (const image of og.images) {\r\n if (typeof image === 'string') {\r\n tags.push(`<meta property=\"og:image\" content=\"${escapeAttr(image)}\">`);\r\n } else {\r\n tags.push(`<meta property=\"og:image\" content=\"${escapeAttr(image.url)}\">`);\r\n if (image.width) tags.push(`<meta property=\"og:image:width\" content=\"${image.width}\">`);\r\n if (image.height) tags.push(`<meta property=\"og:image:height\" content=\"${image.height}\">`);\r\n if (image.alt) tags.push(`<meta property=\"og:image:alt\" content=\"${escapeAttr(image.alt)}\">`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Twitter\r\n if (meta.twitter) {\r\n const tw = meta.twitter;\r\n if (tw.card) tags.push(`<meta name=\"twitter:card\" content=\"${escapeAttr(tw.card)}\">`);\r\n if (tw.site) tags.push(`<meta name=\"twitter:site\" content=\"${escapeAttr(tw.site)}\">`);\r\n if (tw.creator) tags.push(`<meta name=\"twitter:creator\" content=\"${escapeAttr(tw.creator)}\">`);\r\n if (tw.title) tags.push(`<meta name=\"twitter:title\" content=\"${escapeAttr(tw.title)}\">`);\r\n if (tw.description) tags.push(`<meta name=\"twitter:description\" content=\"${escapeAttr(tw.description)}\">`);\r\n\r\n if (tw.images) {\r\n for (const image of tw.images) {\r\n tags.push(`<meta name=\"twitter:image\" content=\"${escapeAttr(image)}\">`);\r\n }\r\n }\r\n }\r\n\r\n // Icons\r\n if (meta.icons) {\r\n const icons = meta.icons;\r\n\r\n if (icons.icon) {\r\n const iconList = Array.isArray(icons.icon) ? icons.icon : [icons.icon];\r\n for (const icon of iconList) {\r\n tags.push(`<link rel=\"icon\" href=\"${escapeAttr(icon)}\">`);\r\n }\r\n }\r\n\r\n if (icons.apple) {\r\n const appleList = Array.isArray(icons.apple) ? icons.apple : [icons.apple];\r\n for (const icon of appleList) {\r\n tags.push(`<link rel=\"apple-touch-icon\" href=\"${escapeAttr(icon)}\">`);\r\n }\r\n }\r\n\r\n if (icons.shortcut) {\r\n tags.push(`<link rel=\"shortcut icon\" href=\"${escapeAttr(icons.shortcut)}\">`);\r\n }\r\n }\r\n\r\n // Alternates\r\n if (meta.alternates) {\r\n if (meta.alternates.canonical) {\r\n tags.push(`<link rel=\"canonical\" href=\"${escapeAttr(meta.alternates.canonical)}\">`);\r\n }\r\n\r\n if (meta.alternates.languages) {\r\n for (const [lang, url] of Object.entries(meta.alternates.languages)) {\r\n tags.push(`<link rel=\"alternate\" hreflang=\"${escapeAttr(lang)}\" href=\"${escapeAttr(url)}\">`);\r\n }\r\n }\r\n }\r\n\r\n // Verification\r\n if (meta.verification) {\r\n if (meta.verification.google) {\r\n tags.push(`<meta name=\"google-site-verification\" content=\"${escapeAttr(meta.verification.google)}\">`);\r\n }\r\n if (meta.verification.bing) {\r\n tags.push(`<meta name=\"msvalidate.01\" content=\"${escapeAttr(meta.verification.bing)}\">`);\r\n }\r\n if (meta.verification.yandex) {\r\n tags.push(`<meta name=\"yandex-verification\" content=\"${escapeAttr(meta.verification.yandex)}\">`);\r\n }\r\n }\r\n\r\n // Custom meta tags\r\n if (meta.other) {\r\n for (const [name, content] of Object.entries(meta.other)) {\r\n tags.push(`<meta name=\"${escapeAttr(name)}\" content=\"${escapeAttr(content)}\">`);\r\n }\r\n }\r\n\r\n return tags.join('\\n ');\r\n}\r\n\r\n/**\r\n * Build robots content string from object\r\n */\r\nfunction buildRobotsContent(robots: Exclude<Metadata['robots'], string | undefined>): string {\r\n const directives: string[] = [];\r\n\r\n if (robots.index === false) directives.push('noindex');\r\n else if (robots.index === true) directives.push('index');\r\n\r\n if (robots.follow === false) directives.push('nofollow');\r\n else if (robots.follow === true) directives.push('follow');\r\n\r\n if (robots.nocache) directives.push('nocache');\r\n\r\n return directives.join(', ') || 'index, follow';\r\n}\r\n\r\n// ============================================================================\r\n// Merge Metadata\r\n// ============================================================================\r\n\r\n/**\r\n * Merge multiple metadata objects (later overrides earlier)\r\n */\r\nexport function mergeMetadata(...metadataList: (Metadata | undefined)[]): Metadata {\r\n const result: Metadata = {};\r\n\r\n for (const meta of metadataList) {\r\n if (!meta) continue;\r\n\r\n // Simple overwrites\r\n if (meta.title !== undefined) result.title = meta.title;\r\n if (meta.description !== undefined) result.description = meta.description;\r\n if (meta.keywords !== undefined) result.keywords = meta.keywords;\r\n if (meta.canonical !== undefined) result.canonical = meta.canonical;\r\n if (meta.robots !== undefined) result.robots = meta.robots;\r\n\r\n // Deep merge objects\r\n if (meta.openGraph) {\r\n result.openGraph = { ...result.openGraph, ...meta.openGraph };\r\n }\r\n if (meta.twitter) {\r\n result.twitter = { ...result.twitter, ...meta.twitter };\r\n }\r\n if (meta.icons) {\r\n result.icons = { ...result.icons, ...meta.icons };\r\n }\r\n if (meta.alternates) {\r\n result.alternates = { ...result.alternates, ...meta.alternates };\r\n }\r\n if (meta.verification) {\r\n result.verification = { ...result.verification, ...meta.verification };\r\n }\r\n if (meta.other) {\r\n result.other = { ...result.other, ...meta.other };\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ============================================================================\r\n// Generate Metadata Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Type for generateMetadata function\r\n */\r\nexport type GenerateMetadataFn<Params = Record<string, string>> = (\r\n props: { params: Params; searchParams?: Record<string, string> }\r\n) => Metadata | Promise<Metadata>;\r\n\r\n/**\r\n * Resolve metadata from a page module\r\n */\r\nexport async function resolveMetadata<Params = Record<string, string>>(\r\n pageModule: { metadata?: Metadata; generateMetadata?: GenerateMetadataFn<Params> },\r\n props: { params: Params; searchParams?: Record<string, string> }\r\n): Promise<Metadata> {\r\n // Static metadata takes precedence\r\n if (pageModule.metadata) {\r\n return pageModule.metadata;\r\n }\r\n\r\n // Dynamic metadata via generateMetadata\r\n if (pageModule.generateMetadata) {\r\n return await pageModule.generateMetadata(props);\r\n }\r\n\r\n return {};\r\n}\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>');\r\n}\r\n\r\nfunction escapeAttr(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n}\r\n","/**\r\n * @flight-framework/core - Local DevTools\r\n * \r\n * Development-only debugging overlay.\r\n * 100% LOCAL - NO telemetry, NO external requests, NO cloud.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { injectDevTools } from '@flight-framework/core';\r\n * \r\n * const html = renderPage() + injectDevTools({ routes, renderTime });\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface DevToolsOptions {\r\n /** Current route path */\r\n route?: string;\r\n /** Render time in milliseconds */\r\n renderTime?: number;\r\n /** Rendering mode used */\r\n renderMode?: 'ssr' | 'ssg' | 'isr' | 'csr';\r\n /** Whether page is hydrated */\r\n hydrated?: boolean;\r\n /** Route params */\r\n params?: Record<string, string>;\r\n /** Cache status */\r\n cacheStatus?: 'hit' | 'miss' | 'stale';\r\n /** Custom data to display */\r\n customData?: Record<string, unknown>;\r\n}\r\n\r\n// ============================================================================\r\n// DevTools Injection\r\n// ============================================================================\r\n\r\n/**\r\n * Inject DevTools overlay into HTML\r\n * Only works in development mode - returns empty string in production\r\n */\r\nexport function injectDevTools(options: DevToolsOptions = {}): string {\r\n // CRITICAL: Only inject in development\r\n if (process.env.NODE_ENV !== 'development') {\r\n return '';\r\n }\r\n\r\n const data = JSON.stringify(options, null, 2);\r\n\r\n return `\r\n<!-- Flight DevTools - Development Only - NO TELEMETRY -->\r\n<div id=\"flight-devtools\" style=\"display:none;\">\r\n <div id=\"flight-devtools-toggle\" style=\"\r\n position: fixed;\r\n bottom: 16px;\r\n right: 16px;\r\n width: 40px;\r\n height: 40px;\r\n background: #1a1a2e;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 99999;\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\r\n font-size: 20px;\r\n \">✈</div>\r\n <div id=\"flight-devtools-panel\" style=\"\r\n position: fixed;\r\n bottom: 70px;\r\n right: 16px;\r\n width: 320px;\r\n max-height: 400px;\r\n background: #1a1a2e;\r\n color: #e0e0e0;\r\n border-radius: 8px;\r\n padding: 16px;\r\n font-family: ui-monospace, monospace;\r\n font-size: 12px;\r\n z-index: 99998;\r\n overflow-y: auto;\r\n display: none;\r\n box-shadow: 0 8px 24px rgba(0,0,0,0.4);\r\n \">\r\n <div style=\"display:flex;justify-content:space-between;margin-bottom:12px;\">\r\n <strong style=\"color:#60a5fa;\">Flight DevTools</strong>\r\n <span style=\"color:#6b7280;font-size:10px;\">LOCAL ONLY</span>\r\n </div>\r\n <div id=\"flight-devtools-content\"></div>\r\n </div>\r\n</div>\r\n<script>\r\n(function() {\r\n // DevTools data\r\n var data = ${data};\r\n \r\n // Wait for DOM\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', init);\r\n } else {\r\n init();\r\n }\r\n \r\n function init() {\r\n var container = document.getElementById('flight-devtools');\r\n var toggle = document.getElementById('flight-devtools-toggle');\r\n var panel = document.getElementById('flight-devtools-panel');\r\n var content = document.getElementById('flight-devtools-content');\r\n \r\n if (!container || !toggle || !panel || !content) return;\r\n \r\n container.style.display = 'block';\r\n \r\n // Render content\r\n var html = '';\r\n \r\n if (data.route) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Route:</span> <span style=\"color:#34d399;\">' + escapeHtml(data.route) + '</span></div>';\r\n }\r\n \r\n if (data.renderMode) {\r\n var modeColor = {ssr:'#f59e0b',ssg:'#10b981',isr:'#8b5cf6',csr:'#3b82f6'}[data.renderMode] || '#6b7280';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Mode:</span> <span style=\"color:' + modeColor + ';text-transform:uppercase;\">' + data.renderMode + '</span></div>';\r\n }\r\n \r\n if (data.renderTime !== undefined) {\r\n var timeColor = data.renderTime < 50 ? '#10b981' : data.renderTime < 200 ? '#f59e0b' : '#ef4444';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Render:</span> <span style=\"color:' + timeColor + ';\">' + data.renderTime + 'ms</span></div>';\r\n }\r\n \r\n if (data.cacheStatus) {\r\n var cacheColor = {hit:'#10b981',miss:'#ef4444',stale:'#f59e0b'}[data.cacheStatus] || '#6b7280';\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Cache:</span> <span style=\"color:' + cacheColor + ';\">' + data.cacheStatus.toUpperCase() + '</span></div>';\r\n }\r\n \r\n if (data.params && Object.keys(data.params).length > 0) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Params:</span></div>';\r\n html += '<pre style=\"background:#0f0f1a;padding:8px;border-radius:4px;margin:0;overflow-x:auto;\">' + escapeHtml(JSON.stringify(data.params, null, 2)) + '</pre>';\r\n }\r\n \r\n if (data.hydrated !== undefined) {\r\n html += '<div style=\"margin-bottom:8px;\"><span style=\"color:#6b7280;\">Hydrated:</span> <span style=\"color:' + (data.hydrated ? '#10b981' : '#f59e0b') + ';\">' + (data.hydrated ? 'Yes' : 'Pending') + '</span></div>';\r\n }\r\n \r\n if (data.customData) {\r\n html += '<details style=\"margin-top:12px;\"><summary style=\"cursor:pointer;color:#6b7280;\">Custom Data</summary>';\r\n html += '<pre style=\"background:#0f0f1a;padding:8px;border-radius:4px;margin-top:8px;overflow-x:auto;\">' + escapeHtml(JSON.stringify(data.customData, null, 2)) + '</pre></details>';\r\n }\r\n \r\n content.innerHTML = html || '<span style=\"color:#6b7280;\">No data available</span>';\r\n \r\n // Toggle panel\r\n toggle.addEventListener('click', function() {\r\n panel.style.display = panel.style.display === 'none' ? 'block' : 'none';\r\n });\r\n \r\n // Update hydration status\r\n window.addEventListener('load', function() {\r\n setTimeout(function() {\r\n var hydrationEl = content.querySelector('[data-hydration]');\r\n if (hydrationEl) {\r\n hydrationEl.textContent = 'Yes';\r\n hydrationEl.style.color = '#10b981';\r\n }\r\n }, 100);\r\n });\r\n }\r\n \r\n function escapeHtml(str) {\r\n return String(str).replace(/[&<>\"']/g, function(m) {\r\n return {'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[m];\r\n });\r\n }\r\n})();\r\n</script>\r\n`;\r\n}\r\n\r\n/**\r\n * Check if DevTools should be enabled\r\n */\r\nexport function isDevToolsEnabled(): boolean {\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\n/**\r\n * Create DevTools data from request context\r\n */\r\nexport function createDevToolsData(\r\n startTime: number,\r\n options: Partial<DevToolsOptions> = {}\r\n): DevToolsOptions {\r\n return {\r\n renderTime: Date.now() - startTime,\r\n hydrated: false,\r\n ...options,\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Environment Utilities\r\n * \r\n * Environment detection utilities that work across Node.js, browsers, and edge runtimes.\r\n * No hardcoded values - detects environment dynamically.\r\n */\r\n\r\n// ============================================================================\r\n// Environment Detection\r\n// ============================================================================\r\n\r\n/**\r\n * Check if running in production environment.\r\n * \r\n * Detection order:\r\n * 1. Node.js process.env.NODE_ENV\r\n * 2. Vite/modern bundlers import.meta.env.MODE or import.meta.env.PROD\r\n * 3. Default: false (not production)\r\n */\r\nexport function isProduction(): boolean {\r\n // Check for Node.js environment via globalThis (universal)\r\n if (typeof globalThis !== 'undefined' && 'process' in globalThis) {\r\n const proc = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process;\r\n return proc?.env?.NODE_ENV === 'production';\r\n }\r\n // Check for import.meta.env (Vite, modern bundlers)\r\n if (typeof import.meta !== 'undefined' && 'env' in import.meta) {\r\n const env = (import.meta as { env?: { MODE?: string; PROD?: boolean } }).env;\r\n return env?.MODE === 'production' || env?.PROD === true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Check if running in development environment.\r\n * \r\n * Detection order:\r\n * 1. Node.js process.env.NODE_ENV\r\n * 2. Vite/modern bundlers import.meta.env.MODE or import.meta.env.DEV\r\n * 3. Default: true (assume development if unknown)\r\n */\r\nexport function isDevelopment(): boolean {\r\n // Check for Node.js environment via globalThis (universal)\r\n if (typeof globalThis !== 'undefined' && 'process' in globalThis) {\r\n const proc = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process;\r\n return proc?.env?.NODE_ENV === 'development';\r\n }\r\n // Check for import.meta.env (Vite, modern bundlers)\r\n if (typeof import.meta !== 'undefined' && 'env' in import.meta) {\r\n const env = (import.meta as { env?: { MODE?: string; DEV?: boolean } }).env;\r\n return env?.MODE === 'development' || env?.DEV === true;\r\n }\r\n // Default to development if we can't detect\r\n return true;\r\n}\r\n\r\n/**\r\n * Check if running in test environment.\r\n */\r\nexport function isTest(): boolean {\r\n if (typeof globalThis !== 'undefined' && 'process' in globalThis) {\r\n const proc = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process;\r\n return proc?.env?.NODE_ENV === 'test';\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Check if running on the server (not browser).\r\n */\r\nexport function isServer(): boolean {\r\n return typeof window === 'undefined';\r\n}\r\n\r\n/**\r\n * Check if running in the browser.\r\n */\r\nexport function isBrowser(): boolean {\r\n return typeof window !== 'undefined';\r\n}\r\n\r\n/**\r\n * Get the current environment name.\r\n */\r\nexport function getEnvironment(): 'production' | 'development' | 'test' | 'unknown' {\r\n if (isProduction()) return 'production';\r\n if (isDevelopment()) return 'development';\r\n if (isTest()) return 'test';\r\n return 'unknown';\r\n}\r\n","/**\r\n * @flight-framework/core - Error Handling\r\n * \r\n * Comprehensive error handling utilities for Flight applications.\r\n * All utilities are OPTIONAL - developers can use their own error handling.\r\n * \r\n * Philosophy: Flight OFFERS these utilities, but never IMPOSES them.\r\n * Using throw new Error() works perfectly fine - this is your choice.\r\n */\r\n\r\nimport { isProduction, isDevelopment } from '../utils/env.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Options for creating a Flight error\r\n */\r\nexport interface FlightErrorOptions {\r\n /** HTTP status code */\r\n statusCode: number;\r\n /** Short status message (e.g., \"Not Found\") */\r\n statusMessage?: string;\r\n /** Detailed error message */\r\n message?: string;\r\n /** Additional data to include with the error */\r\n data?: Record<string, unknown>;\r\n /** If true, shows full-screen error page instead of error boundary */\r\n fatal?: boolean;\r\n /** Original error that caused this error */\r\n cause?: Error;\r\n}\r\n\r\n/**\r\n * Extended error props with digest for production error correlation\r\n */\r\nexport interface FlightErrorProps {\r\n /** The error object */\r\n error: Error & { digest?: string };\r\n /** Function to attempt recovery by re-rendering */\r\n reset: () => void;\r\n}\r\n\r\n/**\r\n * Reset details provided to onReset callback\r\n */\r\nexport interface ResetDetails {\r\n /** Reason for the reset */\r\n reason: 'imperative-api' | 'keys';\r\n /** Arguments passed to resetErrorBoundary (if imperative) */\r\n args?: unknown[];\r\n /** Previous resetKeys values (if keys changed) */\r\n prev?: unknown[];\r\n /** New resetKeys values (if keys changed) */\r\n next?: unknown[];\r\n}\r\n\r\n/**\r\n * Options for error boundary behavior\r\n */\r\nexport interface ErrorBoundaryOptions {\r\n /** Keys that trigger automatic reset when changed */\r\n resetKeys?: unknown[];\r\n /** Callback when error boundary resets */\r\n onReset?: (details: ResetDetails) => void;\r\n /** Callback when error is caught */\r\n onError?: (error: Error, info: { componentStack?: string }) => void;\r\n}\r\n\r\n// ============================================================================\r\n// FlightError Class\r\n// ============================================================================\r\n\r\n/**\r\n * Custom error class with status code and metadata support.\r\n * \r\n * You can use this class or regular Error - Flight handles both.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new FlightError({\r\n * statusCode: 404,\r\n * message: 'User not found',\r\n * data: { userId: '123' }\r\n * });\r\n * ```\r\n */\r\nexport class FlightError extends Error {\r\n /** HTTP status code */\r\n readonly statusCode: number;\r\n /** Short status message */\r\n readonly statusMessage: string;\r\n /** Additional error data */\r\n readonly data?: Record<string, unknown>;\r\n /** Whether this is a fatal error (shows full-screen) */\r\n readonly fatal: boolean;\r\n /** Unique digest for production error correlation */\r\n readonly digest?: string;\r\n\r\n constructor(options: FlightErrorOptions) {\r\n super(options.message || options.statusMessage || 'An error occurred');\r\n\r\n this.name = 'FlightError';\r\n this.statusCode = options.statusCode;\r\n this.statusMessage = options.statusMessage || getDefaultStatusMessage(options.statusCode);\r\n this.data = options.data;\r\n this.fatal = options.fatal ?? false;\r\n\r\n // Generate digest in production for error correlation\r\n // Using typeof check for SSR/browser compatibility\r\n if (isProduction()) {\r\n this.digest = generateDigest();\r\n }\r\n\r\n // Preserve original error stack if cause provided\r\n if (options.cause) {\r\n this.cause = options.cause;\r\n if (options.cause.stack) {\r\n this.stack = `${this.stack}\\nCaused by: ${options.cause.stack}`;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Convert to plain object for serialization\r\n */\r\n toJSON(): Record<string, unknown> {\r\n return {\r\n name: this.name,\r\n message: this.message,\r\n statusCode: this.statusCode,\r\n statusMessage: this.statusMessage,\r\n data: this.data,\r\n fatal: this.fatal,\r\n digest: this.digest,\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// HTTP Error Classes (Convenience)\r\n// ============================================================================\r\n\r\n/**\r\n * 400 Bad Request error\r\n */\r\nexport class BadRequestError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 400, message, data });\r\n this.name = 'BadRequestError';\r\n }\r\n}\r\n\r\n/**\r\n * 401 Unauthorized error\r\n */\r\nexport class UnauthorizedError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 401, message: message || 'Unauthorized', data });\r\n this.name = 'UnauthorizedError';\r\n }\r\n}\r\n\r\n/**\r\n * 403 Forbidden error\r\n */\r\nexport class ForbiddenError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 403, message: message || 'Forbidden', data });\r\n this.name = 'ForbiddenError';\r\n }\r\n}\r\n\r\n/**\r\n * 404 Not Found error\r\n */\r\nexport class NotFoundError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 404, message: message || 'Not Found', data });\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\n/**\r\n * 500 Internal Server Error\r\n */\r\nexport class InternalError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 500, message: message || 'Internal Server Error', data });\r\n this.name = 'InternalError';\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create a FlightError with the specified options.\r\n * \r\n * This is a convenience function - you can also use `new FlightError()` directly\r\n * or just `throw new Error()` - Flight handles all cases.\r\n * \r\n * @example\r\n * ```typescript\r\n * // With full options\r\n * throw createError({\r\n * statusCode: 404,\r\n * message: 'Product not found',\r\n * data: { productId: 'abc123' }\r\n * });\r\n * \r\n * // Simple string shorthand (becomes 500 error)\r\n * throw createError('Something went wrong');\r\n * ```\r\n */\r\nexport function createError(options: FlightErrorOptions | string): FlightError {\r\n if (typeof options === 'string') {\r\n return new FlightError({ statusCode: 500, message: options });\r\n }\r\n return new FlightError(options);\r\n}\r\n\r\n/**\r\n * Create a 404 Not Found error.\r\n * Convenience function equivalent to `createError({ statusCode: 404, ... })`.\r\n * \r\n * @example\r\n * ```typescript\r\n * if (!user) {\r\n * throw notFound('User not found');\r\n * }\r\n * ```\r\n */\r\nexport function notFound(message?: string, data?: Record<string, unknown>): never {\r\n throw new NotFoundError(message, data);\r\n}\r\n\r\n/**\r\n * Create a 403 Forbidden error.\r\n * \r\n * @example\r\n * ```typescript\r\n * if (!user.isAdmin) {\r\n * throw forbidden('Admin access required');\r\n * }\r\n * ```\r\n */\r\nexport function forbidden(message?: string, data?: Record<string, unknown>): never {\r\n throw new ForbiddenError(message, data);\r\n}\r\n\r\n/**\r\n * Create a 401 Unauthorized error.\r\n * \r\n * @example\r\n * ```typescript\r\n * if (!session) {\r\n * throw unauthorized('Please log in to continue');\r\n * }\r\n * ```\r\n */\r\nexport function unauthorized(message?: string, data?: Record<string, unknown>): never {\r\n throw new UnauthorizedError(message, data);\r\n}\r\n\r\n// ============================================================================\r\n// Error State Management (Client-Side)\r\n// ============================================================================\r\n\r\n// Global error state for client-side\r\ndeclare global {\r\n interface Window {\r\n __FLIGHT_ERROR__?: FlightError | null;\r\n }\r\n}\r\n\r\n/**\r\n * Programmatically show an error page.\r\n * \r\n * This triggers the nearest error boundary or navigates to the error page.\r\n * Only works on the client side.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Show error with full options\r\n * showError({\r\n * statusCode: 500,\r\n * message: 'Connection lost'\r\n * });\r\n * \r\n * // Simple string shorthand\r\n * showError('Something went wrong');\r\n * ```\r\n */\r\nexport function showError(error: FlightErrorOptions | FlightError | string): void {\r\n let flightError: FlightError;\r\n\r\n if (typeof error === 'string') {\r\n flightError = new FlightError({ statusCode: 500, message: error });\r\n } else if (error instanceof FlightError) {\r\n flightError = error;\r\n } else {\r\n flightError = new FlightError(error);\r\n }\r\n\r\n // Client-side: dispatch custom event for error boundaries\r\n if (typeof window !== 'undefined') {\r\n window.__FLIGHT_ERROR__ = flightError;\r\n window.dispatchEvent(new CustomEvent('flight:error', {\r\n detail: flightError,\r\n bubbles: true\r\n }));\r\n }\r\n}\r\n\r\n/**\r\n * Clear the current error state and optionally redirect.\r\n * \r\n * Use this to dismiss an error and return to normal state.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Just clear the error\r\n * clearError();\r\n * \r\n * // Clear and redirect to home\r\n * clearError({ redirect: '/' });\r\n * ```\r\n */\r\nexport function clearError(options?: { redirect?: string }): void {\r\n if (typeof window !== 'undefined') {\r\n window.__FLIGHT_ERROR__ = null;\r\n window.dispatchEvent(new CustomEvent('flight:error-clear', { bubbles: true }));\r\n\r\n if (options?.redirect) {\r\n window.location.href = options.redirect;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Get the current error from global state.\r\n * Returns null if no error is active.\r\n */\r\nexport function getError(): FlightError | null {\r\n if (typeof window !== 'undefined') {\r\n return window.__FLIGHT_ERROR__ ?? null;\r\n }\r\n return null;\r\n}\r\n\r\n// ============================================================================\r\n// Type Guards\r\n// ============================================================================\r\n\r\n/**\r\n * Check if an error is a FlightError\r\n */\r\nexport function isFlightError(error: unknown): error is FlightError {\r\n return error instanceof FlightError;\r\n}\r\n\r\n/**\r\n * Check if an error is a NotFoundError (404)\r\n */\r\nexport function isNotFoundError(error: unknown): error is NotFoundError {\r\n return error instanceof NotFoundError ||\r\n (isFlightError(error) && error.statusCode === 404);\r\n}\r\n\r\n/**\r\n * Check if an error is a ForbiddenError (403)\r\n */\r\nexport function isForbiddenError(error: unknown): error is ForbiddenError {\r\n return error instanceof ForbiddenError ||\r\n (isFlightError(error) && error.statusCode === 403);\r\n}\r\n\r\n/**\r\n * Check if an error is an UnauthorizedError (401)\r\n */\r\nexport function isUnauthorizedError(error: unknown): error is UnauthorizedError {\r\n return error instanceof UnauthorizedError ||\r\n (isFlightError(error) && error.statusCode === 401);\r\n}\r\n\r\n/**\r\n * Get the status code from any error.\r\n * Returns 500 for non-FlightError errors.\r\n */\r\nexport function getErrorStatusCode(error: unknown): number {\r\n if (isFlightError(error)) {\r\n return error.statusCode;\r\n }\r\n return 500;\r\n}\r\n\r\n// ============================================================================\r\n// Response Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Create an error Response from a FlightError.\r\n * \r\n * @example\r\n * ```typescript\r\n * try {\r\n * // ... some operation\r\n * } catch (error) {\r\n * return createErrorResponse(error);\r\n * }\r\n * ```\r\n */\r\nexport function createErrorResponse(error: unknown): Response {\r\n const flightError = isFlightError(error)\r\n ? error\r\n : new InternalError(error instanceof Error ? error.message : 'Unknown error');\r\n\r\n return new Response(\r\n JSON.stringify({\r\n error: flightError.statusMessage,\r\n message: flightError.message,\r\n statusCode: flightError.statusCode,\r\n digest: flightError.digest,\r\n ...(isDevelopment() && flightError.data\r\n ? { data: flightError.data }\r\n : {}),\r\n }),\r\n {\r\n status: flightError.statusCode,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n }\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Get default status message for HTTP status code\r\n */\r\nfunction getDefaultStatusMessage(statusCode: number): string {\r\n const messages: Record<number, string> = {\r\n 400: 'Bad Request',\r\n 401: 'Unauthorized',\r\n 403: 'Forbidden',\r\n 404: 'Not Found',\r\n 405: 'Method Not Allowed',\r\n 408: 'Request Timeout',\r\n 409: 'Conflict',\r\n 410: 'Gone',\r\n 422: 'Unprocessable Entity',\r\n 429: 'Too Many Requests',\r\n 500: 'Internal Server Error',\r\n 501: 'Not Implemented',\r\n 502: 'Bad Gateway',\r\n 503: 'Service Unavailable',\r\n 504: 'Gateway Timeout',\r\n };\r\n return messages[statusCode] || 'Error';\r\n}\r\n\r\n/**\r\n * Generate a short digest for error correlation.\r\n * Used in production to correlate client errors with server logs\r\n * without exposing stack traces.\r\n */\r\nfunction generateDigest(): string {\r\n // Use crypto if available (Node.js, modern browsers)\r\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\r\n return crypto.randomUUID().slice(0, 8);\r\n }\r\n // Fallback for older environments\r\n return Math.random().toString(36).slice(2, 10);\r\n}\r\n\r\n/**\r\n * Wrap an error with a digest if it doesn't have one.\r\n * Useful for adding correlation IDs to third-party errors.\r\n */\r\nexport function wrapWithDigest<T extends Error>(error: T): T & { digest: string } {\r\n const wrapped = error as T & { digest: string };\r\n if (!wrapped.digest) {\r\n wrapped.digest = generateDigest();\r\n }\r\n return wrapped;\r\n}\r\n","/**\r\n * Flight Framework - Core\r\n * \r\n * The agnostic full-stack framework primitives.\r\n * Maximum flexibility, zero lock-in.\r\n */\r\n\r\n// Configuration\r\nexport { defineConfig, type FlightConfig, type FlightUserConfig } from './config/index.js';\r\n\r\n// Router\r\nexport {\r\n createRouter,\r\n type Route,\r\n type RouteMatch,\r\n type Router,\r\n type RouteParams,\r\n} from './router/index.js';\r\n\r\n// Server\r\nexport {\r\n createServer,\r\n type FlightServer,\r\n type RouteHandler,\r\n type RouteHandlerContext,\r\n type ServerOptions,\r\n type ServerRoute,\r\n} from './server/index.js';\r\n\r\n// Render\r\nexport {\r\n type RenderMode,\r\n type RenderContext,\r\n type RenderResult,\r\n} from './render/index.js';\r\n\r\n// Cache\r\nexport {\r\n createCache,\r\n memory,\r\n cacheKey,\r\n cached,\r\n dedupe,\r\n jsonSerializer,\r\n type Cache,\r\n type CacheOptions,\r\n type CacheEntry,\r\n type CacheAdapter,\r\n type CacheStats,\r\n type Serializer,\r\n type CreateCacheOptions,\r\n} from './cache/index.js';\r\n\r\n// Middleware\r\nexport {\r\n createMiddlewareChain,\r\n type Middleware,\r\n type MiddlewareContext,\r\n type MiddlewareNext,\r\n} from './middleware/index.js';\r\n\r\n// Adapters\r\nexport {\r\n type FlightAdapter,\r\n type AdapterBuilder,\r\n} from './adapters/index.js';\r\n\r\n// File Router\r\nexport {\r\n createFileRouter,\r\n scanRoutes,\r\n loadRoutes,\r\n type FileRoute,\r\n type FileRouter,\r\n type FileRouterOptions,\r\n type ScanResult,\r\n} from './file-router/index.js';\r\n\r\n// Route Handlers (for file-based routing)\r\nexport {\r\n createRouteContext,\r\n json,\r\n redirect,\r\n error,\r\n parseBody,\r\n type RouteHandler as FileRouteHandler,\r\n type RouteHandlerContext as FileRouteHandlerContext,\r\n type HttpMethod as FileHttpMethod,\r\n} from './handlers/index.js';\r\n\r\n// Server Actions\r\nexport {\r\n registerAction,\r\n getAction,\r\n executeAction,\r\n executeFormAction,\r\n handleActionRequest,\r\n cookies,\r\n redirect as actionRedirect,\r\n parseFormData,\r\n RedirectError,\r\n isRedirectError,\r\n type ServerAction,\r\n type ActionResult,\r\n type CookieOptions,\r\n} from './actions/index.js';\r\n\r\n// Streaming SSR\r\nexport {\r\n createStreamingSSR,\r\n createStreamingResponse,\r\n renderWithStreaming,\r\n createLazyContent,\r\n streamParallel,\r\n streamSequential,\r\n type StreamingRenderOptions,\r\n type StreamingRenderResult,\r\n type SuspenseBoundaryConfig,\r\n} from './streaming/index.js';\r\n\r\n// Priority Streaming (Out-of-Order with Control)\r\nexport {\r\n streamWithPriority,\r\n validateDependencies,\r\n type PriorityBoundary,\r\n type StreamingStrategy,\r\n type BoundaryResolution,\r\n type PriorityStreamConfig,\r\n type PriorityStreamResult,\r\n} from './streaming/priority.js';\r\n\r\n// Streaming Observability (Zero Telemetry)\r\nexport {\r\n createInstrumentedStream,\r\n MetricsAggregator,\r\n createLoggerObserver,\r\n createHttpObserver,\r\n type BoundaryTiming,\r\n type StreamingMetrics,\r\n type StreamingObserver,\r\n type InstrumentedStreamConfig,\r\n type InstrumentedStreamResult,\r\n} from './streaming/observability.js';\r\n\r\n// Conditional Streaming\r\nexport {\r\n streamIf,\r\n isBot,\r\n prefersNoStream,\r\n isSlowConnection,\r\n supportsStreaming,\r\n createConditionalStreamer,\r\n addStreamingHeaders,\r\n createStreamingResponse as createConditionalStreamingResponse,\r\n createStaticResponse,\r\n DEFAULT_BOT_PATTERNS,\r\n type StreamingCondition,\r\n type BuiltInCondition,\r\n type StreamIfConfig,\r\n} from './streaming/conditional.js';\r\n\r\n// Multi-Framework Streaming Adapters\r\nexport {\r\n createReactStreamAdapter,\r\n createVueStreamAdapter,\r\n createSolidStreamAdapter,\r\n createSvelteStreamAdapter,\r\n createHTMXStreamAdapter,\r\n createStreamAdapter,\r\n type StreamingAdapter,\r\n type AdapterOptions,\r\n type ReactAdapterOptions,\r\n type VueAdapterOptions,\r\n type SolidAdapterOptions,\r\n type SvelteAdapterOptions,\r\n type HTMXAdapterOptions,\r\n type FrameworkType,\r\n} from './streaming/adapters/index.js';\r\n\r\n// Islands Architecture\r\nexport {\r\n defineIsland,\r\n renderIsland,\r\n renderIslands,\r\n setIslandAdapter,\r\n createIslandRegistry,\r\n registerIsland,\r\n hydrateIslands,\r\n registerFlightIslandElement,\r\n createReactIslandAdapter,\r\n createPreactIslandAdapter,\r\n createVueIslandAdapter,\r\n createSolidIslandAdapter,\r\n type HydrationTrigger,\r\n type CustomHydrationTrigger,\r\n type IslandConfig,\r\n type Island,\r\n type RenderedIsland,\r\n type IslandRegistry,\r\n type HydrateOptions,\r\n type IslandRenderAdapter,\r\n} from './islands/index.js';\r\n\r\n// File Router Streaming Hints\r\nexport {\r\n resolveStreamingConfig,\r\n loadRouteWithStreaming,\r\n shouldStream,\r\n createStreamingController,\r\n generateCacheKey,\r\n getStreamingCacheHeaders,\r\n hasStreamingConfig,\r\n isValidStreamingHints,\r\n DEFAULT_STREAMING_HINTS,\r\n type StreamingHints,\r\n type GetStreamingConfig,\r\n type StreamingRouteModule,\r\n type ResolvedStreamingConfig,\r\n} from './file-router/streaming-hints.js';\r\n// React Server Components (RSC) Primitives\r\nexport {\r\n hasUseClientDirective,\r\n hasUseServerDirective,\r\n detectBoundaryType,\r\n createServerContext,\r\n notFound,\r\n isNotFoundError,\r\n redirect as rscRedirect,\r\n isRedirectError as isRscRedirectError,\r\n type ServerContext as RSCServerContext,\r\n type BoundaryType as RSCBoundaryType,\r\n} from './rsc/index.js';\r\n\r\n// RSC Legacy exports (backward compatibility)\r\nexport {\r\n createRenderContext,\r\n executeServerComponent,\r\n serverFetch,\r\n revalidateTag as rscRevalidateTag,\r\n revalidatePath as rscRevalidatePath,\r\n serializeProps,\r\n deserializeProps,\r\n createClientBoundary,\r\n createAsyncComponent,\r\n composeComponents,\r\n withErrorBoundary,\r\n type RenderContext as RSCRenderContext,\r\n type ServerComponent,\r\n type ClientComponent,\r\n type ComponentType as RSCComponentType,\r\n} from './rsc/legacy.js';\r\n\r\n// Route Rules (ISR/SSG Configuration)\r\nexport {\r\n matchRouteRule,\r\n mergeRouteRules,\r\n getRenderModeFromRule,\r\n getRevalidateTime,\r\n getCacheOptionsFromRule,\r\n buildCacheControlHeader,\r\n createDefaultRouteRules,\r\n type RouteRule,\r\n type RouteRules,\r\n} from './config/route-rules.js';\r\n\r\n// On-Demand Revalidation\r\nexport {\r\n revalidatePath,\r\n revalidateTag,\r\n revalidatePaths,\r\n createRevalidateHandler,\r\n setISRCache,\r\n getISRCache,\r\n createMemoryISRCache,\r\n createISRCacheFromFlightCache,\r\n type ISRCacheEntry,\r\n type ISRCacheAdapter,\r\n type RevalidationResult,\r\n type RevalidateHandlerOptions,\r\n} from './render/revalidate.js';\r\n\r\n// Build-Time Prerender (SSG)\r\nexport {\r\n prerenderRoutes,\r\n extractLinks,\r\n expandDynamicRoutes,\r\n type PrerenderOptions,\r\n type PrerenderResult,\r\n type PrerenderProgress,\r\n type PrerenderError,\r\n type PrerenderSummary,\r\n} from './build/prerender.js';\r\n\r\n// Static Generation Utilities\r\nexport {\r\n generateAllStaticPaths,\r\n getOrGeneratePage,\r\n purgePage,\r\n purgeAllPages,\r\n shouldDynamicallyRender,\r\n createStreamingResponse as createStaticStreamingResponse,\r\n createHtmlStream,\r\n type StaticParams,\r\n type GenerateStaticParamsFunction,\r\n type PageMetadata,\r\n type GenerateMetadataFunction,\r\n type PageModule,\r\n} from './render/static.js';\r\n\r\n// Metadata API (SEO)\r\nexport {\r\n renderMetadataToHead,\r\n mergeMetadata,\r\n resolveMetadata,\r\n type Metadata,\r\n type GenerateMetadataFn,\r\n} from './render/metadata.js';\r\n\r\n// DevTools (Development only, local, no telemetry)\r\nexport {\r\n injectDevTools,\r\n isDevToolsEnabled,\r\n createDevToolsData,\r\n type DevToolsOptions,\r\n} from './render/devtools.js';\r\n\r\n// Error Handling (OPTIONAL - developers can use their own)\r\nexport {\r\n // Error class\r\n FlightError,\r\n BadRequestError,\r\n UnauthorizedError,\r\n ForbiddenError,\r\n NotFoundError,\r\n InternalError,\r\n // Factory functions\r\n createError,\r\n notFound as createNotFound,\r\n forbidden as createForbidden,\r\n unauthorized as createUnauthorized,\r\n // Client-side state management\r\n showError,\r\n clearError,\r\n getError,\r\n // Type guards\r\n isFlightError,\r\n isNotFoundError as isNotFound,\r\n isForbiddenError as isForbidden,\r\n isUnauthorizedError as isUnauthorized,\r\n getErrorStatusCode,\r\n // Response helpers\r\n createErrorResponse,\r\n wrapWithDigest,\r\n // Types\r\n type FlightErrorOptions,\r\n type FlightErrorProps,\r\n type ResetDetails,\r\n type ErrorBoundaryOptions,\r\n} from './errors/index.js';\r\n\r\n// Environment Utilities\r\nexport {\r\n isProduction,\r\n isDevelopment,\r\n isTest,\r\n isServer,\r\n isBrowser,\r\n getEnvironment,\r\n} from './utils/index.js';\r\n\r\n// Version\r\nexport const VERSION = '0.0.1';\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flight-framework/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Core primitives for Flight Framework - routing, rendering, caching",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"flight",
|
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
18
|
"import": "./dist/index.js"
|
|
19
19
|
},
|
|
20
|
+
"./errors": {
|
|
21
|
+
"types": "./dist/errors/index.d.ts",
|
|
22
|
+
"import": "./dist/errors/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./react": {
|
|
25
|
+
"types": "./dist/react/index.d.ts",
|
|
26
|
+
"import": "./dist/react/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./utils": {
|
|
29
|
+
"types": "./dist/utils/index.d.ts",
|
|
30
|
+
"import": "./dist/utils/index.js"
|
|
31
|
+
},
|
|
20
32
|
"./router": {
|
|
21
33
|
"types": "./dist/router/index.d.ts",
|
|
22
34
|
"import": "./dist/router/index.js"
|
|
@@ -177,15 +189,20 @@
|
|
|
177
189
|
},
|
|
178
190
|
"devDependencies": {
|
|
179
191
|
"@types/node": "^22.0.0",
|
|
192
|
+
"@types/react": "^19.0.0",
|
|
180
193
|
"rimraf": "^6.0.0",
|
|
181
194
|
"tsup": "^8.0.0",
|
|
182
195
|
"typescript": "^5.7.0",
|
|
183
196
|
"vitest": "^2.0.0"
|
|
184
197
|
},
|
|
185
198
|
"peerDependencies": {
|
|
199
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
186
200
|
"vite": "^6.0.0 || ^7.0.0"
|
|
187
201
|
},
|
|
188
202
|
"peerDependenciesMeta": {
|
|
203
|
+
"react": {
|
|
204
|
+
"optional": true
|
|
205
|
+
},
|
|
189
206
|
"vite": {
|
|
190
207
|
"optional": true
|
|
191
208
|
}
|