@flight-framework/core 0.6.2 → 0.6.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/chunk-J7WEZXWH.js +14 -0
- package/dist/chunk-J7WEZXWH.js.map +1 -0
- package/dist/chunk-MFUJN7RV.js +20 -0
- package/dist/chunk-MFUJN7RV.js.map +1 -0
- package/dist/plugins/env-plugin.d.ts +15 -33
- package/dist/plugins/env-plugin.js +1 -1
- package/dist/plugins/index.d.ts +87 -21
- package/dist/plugins/index.js +63 -25
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/server-boundary-plugin.d.ts +27 -38
- package/dist/plugins/server-boundary-plugin.js +1 -1
- package/package.json +235 -235
- package/LICENSE +0 -21
- package/dist/chunk-NU3HX5T7.js +0 -80
- package/dist/chunk-NU3HX5T7.js.map +0 -1
- package/dist/chunk-RFTE6JVG.js +0 -88
- package/dist/chunk-RFTE6JVG.js.map +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/plugins/server-boundary-plugin.ts
|
|
2
|
+
function serverBoundaryPlugin(_options = {}) {
|
|
3
|
+
console.warn(
|
|
4
|
+
"[Flight] serverBoundaryPlugin is deprecated. Use runtime guards (assertServer, assertClient) instead."
|
|
5
|
+
);
|
|
6
|
+
return {
|
|
7
|
+
name: "flight:server-boundary-deprecated"
|
|
8
|
+
// No-op plugin - just shows warning
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { serverBoundaryPlugin };
|
|
13
|
+
//# sourceMappingURL=chunk-J7WEZXWH.js.map
|
|
14
|
+
//# sourceMappingURL=chunk-J7WEZXWH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/server-boundary-plugin.ts"],"names":[],"mappings":";AAsCO,SAAS,oBAAA,CACZ,QAAA,GAAwC,EAAC,EACnC;AACN,EAAA,OAAA,CAAQ,IAAA;AAAA,IACJ;AAAA,GAEJ;AAEA,EAAA,OAAO;AAAA,IACH,IAAA,EAAM;AAAA;AAAA,GAEV;AACJ","file":"chunk-J7WEZXWH.js","sourcesContent":["/**\r\n * @flight-framework/core - Server Boundary Plugin (DEPRECATED)\r\n * \r\n * This plugin has been deprecated due to conflicts with serverActionsPlugin.\r\n * \r\n * The intended functionality (detecting server-only imports in client bundles)\r\n * is difficult to implement correctly with Vite's plugin system because:\r\n * \r\n * 1. It conflicts with serverActionsPlugin which transforms 'use server' files\r\n * 2. The resolveId hook runs before transforms, making detection unreliable\r\n * 3. Vite 6+ has different environment APIs that need careful handling\r\n * \r\n * For now, use runtime guards instead:\r\n * \r\n * @example\r\n * ```typescript\r\n * import { assertServer } from '@flight-framework/core';\r\n * \r\n * export function getSecretData() {\r\n * assertServer('getSecretData'); // Throws if called on client\r\n * return process.env.SECRET_KEY;\r\n * }\r\n * ```\r\n * \r\n * @deprecated Use runtime guards (assertServer, assertClient) instead\r\n */\r\n\r\nimport type { Plugin } from 'vite';\r\n\r\nexport interface ServerBoundaryPluginOptions {\r\n /** @deprecated This plugin is deprecated */\r\n enabled?: boolean;\r\n}\r\n\r\n/**\r\n * @deprecated This plugin has been deprecated due to conflicts with serverActionsPlugin.\r\n * Use runtime guards (assertServer, assertClient) from '@flight-framework/core' instead.\r\n */\r\nexport function serverBoundaryPlugin(\r\n _options: ServerBoundaryPluginOptions = {}\r\n): Plugin {\r\n console.warn(\r\n '[Flight] serverBoundaryPlugin is deprecated. ' +\r\n 'Use runtime guards (assertServer, assertClient) instead.'\r\n );\r\n\r\n return {\r\n name: 'flight:server-boundary-deprecated',\r\n // No-op plugin - just shows warning\r\n };\r\n}\r\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/plugins/env-plugin.ts
|
|
2
|
+
function flightEnvPlugin(options = {}) {
|
|
3
|
+
const {
|
|
4
|
+
publicPrefix = "FLIGHT_PUBLIC_",
|
|
5
|
+
additionalPrefixes = ["VITE_"]
|
|
6
|
+
} = options;
|
|
7
|
+
const prefixes = [.../* @__PURE__ */ new Set([publicPrefix, ...additionalPrefixes])];
|
|
8
|
+
return {
|
|
9
|
+
name: "flight:env",
|
|
10
|
+
config() {
|
|
11
|
+
return {
|
|
12
|
+
envPrefix: prefixes
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { flightEnvPlugin };
|
|
19
|
+
//# sourceMappingURL=chunk-MFUJN7RV.js.map
|
|
20
|
+
//# sourceMappingURL=chunk-MFUJN7RV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/env-plugin.ts"],"names":[],"mappings":";AA8CO,SAAS,eAAA,CAAgB,OAAA,GAAkC,EAAC,EAAW;AAC1E,EAAA,MAAM;AAAA,IACF,YAAA,GAAe,gBAAA;AAAA,IACf,kBAAA,GAAqB,CAAC,OAAO;AAAA,GACjC,GAAI,OAAA;AAGJ,EAAA,MAAM,QAAA,GAAW,CAAC,mBAAG,IAAI,GAAA,CAAI,CAAC,YAAA,EAAc,GAAG,kBAAkB,CAAC,CAAC,CAAA;AAEnE,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,YAAA;AAAA,IACN,MAAA,GAAS;AACL,MAAA,OAAO;AAAA,QACH,SAAA,EAAW;AAAA,OACf;AAAA,IACJ;AAAA,GACJ;AACJ","file":"chunk-MFUJN7RV.js","sourcesContent":["/**\r\n * @flight-framework/core - Environment Plugin\r\n * \r\n * Simple Vite plugin to configure environment variable prefixes.\r\n * \r\n * NOTE: This is mostly a convenience wrapper around Vite's native envPrefix.\r\n * You can achieve the same by adding this to your vite.config.ts:\r\n * \r\n * envPrefix: ['VITE_', 'FLIGHT_PUBLIC_']\r\n * \r\n * Use this plugin if you want a more explicit Flight integration.\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 } from 'vite';\r\n\r\nexport interface FlightEnvPluginOptions {\r\n /**\r\n * Public environment variable prefix. Variables with this prefix\r\n * are exposed to client-side code via import.meta.env.\r\n * @default 'FLIGHT_PUBLIC_'\r\n */\r\n publicPrefix?: string;\r\n\r\n /**\r\n * Additional prefixes to expose (e.g., 'VITE_' is always included).\r\n * @default ['VITE_']\r\n */\r\n additionalPrefixes?: string[];\r\n}\r\n\r\n/**\r\n * Vite plugin to configure Flight's environment variable prefixes.\r\n * \r\n * This adds 'FLIGHT_PUBLIC_' as an additional env prefix alongside 'VITE_'.\r\n * Use FLIGHT_PUBLIC_* for variables you want exposed to the browser.\r\n */\r\nexport function flightEnvPlugin(options: FlightEnvPluginOptions = {}): Plugin {\r\n const {\r\n publicPrefix = 'FLIGHT_PUBLIC_',\r\n additionalPrefixes = ['VITE_'],\r\n } = options;\r\n\r\n // Build the list of prefixes\r\n const prefixes = [...new Set([publicPrefix, ...additionalPrefixes])];\r\n\r\n return {\r\n name: 'flight:env',\r\n config() {\r\n return {\r\n envPrefix: prefixes,\r\n };\r\n },\r\n };\r\n}\r\n"]}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @flight-framework/core - Environment
|
|
4
|
+
* @flight-framework/core - Environment Plugin
|
|
5
5
|
*
|
|
6
|
-
* Vite plugin
|
|
7
|
-
* OPTIONAL - use if you want build-time protection.
|
|
6
|
+
* Simple Vite plugin to configure environment variable prefixes.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* NOTE: This is mostly a convenience wrapper around Vite's native envPrefix.
|
|
9
|
+
* You can achieve the same by adding this to your vite.config.ts:
|
|
10
|
+
*
|
|
11
|
+
* envPrefix: ['VITE_', 'FLIGHT_PUBLIC_']
|
|
12
|
+
*
|
|
13
|
+
* Use this plugin if you want a more explicit Flight integration.
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* ```typescript
|
|
@@ -24,41 +25,22 @@ import { Plugin } from 'vite';
|
|
|
24
25
|
|
|
25
26
|
interface FlightEnvPluginOptions {
|
|
26
27
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
28
|
+
* Public environment variable prefix. Variables with this prefix
|
|
29
|
+
* are exposed to client-side code via import.meta.env.
|
|
29
30
|
* @default 'FLIGHT_PUBLIC_'
|
|
30
31
|
*/
|
|
31
32
|
publicPrefix?: string;
|
|
32
33
|
/**
|
|
33
|
-
* Additional prefixes to
|
|
34
|
+
* Additional prefixes to expose (e.g., 'VITE_' is always included).
|
|
34
35
|
* @default ['VITE_']
|
|
35
36
|
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* How to handle private vars accessed in client code.
|
|
39
|
-
* - 'warn': Log warning, replace with undefined
|
|
40
|
-
* - 'error': Throw build error
|
|
41
|
-
* - 'silent': Replace with undefined, no warning
|
|
42
|
-
* @default 'warn'
|
|
43
|
-
*/
|
|
44
|
-
privateVarBehavior?: 'warn' | 'error' | 'silent';
|
|
45
|
-
/**
|
|
46
|
-
* Specific variables to allow (bypass prefix check).
|
|
47
|
-
* @default ['NODE_ENV', 'MODE']
|
|
48
|
-
*/
|
|
49
|
-
allowList?: string[];
|
|
37
|
+
additionalPrefixes?: string[];
|
|
50
38
|
}
|
|
51
39
|
/**
|
|
52
|
-
* Vite plugin to
|
|
53
|
-
*
|
|
54
|
-
* This plugin is OPTIONAL. Use it if you want build-time
|
|
55
|
-
* protection for your environment variables.
|
|
40
|
+
* Vite plugin to configure Flight's environment variable prefixes.
|
|
56
41
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* - Allow NODE_ENV and MODE
|
|
60
|
-
* - Replace other process.env.* with undefined on client
|
|
61
|
-
* - Show warnings in development
|
|
42
|
+
* This adds 'FLIGHT_PUBLIC_' as an additional env prefix alongside 'VITE_'.
|
|
43
|
+
* Use FLIGHT_PUBLIC_* for variables you want exposed to the browser.
|
|
62
44
|
*/
|
|
63
45
|
declare function flightEnvPlugin(options?: FlightEnvPluginOptions): Plugin;
|
|
64
46
|
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,8 +1,67 @@
|
|
|
1
|
-
import { Plugin } from 'vite';
|
|
2
1
|
import { FlightEnvPluginOptions } from './env-plugin.js';
|
|
3
2
|
export { flightEnvPlugin } from './env-plugin.js';
|
|
4
|
-
import {
|
|
5
|
-
export { serverBoundaryPlugin } from './server-boundary-plugin.js';
|
|
3
|
+
import { Plugin } from 'vite';
|
|
4
|
+
export { ServerBoundaryPluginOptions, serverBoundaryPlugin } from './server-boundary-plugin.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @flight-framework/core - Server Only Plugin
|
|
8
|
+
*
|
|
9
|
+
* Vite plugin to properly handle the `server-only` npm package.
|
|
10
|
+
*
|
|
11
|
+
* The `server-only` package is designed for Next.js and throws an error
|
|
12
|
+
* when imported. In Next.js, the bundler has special handling to:
|
|
13
|
+
* - Allow the import in server context (no error)
|
|
14
|
+
* - Block the import in client bundles (build error)
|
|
15
|
+
*
|
|
16
|
+
* This plugin provides the same behavior for Vite/Flight:
|
|
17
|
+
* - In SSR/Server environment: Replace with empty module (no-op)
|
|
18
|
+
* - In Client environment: Let the build fail (or warn in dev)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // vite.config.ts
|
|
23
|
+
* import { serverOnlyPlugin } from '@flight-framework/core/plugins';
|
|
24
|
+
*
|
|
25
|
+
* export default {
|
|
26
|
+
* plugins: [serverOnlyPlugin()],
|
|
27
|
+
* };
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // In your server-only file:
|
|
33
|
+
* import 'server-only';
|
|
34
|
+
*
|
|
35
|
+
* export async function getSecretData() {
|
|
36
|
+
* return process.env.SECRET_KEY;
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
interface ServerOnlyPluginOptions {
|
|
42
|
+
/**
|
|
43
|
+
* What to do when server-only is imported in client context.
|
|
44
|
+
* - 'error': Throw build error (production)
|
|
45
|
+
* - 'warn': Log warning but continue (development)
|
|
46
|
+
* @default 'error' in build, 'warn' in dev
|
|
47
|
+
*/
|
|
48
|
+
violationBehavior?: 'error' | 'warn';
|
|
49
|
+
/**
|
|
50
|
+
* Additional packages to treat as server-only.
|
|
51
|
+
* These will be replaced with empty modules in server context
|
|
52
|
+
* and blocked in client context.
|
|
53
|
+
* @default []
|
|
54
|
+
*/
|
|
55
|
+
additionalPackages?: string[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Vite plugin to handle `server-only` package for Flight/Vite applications.
|
|
59
|
+
*
|
|
60
|
+
* This replicates Next.js behavior:
|
|
61
|
+
* - SSR/Server: Import succeeds (replaced with empty module)
|
|
62
|
+
* - Client: Build fails with clear error message
|
|
63
|
+
*/
|
|
64
|
+
declare function serverOnlyPlugin(options?: ServerOnlyPluginOptions): Plugin;
|
|
6
65
|
|
|
7
66
|
/**
|
|
8
67
|
* @flight-framework/core - Critical CSS Plugin
|
|
@@ -127,29 +186,36 @@ interface CriticalCSSOptions {
|
|
|
127
186
|
declare function criticalCSS(options?: CriticalCSSOptions): Plugin;
|
|
128
187
|
|
|
129
188
|
/**
|
|
130
|
-
* @flight-framework/core -
|
|
189
|
+
* @flight-framework/core - Vite Plugins
|
|
131
190
|
*
|
|
132
|
-
* Optional Vite plugins for
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* Flight doesn't force you to use any of these - use them if you want.
|
|
191
|
+
* Optional Vite plugins for Flight Framework.
|
|
192
|
+
* All plugins are opt-in - use only what you need.
|
|
136
193
|
*/
|
|
137
194
|
|
|
195
|
+
interface FlightPluginsOptions {
|
|
196
|
+
env?: FlightEnvPluginOptions;
|
|
197
|
+
serverOnly?: ServerOnlyPluginOptions;
|
|
198
|
+
}
|
|
138
199
|
/**
|
|
139
|
-
* Recommended plugins for most
|
|
140
|
-
*
|
|
200
|
+
* Recommended Flight plugins for most projects.
|
|
201
|
+
* Includes:
|
|
202
|
+
* - flightEnvPlugin: Configures FLIGHT_PUBLIC_* env prefix
|
|
203
|
+
* - serverOnlyPlugin: Properly handles `server-only` npm package
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* // vite.config.ts
|
|
208
|
+
* import { flightRecommendedPlugins } from '@flight-framework/core/plugins';
|
|
209
|
+
*
|
|
210
|
+
* export default {
|
|
211
|
+
* plugins: [...flightRecommendedPlugins()],
|
|
212
|
+
* };
|
|
213
|
+
* ```
|
|
141
214
|
*/
|
|
142
|
-
declare function flightRecommendedPlugins(options?:
|
|
143
|
-
env?: FlightEnvPluginOptions;
|
|
144
|
-
serverBoundary?: ServerBoundaryPluginOptions;
|
|
145
|
-
}): Plugin[];
|
|
215
|
+
declare function flightRecommendedPlugins(options?: FlightPluginsOptions): Plugin[];
|
|
146
216
|
/**
|
|
147
|
-
*
|
|
148
|
-
* Recommended for production builds.
|
|
217
|
+
* @deprecated Use flightRecommendedPlugins instead.
|
|
149
218
|
*/
|
|
150
|
-
declare function flightStrictPlugins(options?:
|
|
151
|
-
env?: FlightEnvPluginOptions;
|
|
152
|
-
serverBoundary?: ServerBoundaryPluginOptions;
|
|
153
|
-
}): Plugin[];
|
|
219
|
+
declare function flightStrictPlugins(options?: FlightPluginsOptions): Plugin[];
|
|
154
220
|
|
|
155
|
-
export {
|
|
221
|
+
export { FlightEnvPluginOptions, type FlightPluginsOptions, type ServerOnlyPluginOptions, criticalCSS, flightRecommendedPlugins, flightStrictPlugins, serverOnlyPlugin };
|
package/dist/plugins/index.js
CHANGED
|
@@ -1,7 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export { serverBoundaryPlugin } from '../chunk-J7WEZXWH.js';
|
|
2
|
+
import { flightEnvPlugin } from '../chunk-MFUJN7RV.js';
|
|
3
|
+
export { flightEnvPlugin } from '../chunk-MFUJN7RV.js';
|
|
4
|
+
|
|
5
|
+
// src/plugins/server-only-plugin.ts
|
|
6
|
+
var VIRTUAL_SERVER_ONLY = "\0server-only-noop";
|
|
7
|
+
function serverOnlyPlugin(options = {}) {
|
|
8
|
+
const {
|
|
9
|
+
additionalPackages = []
|
|
10
|
+
} = options;
|
|
11
|
+
const serverOnlyPackages = /* @__PURE__ */ new Set([
|
|
12
|
+
"server-only",
|
|
13
|
+
...additionalPackages
|
|
14
|
+
]);
|
|
15
|
+
let config;
|
|
16
|
+
let isDev = false;
|
|
17
|
+
return {
|
|
18
|
+
name: "flight:server-only",
|
|
19
|
+
enforce: "pre",
|
|
20
|
+
// Run before other plugins
|
|
21
|
+
configResolved(resolvedConfig) {
|
|
22
|
+
config = resolvedConfig;
|
|
23
|
+
isDev = config.command === "serve";
|
|
24
|
+
},
|
|
25
|
+
resolveId(id) {
|
|
26
|
+
if (!serverOnlyPackages.has(id)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const isServer = this.environment?.config?.consumer === "server" || this.environment?.name === "ssr" || // @ts-ignore - Fallback for Vite 5 compatibility
|
|
30
|
+
config.build?.ssr === true;
|
|
31
|
+
if (isServer) {
|
|
32
|
+
return VIRTUAL_SERVER_ONLY;
|
|
33
|
+
}
|
|
34
|
+
const behavior = options.violationBehavior ?? (isDev ? "warn" : "error");
|
|
35
|
+
const message = `[Flight] Cannot import '${id}' in client bundle. This module is marked as server-only and should not be used in client code. Check your import chain to ensure server-only code is not imported from client components.`;
|
|
36
|
+
if (behavior === "error") {
|
|
37
|
+
this.error(message);
|
|
38
|
+
} else {
|
|
39
|
+
console.warn(`
|
|
40
|
+
\u26A0\uFE0F ${message}
|
|
41
|
+
`);
|
|
42
|
+
return VIRTUAL_SERVER_ONLY;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
},
|
|
46
|
+
load(id) {
|
|
47
|
+
if (id === VIRTUAL_SERVER_ONLY) {
|
|
48
|
+
return {
|
|
49
|
+
code: "/* server-only: no-op in server context */",
|
|
50
|
+
map: null
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
5
57
|
|
|
6
58
|
// src/plugins/critical-css.ts
|
|
7
59
|
function criticalCSS(options = {}) {
|
|
@@ -120,31 +172,17 @@ function matchesPattern(path, pattern) {
|
|
|
120
172
|
}
|
|
121
173
|
|
|
122
174
|
// src/plugins/index.ts
|
|
123
|
-
function flightRecommendedPlugins(options) {
|
|
175
|
+
function flightRecommendedPlugins(options = {}) {
|
|
124
176
|
return [
|
|
125
|
-
flightEnvPlugin(
|
|
126
|
-
|
|
127
|
-
...options?.env
|
|
128
|
-
}),
|
|
129
|
-
serverBoundaryPlugin({
|
|
130
|
-
violationBehavior: "warn",
|
|
131
|
-
...options?.serverBoundary
|
|
132
|
-
})
|
|
177
|
+
flightEnvPlugin(options.env),
|
|
178
|
+
serverOnlyPlugin(options.serverOnly)
|
|
133
179
|
];
|
|
134
180
|
}
|
|
135
|
-
function flightStrictPlugins(options) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
privateVarBehavior: "error",
|
|
139
|
-
...options?.env
|
|
140
|
-
}),
|
|
141
|
-
serverBoundaryPlugin({
|
|
142
|
-
violationBehavior: "error",
|
|
143
|
-
...options?.serverBoundary
|
|
144
|
-
})
|
|
145
|
-
];
|
|
181
|
+
function flightStrictPlugins(options = {}) {
|
|
182
|
+
console.warn("[Flight] flightStrictPlugins is deprecated. Use flightRecommendedPlugins instead.");
|
|
183
|
+
return flightRecommendedPlugins(options);
|
|
146
184
|
}
|
|
147
185
|
|
|
148
|
-
export { criticalCSS, flightRecommendedPlugins, flightStrictPlugins };
|
|
186
|
+
export { criticalCSS, flightRecommendedPlugins, flightStrictPlugins, serverOnlyPlugin };
|
|
149
187
|
//# sourceMappingURL=index.js.map
|
|
150
188
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/critical-css.ts","../../src/plugins/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * @flight-framework/core - Critical CSS Plugin\r\n *\r\n * Extract and inline critical CSS for improved Core Web Vitals.\r\n * Uses Critters under the hood for CSS extraction.\r\n *\r\n * This is an OPTIONAL plugin. Install 'critters' only if you use it.\r\n *\r\n * @example\r\n * ```typescript\r\n * // vite.config.ts\r\n * import { criticalCSS } from '@flight-framework/core/plugins';\r\n *\r\n * export default defineConfig({\r\n * plugins: [\r\n * criticalCSS({\r\n * preload: 'swap',\r\n * pruneSource: false,\r\n * }),\r\n * ],\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\n/**\r\n * Preload strategy for non-critical CSS.\r\n *\r\n * - 'body': Move stylesheet links to end of body\r\n * - 'media': Use media=\"print\" and swap to \"all\" on load\r\n * - 'swap': Use link rel=\"preload\" and swap to stylesheet\r\n * - 'swap-high': Like swap, with fetchpriority=\"high\"\r\n * - 'js': Load via JavaScript\r\n * - 'js-lazy': Load via JavaScript when idle\r\n * - false: Don't preload\r\n */\r\nexport type PreloadStrategy =\r\n | 'body'\r\n | 'media'\r\n | 'swap'\r\n | 'swap-high'\r\n | 'js'\r\n | 'js-lazy'\r\n | false;\r\n\r\n/**\r\n * Critical CSS plugin options.\r\n */\r\nexport interface CriticalCSSOptions {\r\n /**\r\n * Enable critical CSS extraction.\r\n * @default true in production\r\n */\r\n enabled?: boolean;\r\n\r\n /**\r\n * Strategy for loading non-critical CSS.\r\n * @default 'swap'\r\n */\r\n preload?: PreloadStrategy;\r\n\r\n /**\r\n * Remove inlined CSS rules from the source stylesheet.\r\n * Reduces duplicate CSS but may cause issues with JS frameworks.\r\n * @default false\r\n */\r\n pruneSource?: boolean;\r\n\r\n /**\r\n * Remove unused CSS selectors from critical CSS.\r\n * @default true\r\n */\r\n reduceInlineStyles?: boolean;\r\n\r\n /**\r\n * Merge adjacent inline <style> tags.\r\n * @default true\r\n */\r\n mergeStylesheets?: boolean;\r\n\r\n /**\r\n * Additional CSS selectors to always include as critical.\r\n */\r\n additionalStylesheets?: string[];\r\n\r\n /**\r\n * CSS selectors to exclude from critical extraction.\r\n */\r\n excludeSelectors?: string[];\r\n\r\n /**\r\n * Routes to include (glob patterns).\r\n * @default ['**\\/*.html']\r\n */\r\n include?: string[];\r\n\r\n /**\r\n * Routes to exclude (glob patterns).\r\n * @default ['/api/**']\r\n */\r\n exclude?: string[];\r\n\r\n /**\r\n * Inline external fonts.\r\n * @default false\r\n */\r\n inlineFonts?: boolean;\r\n\r\n /**\r\n * Preload external fonts.\r\n * @default true\r\n */\r\n preloadFonts?: boolean;\r\n\r\n /**\r\n * Maximum size of inlined CSS (in bytes).\r\n * Larger stylesheets will be loaded normally.\r\n * @default 100000 (100KB)\r\n */\r\n maxInlinedSize?: number;\r\n\r\n /**\r\n * Log extraction stats.\r\n * @default true\r\n */\r\n verbose?: boolean;\r\n}\r\n\r\n// ============================================================================\r\n// Critters Integration\r\n// ============================================================================\r\n\r\n/**\r\n * Critters options interface (subset of full Critters options).\r\n * Full options available at: https://github.com/GoogleChromeLabs/critters\r\n */\r\ninterface CrittersOptions {\r\n preload?: PreloadStrategy;\r\n pruneSource?: boolean;\r\n reduceInlineStyles?: boolean;\r\n mergeStylesheets?: boolean;\r\n external?: boolean;\r\n inlineFonts?: boolean;\r\n preloadFonts?: boolean;\r\n additionalStylesheets?: string[];\r\n noscriptFallback?: boolean;\r\n path?: string;\r\n publicPath?: string;\r\n logLevel?: 'info' | 'warn' | 'error' | 'trace' | 'debug' | 'silent';\r\n}\r\n\r\n// ============================================================================\r\n// Vite Plugin\r\n// ============================================================================\r\n\r\n/**\r\n * Vite plugin for critical CSS extraction.\r\n *\r\n * This plugin extracts critical (above-the-fold) CSS and inlines it\r\n * in the HTML, deferring non-critical CSS for better performance.\r\n *\r\n * Requires 'critters' as a peer dependency:\r\n * ```bash\r\n * npm install critters\r\n * ```\r\n *\r\n * @param options - Plugin configuration\r\n * @returns Vite plugin\r\n */\r\nexport function criticalCSS(options: CriticalCSSOptions = {}): Plugin {\r\n const {\r\n preload = 'swap',\r\n pruneSource = false,\r\n reduceInlineStyles = true,\r\n mergeStylesheets = true,\r\n additionalStylesheets = [],\r\n inlineFonts = false,\r\n preloadFonts = true,\r\n maxInlinedSize = 100000,\r\n include = ['**/*.html'],\r\n exclude = ['/api/**'],\r\n verbose = true,\r\n } = options;\r\n\r\n let config: ResolvedConfig;\r\n let isProduction = false;\r\n let enabled = options.enabled;\r\n let critters: {\r\n process: (html: string) => Promise<string>;\r\n } | null = null;\r\n\r\n return {\r\n name: 'flight-critical-css',\r\n enforce: 'post',\r\n apply: 'build',\r\n\r\n configResolved(resolvedConfig) {\r\n config = resolvedConfig;\r\n isProduction = resolvedConfig.command === 'build';\r\n\r\n // Enable by default only in production\r\n if (enabled === undefined) {\r\n enabled = isProduction;\r\n }\r\n },\r\n\r\n async buildStart() {\r\n if (!enabled) return;\r\n\r\n try {\r\n // Dynamic import of Critters (optional peer dependency)\r\n // @ts-expect-error - critters has broken type exports in its package.json\r\n const CrittersModule = await import('critters');\r\n const Critters = CrittersModule.default || CrittersModule;\r\n\r\n const crittersOptions: CrittersOptions = {\r\n preload,\r\n pruneSource,\r\n reduceInlineStyles,\r\n mergeStylesheets,\r\n inlineFonts,\r\n preloadFonts,\r\n additionalStylesheets,\r\n external: true,\r\n noscriptFallback: true,\r\n path: config.build.outDir,\r\n publicPath: config.base || '/',\r\n logLevel: verbose ? 'info' : 'silent',\r\n };\r\n\r\n critters = new Critters(crittersOptions);\r\n\r\n if (verbose) {\r\n console.log('[flight-critical-css] Critical CSS extraction enabled');\r\n }\r\n } catch (error) {\r\n console.warn(\r\n '[flight-critical-css] Critters not installed. Install with: npm install critters'\r\n );\r\n critters = null;\r\n }\r\n },\r\n\r\n async transformIndexHtml(html, ctx) {\r\n if (!enabled || !critters) {\r\n return html;\r\n }\r\n\r\n // Check if this route should be processed\r\n const path = ctx.path || '';\r\n\r\n // Check exclusions\r\n for (const pattern of exclude) {\r\n if (matchesPattern(path, pattern)) {\r\n return html;\r\n }\r\n }\r\n\r\n // Check inclusions\r\n let shouldProcess = false;\r\n for (const pattern of include) {\r\n if (matchesPattern(path, pattern)) {\r\n shouldProcess = true;\r\n break;\r\n }\r\n }\r\n\r\n if (!shouldProcess) {\r\n return html;\r\n }\r\n\r\n try {\r\n const processedHtml = await critters.process(html);\r\n\r\n // Check if critical CSS is too large\r\n const inlineStyleMatch = processedHtml.match(/<style[^>]*>([\\s\\S]*?)<\\/style>/gi);\r\n if (inlineStyleMatch) {\r\n const totalInlineSize = inlineStyleMatch.reduce(\r\n (sum, style) => sum + style.length, 0\r\n );\r\n\r\n if (totalInlineSize > maxInlinedSize) {\r\n console.warn(\r\n `[flight-critical-css] Inline CSS (${totalInlineSize} bytes) exceeds max (${maxInlinedSize} bytes) for ${path}`\r\n );\r\n }\r\n }\r\n\r\n if (verbose) {\r\n console.log(`[flight-critical-css] Processed: ${path}`);\r\n }\r\n\r\n return processedHtml;\r\n } catch (error) {\r\n console.error(`[flight-critical-css] Error processing ${path}:`, error);\r\n return html;\r\n }\r\n },\r\n\r\n async closeBundle() {\r\n if (verbose && critters) {\r\n console.log('[flight-critical-css] Critical CSS extraction complete');\r\n }\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Helper Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Simple glob pattern matching.\r\n */\r\nfunction matchesPattern(path: string, pattern: string): boolean {\r\n // Convert glob to regex\r\n const regexPattern = pattern\r\n .replace(/\\*\\*/g, '{{DOUBLE_STAR}}')\r\n .replace(/\\*/g, '[^/]*')\r\n .replace(/\\{\\{DOUBLE_STAR\\}\\}/g, '.*')\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// CSS Optimization Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Extract inline styles from HTML.\r\n * Utility for manual critical CSS handling.\r\n */\r\nexport function extractInlineStyles(html: string): {\r\n html: string;\r\n styles: string[];\r\n} {\r\n const styles: string[] = [];\r\n const cleanedHtml = html.replace(\r\n /<style[^>]*>([\\s\\S]*?)<\\/style>/gi,\r\n (match, content) => {\r\n styles.push(content);\r\n return '';\r\n }\r\n );\r\n\r\n return { html: cleanedHtml, styles };\r\n}\r\n\r\n/**\r\n * Merge multiple CSS strings into one.\r\n */\r\nexport function mergeCSS(styles: string[]): string {\r\n return styles\r\n .map(s => s.trim())\r\n .filter(Boolean)\r\n .join('\\n');\r\n}\r\n\r\n/**\r\n * Generate a preload link for a stylesheet.\r\n */\r\nexport function generatePreloadLink(\r\n href: string,\r\n strategy: PreloadStrategy\r\n): string {\r\n switch (strategy) {\r\n case 'swap':\r\n return `<link rel=\"preload\" href=\"${href}\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\">`;\r\n case 'swap-high':\r\n return `<link rel=\"preload\" href=\"${href}\" as=\"style\" fetchpriority=\"high\" onload=\"this.onload=null;this.rel='stylesheet'\">`;\r\n case 'media':\r\n return `<link rel=\"stylesheet\" href=\"${href}\" media=\"print\" onload=\"this.media='all'\">`;\r\n case 'js':\r\n return `<script>\r\n (function(){var l=document.createElement('link');l.rel='stylesheet';l.href='${href}';document.head.appendChild(l);})();\r\n </script>`;\r\n case 'js-lazy':\r\n return `<script>\r\n requestIdleCallback(function(){var l=document.createElement('link');l.rel='stylesheet';l.href='${href}';document.head.appendChild(l);});\r\n </script>`;\r\n default:\r\n return '';\r\n }\r\n}\r\n\r\n/**\r\n * Generate noscript fallback for preloaded stylesheet.\r\n */\r\nexport function generateNoscriptFallback(href: string): string {\r\n return `<noscript><link rel=\"stylesheet\" href=\"${href}\"></noscript>`;\r\n}\r\n\r\n// ============================================================================\r\n// Exports\r\n// ============================================================================\r\n\r\nexport default criticalCSS;\r\n","/**\r\n * @flight-framework/core - Build Plugins\r\n *\r\n * Optional Vite plugins for advanced optimizations.\r\n * These plugins are opt-in and require explicit configuration.\r\n * \r\n * Flight doesn't force you to use any of these - use them if you want.\r\n */\r\n\r\n// Critical CSS Plugin (existing)\r\nexport { criticalCSS } from './critical-css.js';\r\nexport type {\r\n CriticalCSSOptions,\r\n PreloadStrategy,\r\n} from './critical-css.js';\r\n\r\n// Environment Variables Plugin (NEW)\r\nexport {\r\n flightEnvPlugin,\r\n type FlightEnvPluginOptions,\r\n} from './env-plugin.js';\r\n\r\n// Server Boundary Plugin (NEW)\r\nexport {\r\n serverBoundaryPlugin,\r\n type ServerBoundaryPluginOptions,\r\n} from './server-boundary-plugin.js';\r\n\r\n// ============================================================================\r\n// Convenience Presets\r\n// ============================================================================\r\n\r\nimport type { Plugin } from 'vite';\r\nimport { flightEnvPlugin, type FlightEnvPluginOptions } from './env-plugin.js';\r\nimport { serverBoundaryPlugin, type ServerBoundaryPluginOptions } from './server-boundary-plugin.js';\r\n\r\n/**\r\n * Recommended plugins for most apps.\r\n * Provides sensible defaults with warnings for violations.\r\n */\r\nexport function flightRecommendedPlugins(options?: {\r\n env?: FlightEnvPluginOptions;\r\n serverBoundary?: ServerBoundaryPluginOptions;\r\n}): Plugin[] {\r\n return [\r\n flightEnvPlugin({\r\n privateVarBehavior: 'warn',\r\n ...options?.env,\r\n }),\r\n serverBoundaryPlugin({\r\n violationBehavior: 'warn',\r\n ...options?.serverBoundary,\r\n }),\r\n ];\r\n}\r\n\r\n/**\r\n * Strict mode plugins - errors instead of warnings.\r\n * Recommended for production builds.\r\n */\r\nexport function flightStrictPlugins(options?: {\r\n env?: FlightEnvPluginOptions;\r\n serverBoundary?: ServerBoundaryPluginOptions;\r\n}): Plugin[] {\r\n return [\r\n flightEnvPlugin({\r\n privateVarBehavior: 'error',\r\n ...options?.env,\r\n }),\r\n serverBoundaryPlugin({\r\n violationBehavior: 'error',\r\n ...options?.serverBoundary,\r\n }),\r\n ];\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/server-only-plugin.ts","../../src/plugins/critical-css.ts","../../src/plugins/index.ts"],"names":[],"mappings":";;;;;AAwDA,IAAM,mBAAA,GAAsB,oBAAA;AASrB,SAAS,gBAAA,CAAiB,OAAA,GAAmC,EAAC,EAAW;AAC5E,EAAA,MAAM;AAAA,IACF,qBAAqB;AAAC,GAC1B,GAAI,OAAA;AAGJ,EAAA,MAAM,kBAAA,uBAAyB,GAAA,CAAI;AAAA,IAC/B,aAAA;AAAA,IACA,GAAG;AAAA,GACN,CAAA;AAED,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,KAAA,GAAQ,KAAA;AAEZ,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,oBAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA;AAAA,IAET,eAAe,cAAA,EAAgB;AAC3B,MAAA,MAAA,GAAS,cAAA;AACT,MAAA,KAAA,GAAQ,OAAO,OAAA,KAAY,OAAA;AAAA,IAC/B,CAAA;AAAA,IAEA,UAAU,EAAA,EAAI;AAEV,MAAA,IAAI,CAAC,kBAAA,CAAmB,GAAA,CAAI,EAAE,CAAA,EAAG;AAC7B,QAAA,OAAO,IAAA;AAAA,MACX;AAIA,MAAA,MAAM,QAAA,GACF,KAAK,WAAA,EAAa,MAAA,EAAQ,aAAa,QAAA,IACvC,IAAA,CAAK,aAAa,IAAA,KAAS,KAAA;AAAA,MAE3B,MAAA,CAAO,OAAO,GAAA,KAAQ,IAAA;AAE1B,MAAA,IAAI,QAAA,EAAU;AAEV,QAAA,OAAO,mBAAA;AAAA,MACX;AAGA,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,iBAAA,KAAsB,KAAA,GAAQ,MAAA,GAAS,OAAA,CAAA;AAChE,MAAA,MAAM,OAAA,GACF,2BAA2B,EAAE,CAAA,0LAAA,CAAA;AAIjC,MAAA,IAAI,aAAa,OAAA,EAAS;AACtB,QAAA,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MACtB,CAAA,MAAO;AACH,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,cAAA,EAAS,OAAO;AAAA,CAAI,CAAA;AAEjC,QAAA,OAAO,mBAAA;AAAA,MACX;AAEA,MAAA,OAAO,IAAA;AAAA,IACX,CAAA;AAAA,IAEA,KAAK,EAAA,EAAI;AAEL,MAAA,IAAI,OAAO,mBAAA,EAAqB;AAC5B,QAAA,OAAO;AAAA,UACH,IAAA,EAAM,4CAAA;AAAA,UACN,GAAA,EAAK;AAAA,SACT;AAAA,MACJ;AACA,MAAA,OAAO,IAAA;AAAA,IACX;AAAA,GACJ;AACJ;;;ACsCO,SAAS,WAAA,CAAY,OAAA,GAA8B,EAAC,EAAW;AAClE,EAAA,MAAM;AAAA,IACF,OAAA,GAAU,MAAA;AAAA,IACV,WAAA,GAAc,KAAA;AAAA,IACd,kBAAA,GAAqB,IAAA;AAAA,IACrB,gBAAA,GAAmB,IAAA;AAAA,IACnB,wBAAwB,EAAC;AAAA,IACzB,WAAA,GAAc,KAAA;AAAA,IACd,YAAA,GAAe,IAAA;AAAA,IACf,cAAA,GAAiB,GAAA;AAAA,IACjB,OAAA,GAAU,CAAC,WAAW,CAAA;AAAA,IACtB,OAAA,GAAU,CAAC,SAAS,CAAA;AAAA,IACpB,OAAA,GAAU;AAAA,GACd,GAAI,OAAA;AAEJ,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,YAAA,GAAe,KAAA;AACnB,EAAA,IAAI,UAAU,OAAA,CAAQ,OAAA;AACtB,EAAA,IAAI,QAAA,GAEO,IAAA;AAEX,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,qBAAA;AAAA,IACN,OAAA,EAAS,MAAA;AAAA,IACT,KAAA,EAAO,OAAA;AAAA,IAEP,eAAe,cAAA,EAAgB;AAC3B,MAAA,MAAA,GAAS,cAAA;AACT,MAAA,YAAA,GAAe,eAAe,OAAA,KAAY,OAAA;AAG1C,MAAA,IAAI,YAAY,MAAA,EAAW;AACvB,QAAA,OAAA,GAAU,YAAA;AAAA,MACd;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,UAAA,GAAa;AACf,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,IAAI;AAGA,QAAA,MAAM,cAAA,GAAiB,MAAM,OAAO,UAAU,CAAA;AAC9C,QAAA,MAAM,QAAA,GAAW,eAAe,OAAA,IAAW,cAAA;AAE3C,QAAA,MAAM,eAAA,GAAmC;AAAA,UACrC,OAAA;AAAA,UACA,WAAA;AAAA,UACA,kBAAA;AAAA,UACA,gBAAA;AAAA,UACA,WAAA;AAAA,UACA,YAAA;AAAA,UACA,qBAAA;AAAA,UACA,QAAA,EAAU,IAAA;AAAA,UACV,gBAAA,EAAkB,IAAA;AAAA,UAClB,IAAA,EAAM,OAAO,KAAA,CAAM,MAAA;AAAA,UACnB,UAAA,EAAY,OAAO,IAAA,IAAQ,GAAA;AAAA,UAC3B,QAAA,EAAU,UAAU,MAAA,GAAS;AAAA,SACjC;AAEA,QAAA,QAAA,GAAW,IAAI,SAAS,eAAe,CAAA;AAEvC,QAAA,IAAI,OAAA,EAAS;AACT,UAAA,OAAA,CAAQ,IAAI,uDAAuD,CAAA;AAAA,QACvE;AAAA,MACJ,SAAS,KAAA,EAAO;AACZ,QAAA,OAAA,CAAQ,IAAA;AAAA,UACJ;AAAA,SACJ;AACA,QAAA,QAAA,GAAW,IAAA;AAAA,MACf;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,kBAAA,CAAmB,IAAA,EAAM,GAAA,EAAK;AAChC,MAAA,IAAI,CAAC,OAAA,IAAW,CAAC,QAAA,EAAU;AACvB,QAAA,OAAO,IAAA;AAAA,MACX;AAGA,MAAA,MAAM,IAAA,GAAO,IAAI,IAAA,IAAQ,EAAA;AAGzB,MAAA,KAAA,MAAW,WAAW,OAAA,EAAS;AAC3B,QAAA,IAAI,cAAA,CAAe,IAAA,EAAM,OAAO,CAAA,EAAG;AAC/B,UAAA,OAAO,IAAA;AAAA,QACX;AAAA,MACJ;AAGA,MAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,MAAA,KAAA,MAAW,WAAW,OAAA,EAAS;AAC3B,QAAA,IAAI,cAAA,CAAe,IAAA,EAAM,OAAO,CAAA,EAAG;AAC/B,UAAA,aAAA,GAAgB,IAAA;AAChB,UAAA;AAAA,QACJ;AAAA,MACJ;AAEA,MAAA,IAAI,CAAC,aAAA,EAAe;AAChB,QAAA,OAAO,IAAA;AAAA,MACX;AAEA,MAAA,IAAI;AACA,QAAA,MAAM,aAAA,GAAgB,MAAM,QAAA,CAAS,OAAA,CAAQ,IAAI,CAAA;AAGjD,QAAA,MAAM,gBAAA,GAAmB,aAAA,CAAc,KAAA,CAAM,mCAAmC,CAAA;AAChF,QAAA,IAAI,gBAAA,EAAkB;AAClB,UAAA,MAAM,kBAAkB,gBAAA,CAAiB,MAAA;AAAA,YACrC,CAAC,GAAA,EAAK,KAAA,KAAU,GAAA,GAAM,KAAA,CAAM,MAAA;AAAA,YAAQ;AAAA,WACxC;AAEA,UAAA,IAAI,kBAAkB,cAAA,EAAgB;AAClC,YAAA,OAAA,CAAQ,IAAA;AAAA,cACJ,CAAA,kCAAA,EAAqC,eAAe,CAAA,qBAAA,EAAwB,cAAc,eAAe,IAAI,CAAA;AAAA,aACjH;AAAA,UACJ;AAAA,QACJ;AAEA,QAAA,IAAI,OAAA,EAAS;AACT,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,iCAAA,EAAoC,IAAI,CAAA,CAAE,CAAA;AAAA,QAC1D;AAEA,QAAA,OAAO,aAAA;AAAA,MACX,SAAS,KAAA,EAAO;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,uCAAA,EAA0C,IAAI,CAAA,CAAA,CAAA,EAAK,KAAK,CAAA;AACtE,QAAA,OAAO,IAAA;AAAA,MACX;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,WAAA,GAAc;AAChB,MAAA,IAAI,WAAW,QAAA,EAAU;AACrB,QAAA,OAAA,CAAQ,IAAI,wDAAwD,CAAA;AAAA,MACxE;AAAA,IACJ;AAAA,GACJ;AACJ;AASA,SAAS,cAAA,CAAe,MAAc,OAAA,EAA0B;AAE5D,EAAA,MAAM,eAAe,OAAA,CAChB,OAAA,CAAQ,OAAA,EAAS,iBAAiB,EAClC,OAAA,CAAQ,KAAA,EAAO,OAAO,CAAA,CACtB,QAAQ,sBAAA,EAAwB,IAAI,CAAA,CACpC,OAAA,CAAQ,OAAO,GAAG,CAAA;AAEvB,EAAA,MAAM,KAAA,GAAQ,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA,CAAG,CAAA;AAC5C,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAC1B;;;ACtRO,SAAS,wBAAA,CAAyB,OAAA,GAAgC,EAAC,EAAa;AACnF,EAAA,OAAO;AAAA,IACH,eAAA,CAAgB,QAAQ,GAAG,CAAA;AAAA,IAC3B,gBAAA,CAAiB,QAAQ,UAAU;AAAA,GACvC;AACJ;AAKO,SAAS,mBAAA,CAAoB,OAAA,GAAgC,EAAC,EAAa;AAC9E,EAAA,OAAA,CAAQ,KAAK,mFAAmF,CAAA;AAChG,EAAA,OAAO,yBAAyB,OAAO,CAAA;AAC3C","file":"index.js","sourcesContent":["/**\r\n * @flight-framework/core - Server Only Plugin\r\n * \r\n * Vite plugin to properly handle the `server-only` npm package.\r\n * \r\n * The `server-only` package is designed for Next.js and throws an error\r\n * when imported. In Next.js, the bundler has special handling to:\r\n * - Allow the import in server context (no error)\r\n * - Block the import in client bundles (build error)\r\n * \r\n * This plugin provides the same behavior for Vite/Flight:\r\n * - In SSR/Server environment: Replace with empty module (no-op)\r\n * - In Client environment: Let the build fail (or warn in dev)\r\n * \r\n * @example\r\n * ```typescript\r\n * // vite.config.ts\r\n * import { serverOnlyPlugin } from '@flight-framework/core/plugins';\r\n * \r\n * export default {\r\n * plugins: [serverOnlyPlugin()],\r\n * };\r\n * ```\r\n * \r\n * @example\r\n * ```typescript\r\n * // In your server-only file:\r\n * import 'server-only';\r\n * \r\n * export async function getSecretData() {\r\n * return process.env.SECRET_KEY;\r\n * }\r\n * ```\r\n */\r\n\r\nimport type { Plugin, ResolvedConfig } from 'vite';\r\n\r\nexport interface ServerOnlyPluginOptions {\r\n /**\r\n * What to do when server-only is imported in client context.\r\n * - 'error': Throw build error (production)\r\n * - 'warn': Log warning but continue (development)\r\n * @default 'error' in build, 'warn' in dev\r\n */\r\n violationBehavior?: 'error' | 'warn';\r\n\r\n /**\r\n * Additional packages to treat as server-only.\r\n * These will be replaced with empty modules in server context\r\n * and blocked in client context.\r\n * @default []\r\n */\r\n additionalPackages?: string[];\r\n}\r\n\r\n// Virtual module ID for the empty replacement\r\nconst VIRTUAL_SERVER_ONLY = '\\0server-only-noop';\r\n\r\n/**\r\n * Vite plugin to handle `server-only` package for Flight/Vite applications.\r\n * \r\n * This replicates Next.js behavior:\r\n * - SSR/Server: Import succeeds (replaced with empty module)\r\n * - Client: Build fails with clear error message\r\n */\r\nexport function serverOnlyPlugin(options: ServerOnlyPluginOptions = {}): Plugin {\r\n const {\r\n additionalPackages = [],\r\n } = options;\r\n\r\n // Packages to intercept\r\n const serverOnlyPackages = new Set([\r\n 'server-only',\r\n ...additionalPackages,\r\n ]);\r\n\r\n let config: ResolvedConfig;\r\n let isDev = false;\r\n\r\n return {\r\n name: 'flight:server-only',\r\n enforce: 'pre', // Run before other plugins\r\n\r\n configResolved(resolvedConfig) {\r\n config = resolvedConfig;\r\n isDev = config.command === 'serve';\r\n },\r\n\r\n resolveId(id) {\r\n // Check if this is a server-only package\r\n if (!serverOnlyPackages.has(id)) {\r\n return null;\r\n }\r\n\r\n // Determine if we're in server or client context\r\n // Vite 6 uses this.environment, fallback to config.build.ssr for older versions\r\n const isServer =\r\n this.environment?.config?.consumer === 'server' ||\r\n this.environment?.name === 'ssr' ||\r\n // @ts-ignore - Fallback for Vite 5 compatibility\r\n config.build?.ssr === true;\r\n\r\n if (isServer) {\r\n // Server context: Replace with empty virtual module\r\n return VIRTUAL_SERVER_ONLY;\r\n }\r\n\r\n // Client context: This is a violation!\r\n const behavior = options.violationBehavior ?? (isDev ? 'warn' : 'error');\r\n const message =\r\n `[Flight] Cannot import '${id}' in client bundle. ` +\r\n `This module is marked as server-only and should not be used in client code. ` +\r\n `Check your import chain to ensure server-only code is not imported from client components.`;\r\n\r\n if (behavior === 'error') {\r\n this.error(message);\r\n } else {\r\n console.warn(`\\n⚠️ ${message}\\n`);\r\n // In dev/warn mode, still return the virtual module to avoid crashes\r\n return VIRTUAL_SERVER_ONLY;\r\n }\r\n\r\n return null;\r\n },\r\n\r\n load(id) {\r\n // Serve the empty module for server-only\r\n if (id === VIRTUAL_SERVER_ONLY) {\r\n return {\r\n code: '/* server-only: no-op in server context */',\r\n map: null,\r\n };\r\n }\r\n return null;\r\n },\r\n };\r\n}\r\n","/**\r\n * @flight-framework/core - Critical CSS Plugin\r\n *\r\n * Extract and inline critical CSS for improved Core Web Vitals.\r\n * Uses Critters under the hood for CSS extraction.\r\n *\r\n * This is an OPTIONAL plugin. Install 'critters' only if you use it.\r\n *\r\n * @example\r\n * ```typescript\r\n * // vite.config.ts\r\n * import { criticalCSS } from '@flight-framework/core/plugins';\r\n *\r\n * export default defineConfig({\r\n * plugins: [\r\n * criticalCSS({\r\n * preload: 'swap',\r\n * pruneSource: false,\r\n * }),\r\n * ],\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\n/**\r\n * Preload strategy for non-critical CSS.\r\n *\r\n * - 'body': Move stylesheet links to end of body\r\n * - 'media': Use media=\"print\" and swap to \"all\" on load\r\n * - 'swap': Use link rel=\"preload\" and swap to stylesheet\r\n * - 'swap-high': Like swap, with fetchpriority=\"high\"\r\n * - 'js': Load via JavaScript\r\n * - 'js-lazy': Load via JavaScript when idle\r\n * - false: Don't preload\r\n */\r\nexport type PreloadStrategy =\r\n | 'body'\r\n | 'media'\r\n | 'swap'\r\n | 'swap-high'\r\n | 'js'\r\n | 'js-lazy'\r\n | false;\r\n\r\n/**\r\n * Critical CSS plugin options.\r\n */\r\nexport interface CriticalCSSOptions {\r\n /**\r\n * Enable critical CSS extraction.\r\n * @default true in production\r\n */\r\n enabled?: boolean;\r\n\r\n /**\r\n * Strategy for loading non-critical CSS.\r\n * @default 'swap'\r\n */\r\n preload?: PreloadStrategy;\r\n\r\n /**\r\n * Remove inlined CSS rules from the source stylesheet.\r\n * Reduces duplicate CSS but may cause issues with JS frameworks.\r\n * @default false\r\n */\r\n pruneSource?: boolean;\r\n\r\n /**\r\n * Remove unused CSS selectors from critical CSS.\r\n * @default true\r\n */\r\n reduceInlineStyles?: boolean;\r\n\r\n /**\r\n * Merge adjacent inline <style> tags.\r\n * @default true\r\n */\r\n mergeStylesheets?: boolean;\r\n\r\n /**\r\n * Additional CSS selectors to always include as critical.\r\n */\r\n additionalStylesheets?: string[];\r\n\r\n /**\r\n * CSS selectors to exclude from critical extraction.\r\n */\r\n excludeSelectors?: string[];\r\n\r\n /**\r\n * Routes to include (glob patterns).\r\n * @default ['**\\/*.html']\r\n */\r\n include?: string[];\r\n\r\n /**\r\n * Routes to exclude (glob patterns).\r\n * @default ['/api/**']\r\n */\r\n exclude?: string[];\r\n\r\n /**\r\n * Inline external fonts.\r\n * @default false\r\n */\r\n inlineFonts?: boolean;\r\n\r\n /**\r\n * Preload external fonts.\r\n * @default true\r\n */\r\n preloadFonts?: boolean;\r\n\r\n /**\r\n * Maximum size of inlined CSS (in bytes).\r\n * Larger stylesheets will be loaded normally.\r\n * @default 100000 (100KB)\r\n */\r\n maxInlinedSize?: number;\r\n\r\n /**\r\n * Log extraction stats.\r\n * @default true\r\n */\r\n verbose?: boolean;\r\n}\r\n\r\n// ============================================================================\r\n// Critters Integration\r\n// ============================================================================\r\n\r\n/**\r\n * Critters options interface (subset of full Critters options).\r\n * Full options available at: https://github.com/GoogleChromeLabs/critters\r\n */\r\ninterface CrittersOptions {\r\n preload?: PreloadStrategy;\r\n pruneSource?: boolean;\r\n reduceInlineStyles?: boolean;\r\n mergeStylesheets?: boolean;\r\n external?: boolean;\r\n inlineFonts?: boolean;\r\n preloadFonts?: boolean;\r\n additionalStylesheets?: string[];\r\n noscriptFallback?: boolean;\r\n path?: string;\r\n publicPath?: string;\r\n logLevel?: 'info' | 'warn' | 'error' | 'trace' | 'debug' | 'silent';\r\n}\r\n\r\n// ============================================================================\r\n// Vite Plugin\r\n// ============================================================================\r\n\r\n/**\r\n * Vite plugin for critical CSS extraction.\r\n *\r\n * This plugin extracts critical (above-the-fold) CSS and inlines it\r\n * in the HTML, deferring non-critical CSS for better performance.\r\n *\r\n * Requires 'critters' as a peer dependency:\r\n * ```bash\r\n * npm install critters\r\n * ```\r\n *\r\n * @param options - Plugin configuration\r\n * @returns Vite plugin\r\n */\r\nexport function criticalCSS(options: CriticalCSSOptions = {}): Plugin {\r\n const {\r\n preload = 'swap',\r\n pruneSource = false,\r\n reduceInlineStyles = true,\r\n mergeStylesheets = true,\r\n additionalStylesheets = [],\r\n inlineFonts = false,\r\n preloadFonts = true,\r\n maxInlinedSize = 100000,\r\n include = ['**/*.html'],\r\n exclude = ['/api/**'],\r\n verbose = true,\r\n } = options;\r\n\r\n let config: ResolvedConfig;\r\n let isProduction = false;\r\n let enabled = options.enabled;\r\n let critters: {\r\n process: (html: string) => Promise<string>;\r\n } | null = null;\r\n\r\n return {\r\n name: 'flight-critical-css',\r\n enforce: 'post',\r\n apply: 'build',\r\n\r\n configResolved(resolvedConfig) {\r\n config = resolvedConfig;\r\n isProduction = resolvedConfig.command === 'build';\r\n\r\n // Enable by default only in production\r\n if (enabled === undefined) {\r\n enabled = isProduction;\r\n }\r\n },\r\n\r\n async buildStart() {\r\n if (!enabled) return;\r\n\r\n try {\r\n // Dynamic import of Critters (optional peer dependency)\r\n // @ts-expect-error - critters has broken type exports in its package.json\r\n const CrittersModule = await import('critters');\r\n const Critters = CrittersModule.default || CrittersModule;\r\n\r\n const crittersOptions: CrittersOptions = {\r\n preload,\r\n pruneSource,\r\n reduceInlineStyles,\r\n mergeStylesheets,\r\n inlineFonts,\r\n preloadFonts,\r\n additionalStylesheets,\r\n external: true,\r\n noscriptFallback: true,\r\n path: config.build.outDir,\r\n publicPath: config.base || '/',\r\n logLevel: verbose ? 'info' : 'silent',\r\n };\r\n\r\n critters = new Critters(crittersOptions);\r\n\r\n if (verbose) {\r\n console.log('[flight-critical-css] Critical CSS extraction enabled');\r\n }\r\n } catch (error) {\r\n console.warn(\r\n '[flight-critical-css] Critters not installed. Install with: npm install critters'\r\n );\r\n critters = null;\r\n }\r\n },\r\n\r\n async transformIndexHtml(html, ctx) {\r\n if (!enabled || !critters) {\r\n return html;\r\n }\r\n\r\n // Check if this route should be processed\r\n const path = ctx.path || '';\r\n\r\n // Check exclusions\r\n for (const pattern of exclude) {\r\n if (matchesPattern(path, pattern)) {\r\n return html;\r\n }\r\n }\r\n\r\n // Check inclusions\r\n let shouldProcess = false;\r\n for (const pattern of include) {\r\n if (matchesPattern(path, pattern)) {\r\n shouldProcess = true;\r\n break;\r\n }\r\n }\r\n\r\n if (!shouldProcess) {\r\n return html;\r\n }\r\n\r\n try {\r\n const processedHtml = await critters.process(html);\r\n\r\n // Check if critical CSS is too large\r\n const inlineStyleMatch = processedHtml.match(/<style[^>]*>([\\s\\S]*?)<\\/style>/gi);\r\n if (inlineStyleMatch) {\r\n const totalInlineSize = inlineStyleMatch.reduce(\r\n (sum, style) => sum + style.length, 0\r\n );\r\n\r\n if (totalInlineSize > maxInlinedSize) {\r\n console.warn(\r\n `[flight-critical-css] Inline CSS (${totalInlineSize} bytes) exceeds max (${maxInlinedSize} bytes) for ${path}`\r\n );\r\n }\r\n }\r\n\r\n if (verbose) {\r\n console.log(`[flight-critical-css] Processed: ${path}`);\r\n }\r\n\r\n return processedHtml;\r\n } catch (error) {\r\n console.error(`[flight-critical-css] Error processing ${path}:`, error);\r\n return html;\r\n }\r\n },\r\n\r\n async closeBundle() {\r\n if (verbose && critters) {\r\n console.log('[flight-critical-css] Critical CSS extraction complete');\r\n }\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Helper Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Simple glob pattern matching.\r\n */\r\nfunction matchesPattern(path: string, pattern: string): boolean {\r\n // Convert glob to regex\r\n const regexPattern = pattern\r\n .replace(/\\*\\*/g, '{{DOUBLE_STAR}}')\r\n .replace(/\\*/g, '[^/]*')\r\n .replace(/\\{\\{DOUBLE_STAR\\}\\}/g, '.*')\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// CSS Optimization Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Extract inline styles from HTML.\r\n * Utility for manual critical CSS handling.\r\n */\r\nexport function extractInlineStyles(html: string): {\r\n html: string;\r\n styles: string[];\r\n} {\r\n const styles: string[] = [];\r\n const cleanedHtml = html.replace(\r\n /<style[^>]*>([\\s\\S]*?)<\\/style>/gi,\r\n (match, content) => {\r\n styles.push(content);\r\n return '';\r\n }\r\n );\r\n\r\n return { html: cleanedHtml, styles };\r\n}\r\n\r\n/**\r\n * Merge multiple CSS strings into one.\r\n */\r\nexport function mergeCSS(styles: string[]): string {\r\n return styles\r\n .map(s => s.trim())\r\n .filter(Boolean)\r\n .join('\\n');\r\n}\r\n\r\n/**\r\n * Generate a preload link for a stylesheet.\r\n */\r\nexport function generatePreloadLink(\r\n href: string,\r\n strategy: PreloadStrategy\r\n): string {\r\n switch (strategy) {\r\n case 'swap':\r\n return `<link rel=\"preload\" href=\"${href}\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\">`;\r\n case 'swap-high':\r\n return `<link rel=\"preload\" href=\"${href}\" as=\"style\" fetchpriority=\"high\" onload=\"this.onload=null;this.rel='stylesheet'\">`;\r\n case 'media':\r\n return `<link rel=\"stylesheet\" href=\"${href}\" media=\"print\" onload=\"this.media='all'\">`;\r\n case 'js':\r\n return `<script>\r\n (function(){var l=document.createElement('link');l.rel='stylesheet';l.href='${href}';document.head.appendChild(l);})();\r\n </script>`;\r\n case 'js-lazy':\r\n return `<script>\r\n requestIdleCallback(function(){var l=document.createElement('link');l.rel='stylesheet';l.href='${href}';document.head.appendChild(l);});\r\n </script>`;\r\n default:\r\n return '';\r\n }\r\n}\r\n\r\n/**\r\n * Generate noscript fallback for preloaded stylesheet.\r\n */\r\nexport function generateNoscriptFallback(href: string): string {\r\n return `<noscript><link rel=\"stylesheet\" href=\"${href}\"></noscript>`;\r\n}\r\n\r\n// ============================================================================\r\n// Exports\r\n// ============================================================================\r\n\r\nexport default criticalCSS;\r\n","/**\r\n * @flight-framework/core - Vite Plugins\r\n * \r\n * Optional Vite plugins for Flight Framework.\r\n * All plugins are opt-in - use only what you need.\r\n */\r\n\r\n// Environment Variables Plugin\r\nexport { flightEnvPlugin, type FlightEnvPluginOptions } from './env-plugin.js';\r\n\r\n// Server Only Plugin (handles `server-only` npm package)\r\nexport { serverOnlyPlugin, type ServerOnlyPluginOptions } from './server-only-plugin.js';\r\n\r\n// Server Boundary Plugin (DEPRECATED - use serverOnlyPlugin instead)\r\nexport {\r\n serverBoundaryPlugin,\r\n type ServerBoundaryPluginOptions\r\n} from './server-boundary-plugin.js';\r\n\r\n// Critical CSS (existing)\r\nexport { criticalCSS } from './critical-css.js';\r\n\r\n// ============================================================================\r\n// Convenience Presets\r\n// ============================================================================\r\n\r\nimport type { Plugin } from 'vite';\r\nimport { flightEnvPlugin, type FlightEnvPluginOptions } from './env-plugin.js';\r\nimport { serverOnlyPlugin, type ServerOnlyPluginOptions } from './server-only-plugin.js';\r\n\r\nexport interface FlightPluginsOptions {\r\n env?: FlightEnvPluginOptions;\r\n serverOnly?: ServerOnlyPluginOptions;\r\n}\r\n\r\n/**\r\n * Recommended Flight plugins for most projects.\r\n * Includes:\r\n * - flightEnvPlugin: Configures FLIGHT_PUBLIC_* env prefix\r\n * - serverOnlyPlugin: Properly handles `server-only` npm package\r\n * \r\n * @example\r\n * ```typescript\r\n * // vite.config.ts\r\n * import { flightRecommendedPlugins } from '@flight-framework/core/plugins';\r\n * \r\n * export default {\r\n * plugins: [...flightRecommendedPlugins()],\r\n * };\r\n * ```\r\n */\r\nexport function flightRecommendedPlugins(options: FlightPluginsOptions = {}): Plugin[] {\r\n return [\r\n flightEnvPlugin(options.env),\r\n serverOnlyPlugin(options.serverOnly),\r\n ];\r\n}\r\n\r\n/**\r\n * @deprecated Use flightRecommendedPlugins instead.\r\n */\r\nexport function flightStrictPlugins(options: FlightPluginsOptions = {}): Plugin[] {\r\n console.warn('[Flight] flightStrictPlugins is deprecated. Use flightRecommendedPlugins instead.');\r\n return flightRecommendedPlugins(options);\r\n}\r\n\r\n"]}
|
|
@@ -1,51 +1,40 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @flight-framework/core - Server Boundary Plugin
|
|
4
|
+
* @flight-framework/core - Server Boundary Plugin (DEPRECATED)
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* OPTIONAL - use if you want build-time protection.
|
|
6
|
+
* This plugin has been deprecated due to conflicts with serverActionsPlugin.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* The intended functionality (detecting server-only imports in client bundles)
|
|
9
|
+
* is difficult to implement correctly with Vite's plugin system because:
|
|
10
|
+
*
|
|
11
|
+
* 1. It conflicts with serverActionsPlugin which transforms 'use server' files
|
|
12
|
+
* 2. The resolveId hook runs before transforms, making detection unreliable
|
|
13
|
+
* 3. Vite 6+ has different environment APIs that need careful handling
|
|
14
|
+
*
|
|
15
|
+
* For now, use runtime guards instead:
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { assertServer } from '@flight-framework/core';
|
|
20
|
+
*
|
|
21
|
+
* export function getSecretData() {
|
|
22
|
+
* assertServer('getSecretData'); // Throws if called on client
|
|
23
|
+
* return process.env.SECRET_KEY;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @deprecated Use runtime guards (assertServer, assertClient) instead
|
|
12
28
|
*/
|
|
13
29
|
|
|
14
30
|
interface ServerBoundaryPluginOptions {
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
* @default ['.server.ts', '.server.tsx', '.server.js', '.server.jsx']
|
|
18
|
-
*/
|
|
19
|
-
serverFilePatterns?: string[];
|
|
20
|
-
/**
|
|
21
|
-
* Directory patterns that are server-only.
|
|
22
|
-
* @default ['/server/']
|
|
23
|
-
*/
|
|
24
|
-
serverDirPatterns?: string[];
|
|
25
|
-
/**
|
|
26
|
-
* How to handle violations.
|
|
27
|
-
* - 'error': Build error (recommended for production)
|
|
28
|
-
* - 'warn': Warning only (for migration)
|
|
29
|
-
* @default 'warn'
|
|
30
|
-
*/
|
|
31
|
-
violationBehavior?: 'error' | 'warn';
|
|
32
|
-
/**
|
|
33
|
-
* Custom error message template.
|
|
34
|
-
*/
|
|
35
|
-
customErrorMessage?: (module: string, importer: string) => string;
|
|
36
|
-
/**
|
|
37
|
-
* Files to exclude from checking.
|
|
38
|
-
*/
|
|
39
|
-
exclude?: string[];
|
|
40
|
-
/**
|
|
41
|
-
* Skip checking 'use server' files. These are handled by serverActionsPlugin.
|
|
42
|
-
* @default true
|
|
43
|
-
*/
|
|
44
|
-
skipServerActions?: boolean;
|
|
31
|
+
/** @deprecated This plugin is deprecated */
|
|
32
|
+
enabled?: boolean;
|
|
45
33
|
}
|
|
46
34
|
/**
|
|
47
|
-
*
|
|
35
|
+
* @deprecated This plugin has been deprecated due to conflicts with serverActionsPlugin.
|
|
36
|
+
* Use runtime guards (assertServer, assertClient) from '@flight-framework/core' instead.
|
|
48
37
|
*/
|
|
49
|
-
declare function serverBoundaryPlugin(
|
|
38
|
+
declare function serverBoundaryPlugin(_options?: ServerBoundaryPluginOptions): Plugin;
|
|
50
39
|
|
|
51
40
|
export { type ServerBoundaryPluginOptions, serverBoundaryPlugin };
|