@flight-framework/core 0.5.0 → 0.6.0

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.
@@ -0,0 +1,93 @@
1
+ // src/plugins/server-boundary-plugin.ts
2
+ function serverBoundaryPlugin(options = {}) {
3
+ const {
4
+ serverFilePatterns = [".server.ts", ".server.tsx", ".server.js", ".server.jsx"],
5
+ serverDirPatterns = ["/server/", "/api/"],
6
+ violationBehavior = "error",
7
+ customErrorMessage,
8
+ exclude = ["**/*.test.*", "**/*.spec.*", "**/node_modules/**"]
9
+ } = options;
10
+ const filePatterns = serverFilePatterns.map(
11
+ (p) => new RegExp(p.replace(/\./g, "\\.") + "$", "i")
12
+ );
13
+ const dirPatterns = serverDirPatterns.map(
14
+ (p) => new RegExp(p.replace(/\//g, "[\\\\/]"), "i")
15
+ );
16
+ function isServerOnlyModule(id) {
17
+ for (const pattern of filePatterns) {
18
+ if (pattern.test(id)) return true;
19
+ }
20
+ for (const pattern of dirPatterns) {
21
+ if (pattern.test(id)) return true;
22
+ }
23
+ return false;
24
+ }
25
+ function isExcluded(id) {
26
+ for (const pattern of exclude) {
27
+ const regex = new RegExp(
28
+ pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/\\\\]*").replace(/\./g, "\\.")
29
+ );
30
+ if (regex.test(id)) return true;
31
+ }
32
+ return false;
33
+ }
34
+ function createErrorMessage(module, importer) {
35
+ if (customErrorMessage) {
36
+ return customErrorMessage(module, importer);
37
+ }
38
+ return `[Flight] Cannot import server-only module in client code.
39
+
40
+ Module: ${module}
41
+ Imported by: ${importer}
42
+
43
+ Solutions:
44
+ 1. Move the import to a 'use server' file
45
+ 2. Use an API route instead
46
+ 3. Use dynamic import with typeof window check
47
+ 4. Rename the importing file to *.server.ts
48
+
49
+ Learn more: https://flight-framework.dev/docs/server-client-boundaries`;
50
+ }
51
+ return {
52
+ name: "flight:server-boundary",
53
+ enforce: "pre",
54
+ resolveId(source, importer, options2) {
55
+ if (options2?.ssr) return null;
56
+ if (!importer) return null;
57
+ if (isExcluded(importer)) return null;
58
+ if (isServerOnlyModule(importer)) return null;
59
+ if (isServerOnlyModule(source)) {
60
+ const message = createErrorMessage(source, importer);
61
+ if (violationBehavior === "error") {
62
+ this.error(message);
63
+ } else {
64
+ this.warn(message);
65
+ }
66
+ }
67
+ return null;
68
+ },
69
+ transform(code, id, options2) {
70
+ if (options2?.ssr) return null;
71
+ if (isExcluded(id)) return null;
72
+ if (isServerOnlyModule(id)) return null;
73
+ const trimmed = code.trim();
74
+ if (trimmed.startsWith("'use server'") || trimmed.startsWith('"use server"')) {
75
+ const message = `[Flight] 'use server' file imported in client bundle.
76
+
77
+ File: ${id}
78
+
79
+ This file should only run on the server. Check your import graph to find where this is imported.`;
80
+ if (violationBehavior === "error") {
81
+ this.error(message);
82
+ } else {
83
+ this.warn(message);
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ };
89
+ }
90
+
91
+ export { serverBoundaryPlugin };
92
+ //# sourceMappingURL=chunk-56ZZNOJD.js.map
93
+ //# sourceMappingURL=chunk-56ZZNOJD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugins/server-boundary-plugin.ts"],"names":["options"],"mappings":"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","file":"chunk-56ZZNOJD.js","sourcesContent":["/**\r\n * @flight-framework/core - Server Boundary Plugin\r\n * \r\n * Vite plugin to detect server-only code imported in client bundles.\r\n * OPTIONAL - use if you want build-time protection.\r\n * \r\n * Features:\r\n * - Detects *.server.ts files imported in client code\r\n * - Detects /server/ and /api/ directory imports\r\n * - Configurable behavior (warn, error)\r\n * - Clear error messages with solutions\r\n * \r\n * @example\r\n * ```typescript\r\n * // vite.config.ts\r\n * import { serverBoundaryPlugin } from '@flight-framework/core/plugins';\r\n * \r\n * export default {\r\n * plugins: [serverBoundaryPlugin()],\r\n * };\r\n * ```\r\n */\r\n\r\nimport type { Plugin } from 'vite';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface ServerBoundaryPluginOptions {\r\n /**\r\n * File patterns that are server-only.\r\n * @default ['.server.ts', '.server.tsx', '.server.js', '.server.jsx']\r\n */\r\n serverFilePatterns?: string[];\r\n\r\n /**\r\n * Directory patterns that are server-only.\r\n * @default ['/server/', '/api/']\r\n */\r\n serverDirPatterns?: string[];\r\n\r\n /**\r\n * How to handle violations.\r\n * - 'error': Build error (recommended for production)\r\n * - 'warn': Warning only (for migration)\r\n * @default 'error'\r\n */\r\n violationBehavior?: 'error' | 'warn';\r\n\r\n /**\r\n * Custom error message template.\r\n */\r\n customErrorMessage?: (module: string, importer: string) => string;\r\n\r\n /**\r\n * Files to exclude from checking (e.g., tests).\r\n * @default ['**\\/*.test.*', '**\\/*.spec.*']\r\n */\r\n exclude?: string[];\r\n}\r\n\r\n// ============================================================================\r\n// Plugin\r\n// ============================================================================\r\n\r\n/**\r\n * Vite plugin to detect server-only imports in client code.\r\n * \r\n * This plugin is OPTIONAL. Use it if you want build-time\r\n * detection of server code leaking to the client.\r\n * \r\n * By default, it will:\r\n * - Block imports of *.server.ts files in client code\r\n * - Block imports from /server/ and /api/ directories\r\n * - Throw build errors with clear solutions\r\n */\r\nexport function serverBoundaryPlugin(\r\n options: ServerBoundaryPluginOptions = {}\r\n): Plugin {\r\n const {\r\n serverFilePatterns = ['.server.ts', '.server.tsx', '.server.js', '.server.jsx'],\r\n serverDirPatterns = ['/server/', '/api/'],\r\n violationBehavior = 'error',\r\n customErrorMessage,\r\n exclude = ['**/*.test.*', '**/*.spec.*', '**/node_modules/**'],\r\n } = options;\r\n\r\n // Build regex patterns\r\n const filePatterns = serverFilePatterns.map(p =>\r\n new RegExp(p.replace(/\\./g, '\\\\.') + '$', 'i')\r\n );\r\n const dirPatterns = serverDirPatterns.map(p =>\r\n new RegExp(p.replace(/\\//g, '[\\\\\\\\/]'), 'i')\r\n );\r\n\r\n function isServerOnlyModule(id: string): boolean {\r\n // Check file patterns\r\n for (const pattern of filePatterns) {\r\n if (pattern.test(id)) return true;\r\n }\r\n\r\n // Check directory patterns\r\n for (const pattern of dirPatterns) {\r\n if (pattern.test(id)) return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n function isExcluded(id: string): boolean {\r\n for (const pattern of exclude) {\r\n // Simple glob matching\r\n const regex = new RegExp(\r\n pattern\r\n .replace(/\\*\\*/g, '.*')\r\n .replace(/\\*/g, '[^/\\\\\\\\]*')\r\n .replace(/\\./g, '\\\\.')\r\n );\r\n if (regex.test(id)) return true;\r\n }\r\n return false;\r\n }\r\n\r\n function createErrorMessage(module: string, importer: string): string {\r\n if (customErrorMessage) {\r\n return customErrorMessage(module, importer);\r\n }\r\n\r\n return (\r\n `[Flight] Cannot import server-only module in client code.\\n\\n` +\r\n ` Module: ${module}\\n` +\r\n ` Imported by: ${importer}\\n\\n` +\r\n `Solutions:\\n` +\r\n ` 1. Move the import to a 'use server' file\\n` +\r\n ` 2. Use an API route instead\\n` +\r\n ` 3. Use dynamic import with typeof window check\\n` +\r\n ` 4. Rename the importing file to *.server.ts\\n\\n` +\r\n `Learn more: https://flight-framework.dev/docs/server-client-boundaries`\r\n );\r\n }\r\n\r\n return {\r\n name: 'flight:server-boundary',\r\n enforce: 'pre',\r\n\r\n resolveId(source, importer, options) {\r\n // Skip SSR builds - server can import anything\r\n if (options?.ssr) return null;\r\n\r\n // Need an importer to check\r\n if (!importer) return null;\r\n\r\n // Skip excluded files\r\n if (isExcluded(importer)) return null;\r\n\r\n // Skip if importer is also server-only\r\n if (isServerOnlyModule(importer)) return null;\r\n\r\n // Check if the import target is server-only\r\n // This is a simplified check - the resolved ID would be more accurate\r\n if (isServerOnlyModule(source)) {\r\n const message = createErrorMessage(source, importer);\r\n\r\n if (violationBehavior === 'error') {\r\n this.error(message);\r\n } else {\r\n this.warn(message);\r\n }\r\n }\r\n\r\n return null;\r\n },\r\n\r\n transform(code, id, options) {\r\n // Skip SSR builds\r\n if (options?.ssr) return null;\r\n\r\n // Skip excluded files\r\n if (isExcluded(id)) return null;\r\n\r\n // Skip server-only files (they shouldn't be in client bundle anyway)\r\n if (isServerOnlyModule(id)) return null;\r\n\r\n // Check for 'use server' directive at file level\r\n const trimmed = code.trim();\r\n if (trimmed.startsWith(\"'use server'\") || trimmed.startsWith('\"use server\"')) {\r\n const message =\r\n `[Flight] 'use server' file imported in client bundle.\\n\\n` +\r\n ` File: ${id}\\n\\n` +\r\n `This file should only run on the server. ` +\r\n `Check your import graph to find where this is imported.`;\r\n\r\n if (violationBehavior === 'error') {\r\n this.error(message);\r\n } else {\r\n this.warn(message);\r\n }\r\n }\r\n\r\n return null;\r\n },\r\n };\r\n}\r\n"]}
@@ -0,0 +1,88 @@
1
+ // src/plugins/env-plugin.ts
2
+ function flightEnvPlugin(options = {}) {
3
+ const {
4
+ publicPrefix = "FLIGHT_PUBLIC_",
5
+ additionalPublicPrefixes = ["VITE_"],
6
+ privateVarBehavior = "warn",
7
+ allowList = ["NODE_ENV", "MODE"]
8
+ } = options;
9
+ const allPublicPrefixes = [publicPrefix, ...additionalPublicPrefixes];
10
+ return {
11
+ name: "flight:env",
12
+ enforce: "pre",
13
+ configResolved(resolvedConfig) {
14
+ },
15
+ config(_, { isSsrBuild }) {
16
+ if (isSsrBuild) return {};
17
+ const publicEnvVars = {};
18
+ for (const [key, value] of Object.entries(process.env)) {
19
+ if (value !== void 0 && isPublicKey(key, allPublicPrefixes, allowList)) {
20
+ publicEnvVars[`process.env.${key}`] = JSON.stringify(value);
21
+ }
22
+ }
23
+ return {
24
+ define: publicEnvVars
25
+ };
26
+ },
27
+ transform(code, id, options2) {
28
+ if (options2?.ssr) return null;
29
+ if (id.includes("node_modules")) return null;
30
+ if (!code.includes("process.env.")) return null;
31
+ const envVarPattern = /process\.env\.([A-Z_][A-Z0-9_]*)/g;
32
+ let hasModifications = false;
33
+ let modifiedCode = code;
34
+ let match;
35
+ const issues = [];
36
+ while ((match = envVarPattern.exec(code)) !== null) {
37
+ const varName = match[1];
38
+ if (isPublicKey(varName, allPublicPrefixes, allowList)) {
39
+ continue;
40
+ }
41
+ hasModifications = true;
42
+ if (privateVarBehavior === "error") {
43
+ issues.push(
44
+ `Private env var "${varName}" accessed in client code.
45
+ File: ${id}
46
+ Use FLIGHT_PUBLIC_${varName} if this should be public.`
47
+ );
48
+ } else if (privateVarBehavior === "warn") {
49
+ console.warn(
50
+ `[Flight] Private env var "process.env.${varName}" in ${id}
51
+ \u2192 Replaced with undefined for security.
52
+ \u2192 Use FLIGHT_PUBLIC_${varName} if this should be public.`
53
+ );
54
+ }
55
+ modifiedCode = modifiedCode.replace(
56
+ new RegExp(`process\\.env\\.${varName}`, "g"),
57
+ "undefined"
58
+ );
59
+ }
60
+ if (issues.length > 0 && privateVarBehavior === "error") {
61
+ throw new Error(
62
+ `[Flight] Environment variable security violations:
63
+
64
+ ${issues.join("\n\n")}`
65
+ );
66
+ }
67
+ if (hasModifications) {
68
+ return {
69
+ code: modifiedCode,
70
+ map: null
71
+ // TODO: source map
72
+ };
73
+ }
74
+ return null;
75
+ }
76
+ };
77
+ }
78
+ function isPublicKey(key, prefixes, allowList) {
79
+ if (allowList.includes(key)) return true;
80
+ for (const prefix of prefixes) {
81
+ if (key.startsWith(prefix)) return true;
82
+ }
83
+ return false;
84
+ }
85
+
86
+ export { flightEnvPlugin };
87
+ //# sourceMappingURL=chunk-RFTE6JVG.js.map
88
+ //# sourceMappingURL=chunk-RFTE6JVG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugins/env-plugin.ts"],"names":["options"],"mappings":"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","file":"chunk-RFTE6JVG.js","sourcesContent":["/**\r\n * @flight-framework/core - Environment Variables Plugin\r\n * \r\n * Vite plugin for environment variable protection.\r\n * OPTIONAL - use if you want build-time protection.\r\n * \r\n * Features:\r\n * - FLIGHT_PUBLIC_* and VITE_* accessible on client\r\n * - Other vars replaced with undefined on client\r\n * - Configurable behavior (warn, error, silent)\r\n * \r\n * @example\r\n * ```typescript\r\n * // vite.config.ts\r\n * import { flightEnvPlugin } from '@flight-framework/core/plugins';\r\n * \r\n * export default {\r\n * plugins: [flightEnvPlugin()],\r\n * };\r\n * ```\r\n */\r\n\r\nimport type { Plugin, ResolvedConfig } from 'vite';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface FlightEnvPluginOptions {\r\n /**\r\n * Prefix for public environment variables.\r\n * Variables with this prefix will be accessible on the client.\r\n * @default 'FLIGHT_PUBLIC_'\r\n */\r\n publicPrefix?: string;\r\n\r\n /**\r\n * Additional prefixes to treat as public.\r\n * @default ['VITE_']\r\n */\r\n additionalPublicPrefixes?: string[];\r\n\r\n /**\r\n * How to handle private vars accessed in client code.\r\n * - 'warn': Log warning, replace with undefined\r\n * - 'error': Throw build error\r\n * - 'silent': Replace with undefined, no warning\r\n * @default 'warn'\r\n */\r\n privateVarBehavior?: 'warn' | 'error' | 'silent';\r\n\r\n /**\r\n * Specific variables to allow (bypass prefix check).\r\n * @default ['NODE_ENV', 'MODE']\r\n */\r\n allowList?: string[];\r\n}\r\n\r\n// ============================================================================\r\n// Plugin\r\n// ============================================================================\r\n\r\n/**\r\n * Vite plugin to protect environment variables.\r\n * \r\n * This plugin is OPTIONAL. Use it if you want build-time\r\n * protection for your environment variables.\r\n * \r\n * By default, it will:\r\n * - Allow FLIGHT_PUBLIC_* and VITE_* on client\r\n * - Allow NODE_ENV and MODE\r\n * - Replace other process.env.* with undefined on client\r\n * - Show warnings in development\r\n */\r\nexport function flightEnvPlugin(options: FlightEnvPluginOptions = {}): Plugin {\r\n const {\r\n publicPrefix = 'FLIGHT_PUBLIC_',\r\n additionalPublicPrefixes = ['VITE_'],\r\n privateVarBehavior = 'warn',\r\n allowList = ['NODE_ENV', 'MODE'],\r\n } = options;\r\n\r\n const allPublicPrefixes = [publicPrefix, ...additionalPublicPrefixes];\r\n let config: ResolvedConfig;\r\n\r\n return {\r\n name: 'flight:env',\r\n enforce: 'pre',\r\n\r\n configResolved(resolvedConfig) {\r\n config = resolvedConfig;\r\n },\r\n\r\n config(_, { isSsrBuild }) {\r\n // For SSR builds, don't modify anything\r\n if (isSsrBuild) return {};\r\n\r\n // Collect public environment variables\r\n const publicEnvVars: Record<string, string> = {};\r\n\r\n for (const [key, value] of Object.entries(process.env)) {\r\n if (value !== undefined && isPublicKey(key, allPublicPrefixes, allowList)) {\r\n publicEnvVars[`process.env.${key}`] = JSON.stringify(value);\r\n }\r\n }\r\n\r\n return {\r\n define: publicEnvVars,\r\n };\r\n },\r\n\r\n transform(code, id, options) {\r\n // Skip SSR builds - server can access everything\r\n if (options?.ssr) return null;\r\n\r\n // Skip node_modules\r\n if (id.includes('node_modules')) return null;\r\n\r\n // Skip if no process.env references\r\n if (!code.includes('process.env.')) return null;\r\n\r\n // Find all process.env.VARIABLE_NAME patterns\r\n const envVarPattern = /process\\.env\\.([A-Z_][A-Z0-9_]*)/g;\r\n let hasModifications = false;\r\n let modifiedCode = code;\r\n\r\n let match;\r\n const issues: string[] = [];\r\n\r\n while ((match = envVarPattern.exec(code)) !== null) {\r\n const varName = match[1];\r\n\r\n // Skip public vars\r\n if (isPublicKey(varName, allPublicPrefixes, allowList)) {\r\n continue;\r\n }\r\n\r\n // Private var accessed in client code\r\n hasModifications = true;\r\n\r\n if (privateVarBehavior === 'error') {\r\n issues.push(\r\n `Private env var \"${varName}\" accessed in client code.\\n` +\r\n ` File: ${id}\\n` +\r\n ` Use FLIGHT_PUBLIC_${varName} if this should be public.`\r\n );\r\n } else if (privateVarBehavior === 'warn') {\r\n console.warn(\r\n `[Flight] Private env var \"process.env.${varName}\" in ${id}\\n` +\r\n ` → Replaced with undefined for security.\\n` +\r\n ` → Use FLIGHT_PUBLIC_${varName} if this should be public.`\r\n );\r\n }\r\n\r\n // Replace with undefined\r\n modifiedCode = modifiedCode.replace(\r\n new RegExp(`process\\\\.env\\\\.${varName}`, 'g'),\r\n 'undefined'\r\n );\r\n }\r\n\r\n // Throw if using error mode\r\n if (issues.length > 0 && privateVarBehavior === 'error') {\r\n throw new Error(\r\n `[Flight] Environment variable security violations:\\n\\n${issues.join('\\n\\n')}`\r\n );\r\n }\r\n\r\n if (hasModifications) {\r\n return {\r\n code: modifiedCode,\r\n map: null, // TODO: source map\r\n };\r\n }\r\n\r\n return null;\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Helpers\r\n// ============================================================================\r\n\r\nfunction isPublicKey(\r\n key: string,\r\n prefixes: string[],\r\n allowList: string[]\r\n): boolean {\r\n // Check allow list\r\n if (allowList.includes(key)) return true;\r\n\r\n // Check prefixes\r\n for (const prefix of prefixes) {\r\n if (key.startsWith(prefix)) return true;\r\n }\r\n\r\n return false;\r\n}\r\n"]}
@@ -0,0 +1,67 @@
1
+ // src/utils/boundaries.ts
2
+ function assertServer(context) {
3
+ if (typeof window !== "undefined") {
4
+ const name = context || "This function";
5
+ throw new Error(
6
+ `[Flight] ${name} can only be called on the server. If you need this on the client, use an API route or server action.`
7
+ );
8
+ }
9
+ }
10
+ function assertClient(context) {
11
+ if (typeof window === "undefined") {
12
+ const name = context || "This function";
13
+ throw new Error(
14
+ `[Flight] ${name} can only be called on the client. This code should not run during SSR.`
15
+ );
16
+ }
17
+ }
18
+ function getEnv(key) {
19
+ if (isPublicEnvVar(key)) {
20
+ return getEnvValue(key);
21
+ }
22
+ if (typeof window !== "undefined") {
23
+ if (process.env.NODE_ENV === "development") {
24
+ console.warn(
25
+ `[Flight] Attempted to access private env var "${key}" on client. This returns undefined for security. If this should be public, rename it to FLIGHT_PUBLIC_${key}`
26
+ );
27
+ }
28
+ return void 0;
29
+ }
30
+ return getEnvValue(key);
31
+ }
32
+ function requireEnv(key) {
33
+ const value = getEnv(key);
34
+ if (value === void 0) {
35
+ if (typeof window !== "undefined" && !isPublicEnvVar(key)) {
36
+ throw new Error(
37
+ `[Flight] Cannot access private env var "${key}" on client. Move this code to the server or use FLIGHT_PUBLIC_${key}`
38
+ );
39
+ }
40
+ throw new Error(
41
+ `[Flight] Required environment variable "${key}" is not set. Check your .env file or environment configuration.`
42
+ );
43
+ }
44
+ return value;
45
+ }
46
+ function isPublicEnvVar(key) {
47
+ return key.startsWith("FLIGHT_PUBLIC_") || key.startsWith("VITE_") || key === "NODE_ENV" || key === "MODE";
48
+ }
49
+ function getEnvValue(key) {
50
+ if (typeof process !== "undefined" && process.env) {
51
+ const value = process.env[key];
52
+ if (value !== void 0) return value;
53
+ }
54
+ try {
55
+ const meta = import.meta;
56
+ if (meta.env) {
57
+ const value = meta.env[key];
58
+ if (value !== void 0) return value;
59
+ }
60
+ } catch {
61
+ }
62
+ return void 0;
63
+ }
64
+
65
+ export { assertClient, assertServer, getEnv, requireEnv };
66
+ //# sourceMappingURL=chunk-WF46NESN.js.map
67
+ //# sourceMappingURL=chunk-WF46NESN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/boundaries.ts"],"names":[],"mappings":";AAyCO,SAAS,aAAa,OAAA,EAAwB;AACjD,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAC/B,IAAA,MAAM,OAAO,OAAA,IAAW,eAAA;AACxB,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,YAAY,IAAI,CAAA,qGAAA;AAAA,KAEpB;AAAA,EACJ;AACJ;AAoBO,SAAS,aAAa,OAAA,EAAwB;AACjD,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAC/B,IAAA,MAAM,OAAO,OAAA,IAAW,eAAA;AACxB,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,YAAY,IAAI,CAAA,uEAAA;AAAA,KAEpB;AAAA,EACJ;AACJ;AA2BO,SAAS,OAAO,GAAA,EAAiC;AAEpD,EAAA,IAAI,cAAA,CAAe,GAAG,CAAA,EAAG;AACrB,IAAA,OAAO,YAAY,GAAG,CAAA;AAAA,EAC1B;AAGA,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAE/B,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,EAAe;AACxC,MAAA,OAAA,CAAQ,IAAA;AAAA,QACJ,CAAA,8CAAA,EAAiD,GAAG,CAAA,uGAAA,EAEI,GAAG,CAAA;AAAA,OAC/D;AAAA,IACJ;AACA,IAAA,OAAO,MAAA;AAAA,EACX;AAGA,EAAA,OAAO,YAAY,GAAG,CAAA;AAC1B;AAgBO,SAAS,WAAW,GAAA,EAAqB;AAC5C,EAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AAExB,EAAA,IAAI,UAAU,MAAA,EAAW;AAErB,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,cAAA,CAAe,GAAG,CAAA,EAAG;AACvD,MAAA,MAAM,IAAI,KAAA;AAAA,QACN,CAAA,wCAAA,EAA2C,GAAG,CAAA,+DAAA,EACO,GAAG,CAAA;AAAA,OAC5D;AAAA,IACJ;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,2CAA2C,GAAG,CAAA,gEAAA;AAAA,KAElD;AAAA,EACJ;AAEA,EAAA,OAAO,KAAA;AACX;AASA,SAAS,eAAe,GAAA,EAAsB;AAC1C,EAAA,OACI,GAAA,CAAI,UAAA,CAAW,gBAAgB,CAAA,IAC/B,GAAA,CAAI,WAAW,OAAO,CAAA,IACtB,GAAA,KAAQ,UAAA,IACR,GAAA,KAAQ,MAAA;AAEhB;AAKA,SAAS,YAAY,GAAA,EAAiC;AAElD,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,GAAA,EAAK;AAC/C,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAC7B,IAAA,IAAI,KAAA,KAAU,QAAW,OAAO,KAAA;AAAA,EACpC;AAGA,EAAA,IAAI;AACA,IAAA,MAAM,IAAA,GAAO,MAAA,CAAA,IAAA;AACb,IAAA,IAAI,KAAK,GAAA,EAAK;AACV,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AAC1B,MAAA,IAAI,KAAA,KAAU,QAAW,OAAO,KAAA;AAAA,IACpC;AAAA,EACJ,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,OAAO,MAAA;AACX","file":"chunk-WF46NESN.js","sourcesContent":["/**\r\n * @flight-framework/core - Server/Client Boundaries\r\n * \r\n * Runtime utilities for server/client code separation.\r\n * These are OPTIONAL - use them if you want safety guards.\r\n * Flight doesn't force you to use them.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { assertServer, getEnv } from '@flight-framework/core';\r\n * \r\n * export async function fetchFromDatabase() {\r\n * assertServer('fetchFromDatabase'); // Throws if called on client\r\n * const dbUrl = getEnv('DATABASE_URL'); // Returns undefined on client\r\n * // ... your code\r\n * }\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Runtime Assertions\r\n// ============================================================================\r\n\r\n/**\r\n * Assert that code is running on the server.\r\n * Throws an error if called from the client (browser).\r\n * \r\n * Use this to protect server-only code from being accidentally\r\n * called on the client.\r\n * \r\n * @param context - Optional context string for the error message\r\n * @throws Error if called on client\r\n * \r\n * @example\r\n * ```typescript\r\n * export async function queryDatabase() {\r\n * assertServer('queryDatabase');\r\n * // Safe to use process.env, database connections, etc.\r\n * }\r\n * ```\r\n */\r\nexport function assertServer(context?: string): void {\r\n if (typeof window !== 'undefined') {\r\n const name = context || 'This function';\r\n throw new Error(\r\n `[Flight] ${name} can only be called on the server. ` +\r\n `If you need this on the client, use an API route or server action.`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Assert that code is running on the client.\r\n * Throws an error if called from the server.\r\n * \r\n * Use this to protect client-only code (e.g., DOM manipulation,\r\n * browser APIs) from being accidentally called during SSR.\r\n * \r\n * @param context - Optional context string for the error message\r\n * @throws Error if called on server\r\n * \r\n * @example\r\n * ```typescript\r\n * export function scrollToTop() {\r\n * assertClient('scrollToTop');\r\n * window.scrollTo(0, 0);\r\n * }\r\n * ```\r\n */\r\nexport function assertClient(context?: string): void {\r\n if (typeof window === 'undefined') {\r\n const name = context || 'This function';\r\n throw new Error(\r\n `[Flight] ${name} can only be called on the client. ` +\r\n `This code should not run during SSR.`\r\n );\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Environment Variable Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Get an environment variable safely.\r\n * \r\n * On the server: Returns the variable value.\r\n * On the client: Returns undefined for non-public vars.\r\n * \r\n * Public variables (prefixed with FLIGHT_PUBLIC_) are always accessible.\r\n * \r\n * @param key - Environment variable name\r\n * @returns The value or undefined\r\n * \r\n * @example\r\n * ```typescript\r\n * // On server: returns actual value\r\n * // On client: returns undefined (safe!)\r\n * const dbUrl = getEnv('DATABASE_URL');\r\n * \r\n * // Works on both server and client\r\n * const apiUrl = getEnv('FLIGHT_PUBLIC_API_URL');\r\n * ```\r\n */\r\nexport function getEnv(key: string): string | undefined {\r\n // Public vars are always accessible\r\n if (isPublicEnvVar(key)) {\r\n return getEnvValue(key);\r\n }\r\n\r\n // Private vars only on server\r\n if (typeof window !== 'undefined') {\r\n // On client - return undefined safely\r\n if (process.env.NODE_ENV === 'development') {\r\n console.warn(\r\n `[Flight] Attempted to access private env var \"${key}\" on client. ` +\r\n `This returns undefined for security. ` +\r\n `If this should be public, rename it to FLIGHT_PUBLIC_${key}`\r\n );\r\n }\r\n return undefined;\r\n }\r\n\r\n // On server - return actual value\r\n return getEnvValue(key);\r\n}\r\n\r\n/**\r\n * Get an environment variable, throwing if not found.\r\n * Use this when a variable is required.\r\n * \r\n * @param key - Environment variable name\r\n * @returns The value\r\n * @throws Error if variable is not set or inaccessible\r\n * \r\n * @example\r\n * ```typescript\r\n * // Throws if DATABASE_URL is not set\r\n * const dbUrl = requireEnv('DATABASE_URL');\r\n * ```\r\n */\r\nexport function requireEnv(key: string): string {\r\n const value = getEnv(key);\r\n\r\n if (value === undefined) {\r\n // Check if we're on client accessing private var\r\n if (typeof window !== 'undefined' && !isPublicEnvVar(key)) {\r\n throw new Error(\r\n `[Flight] Cannot access private env var \"${key}\" on client. ` +\r\n `Move this code to the server or use FLIGHT_PUBLIC_${key}`\r\n );\r\n }\r\n throw new Error(\r\n `[Flight] Required environment variable \"${key}\" is not set. ` +\r\n `Check your .env file or environment configuration.`\r\n );\r\n }\r\n\r\n return value;\r\n}\r\n\r\n// ============================================================================\r\n// Helper Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Check if an environment variable is public (safe for client).\r\n */\r\nfunction isPublicEnvVar(key: string): boolean {\r\n return (\r\n key.startsWith('FLIGHT_PUBLIC_') ||\r\n key.startsWith('VITE_') ||\r\n key === 'NODE_ENV' ||\r\n key === 'MODE'\r\n );\r\n}\r\n\r\n/**\r\n * Get environment variable value from available sources.\r\n */\r\nfunction getEnvValue(key: string): string | undefined {\r\n // Try process.env (Node.js / SSR)\r\n if (typeof process !== 'undefined' && process.env) {\r\n const value = process.env[key];\r\n if (value !== undefined) return value;\r\n }\r\n\r\n // Try import.meta.env (Vite) - use type-safe access\r\n try {\r\n const meta = import.meta as { env?: Record<string, string | undefined> };\r\n if (meta.env) {\r\n const value = meta.env[key];\r\n if (value !== undefined) return value;\r\n }\r\n } catch {\r\n // import.meta not available in this environment\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n// ============================================================================\r\n// Type Guards\r\n// ============================================================================\r\n\r\n/**\r\n * Check if code is running on the server.\r\n * This is a re-export for convenience.\r\n */\r\nexport { isServer } from './env.js';\r\n\r\n/**\r\n * Check if code is running in the browser.\r\n * This is a re-export for convenience.\r\n */\r\nexport { isBrowser } from './env.js';\r\n"]}
package/dist/client.d.ts CHANGED
@@ -5,7 +5,7 @@ export { Middleware, MiddlewareContext, MiddlewareNext, createMiddlewareChain }
5
5
  export { CustomHydrationTrigger, HydrateOptions, HydrationTrigger, IslandConfig, hydrateIslands, registerFlightIslandElement } from './islands/index.js';
6
6
  export { BuiltInCondition, DEFAULT_BOT_PATTERNS, StreamingCondition, isBot, isSlowConnection, prefersNoStream, supportsStreaming } from './streaming/conditional.js';
7
7
  export { BadRequestError, ErrorBoundaryOptions, FlightError, FlightErrorOptions, FlightErrorProps, ForbiddenError, InternalError, NotFoundError, ResetDetails, UnauthorizedError, clearError, createError, getError, getErrorStatusCode, isFlightError, isForbiddenError as isForbidden, isNotFoundError as isNotFound, isUnauthorizedError as isUnauthorized, showError } from './errors/index.js';
8
- export { getEnvironment, isBrowser, isDevelopment, isProduction, isServer, isTest } from './utils/index.js';
8
+ export { g as getEnvironment, d as isBrowser, a as isDevelopment, i as isProduction, c as isServer, b as isTest } from './env-9do2c6yn.js';
9
9
  import './render/index.js';
10
10
  import './adapters/index.js';
11
11
 
package/dist/client.js CHANGED
@@ -3,7 +3,7 @@ export { hydrateIslands, registerFlightIslandElement } from './chunk-WFAWAHJH.js
3
3
  export { createMiddlewareChain } from './chunk-OYF2OAKS.js';
4
4
  import './chunk-IXMD5QH2.js';
5
5
  export { BadRequestError, FlightError, ForbiddenError, InternalError, NotFoundError, UnauthorizedError, clearError, createError, getError, getErrorStatusCode, isFlightError, isForbiddenError as isForbidden, isNotFoundError as isNotFound, isUnauthorizedError as isUnauthorized, showError } from './chunk-FSJNOPYE.js';
6
- import './chunk-PL37KFRJ.js';
6
+ import './chunk-WF46NESN.js';
7
7
  export { getEnvironment, isBrowser, isDevelopment, isProduction, isServer, isTest } from './chunk-YHEVHRLH.js';
8
8
  export { createRouter } from './chunk-GCQZ4FHI.js';
9
9
  export { cacheKey, cached, createCache, dedupe, jsonSerializer, memory } from './chunk-R7SQAREQ.js';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @flight-framework/core - Environment Utilities
3
+ *
4
+ * Environment detection utilities that work across Node.js, browsers, and edge runtimes.
5
+ * No hardcoded values - detects environment dynamically.
6
+ */
7
+ /**
8
+ * Check if running in production environment.
9
+ *
10
+ * Detection order:
11
+ * 1. Node.js process.env.NODE_ENV
12
+ * 2. Vite/modern bundlers import.meta.env.MODE or import.meta.env.PROD
13
+ * 3. Default: false (not production)
14
+ */
15
+ declare function isProduction(): boolean;
16
+ /**
17
+ * Check if running in development environment.
18
+ *
19
+ * Detection order:
20
+ * 1. Node.js process.env.NODE_ENV
21
+ * 2. Vite/modern bundlers import.meta.env.MODE or import.meta.env.DEV
22
+ * 3. Default: true (assume development if unknown)
23
+ */
24
+ declare function isDevelopment(): boolean;
25
+ /**
26
+ * Check if running in test environment.
27
+ */
28
+ declare function isTest(): boolean;
29
+ /**
30
+ * Check if running on the server (not browser).
31
+ */
32
+ declare function isServer(): boolean;
33
+ /**
34
+ * Check if running in the browser.
35
+ */
36
+ declare function isBrowser(): boolean;
37
+ /**
38
+ * Get the current environment name.
39
+ */
40
+ declare function getEnvironment(): 'production' | 'development' | 'test' | 'unknown';
41
+
42
+ export { isDevelopment as a, isTest as b, isServer as c, isBrowser as d, getEnvironment as g, isProduction as i };
package/dist/index.d.ts CHANGED
@@ -20,7 +20,8 @@ export { ServerContext as RSCServerContext, createServerContext, isNotFoundError
20
20
  export { BoundaryType as RSCBoundaryType, detectBoundaryType, hasUseClientDirective, hasUseServerDirective } from './rsc/boundaries.js';
21
21
  export { ClientComponent, ComponentType as RSCComponentType, RenderContext as RSCRenderContext, ServerComponent, composeComponents, createAsyncComponent, createClientBoundary, createRenderContext, deserializeProps, executeServerComponent, revalidatePath as rscRevalidatePath, revalidateTag as rscRevalidateTag, serializeProps, serverFetch, withErrorBoundary } from './rsc/legacy.js';
22
22
  export { BadRequestError, ErrorBoundaryOptions, FlightError, FlightErrorOptions, FlightErrorProps, ForbiddenError, InternalError, NotFoundError, ResetDetails, UnauthorizedError, clearError, createError, createErrorResponse, forbidden as createForbidden, notFound as createNotFound, unauthorized as createUnauthorized, getError, getErrorStatusCode, isFlightError, isForbiddenError as isForbidden, isNotFoundError as isNotFound, isUnauthorizedError as isUnauthorized, showError, wrapWithDigest } from './errors/index.js';
23
- export { getEnvironment, isBrowser, isDevelopment, isProduction, isServer, isTest } from './utils/index.js';
23
+ export { g as getEnvironment, d as isBrowser, a as isDevelopment, i as isProduction, c as isServer, b as isTest } from './env-9do2c6yn.js';
24
+ export { assertClient, assertServer, getEnv, requireEnv } from './utils/index.js';
24
25
 
25
26
  /**
26
27
  * @flight-framework/core - Route Rules Configuration
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ export { createIslandRegistry, createPreactIslandAdapter, createReactIslandAdapt
26
26
  export { createMiddlewareChain } from './chunk-OYF2OAKS.js';
27
27
  export { defineConfig } from './chunk-IXMD5QH2.js';
28
28
  export { BadRequestError, FlightError, ForbiddenError, InternalError, NotFoundError, UnauthorizedError, clearError, createError, createErrorResponse, forbidden as createForbidden, notFound as createNotFound, unauthorized as createUnauthorized, getError, getErrorStatusCode, isFlightError, isForbiddenError as isForbidden, isNotFoundError as isNotFound, isUnauthorizedError as isUnauthorized, showError, wrapWithDigest } from './chunk-FSJNOPYE.js';
29
- import './chunk-PL37KFRJ.js';
29
+ export { assertClient, assertServer, getEnv, requireEnv } from './chunk-WF46NESN.js';
30
30
  export { getEnvironment, isBrowser, isDevelopment, isProduction, isServer, isTest } from './chunk-YHEVHRLH.js';
31
31
  export { createRouter } from './chunk-GCQZ4FHI.js';
32
32
  import './chunk-ZVC3ZWLM.js';