@flight-framework/core 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{chunk-5KF3QQWZ.js → chunk-3ZSSRE6M.js} +5 -19
  3. package/dist/chunk-3ZSSRE6M.js.map +1 -0
  4. package/dist/chunk-4S5JWTGN.js +218 -0
  5. package/dist/chunk-4S5JWTGN.js.map +1 -0
  6. package/dist/chunk-62C7LX2E.js +205 -0
  7. package/dist/chunk-62C7LX2E.js.map +1 -0
  8. package/dist/chunk-63SCEXD7.js +3 -0
  9. package/dist/chunk-63SCEXD7.js.map +1 -0
  10. package/dist/{chunk-YIOQC3DC.js → chunk-6BDCTUQY.js} +3 -3
  11. package/dist/{chunk-YIOQC3DC.js.map → chunk-6BDCTUQY.js.map} +1 -1
  12. package/dist/chunk-6Z2RYHEU.js +212 -0
  13. package/dist/chunk-6Z2RYHEU.js.map +1 -0
  14. package/dist/chunk-HAX5OAB6.js +324 -0
  15. package/dist/chunk-HAX5OAB6.js.map +1 -0
  16. package/dist/chunk-K2CQZPCG.js +257 -0
  17. package/dist/chunk-K2CQZPCG.js.map +1 -0
  18. package/dist/chunk-N3TUOEV4.js +213 -0
  19. package/dist/chunk-N3TUOEV4.js.map +1 -0
  20. package/dist/chunk-NWMJYTMB.js +300 -0
  21. package/dist/chunk-NWMJYTMB.js.map +1 -0
  22. package/dist/chunk-OCVLNLTI.js +252 -0
  23. package/dist/chunk-OCVLNLTI.js.map +1 -0
  24. package/dist/chunk-PDW5WCMW.js +258 -0
  25. package/dist/chunk-PDW5WCMW.js.map +1 -0
  26. package/dist/chunk-PVUMB632.js +256 -0
  27. package/dist/chunk-PVUMB632.js.map +1 -0
  28. package/dist/{chunk-6WSPUG5L.js → chunk-RSVA2EYO.js} +2 -2
  29. package/dist/chunk-RSVA2EYO.js.map +1 -0
  30. package/dist/chunk-T4Z4HM4W.js +285 -0
  31. package/dist/chunk-T4Z4HM4W.js.map +1 -0
  32. package/dist/{chunk-OBNYNJB5.js → chunk-WOEIJWGJ.js} +6 -8
  33. package/dist/chunk-WOEIJWGJ.js.map +1 -0
  34. package/dist/{chunk-I2B4WSHC.js → chunk-XSY5AAXT.js} +3 -4
  35. package/dist/chunk-XSY5AAXT.js.map +1 -0
  36. package/dist/chunk-Y22AMGTM.js +3 -0
  37. package/dist/chunk-Y22AMGTM.js.map +1 -0
  38. package/dist/chunk-ZIE56LCA.js +341 -0
  39. package/dist/chunk-ZIE56LCA.js.map +1 -0
  40. package/dist/file-router/streaming-hints.d.ts +1 -1
  41. package/dist/file-router/streaming-hints.js +1 -1
  42. package/dist/index.d.ts +3 -1
  43. package/dist/index.js +19 -7
  44. package/dist/index.js.map +1 -1
  45. package/dist/rsc/adapters/index.d.ts +8 -0
  46. package/dist/rsc/adapters/index.js +7 -0
  47. package/dist/rsc/adapters/index.js.map +1 -0
  48. package/dist/rsc/adapters/preact.d.ts +97 -0
  49. package/dist/rsc/adapters/preact.js +3 -0
  50. package/dist/rsc/adapters/preact.js.map +1 -0
  51. package/dist/rsc/adapters/react.d.ts +82 -0
  52. package/dist/rsc/adapters/react.js +3 -0
  53. package/dist/rsc/adapters/react.js.map +1 -0
  54. package/dist/rsc/adapters/solid.d.ts +84 -0
  55. package/dist/rsc/adapters/solid.js +3 -0
  56. package/dist/rsc/adapters/solid.js.map +1 -0
  57. package/dist/rsc/adapters/vue.d.ts +80 -0
  58. package/dist/rsc/adapters/vue.js +3 -0
  59. package/dist/rsc/adapters/vue.js.map +1 -0
  60. package/dist/rsc/boundaries.d.ts +182 -0
  61. package/dist/rsc/boundaries.js +3 -0
  62. package/dist/rsc/boundaries.js.map +1 -0
  63. package/dist/rsc/context.d.ts +201 -0
  64. package/dist/rsc/context.js +3 -0
  65. package/dist/rsc/context.js.map +1 -0
  66. package/dist/rsc/index.d.ts +20 -124
  67. package/dist/rsc/index.js +13 -1
  68. package/dist/rsc/legacy.d.ts +131 -0
  69. package/dist/rsc/legacy.js +3 -0
  70. package/dist/rsc/legacy.js.map +1 -0
  71. package/dist/rsc/payload.d.ts +262 -0
  72. package/dist/rsc/payload.js +3 -0
  73. package/dist/rsc/payload.js.map +1 -0
  74. package/dist/rsc/plugins/esbuild.d.ts +124 -0
  75. package/dist/rsc/plugins/esbuild.js +4 -0
  76. package/dist/rsc/plugins/esbuild.js.map +1 -0
  77. package/dist/rsc/plugins/index.d.ts +4 -0
  78. package/dist/rsc/plugins/index.js +6 -0
  79. package/dist/rsc/plugins/index.js.map +1 -0
  80. package/dist/rsc/plugins/rollup.d.ts +103 -0
  81. package/dist/rsc/plugins/rollup.js +4 -0
  82. package/dist/rsc/plugins/rollup.js.map +1 -0
  83. package/dist/rsc/renderer.d.ts +160 -0
  84. package/dist/rsc/renderer.js +5 -0
  85. package/dist/rsc/renderer.js.map +1 -0
  86. package/dist/rsc/stream.d.ts +129 -0
  87. package/dist/rsc/stream.js +3 -0
  88. package/dist/rsc/stream.js.map +1 -0
  89. package/dist/rsc/vite-plugin.d.ts +78 -0
  90. package/dist/rsc/vite-plugin.js +4 -0
  91. package/dist/rsc/vite-plugin.js.map +1 -0
  92. package/dist/streaming/index.js +1 -1
  93. package/dist/streaming/observability.js +2 -2
  94. package/dist/streaming/priority.js +1 -1
  95. package/package.json +180 -124
  96. package/dist/chunk-5KF3QQWZ.js.map +0 -1
  97. package/dist/chunk-6WSPUG5L.js.map +0 -1
  98. package/dist/chunk-I2B4WSHC.js.map +0 -1
  99. package/dist/chunk-OBNYNJB5.js.map +0 -1
@@ -0,0 +1,285 @@
1
+ import { analyzeModule, hasUseClientDirective, hasUseServerDirective, detectInlineServerActions } from './chunk-PDW5WCMW.js';
2
+
3
+ // src/rsc/plugins/esbuild.ts
4
+ function flightRSCEsbuild(options = {}) {
5
+ const {
6
+ include = /\.(tsx?|jsx?)$/,
7
+ exclude = /node_modules/,
8
+ actionsEndpoint = "/_flight/action",
9
+ manifestDir = ".flight",
10
+ ssr = false,
11
+ dev = false
12
+ } = options;
13
+ const state = {
14
+ clientModules: /* @__PURE__ */ new Map(),
15
+ serverActions: /* @__PURE__ */ new Map()};
16
+ return {
17
+ name: "flight-rsc",
18
+ setup(build) {
19
+ const outdir = build.initialOptions.outdir || "dist";
20
+ build.onStart(() => {
21
+ state.clientModules.clear();
22
+ state.serverActions.clear();
23
+ });
24
+ build.onLoad({ filter: include }, async (args) => {
25
+ if (exclude.test(args.path)) {
26
+ return null;
27
+ }
28
+ const fs = await import('fs/promises');
29
+ const code = await fs.readFile(args.path, "utf-8");
30
+ const analysis = analyzeModule(code, args.path);
31
+ const moduleId = createModuleId(args.path);
32
+ if (analysis.fileDirective === "client") {
33
+ state.clientModules.set(args.path, {
34
+ id: moduleId,
35
+ file: args.path,
36
+ exports: analysis.clientComponents
37
+ });
38
+ }
39
+ if (analysis.fileDirective === "server" || analysis.serverActions.length > 0) {
40
+ state.serverActions.set(args.path, {
41
+ id: moduleId,
42
+ file: args.path,
43
+ exports: analysis.serverActions
44
+ });
45
+ }
46
+ if (ssr) {
47
+ if (hasUseClientDirective(code)) {
48
+ return {
49
+ contents: transformClientForSSR(code, moduleId),
50
+ loader: getLoader(args.path)
51
+ };
52
+ }
53
+ } else {
54
+ if (hasUseServerDirective(code)) {
55
+ return {
56
+ contents: transformServerForClient(code, moduleId, actionsEndpoint),
57
+ loader: getLoader(args.path)
58
+ };
59
+ }
60
+ const inlineActions = detectInlineServerActions(code);
61
+ if (inlineActions.length > 0) {
62
+ return {
63
+ contents: transformInlineActions(code, moduleId, inlineActions, actionsEndpoint),
64
+ loader: getLoader(args.path)
65
+ };
66
+ }
67
+ }
68
+ return null;
69
+ });
70
+ build.onEnd(async () => {
71
+ const fs = await import('fs/promises');
72
+ const path = await import('path');
73
+ const manifestPath = path.join(outdir, manifestDir);
74
+ await fs.mkdir(manifestPath, { recursive: true });
75
+ if (state.clientModules.size > 0) {
76
+ const clientManifest = Object.fromEntries(state.clientModules);
77
+ await fs.writeFile(
78
+ path.join(manifestPath, "client-manifest.json"),
79
+ JSON.stringify(clientManifest, null, 2)
80
+ );
81
+ }
82
+ if (state.serverActions.size > 0) {
83
+ const serverManifest = Object.fromEntries(state.serverActions);
84
+ await fs.writeFile(
85
+ path.join(manifestPath, "server-manifest.json"),
86
+ JSON.stringify(serverManifest, null, 2)
87
+ );
88
+ }
89
+ if (dev) {
90
+ console.log(`[Flight RSC] Client modules: ${state.clientModules.size}`);
91
+ console.log(`[Flight RSC] Server actions: ${state.serverActions.size}`);
92
+ }
93
+ });
94
+ }
95
+ };
96
+ }
97
+ function transformClientForSSR(code, moduleId) {
98
+ const exports$1 = extractExportNames(code);
99
+ let transformed = `
100
+ // Flight RSC: Client Component Reference (esbuild)
101
+ // Original module: ${moduleId}
102
+
103
+ const __flight_module_id = ${JSON.stringify(moduleId)};
104
+
105
+ `;
106
+ for (const exportName of exports$1) {
107
+ if (exportName === "default") {
108
+ transformed += `
109
+ const __flight_default = Object.assign(
110
+ function() {
111
+ throw new Error('Client Component cannot be called on the server. Module: ' + __flight_module_id);
112
+ },
113
+ {
114
+ $$typeof: Symbol.for('flight.client.reference'),
115
+ $$id: __flight_module_id + '#default',
116
+ $$async: false,
117
+ __flight_client: true,
118
+ __flight_module: __flight_module_id,
119
+ __flight_export: 'default',
120
+ }
121
+ );
122
+ export default __flight_default;
123
+ `;
124
+ } else {
125
+ transformed += `
126
+ export const ${exportName} = Object.assign(
127
+ function() {
128
+ throw new Error('Client Component cannot be called on the server. Module: ' + __flight_module_id);
129
+ },
130
+ {
131
+ $$typeof: Symbol.for('flight.client.reference'),
132
+ $$id: __flight_module_id + '#${exportName}',
133
+ $$async: false,
134
+ __flight_client: true,
135
+ __flight_module: __flight_module_id,
136
+ __flight_export: '${exportName}',
137
+ }
138
+ );
139
+ `;
140
+ }
141
+ }
142
+ return transformed;
143
+ }
144
+ function transformServerForClient(code, moduleId, endpoint) {
145
+ const exports$1 = extractExportNames(code);
146
+ let transformed = `
147
+ // Flight RSC: Server Actions RPC Proxies (esbuild)
148
+ // Original module: ${moduleId}
149
+
150
+ const __flight_endpoint = ${JSON.stringify(endpoint)};
151
+ const __flight_module_id = ${JSON.stringify(moduleId)};
152
+
153
+ async function __flight_rpc(actionId, args) {
154
+ const response = await fetch(__flight_endpoint, {
155
+ method: 'POST',
156
+ headers: {
157
+ 'Content-Type': 'application/json',
158
+ 'X-Flight-Action': actionId,
159
+ },
160
+ body: JSON.stringify({ actionId, args }),
161
+ });
162
+
163
+ if (!response.ok) {
164
+ const error = await response.json().catch(() => ({ message: 'Server action failed' }));
165
+ throw new Error(error.message || 'Server action failed');
166
+ }
167
+
168
+ return response.json();
169
+ }
170
+
171
+ `;
172
+ for (const exportName of exports$1) {
173
+ const actionId = `${moduleId}#${exportName}`;
174
+ if (exportName === "default") {
175
+ transformed += `
176
+ export default async function(...args) {
177
+ return __flight_rpc(${JSON.stringify(actionId)}, args);
178
+ }
179
+ `;
180
+ } else {
181
+ transformed += `
182
+ export async function ${exportName}(...args) {
183
+ return __flight_rpc(${JSON.stringify(actionId)}, args);
184
+ }
185
+ `;
186
+ }
187
+ }
188
+ return transformed;
189
+ }
190
+ function transformInlineActions(code, moduleId, actions, endpoint) {
191
+ let transformed = code;
192
+ const rpcHelper = `
193
+ // Flight RSC: Inline Server Action Helpers
194
+ const __flight_endpoint_inline = ${JSON.stringify(endpoint)};
195
+ async function __flight_rpc_inline(actionId, args) {
196
+ const response = await fetch(__flight_endpoint_inline, {
197
+ method: 'POST',
198
+ headers: { 'Content-Type': 'application/json', 'X-Flight-Action': actionId },
199
+ body: JSON.stringify({ actionId, args }),
200
+ });
201
+ if (!response.ok) throw new Error('Server action failed');
202
+ return response.json();
203
+ }
204
+ `;
205
+ const lastImportMatch = code.match(/^import\s.+$/gm);
206
+ if (lastImportMatch) {
207
+ const lastImport = lastImportMatch[lastImportMatch.length - 1] || "";
208
+ const insertPos = code.indexOf(lastImport) + lastImport.length;
209
+ transformed = code.slice(0, insertPos) + "\n" + rpcHelper + code.slice(insertPos);
210
+ } else {
211
+ transformed = rpcHelper + code;
212
+ }
213
+ for (const actionName of actions) {
214
+ const actionId = `${moduleId}#${actionName}`;
215
+ const patterns = [
216
+ // async function name() { 'use server'; ... }
217
+ new RegExp(
218
+ `async\\s+function\\s+${actionName}\\s*\\([^)]*\\)\\s*\\{[\\s\\S]*?['"]use server['"][\\s\\S]*?\\}`,
219
+ "g"
220
+ ),
221
+ // const name = async () => { 'use server'; ... }
222
+ new RegExp(
223
+ `const\\s+${actionName}\\s*=\\s*async\\s*\\([^)]*\\)\\s*=>\\s*\\{[\\s\\S]*?['"]use server['"][\\s\\S]*?\\}`,
224
+ "g"
225
+ )
226
+ ];
227
+ for (const pattern of patterns) {
228
+ transformed = transformed.replace(
229
+ pattern,
230
+ `async function ${actionName}(...args) { return __flight_rpc_inline(${JSON.stringify(actionId)}, args); }`
231
+ );
232
+ }
233
+ }
234
+ return transformed;
235
+ }
236
+ function createModuleId(filePath) {
237
+ let id = filePath.replace(/\\/g, "/");
238
+ const prefixes = ["/src/", "src/"];
239
+ for (const prefix of prefixes) {
240
+ const idx = id.indexOf(prefix);
241
+ if (idx !== -1) {
242
+ id = id.slice(idx + prefix.length);
243
+ break;
244
+ }
245
+ }
246
+ if (!id.startsWith("/")) {
247
+ id = "/" + id;
248
+ }
249
+ return id;
250
+ }
251
+ function getLoader(filePath) {
252
+ if (filePath.endsWith(".tsx")) return "tsx";
253
+ if (filePath.endsWith(".ts")) return "ts";
254
+ if (filePath.endsWith(".jsx")) return "jsx";
255
+ return "js";
256
+ }
257
+ function extractExportNames(code) {
258
+ const exports$1 = [];
259
+ if (/export\s+default\s+/.test(code)) {
260
+ exports$1.push("default");
261
+ }
262
+ const namedPattern = /export\s+(?:async\s+)?(?:function|const|let|var|class)\s+(\w+)/g;
263
+ let match;
264
+ while ((match = namedPattern.exec(code)) !== null) {
265
+ if (match[1] && match[1] !== "default") {
266
+ exports$1.push(match[1]);
267
+ }
268
+ }
269
+ const bracketPattern = /export\s*\{\s*([^}]+)\s*\}/g;
270
+ while ((match = bracketPattern.exec(code)) !== null) {
271
+ if (match[1]) {
272
+ const names = match[1].split(",").map((n) => {
273
+ const parts = n.trim().split(/\s+as\s+/);
274
+ return parts[parts.length - 1]?.trim() || "";
275
+ });
276
+ exports$1.push(...names.filter((n) => n && n !== "default"));
277
+ }
278
+ }
279
+ return [...new Set(exports$1)];
280
+ }
281
+ var esbuild_default = flightRSCEsbuild;
282
+
283
+ export { esbuild_default, flightRSCEsbuild };
284
+ //# sourceMappingURL=chunk-T4Z4HM4W.js.map
285
+ //# sourceMappingURL=chunk-T4Z4HM4W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rsc/plugins/esbuild.ts"],"names":["exports"],"mappings":"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","file":"chunk-T4Z4HM4W.js","sourcesContent":["/**\r\n * @flight-framework/core - esbuild Plugin for RSC\r\n * \r\n * esbuild plugin for Flight Server Components.\r\n * Transforms 'use client' and 'use server' directives at build time.\r\n * \r\n * Philosophy: Zero lock-in - esbuild is optional, user decides bundler.\r\n * \r\n * @module @flight-framework/core/rsc/plugins/esbuild\r\n */\r\n\r\nimport {\r\n analyzeModule,\r\n hasUseClientDirective,\r\n hasUseServerDirective,\r\n detectInlineServerActions,\r\n} from '../boundaries.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * esbuild Plugin interface (minimal)\r\n * We define our own to avoid requiring esbuild as dependency\r\n */\r\nexport interface EsbuildPlugin {\r\n name: string;\r\n setup: (build: EsbuildBuild) => void | Promise<void>;\r\n}\r\n\r\nexport interface EsbuildBuild {\r\n initialOptions: EsbuildBuildOptions;\r\n onStart: (callback: () => void | Promise<void>) => void;\r\n onEnd: (callback: (result: EsbuildResult) => void | Promise<void>) => void;\r\n onResolve: (\r\n options: { filter: RegExp; namespace?: string },\r\n callback: (args: EsbuildResolveArgs) => EsbuildResolveResult | null | undefined | Promise<EsbuildResolveResult | null | undefined>\r\n ) => void;\r\n onLoad: (\r\n options: { filter: RegExp; namespace?: string },\r\n callback: (args: EsbuildLoadArgs) => EsbuildLoadResult | null | undefined | Promise<EsbuildLoadResult | null | undefined>\r\n ) => void;\r\n}\r\n\r\nexport interface EsbuildBuildOptions {\r\n outdir?: string;\r\n write?: boolean;\r\n metafile?: boolean;\r\n}\r\n\r\nexport interface EsbuildResult {\r\n errors: unknown[];\r\n warnings: unknown[];\r\n metafile?: unknown;\r\n}\r\n\r\nexport interface EsbuildResolveArgs {\r\n path: string;\r\n importer: string;\r\n namespace: string;\r\n resolveDir: string;\r\n kind: string;\r\n}\r\n\r\nexport interface EsbuildResolveResult {\r\n path?: string;\r\n external?: boolean;\r\n namespace?: string;\r\n suffix?: string;\r\n pluginData?: unknown;\r\n errors?: unknown[];\r\n warnings?: unknown[];\r\n watchFiles?: string[];\r\n watchDirs?: string[];\r\n}\r\n\r\nexport interface EsbuildLoadArgs {\r\n path: string;\r\n namespace: string;\r\n suffix: string;\r\n pluginData: unknown;\r\n}\r\n\r\nexport interface EsbuildLoadResult {\r\n contents?: string;\r\n loader?: 'js' | 'jsx' | 'ts' | 'tsx' | 'json' | 'text' | 'css';\r\n resolveDir?: string;\r\n errors?: unknown[];\r\n warnings?: unknown[];\r\n watchFiles?: string[];\r\n watchDirs?: string[];\r\n}\r\n\r\n/**\r\n * Plugin configuration\r\n */\r\nexport interface FlightEsbuildPluginOptions {\r\n /** Include patterns (regex) */\r\n include?: RegExp;\r\n\r\n /** Exclude patterns (regex) */\r\n exclude?: RegExp;\r\n\r\n /** Server actions endpoint */\r\n actionsEndpoint?: string;\r\n\r\n /** Output directory for manifests */\r\n manifestDir?: string;\r\n\r\n /** Is this for SSR build? */\r\n ssr?: boolean;\r\n\r\n /** Dev mode (include extra debug info) */\r\n dev?: boolean;\r\n}\r\n\r\n/**\r\n * Manifest entry\r\n */\r\nexport interface ManifestEntry {\r\n id: string;\r\n file: string;\r\n exports: string[];\r\n}\r\n\r\n// ============================================================================\r\n// Plugin State\r\n// ============================================================================\r\n\r\ninterface PluginState {\r\n clientModules: Map<string, ManifestEntry>;\r\n serverActions: Map<string, ManifestEntry>;\r\n isSSR: boolean;\r\n}\r\n\r\n// ============================================================================\r\n// Plugin Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Flight RSC esbuild Plugin\r\n * \r\n * @example\r\n * ```typescript\r\n * // build.js\r\n * import * as esbuild from 'esbuild';\r\n * import { flightRSCEsbuild } from '@flight-framework/core/rsc/plugins/esbuild';\r\n * \r\n * await esbuild.build({\r\n * entryPoints: ['src/index.tsx'],\r\n * bundle: true,\r\n * outdir: 'dist',\r\n * plugins: [\r\n * flightRSCEsbuild({\r\n * actionsEndpoint: '/_flight/action',\r\n * ssr: true,\r\n * }),\r\n * ],\r\n * });\r\n * ```\r\n */\r\nexport function flightRSCEsbuild(options: FlightEsbuildPluginOptions = {}): EsbuildPlugin {\r\n const {\r\n include = /\\.(tsx?|jsx?)$/,\r\n exclude = /node_modules/,\r\n actionsEndpoint = '/_flight/action',\r\n manifestDir = '.flight',\r\n ssr = false,\r\n dev = false,\r\n } = options;\r\n\r\n const state: PluginState = {\r\n clientModules: new Map(),\r\n serverActions: new Map(),\r\n isSSR: ssr,\r\n };\r\n\r\n return {\r\n name: 'flight-rsc',\r\n\r\n setup(build) {\r\n const outdir = build.initialOptions.outdir || 'dist';\r\n\r\n // ============================================================\r\n // onStart: Reset state\r\n // ============================================================\r\n build.onStart(() => {\r\n state.clientModules.clear();\r\n state.serverActions.clear();\r\n });\r\n\r\n // ============================================================\r\n // onLoad: Transform client/server modules\r\n // ============================================================\r\n build.onLoad({ filter: include }, async (args) => {\r\n // Skip excluded\r\n if (exclude.test(args.path)) {\r\n return null;\r\n }\r\n\r\n // Read file\r\n const fs = await import('fs/promises');\r\n const code = await fs.readFile(args.path, 'utf-8');\r\n\r\n // Analyze module\r\n const analysis = analyzeModule(code, args.path);\r\n const moduleId = createModuleId(args.path);\r\n\r\n // Track client modules\r\n if (analysis.fileDirective === 'client') {\r\n state.clientModules.set(args.path, {\r\n id: moduleId,\r\n file: args.path,\r\n exports: analysis.clientComponents,\r\n });\r\n }\r\n\r\n // Track server actions\r\n if (analysis.fileDirective === 'server' || analysis.serverActions.length > 0) {\r\n state.serverActions.set(args.path, {\r\n id: moduleId,\r\n file: args.path,\r\n exports: analysis.serverActions,\r\n });\r\n }\r\n\r\n // Transform based on build type\r\n if (ssr) {\r\n // SSR build: Transform 'use client' to references\r\n if (hasUseClientDirective(code)) {\r\n return {\r\n contents: transformClientForSSR(code, moduleId),\r\n loader: getLoader(args.path),\r\n };\r\n }\r\n } else {\r\n // Client build: Transform 'use server' to RPC calls\r\n if (hasUseServerDirective(code)) {\r\n return {\r\n contents: transformServerForClient(code, moduleId, actionsEndpoint),\r\n loader: getLoader(args.path),\r\n };\r\n }\r\n\r\n // Transform inline server actions\r\n const inlineActions = detectInlineServerActions(code);\r\n if (inlineActions.length > 0) {\r\n return {\r\n contents: transformInlineActions(code, moduleId, inlineActions, actionsEndpoint),\r\n loader: getLoader(args.path),\r\n };\r\n }\r\n }\r\n\r\n return null;\r\n });\r\n\r\n // ============================================================\r\n // onEnd: Write manifests\r\n // ============================================================\r\n build.onEnd(async () => {\r\n const fs = await import('fs/promises');\r\n const path = await import('path');\r\n\r\n const manifestPath = path.join(outdir, manifestDir);\r\n\r\n // Ensure directory exists\r\n await fs.mkdir(manifestPath, { recursive: true });\r\n\r\n // Write client manifest\r\n if (state.clientModules.size > 0) {\r\n const clientManifest = Object.fromEntries(state.clientModules);\r\n await fs.writeFile(\r\n path.join(manifestPath, 'client-manifest.json'),\r\n JSON.stringify(clientManifest, null, 2)\r\n );\r\n }\r\n\r\n // Write server manifest\r\n if (state.serverActions.size > 0) {\r\n const serverManifest = Object.fromEntries(state.serverActions);\r\n await fs.writeFile(\r\n path.join(manifestPath, 'server-manifest.json'),\r\n JSON.stringify(serverManifest, null, 2)\r\n );\r\n }\r\n\r\n if (dev) {\r\n console.log(`[Flight RSC] Client modules: ${state.clientModules.size}`);\r\n console.log(`[Flight RSC] Server actions: ${state.serverActions.size}`);\r\n }\r\n });\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Transform Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Transform 'use client' module for SSR build\r\n */\r\nfunction transformClientForSSR(code: string, moduleId: string): string {\r\n const exports = extractExportNames(code);\r\n\r\n let transformed = `\r\n// Flight RSC: Client Component Reference (esbuild)\r\n// Original module: ${moduleId}\r\n\r\nconst __flight_module_id = ${JSON.stringify(moduleId)};\r\n\r\n`;\r\n\r\n for (const exportName of exports) {\r\n if (exportName === 'default') {\r\n transformed += `\r\nconst __flight_default = Object.assign(\r\n function() {\r\n throw new Error('Client Component cannot be called on the server. Module: ' + __flight_module_id);\r\n },\r\n {\r\n $$typeof: Symbol.for('flight.client.reference'),\r\n $$id: __flight_module_id + '#default',\r\n $$async: false,\r\n __flight_client: true,\r\n __flight_module: __flight_module_id,\r\n __flight_export: 'default',\r\n }\r\n);\r\nexport default __flight_default;\r\n`;\r\n } else {\r\n transformed += `\r\nexport const ${exportName} = Object.assign(\r\n function() {\r\n throw new Error('Client Component cannot be called on the server. Module: ' + __flight_module_id);\r\n },\r\n {\r\n $$typeof: Symbol.for('flight.client.reference'),\r\n $$id: __flight_module_id + '#${exportName}',\r\n $$async: false,\r\n __flight_client: true,\r\n __flight_module: __flight_module_id,\r\n __flight_export: '${exportName}',\r\n }\r\n);\r\n`;\r\n }\r\n }\r\n\r\n return transformed;\r\n}\r\n\r\n/**\r\n * Transform 'use server' module for client build\r\n */\r\nfunction transformServerForClient(code: string, moduleId: string, endpoint: string): string {\r\n const exports = extractExportNames(code);\r\n\r\n let transformed = `\r\n// Flight RSC: Server Actions RPC Proxies (esbuild)\r\n// Original module: ${moduleId}\r\n\r\nconst __flight_endpoint = ${JSON.stringify(endpoint)};\r\nconst __flight_module_id = ${JSON.stringify(moduleId)};\r\n\r\nasync function __flight_rpc(actionId, args) {\r\n const response = await fetch(__flight_endpoint, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'X-Flight-Action': actionId,\r\n },\r\n body: JSON.stringify({ actionId, args }),\r\n });\r\n \r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Server action failed' }));\r\n throw new Error(error.message || 'Server action failed');\r\n }\r\n \r\n return response.json();\r\n}\r\n\r\n`;\r\n\r\n for (const exportName of exports) {\r\n const actionId = `${moduleId}#${exportName}`;\r\n if (exportName === 'default') {\r\n transformed += `\r\nexport default async function(...args) {\r\n return __flight_rpc(${JSON.stringify(actionId)}, args);\r\n}\r\n`;\r\n } else {\r\n transformed += `\r\nexport async function ${exportName}(...args) {\r\n return __flight_rpc(${JSON.stringify(actionId)}, args);\r\n}\r\n`;\r\n }\r\n }\r\n\r\n return transformed;\r\n}\r\n\r\n/**\r\n * Transform inline server actions\r\n */\r\nfunction transformInlineActions(\r\n code: string,\r\n moduleId: string,\r\n actions: string[],\r\n endpoint: string\r\n): string {\r\n let transformed = code;\r\n\r\n // Add RPC helper at the top (after any imports)\r\n const rpcHelper = `\r\n// Flight RSC: Inline Server Action Helpers\r\nconst __flight_endpoint_inline = ${JSON.stringify(endpoint)};\r\nasync function __flight_rpc_inline(actionId, args) {\r\n const response = await fetch(__flight_endpoint_inline, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json', 'X-Flight-Action': actionId },\r\n body: JSON.stringify({ actionId, args }),\r\n });\r\n if (!response.ok) throw new Error('Server action failed');\r\n return response.json();\r\n}\r\n`;\r\n\r\n // Find last import statement\r\n const lastImportMatch = code.match(/^import\\s.+$/gm);\r\n if (lastImportMatch) {\r\n const lastImport = lastImportMatch[lastImportMatch.length - 1] || '';\r\n const insertPos = code.indexOf(lastImport) + lastImport.length;\r\n transformed = code.slice(0, insertPos) + '\\n' + rpcHelper + code.slice(insertPos);\r\n } else {\r\n transformed = rpcHelper + code;\r\n }\r\n\r\n // Transform each action function\r\n for (const actionName of actions) {\r\n const actionId = `${moduleId}#${actionName}`;\r\n\r\n // Replace async function with RPC call\r\n // This is simplified - production would use proper AST transformation\r\n const patterns = [\r\n // async function name() { 'use server'; ... }\r\n new RegExp(\r\n `async\\\\s+function\\\\s+${actionName}\\\\s*\\\\([^)]*\\\\)\\\\s*\\\\{[\\\\s\\\\S]*?['\"]use server['\"][\\\\s\\\\S]*?\\\\}`,\r\n 'g'\r\n ),\r\n // const name = async () => { 'use server'; ... }\r\n new RegExp(\r\n `const\\\\s+${actionName}\\\\s*=\\\\s*async\\\\s*\\\\([^)]*\\\\)\\\\s*=>\\\\s*\\\\{[\\\\s\\\\S]*?['\"]use server['\"][\\\\s\\\\S]*?\\\\}`,\r\n 'g'\r\n ),\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n transformed = transformed.replace(\r\n pattern,\r\n `async function ${actionName}(...args) { return __flight_rpc_inline(${JSON.stringify(actionId)}, args); }`\r\n );\r\n }\r\n }\r\n\r\n return transformed;\r\n}\r\n\r\n// ============================================================================\r\n// Helper Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create module ID from file path\r\n */\r\nfunction createModuleId(filePath: string): string {\r\n // Normalize and create relative path\r\n let id = filePath.replace(/\\\\/g, '/');\r\n\r\n // Remove common prefixes\r\n const prefixes = ['/src/', 'src/'];\r\n for (const prefix of prefixes) {\r\n const idx = id.indexOf(prefix);\r\n if (idx !== -1) {\r\n id = id.slice(idx + prefix.length);\r\n break;\r\n }\r\n }\r\n\r\n if (!id.startsWith('/')) {\r\n id = '/' + id;\r\n }\r\n\r\n return id;\r\n}\r\n\r\n/**\r\n * Get esbuild loader from file extension\r\n */\r\nfunction getLoader(filePath: string): 'tsx' | 'ts' | 'jsx' | 'js' {\r\n if (filePath.endsWith('.tsx')) return 'tsx';\r\n if (filePath.endsWith('.ts')) return 'ts';\r\n if (filePath.endsWith('.jsx')) return 'jsx';\r\n return 'js';\r\n}\r\n\r\n/**\r\n * Extract export names from source code\r\n */\r\nfunction extractExportNames(code: string): string[] {\r\n const exports: string[] = [];\r\n\r\n // export default\r\n if (/export\\s+default\\s+/.test(code)) {\r\n exports.push('default');\r\n }\r\n\r\n // export function/const/let/class Name\r\n const namedPattern = /export\\s+(?:async\\s+)?(?:function|const|let|var|class)\\s+(\\w+)/g;\r\n let match;\r\n while ((match = namedPattern.exec(code)) !== null) {\r\n if (match[1] && match[1] !== 'default') {\r\n exports.push(match[1]);\r\n }\r\n }\r\n\r\n // export { a, b, c }\r\n const bracketPattern = /export\\s*\\{\\s*([^}]+)\\s*\\}/g;\r\n while ((match = bracketPattern.exec(code)) !== null) {\r\n if (match[1]) {\r\n const names = match[1].split(',').map(n => {\r\n const parts = n.trim().split(/\\s+as\\s+/);\r\n return parts[parts.length - 1]?.trim() || '';\r\n });\r\n exports.push(...names.filter(n => n && n !== 'default'));\r\n }\r\n }\r\n\r\n return [...new Set(exports)];\r\n}\r\n\r\nexport default flightRSCEsbuild;\r\n"]}
@@ -10,7 +10,6 @@ async function streamWithPriority(config) {
10
10
  globalTimeout
11
11
  } = config;
12
12
  let shellResolved = false;
13
- let allResolved = false;
14
13
  const resolutionsPromise = [];
15
14
  let resolveShell;
16
15
  let resolveAll;
@@ -64,7 +63,6 @@ async function streamWithPriority(config) {
64
63
  const hydrationScript = buildHydrationScripts(options);
65
64
  controller.enqueue(encoder.encode(hydrationScript));
66
65
  }
67
- allResolved = true;
68
66
  options.onAllReady?.();
69
67
  resolveAll();
70
68
  controller.close();
@@ -123,7 +121,7 @@ async function processPriorityFirst(controller, encoder, boundaries, resolvedIds
123
121
  }
124
122
  }
125
123
  }
126
- async function processFirstReady(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, globalTimeout, options) {
124
+ async function processFirstReady(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, globalTimeout, _options) {
127
125
  const pending = boundaries.map((b) => resolveBoundary(b, globalTimeout));
128
126
  const results = await Promise.allSettled(pending);
129
127
  for (let i = 0; i < results.length; i++) {
@@ -144,7 +142,7 @@ async function processFirstReady(controller, encoder, boundaries, resolvedIds, r
144
142
  }
145
143
  }
146
144
  }
147
- async function processDependencyAware(controller, encoder, boundaries, dependencyMap, resolvedIds, canProcess, resolutions, onResolved, globalTimeout, options) {
145
+ async function processDependencyAware(controller, encoder, boundaries, dependencyMap, resolvedIds, canProcess, resolutions, onResolved, globalTimeout, _options) {
148
146
  const remaining = [...boundaries];
149
147
  while (remaining.length > 0) {
150
148
  const readyIndex = remaining.findIndex((b) => canProcess(b.id));
@@ -173,7 +171,7 @@ async function processDependencyAware(controller, encoder, boundaries, dependenc
173
171
  }
174
172
  }
175
173
  }
176
- async function processDeadlineStrict(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, options) {
174
+ async function processDeadlineStrict(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, _options) {
177
175
  const promises = boundaries.map(async (boundary) => {
178
176
  const deadline = boundary.deadline || 5e3;
179
177
  const resolution = await resolveBoundary(boundary, deadline);
@@ -196,7 +194,7 @@ async function processDeadlineStrict(controller, encoder, boundaries, resolvedId
196
194
  }
197
195
  }
198
196
  }
199
- async function processRoundRobin(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, globalTimeout, options) {
197
+ async function processRoundRobin(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, globalTimeout, _options) {
200
198
  const groups = /* @__PURE__ */ new Map();
201
199
  for (const b of boundaries) {
202
200
  const group = groups.get(b.priority) || [];
@@ -349,5 +347,5 @@ function validateDependencies(boundaries) {
349
347
  }
350
348
 
351
349
  export { streamWithPriority, validateDependencies };
352
- //# sourceMappingURL=chunk-OBNYNJB5.js.map
353
- //# sourceMappingURL=chunk-OBNYNJB5.js.map
350
+ //# sourceMappingURL=chunk-WOEIJWGJ.js.map
351
+ //# sourceMappingURL=chunk-WOEIJWGJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/streaming/priority.ts"],"names":["resolution"],"mappings":"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","file":"chunk-WOEIJWGJ.js","sourcesContent":["/**\r\n * @flight-framework/core - Priority-Based Streaming SSR\r\n * \r\n * Out-of-order streaming with priority control, deadlines, and dependencies.\r\n * Gives developers full control over streaming order and timing.\r\n * \r\n * Best Practices 2026:\r\n * - Priority-based content delivery for optimal UX\r\n * - Deadline-aware streaming to prevent slow boundaries from blocking\r\n * - Dependency graphs for complex data relationships\r\n * - Strategy-based streaming modes for different use cases\r\n * \r\n * @example\r\n * ```typescript\r\n * import { streamWithPriority } from '@flight-framework/core/streaming';\r\n * \r\n * const result = await streamWithPriority({\r\n * shell: '<html>...',\r\n * shellEnd: '</html>',\r\n * boundaries: [\r\n * { id: 'hero', priority: 1, content: fetchHero() },\r\n * { id: 'nav', priority: 2, content: fetchNav() },\r\n * { id: 'comments', priority: 10, content: fetchComments() },\r\n * ],\r\n * strategy: 'priority-first',\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { StreamingRenderOptions, StreamingRenderResult } from './index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Boundary with priority and advanced options\r\n */\r\nexport interface PriorityBoundary {\r\n /** Unique identifier for this boundary */\r\n id: string;\r\n /** Fallback HTML while loading */\r\n fallback: string;\r\n /** Content promise or factory function */\r\n content: Promise<string> | (() => Promise<string>);\r\n /** Priority level (lower number = higher priority, rendered first) */\r\n priority: number;\r\n /** Maximum time to wait before skipping (ms). Boundary shows fallback if exceeded. */\r\n deadline?: number;\r\n /** IDs of boundaries that must resolve before this one starts */\r\n dependsOn?: string[];\r\n /** Optional metadata for observability */\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Streaming strategy - how to order content delivery\r\n */\r\nexport type StreamingStrategy =\r\n | 'priority-first' // Strictly respect priority order\r\n | 'first-ready' // Send as soon as ready (fastest TTFB)\r\n | 'dependency-aware' // Respect dependencies, then priority\r\n | 'round-robin' // Alternate between priority levels\r\n | 'deadline-strict'; // Skip any boundary that misses deadline\r\n\r\n/**\r\n * Result of a priority boundary resolution\r\n */\r\nexport interface BoundaryResolution {\r\n id: string;\r\n content: string | null;\r\n duration: number;\r\n status: 'resolved' | 'timeout' | 'error' | 'skipped';\r\n error?: Error;\r\n}\r\n\r\n/**\r\n * Priority streaming configuration\r\n */\r\nexport interface PriorityStreamConfig {\r\n /** Initial HTML shell */\r\n shell: string;\r\n /** Closing HTML */\r\n shellEnd: string;\r\n /** Boundaries with priorities */\r\n boundaries: PriorityBoundary[];\r\n /** Streaming strategy */\r\n strategy: StreamingStrategy;\r\n /** Base streaming options */\r\n options?: StreamingRenderOptions;\r\n /** Callback when a boundary resolves */\r\n onBoundaryResolved?: (resolution: BoundaryResolution) => void;\r\n /** Global timeout for all boundaries */\r\n globalTimeout?: number;\r\n}\r\n\r\n/**\r\n * Priority streaming result with additional metrics\r\n */\r\nexport interface PriorityStreamResult extends StreamingRenderResult {\r\n /** Resolution details for each boundary */\r\n resolutions: Promise<BoundaryResolution[]>;\r\n}\r\n\r\n// ============================================================================\r\n// Priority Queue Implementation\r\n// ============================================================================\r\n\r\n// Note: QueuedBoundary interface removed - not currently used\r\n// Can be added back when implementing more advanced queue features\r\n\r\n/**\r\n * Create a priority-ordered streaming SSR response\r\n */\r\nexport async function streamWithPriority(\r\n config: PriorityStreamConfig\r\n): Promise<PriorityStreamResult> {\r\n const {\r\n shell,\r\n shellEnd,\r\n boundaries,\r\n strategy,\r\n options = {},\r\n onBoundaryResolved,\r\n globalTimeout,\r\n } = config;\r\n\r\n let shellResolved = false;\r\n // State tracking variables available for future use if needed\r\n const resolutionsPromise: BoundaryResolution[] = [];\r\n\r\n // Promises for lifecycle events\r\n let resolveShell: () => void;\r\n let resolveAll: () => void;\r\n const shellReady = new Promise<void>((r) => { resolveShell = r; });\r\n const allReady = new Promise<void>((r) => { resolveAll = r; });\r\n\r\n const encoder = new TextEncoder();\r\n\r\n // Sort boundaries by priority and prepare queue\r\n const sortedBoundaries = [...boundaries].sort((a, b) => a.priority - b.priority);\r\n\r\n // Build dependency graph\r\n const dependencyMap = new Map<string, Set<string>>();\r\n const resolvedIds = new Set<string>();\r\n\r\n for (const b of boundaries) {\r\n if (b.dependsOn && b.dependsOn.length > 0) {\r\n dependencyMap.set(b.id, new Set(b.dependsOn));\r\n }\r\n }\r\n\r\n // Check if a boundary's dependencies are satisfied\r\n const canProcess = (id: string): boolean => {\r\n const deps = dependencyMap.get(id);\r\n if (!deps) return true;\r\n for (const dep of deps) {\r\n if (!resolvedIds.has(dep)) return false;\r\n }\r\n return true;\r\n };\r\n\r\n // Create the readable stream\r\n const stream = new ReadableStream<Uint8Array>({\r\n async start(controller) {\r\n try {\r\n // 1. Send shell with fallback placeholders\r\n const shellHtml = buildShellWithPriorityPlaceholders(shell, sortedBoundaries, shellEnd, options);\r\n controller.enqueue(encoder.encode(shellHtml));\r\n\r\n shellResolved = true;\r\n options.onShellReady?.();\r\n resolveShell!();\r\n\r\n // 2. Process boundaries based on strategy\r\n if (boundaries.length > 0) {\r\n await processBoundariesByStrategy(\r\n controller,\r\n encoder,\r\n sortedBoundaries,\r\n strategy,\r\n dependencyMap,\r\n resolvedIds,\r\n canProcess,\r\n resolutionsPromise,\r\n onBoundaryResolved,\r\n globalTimeout,\r\n options\r\n );\r\n }\r\n\r\n // 3. Send hydration scripts\r\n if (options.bootstrapScripts?.length || options.bootstrapModules?.length) {\r\n const hydrationScript = buildHydrationScripts(options);\r\n controller.enqueue(encoder.encode(hydrationScript));\r\n }\r\n\r\n options.onAllReady?.();\r\n resolveAll!();\r\n controller.close();\r\n\r\n } catch (error) {\r\n if (!shellResolved) {\r\n options.onShellError?.(error as Error);\r\n }\r\n options.onError?.(error as Error);\r\n controller.error(error);\r\n }\r\n },\r\n\r\n cancel() {\r\n // Stream cancelled by consumer\r\n },\r\n });\r\n\r\n return {\r\n stream,\r\n abort: () => { /* abort requested */ },\r\n shellReady,\r\n allReady,\r\n resolutions: Promise.resolve(resolutionsPromise),\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Strategy Processors\r\n// ============================================================================\r\n\r\nasync function processBoundariesByStrategy(\r\n controller: ReadableStreamDefaultController<Uint8Array>,\r\n encoder: TextEncoder,\r\n boundaries: PriorityBoundary[],\r\n strategy: StreamingStrategy,\r\n dependencyMap: Map<string, Set<string>>,\r\n resolvedIds: Set<string>,\r\n canProcess: (id: string) => boolean,\r\n resolutions: BoundaryResolution[],\r\n onResolved?: (r: BoundaryResolution) => void,\r\n globalTimeout?: number,\r\n options?: StreamingRenderOptions\r\n): Promise<void> {\r\n switch (strategy) {\r\n case 'priority-first':\r\n await processPriorityFirst(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, globalTimeout, options);\r\n break;\r\n case 'first-ready':\r\n await processFirstReady(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, globalTimeout, options);\r\n break;\r\n case 'dependency-aware':\r\n await processDependencyAware(controller, encoder, boundaries, dependencyMap, resolvedIds, canProcess, resolutions, onResolved, globalTimeout, options);\r\n break;\r\n case 'deadline-strict':\r\n await processDeadlineStrict(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, options);\r\n break;\r\n case 'round-robin':\r\n await processRoundRobin(controller, encoder, boundaries, resolvedIds, resolutions, onResolved, globalTimeout, options);\r\n break;\r\n }\r\n}\r\n\r\n/**\r\n * Priority-first: Process boundaries strictly by priority order\r\n */\r\nasync function processPriorityFirst(\r\n controller: ReadableStreamDefaultController<Uint8Array>,\r\n encoder: TextEncoder,\r\n boundaries: PriorityBoundary[],\r\n resolvedIds: Set<string>,\r\n resolutions: BoundaryResolution[],\r\n onResolved?: (r: BoundaryResolution) => void,\r\n globalTimeout?: number,\r\n options?: StreamingRenderOptions\r\n): Promise<void> {\r\n for (const boundary of boundaries) {\r\n const resolution = await resolveBoundary(boundary, globalTimeout);\r\n resolutions.push(resolution);\r\n resolvedIds.add(boundary.id);\r\n onResolved?.(resolution);\r\n\r\n if (resolution.status === 'resolved' && resolution.content) {\r\n const script = buildContentReplacement(boundary.id, resolution.content);\r\n controller.enqueue(encoder.encode(script));\r\n } else if (resolution.status === 'error' || resolution.status === 'timeout') {\r\n const errorScript = buildErrorReplacement(boundary.id, resolution.error?.message || 'Timeout');\r\n controller.enqueue(encoder.encode(errorScript));\r\n options?.onError?.(resolution.error || new Error('Boundary timeout'));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * First-ready: Process boundaries as they resolve (race all)\r\n */\r\nasync function processFirstReady(\r\n controller: ReadableStreamDefaultController<Uint8Array>,\r\n encoder: TextEncoder,\r\n boundaries: PriorityBoundary[],\r\n resolvedIds: Set<string>,\r\n resolutions: BoundaryResolution[],\r\n onResolved?: (r: BoundaryResolution) => void,\r\n globalTimeout?: number,\r\n _options?: StreamingRenderOptions\r\n): Promise<void> {\r\n const pending = boundaries.map(b => resolveBoundary(b, globalTimeout));\r\n const results = await Promise.allSettled(pending);\r\n\r\n for (let i = 0; i < results.length; i++) {\r\n const result = results[i];\r\n const boundary = boundaries[i];\r\n\r\n if (result.status === 'fulfilled') {\r\n const resolution = result.value;\r\n resolutions.push(resolution);\r\n resolvedIds.add(boundary.id);\r\n onResolved?.(resolution);\r\n\r\n if (resolution.status === 'resolved' && resolution.content) {\r\n const script = buildContentReplacement(boundary.id, resolution.content);\r\n controller.enqueue(encoder.encode(script));\r\n } else {\r\n const errorScript = buildErrorReplacement(boundary.id, resolution.error?.message || 'Failed');\r\n controller.enqueue(encoder.encode(errorScript));\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Dependency-aware: Respect dependencies before processing\r\n */\r\nasync function processDependencyAware(\r\n controller: ReadableStreamDefaultController<Uint8Array>,\r\n encoder: TextEncoder,\r\n boundaries: PriorityBoundary[],\r\n dependencyMap: Map<string, Set<string>>,\r\n resolvedIds: Set<string>,\r\n canProcess: (id: string) => boolean,\r\n resolutions: BoundaryResolution[],\r\n onResolved?: (r: BoundaryResolution) => void,\r\n globalTimeout?: number,\r\n _options?: StreamingRenderOptions\r\n): Promise<void> {\r\n const remaining = [...boundaries];\r\n\r\n while (remaining.length > 0) {\r\n // Find next boundary that can be processed\r\n const readyIndex = remaining.findIndex(b => canProcess(b.id));\r\n\r\n if (readyIndex === -1) {\r\n // Circular dependency detected - process remaining by priority\r\n console.warn('[Flight] Circular dependency detected, falling back to priority order');\r\n for (const b of remaining) {\r\n const resolution = await resolveBoundary(b, globalTimeout);\r\n resolutions.push(resolution);\r\n resolvedIds.add(b.id);\r\n onResolved?.(resolution);\r\n\r\n if (resolution.content) {\r\n controller.enqueue(encoder.encode(buildContentReplacement(b.id, resolution.content)));\r\n }\r\n }\r\n break;\r\n }\r\n\r\n const boundary = remaining.splice(readyIndex, 1)[0];\r\n const resolution = await resolveBoundary(boundary, globalTimeout);\r\n resolutions.push(resolution);\r\n resolvedIds.add(boundary.id);\r\n onResolved?.(resolution);\r\n\r\n if (resolution.status === 'resolved' && resolution.content) {\r\n controller.enqueue(encoder.encode(buildContentReplacement(boundary.id, resolution.content)));\r\n } else {\r\n controller.enqueue(encoder.encode(buildErrorReplacement(boundary.id, resolution.error?.message || 'Failed')));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Deadline-strict: Skip boundaries that exceed their deadline\r\n */\r\nasync function processDeadlineStrict(\r\n controller: ReadableStreamDefaultController<Uint8Array>,\r\n encoder: TextEncoder,\r\n boundaries: PriorityBoundary[],\r\n resolvedIds: Set<string>,\r\n resolutions: BoundaryResolution[],\r\n onResolved?: (r: BoundaryResolution) => void,\r\n _options?: StreamingRenderOptions\r\n): Promise<void> {\r\n const promises = boundaries.map(async (boundary) => {\r\n const deadline = boundary.deadline || 5000; // Default 5s\r\n const resolution = await resolveBoundary(boundary, deadline);\r\n return { boundary, resolution };\r\n });\r\n\r\n const results = await Promise.allSettled(promises);\r\n\r\n for (const result of results) {\r\n if (result.status === 'fulfilled') {\r\n const { boundary, resolution } = result.value;\r\n resolutions.push(resolution);\r\n resolvedIds.add(boundary.id);\r\n onResolved?.(resolution);\r\n\r\n if (resolution.status === 'timeout') {\r\n // Skip - leave fallback in place\r\n console.log(`[Flight] Boundary ${boundary.id} skipped due to deadline`);\r\n } else if (resolution.status === 'resolved' && resolution.content) {\r\n controller.enqueue(encoder.encode(buildContentReplacement(boundary.id, resolution.content)));\r\n } else {\r\n controller.enqueue(encoder.encode(buildErrorReplacement(boundary.id, resolution.error?.message || 'Error')));\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Round-robin: Alternate between priority groups\r\n */\r\nasync function processRoundRobin(\r\n controller: ReadableStreamDefaultController<Uint8Array>,\r\n encoder: TextEncoder,\r\n boundaries: PriorityBoundary[],\r\n resolvedIds: Set<string>,\r\n resolutions: BoundaryResolution[],\r\n onResolved?: (r: BoundaryResolution) => void,\r\n globalTimeout?: number,\r\n _options?: StreamingRenderOptions\r\n): Promise<void> {\r\n // Group by priority\r\n const groups = new Map<number, PriorityBoundary[]>();\r\n for (const b of boundaries) {\r\n const group = groups.get(b.priority) || [];\r\n group.push(b);\r\n groups.set(b.priority, group);\r\n }\r\n\r\n const sortedPriorities = [...groups.keys()].sort((a, b) => a - b);\r\n const queues = sortedPriorities.map(p => [...groups.get(p)!]);\r\n\r\n // Process round-robin\r\n while (queues.some(q => q.length > 0)) {\r\n for (const queue of queues) {\r\n if (queue.length === 0) continue;\r\n\r\n const boundary = queue.shift()!;\r\n const resolution = await resolveBoundary(boundary, globalTimeout);\r\n resolutions.push(resolution);\r\n resolvedIds.add(boundary.id);\r\n onResolved?.(resolution);\r\n\r\n if (resolution.status === 'resolved' && resolution.content) {\r\n controller.enqueue(encoder.encode(buildContentReplacement(boundary.id, resolution.content)));\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Boundary Resolution\r\n// ============================================================================\r\n\r\nasync function resolveBoundary(\r\n boundary: PriorityBoundary,\r\n timeout?: number\r\n): Promise<BoundaryResolution> {\r\n const startTime = Date.now();\r\n const contentPromise = typeof boundary.content === 'function'\r\n ? boundary.content()\r\n : boundary.content;\r\n\r\n try {\r\n let content: string;\r\n\r\n if (timeout) {\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n setTimeout(() => reject(new Error('Deadline exceeded')), timeout);\r\n });\r\n content = await Promise.race([contentPromise, timeoutPromise]);\r\n } else {\r\n content = await contentPromise;\r\n }\r\n\r\n return {\r\n id: boundary.id,\r\n content,\r\n duration: Date.now() - startTime,\r\n status: 'resolved',\r\n };\r\n } catch (error) {\r\n const isTimeout = (error as Error).message === 'Deadline exceeded';\r\n return {\r\n id: boundary.id,\r\n content: null,\r\n duration: Date.now() - startTime,\r\n status: isTimeout ? 'timeout' : 'error',\r\n error: error as Error,\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// HTML Builders\r\n// ============================================================================\r\n\r\nfunction buildShellWithPriorityPlaceholders(\r\n shell: string,\r\n boundaries: PriorityBoundary[],\r\n shellEnd: string,\r\n options: StreamingRenderOptions\r\n): string {\r\n let html = shell;\r\n\r\n if (options.bootstrapScriptContent) {\r\n html += `<script>${options.bootstrapScriptContent}</script>`;\r\n }\r\n\r\n // Add placeholders with priority data attributes\r\n for (const boundary of boundaries) {\r\n html += `\r\n<!--$?--><template id=\"B:${boundary.id}\" data-priority=\"${boundary.priority}\"></template>\r\n${boundary.fallback}\r\n<!--/$-->`;\r\n }\r\n\r\n html += shellEnd;\r\n return html;\r\n}\r\n\r\nfunction buildContentReplacement(id: string, content: string): string {\r\n const escaped = content\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/</g, '\\\\u003c')\r\n .replace(/>/g, '\\\\u003e')\r\n .replace(/'/g, \"\\\\'\")\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r');\r\n\r\n return `\r\n<script>\r\n(function(){\r\n var b=document.getElementById(\"B:${id}\");\r\n if(b){\r\n var p=b.previousSibling;\r\n while(p&&p.nodeType===8&&p.data===\"$?\")p=p.previousSibling;\r\n var n=b.nextSibling;\r\n var f=document.createDocumentFragment();\r\n var t=document.createElement(\"template\");\r\n t.innerHTML=\"${escaped}\";\r\n while(t.content.firstChild)f.appendChild(t.content.firstChild);\r\n if(n&&n.nodeType===8&&n.data===\"/$\"){\r\n var s=n.nextSibling;\r\n while(s&&s!==b){var x=s.nextSibling;s.parentNode.removeChild(s);s=x;}\r\n }\r\n b.parentNode.replaceChild(f,b);\r\n }\r\n})();\r\n</script>`;\r\n}\r\n\r\nfunction buildErrorReplacement(id: string, message: string): string {\r\n const escaped = message.replace(/'/g, \"\\\\'\").replace(/\"/g, '\\\\\"');\r\n return `\r\n<script>\r\n(function(){\r\n var b=document.getElementById(\"B:${id}\");\r\n if(b){\r\n var t=document.createElement(\"div\");\r\n t.className=\"flight-streaming-error\";\r\n t.setAttribute(\"data-boundary-id\",\"${id}\");\r\n t.textContent=\"Error: ${escaped}\";\r\n b.parentNode.replaceChild(t,b);\r\n }\r\n})();\r\n</script>`;\r\n}\r\n\r\nfunction buildHydrationScripts(options: StreamingRenderOptions): string {\r\n let scripts = '';\r\n\r\n if (options.bootstrapScripts?.length) {\r\n for (const src of options.bootstrapScripts) {\r\n const nonceAttr = options.nonce ? ` nonce=\"${options.nonce}\"` : '';\r\n scripts += `<script src=\"${src}\"${nonceAttr} async></script>`;\r\n }\r\n }\r\n\r\n if (options.bootstrapModules?.length) {\r\n for (const src of options.bootstrapModules) {\r\n const nonceAttr = options.nonce ? ` nonce=\"${options.nonce}\"` : '';\r\n scripts += `<script type=\"module\" src=\"${src}\"${nonceAttr}></script>`;\r\n }\r\n }\r\n\r\n return scripts;\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Validate Dependencies (check for cycles)\r\n// ============================================================================\r\n\r\n/**\r\n * Validate that boundaries don't have circular dependencies\r\n */\r\nexport function validateDependencies(boundaries: PriorityBoundary[]): { valid: boolean; cycles?: string[][] } {\r\n const graph = new Map<string, string[]>();\r\n const allIds = new Set(boundaries.map(b => b.id));\r\n\r\n for (const b of boundaries) {\r\n graph.set(b.id, b.dependsOn?.filter(d => allIds.has(d)) || []);\r\n }\r\n\r\n const cycles: string[][] = [];\r\n const visited = new Set<string>();\r\n const recursionStack = new Set<string>();\r\n\r\n function dfs(id: string, path: string[]): boolean {\r\n if (recursionStack.has(id)) {\r\n const cycleStart = path.indexOf(id);\r\n cycles.push(path.slice(cycleStart));\r\n return true;\r\n }\r\n if (visited.has(id)) return false;\r\n\r\n visited.add(id);\r\n recursionStack.add(id);\r\n\r\n for (const dep of graph.get(id) || []) {\r\n if (dfs(dep, [...path, id])) return true;\r\n }\r\n\r\n recursionStack.delete(id);\r\n return false;\r\n }\r\n\r\n for (const id of graph.keys()) {\r\n dfs(id, []);\r\n }\r\n\r\n return { valid: cycles.length === 0, cycles: cycles.length > 0 ? cycles : undefined };\r\n}\r\n"]}
@@ -63,7 +63,6 @@ function shouldStream(config, request) {
63
63
  return { stream: false, reason: "streaming disabled in config" };
64
64
  }
65
65
  if (request) {
66
- request.headers.get("user-agent") || "";
67
66
  if (request.headers.get("x-no-stream") === "true") {
68
67
  return { stream: false, reason: "x-no-stream header" };
69
68
  }
@@ -87,7 +86,7 @@ function createStreamingController(timeout) {
87
86
  cleanup: () => clearTimeout(timeoutId)
88
87
  };
89
88
  }
90
- function generateCacheKey(routePath, params, config) {
89
+ function generateCacheKey(routePath, params, _config) {
91
90
  const paramString = Object.entries(params).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join("&");
92
91
  return `streaming:${routePath}:${paramString}`;
93
92
  }
@@ -122,5 +121,5 @@ function isValidStreamingHints(obj) {
122
121
  }
123
122
 
124
123
  export { DEFAULT_STREAMING_HINTS, createStreamingController, generateCacheKey, getStreamingCacheHeaders, hasStreamingConfig, isValidStreamingHints, loadRouteWithStreaming, resolveStreamingConfig, shouldStream };
125
- //# sourceMappingURL=chunk-I2B4WSHC.js.map
126
- //# sourceMappingURL=chunk-I2B4WSHC.js.map
124
+ //# sourceMappingURL=chunk-XSY5AAXT.js.map
125
+ //# sourceMappingURL=chunk-XSY5AAXT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/file-router/streaming-hints.ts"],"names":[],"mappings":"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","file":"chunk-XSY5AAXT.js","sourcesContent":["/**\r\n * @flight-framework/core - File Router Streaming Hints\r\n * \r\n * Per-route streaming configuration through exports.\r\n * The user defines streaming behavior at the route level.\r\n * \r\n * @example\r\n * ```typescript\r\n * // src/routes/products/[id].page.tsx\r\n * \r\n * // Static export for streaming hints\r\n * export const streaming = {\r\n * enabled: true,\r\n * timeout: 5000,\r\n * priority: 'high',\r\n * };\r\n * \r\n * // Or dynamic function based on params\r\n * export function getStreamingConfig(params: { id: string }) {\r\n * return {\r\n * enabled: params.id !== 'preview',\r\n * timeout: 3000,\r\n * };\r\n * }\r\n * \r\n * export default function ProductPage({ params }) {\r\n * return <Product id={params.id} />;\r\n * }\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Static streaming configuration export\r\n */\r\nexport interface StreamingHints {\r\n /** Whether streaming is enabled for this route (default: true) */\r\n enabled?: boolean;\r\n /** Timeout before aborting streaming (ms) */\r\n timeout?: number;\r\n /** Priority hint for streaming scheduler */\r\n priority?: 'high' | 'normal' | 'low';\r\n /** Expected suspense boundary IDs */\r\n boundaries?: string[];\r\n /** Force static rendering (no streaming) */\r\n forceStatic?: boolean;\r\n /** Cache the static version */\r\n cache?: {\r\n /** Time to cache in seconds */\r\n ttl?: number;\r\n /** Stale-while-revalidate time in seconds */\r\n swr?: number;\r\n /** Cache tags for invalidation */\r\n tags?: string[];\r\n };\r\n}\r\n\r\n/**\r\n * Dynamic streaming configuration function\r\n */\r\nexport type GetStreamingConfig<TParams = Record<string, string>> = (\r\n params: TParams,\r\n request?: Request\r\n) => StreamingHints | Promise<StreamingHints>;\r\n\r\n/**\r\n * Route module with streaming exports\r\n */\r\nexport interface StreamingRouteModule {\r\n /** Default component/handler */\r\n default: unknown;\r\n /** Static streaming configuration */\r\n streaming?: StreamingHints;\r\n /** Dynamic streaming configuration function */\r\n getStreamingConfig?: GetStreamingConfig;\r\n /** Other route exports (metadata, generateStaticParams, etc.) */\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * Resolved streaming configuration for a request\r\n */\r\nexport interface ResolvedStreamingConfig extends StreamingHints {\r\n /** Source of the configuration */\r\n source: 'static' | 'dynamic' | 'default';\r\n /** Route path */\r\n routePath: string;\r\n}\r\n\r\n// ============================================================================\r\n// Default Configuration\r\n// ============================================================================\r\n\r\n/**\r\n * Default streaming hints when none are specified\r\n */\r\nexport const DEFAULT_STREAMING_HINTS: Required<StreamingHints> = {\r\n enabled: true,\r\n timeout: 10000, // 10 seconds\r\n priority: 'normal',\r\n boundaries: [],\r\n forceStatic: false,\r\n cache: {\r\n ttl: undefined as unknown as number,\r\n swr: undefined as unknown as number,\r\n tags: [],\r\n },\r\n};\r\n\r\n// ============================================================================\r\n// Configuration Resolution\r\n// ============================================================================\r\n\r\n/**\r\n * Resolve streaming configuration for a route request\r\n */\r\nexport async function resolveStreamingConfig(\r\n module: StreamingRouteModule,\r\n params: Record<string, string>,\r\n request?: Request,\r\n routePath: string = '/'\r\n): Promise<ResolvedStreamingConfig> {\r\n // Check for dynamic config first (takes precedence)\r\n if (typeof module.getStreamingConfig === 'function') {\r\n try {\r\n const dynamicConfig = await module.getStreamingConfig(params, request);\r\n return {\r\n ...DEFAULT_STREAMING_HINTS,\r\n ...dynamicConfig,\r\n source: 'dynamic',\r\n routePath,\r\n };\r\n } catch (error) {\r\n console.warn(`[Flight] Error in getStreamingConfig for ${routePath}:`, error);\r\n // Fall through to static config\r\n }\r\n }\r\n\r\n // Check for static config\r\n if (module.streaming) {\r\n return {\r\n ...DEFAULT_STREAMING_HINTS,\r\n ...module.streaming,\r\n source: 'static',\r\n routePath,\r\n };\r\n }\r\n\r\n // Return defaults\r\n return {\r\n ...DEFAULT_STREAMING_HINTS,\r\n source: 'default',\r\n routePath,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Route Loader Enhancement\r\n// ============================================================================\r\n\r\n/**\r\n * Load route module and extract streaming configuration\r\n */\r\nexport async function loadRouteWithStreaming(\r\n filePath: string,\r\n moduleLoader?: (path: string) => Promise<StreamingRouteModule>\r\n): Promise<{\r\n module: StreamingRouteModule;\r\n hasStreamingConfig: boolean;\r\n hasGetStreamingConfig: boolean;\r\n}> {\r\n // Use custom loader or native import\r\n let module: StreamingRouteModule;\r\n if (moduleLoader) {\r\n module = await moduleLoader(filePath);\r\n } else {\r\n const { pathToFileURL } = await import('node:url');\r\n const fileUrl = pathToFileURL(filePath).href;\r\n module = await import(fileUrl);\r\n }\r\n\r\n return {\r\n module,\r\n hasStreamingConfig: 'streaming' in module,\r\n hasGetStreamingConfig: typeof module.getStreamingConfig === 'function',\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Streaming Decision Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Determine if streaming should be used based on config and request\r\n */\r\nexport function shouldStream(\r\n config: ResolvedStreamingConfig,\r\n request?: Request\r\n): { stream: boolean; reason: string } {\r\n // Force static always wins\r\n if (config.forceStatic) {\r\n return { stream: false, reason: 'forceStatic enabled' };\r\n }\r\n\r\n // Check enabled flag\r\n if (config.enabled === false) {\r\n return { stream: false, reason: 'streaming disabled in config' };\r\n }\r\n\r\n // Check for bot user agents (optional, user can also use conditional.ts)\r\n if (request) {\r\n // userAgent could be used here for bot detection if needed\r\n\r\n // Check for explicit no-stream header\r\n if (request.headers.get('x-no-stream') === 'true') {\r\n return { stream: false, reason: 'x-no-stream header' };\r\n }\r\n\r\n // Check for low priority and slow connection\r\n if (config.priority === 'low') {\r\n const ect = request.headers.get('ect');\r\n if (ect && ['slow-2g', '2g'].includes(ect)) {\r\n return { stream: false, reason: 'low priority + slow connection' };\r\n }\r\n }\r\n }\r\n\r\n return { stream: true, reason: 'streaming enabled' };\r\n}\r\n\r\n// ============================================================================\r\n// Timeout Controller\r\n// ============================================================================\r\n\r\n/**\r\n * Create an abort controller with timeout\r\n */\r\nexport function createStreamingController(\r\n timeout: number\r\n): {\r\n controller: AbortController;\r\n signal: AbortSignal;\r\n cleanup: () => void;\r\n} {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => {\r\n controller.abort(new Error(`Streaming timeout after ${timeout}ms`));\r\n }, timeout);\r\n\r\n return {\r\n controller,\r\n signal: controller.signal,\r\n cleanup: () => clearTimeout(timeoutId),\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Caching Integration\r\n// ============================================================================\r\n\r\n/**\r\n * Generate cache key for a streaming route\r\n */\r\nexport function generateCacheKey(\r\n routePath: string,\r\n params: Record<string, string>,\r\n _config: StreamingHints\r\n): string {\r\n const paramString = Object.entries(params)\r\n .sort(([a], [b]) => a.localeCompare(b))\r\n .map(([k, v]) => `${k}=${v}`)\r\n .join('&');\r\n\r\n return `streaming:${routePath}:${paramString}`;\r\n}\r\n\r\n/**\r\n * Cache headers for static streaming fallback\r\n */\r\nexport function getStreamingCacheHeaders(config: StreamingHints): Record<string, string> {\r\n if (!config.cache) return {};\r\n\r\n const headers: Record<string, string> = {};\r\n\r\n if (config.cache.ttl) {\r\n if (config.cache.swr) {\r\n headers['Cache-Control'] = `s-maxage=${config.cache.ttl}, stale-while-revalidate=${config.cache.swr}`;\r\n } else {\r\n headers['Cache-Control'] = `s-maxage=${config.cache.ttl}`;\r\n }\r\n }\r\n\r\n if (config.cache.tags && config.cache.tags.length > 0) {\r\n headers['X-Cache-Tags'] = config.cache.tags.join(',');\r\n }\r\n\r\n return headers;\r\n}\r\n\r\n// ============================================================================\r\n// Type Guards\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a module has streaming configuration\r\n */\r\nexport function hasStreamingConfig(module: unknown): module is StreamingRouteModule {\r\n if (!module || typeof module !== 'object') return false;\r\n return 'streaming' in module || 'getStreamingConfig' in module;\r\n}\r\n\r\n/**\r\n * Validate streaming hints object\r\n */\r\nexport function isValidStreamingHints(obj: unknown): obj is StreamingHints {\r\n if (!obj || typeof obj !== 'object') return false;\r\n const hints = obj as StreamingHints;\r\n\r\n if (hints.enabled !== undefined && typeof hints.enabled !== 'boolean') return false;\r\n if (hints.timeout !== undefined && typeof hints.timeout !== 'number') return false;\r\n if (hints.priority !== undefined && !['high', 'normal', 'low'].includes(hints.priority)) return false;\r\n if (hints.boundaries !== undefined && !Array.isArray(hints.boundaries)) return false;\r\n if (hints.forceStatic !== undefined && typeof hints.forceStatic !== 'boolean') return false;\r\n\r\n return true;\r\n}\r\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-Y22AMGTM.js.map
3
+ //# sourceMappingURL=chunk-Y22AMGTM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-Y22AMGTM.js"}