@flightdev/core 0.6.7

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 (187) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +541 -0
  3. package/dist/actions/index.d.ts +743 -0
  4. package/dist/actions/index.js +3 -0
  5. package/dist/actions/index.js.map +1 -0
  6. package/dist/adapters/index.d.ts +502 -0
  7. package/dist/adapters/index.js +3 -0
  8. package/dist/adapters/index.js.map +1 -0
  9. package/dist/cache/index.d.ts +191 -0
  10. package/dist/cache/index.js +3 -0
  11. package/dist/cache/index.js.map +1 -0
  12. package/dist/chunk-62HISNA3.js +354 -0
  13. package/dist/chunk-62HISNA3.js.map +1 -0
  14. package/dist/chunk-63LWTEDQ.js +341 -0
  15. package/dist/chunk-63LWTEDQ.js.map +1 -0
  16. package/dist/chunk-63SCEXD7.js +3 -0
  17. package/dist/chunk-63SCEXD7.js.map +1 -0
  18. package/dist/chunk-72MYOTUB.js +667 -0
  19. package/dist/chunk-72MYOTUB.js.map +1 -0
  20. package/dist/chunk-7CNW24MQ.js +257 -0
  21. package/dist/chunk-7CNW24MQ.js.map +1 -0
  22. package/dist/chunk-7WIEAUJT.js +300 -0
  23. package/dist/chunk-7WIEAUJT.js.map +1 -0
  24. package/dist/chunk-7ZZF4ULK.js +259 -0
  25. package/dist/chunk-7ZZF4ULK.js.map +1 -0
  26. package/dist/chunk-AE3JTS73.js +222 -0
  27. package/dist/chunk-AE3JTS73.js.map +1 -0
  28. package/dist/chunk-AP5NLUSB.js +258 -0
  29. package/dist/chunk-AP5NLUSB.js.map +1 -0
  30. package/dist/chunk-C37YQQI7.js +221 -0
  31. package/dist/chunk-C37YQQI7.js.map +1 -0
  32. package/dist/chunk-DCLVXFVH.js +225 -0
  33. package/dist/chunk-DCLVXFVH.js.map +1 -0
  34. package/dist/chunk-DZMWWDFD.js +223 -0
  35. package/dist/chunk-DZMWWDFD.js.map +1 -0
  36. package/dist/chunk-GCQZ4FHI.js +245 -0
  37. package/dist/chunk-GCQZ4FHI.js.map +1 -0
  38. package/dist/chunk-IPP44XY6.js +47 -0
  39. package/dist/chunk-IPP44XY6.js.map +1 -0
  40. package/dist/chunk-IW7FTQQX.js +267 -0
  41. package/dist/chunk-IW7FTQQX.js.map +1 -0
  42. package/dist/chunk-JX4YSCBH.js +428 -0
  43. package/dist/chunk-JX4YSCBH.js.map +1 -0
  44. package/dist/chunk-KX6UYWWR.js +229 -0
  45. package/dist/chunk-KX6UYWWR.js.map +1 -0
  46. package/dist/chunk-LWVETFJV.js +46 -0
  47. package/dist/chunk-LWVETFJV.js.map +1 -0
  48. package/dist/chunk-MCL2MCA2.js +285 -0
  49. package/dist/chunk-MCL2MCA2.js.map +1 -0
  50. package/dist/chunk-MZXCF35B.js +205 -0
  51. package/dist/chunk-MZXCF35B.js.map +1 -0
  52. package/dist/chunk-NCGPUFWV.js +96 -0
  53. package/dist/chunk-NCGPUFWV.js.map +1 -0
  54. package/dist/chunk-OEJMIE2Q.js +351 -0
  55. package/dist/chunk-OEJMIE2Q.js.map +1 -0
  56. package/dist/chunk-OYF2OAKS.js +394 -0
  57. package/dist/chunk-OYF2OAKS.js.map +1 -0
  58. package/dist/chunk-P6S43FYZ.js +316 -0
  59. package/dist/chunk-P6S43FYZ.js.map +1 -0
  60. package/dist/chunk-PL37KFRJ.js +3 -0
  61. package/dist/chunk-PL37KFRJ.js.map +1 -0
  62. package/dist/chunk-Q7BS5QC5.js +197 -0
  63. package/dist/chunk-Q7BS5QC5.js.map +1 -0
  64. package/dist/chunk-SDYPG3JD.js +288 -0
  65. package/dist/chunk-SDYPG3JD.js.map +1 -0
  66. package/dist/chunk-SUG56SZO.js +256 -0
  67. package/dist/chunk-SUG56SZO.js.map +1 -0
  68. package/dist/chunk-UVH5XJRP.js +164 -0
  69. package/dist/chunk-UVH5XJRP.js.map +1 -0
  70. package/dist/chunk-WZIJKCL3.js +282 -0
  71. package/dist/chunk-WZIJKCL3.js.map +1 -0
  72. package/dist/chunk-Y22AMGTM.js +3 -0
  73. package/dist/chunk-Y22AMGTM.js.map +1 -0
  74. package/dist/chunk-Z7G23XWU.js +200 -0
  75. package/dist/chunk-Z7G23XWU.js.map +1 -0
  76. package/dist/chunk-ZJU5M4IB.js +125 -0
  77. package/dist/chunk-ZJU5M4IB.js.map +1 -0
  78. package/dist/chunk-ZVC3ZWLM.js +52 -0
  79. package/dist/chunk-ZVC3ZWLM.js.map +1 -0
  80. package/dist/chunk-ZZZML7Y3.js +310 -0
  81. package/dist/chunk-ZZZML7Y3.js.map +1 -0
  82. package/dist/client.d.ts +25 -0
  83. package/dist/client.js +16 -0
  84. package/dist/client.js.map +1 -0
  85. package/dist/config/index.d.ts +170 -0
  86. package/dist/config/index.js +3 -0
  87. package/dist/config/index.js.map +1 -0
  88. package/dist/errors/index.d.ts +267 -0
  89. package/dist/errors/index.js +4 -0
  90. package/dist/errors/index.js.map +1 -0
  91. package/dist/file-router/index.d.ts +184 -0
  92. package/dist/file-router/index.js +3 -0
  93. package/dist/file-router/index.js.map +1 -0
  94. package/dist/file-router/streaming-hints.d.ts +129 -0
  95. package/dist/file-router/streaming-hints.js +3 -0
  96. package/dist/file-router/streaming-hints.js.map +1 -0
  97. package/dist/handlers/index.d.ts +59 -0
  98. package/dist/handlers/index.js +3 -0
  99. package/dist/handlers/index.js.map +1 -0
  100. package/dist/index.d.ts +588 -0
  101. package/dist/index.js +886 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/islands/index.d.ts +234 -0
  104. package/dist/islands/index.js +3 -0
  105. package/dist/islands/index.js.map +1 -0
  106. package/dist/middleware/index.d.ts +305 -0
  107. package/dist/middleware/index.js +3 -0
  108. package/dist/middleware/index.js.map +1 -0
  109. package/dist/react/index.d.ts +73 -0
  110. package/dist/react/index.js +52 -0
  111. package/dist/react/index.js.map +1 -0
  112. package/dist/render/index.d.ts +131 -0
  113. package/dist/render/index.js +3 -0
  114. package/dist/render/index.js.map +1 -0
  115. package/dist/router/index.d.ts +65 -0
  116. package/dist/router/index.js +3 -0
  117. package/dist/router/index.js.map +1 -0
  118. package/dist/rsc/adapters/index.d.ts +8 -0
  119. package/dist/rsc/adapters/index.js +7 -0
  120. package/dist/rsc/adapters/index.js.map +1 -0
  121. package/dist/rsc/adapters/preact.d.ts +97 -0
  122. package/dist/rsc/adapters/preact.js +3 -0
  123. package/dist/rsc/adapters/preact.js.map +1 -0
  124. package/dist/rsc/adapters/react.d.ts +82 -0
  125. package/dist/rsc/adapters/react.js +3 -0
  126. package/dist/rsc/adapters/react.js.map +1 -0
  127. package/dist/rsc/adapters/solid.d.ts +84 -0
  128. package/dist/rsc/adapters/solid.js +3 -0
  129. package/dist/rsc/adapters/solid.js.map +1 -0
  130. package/dist/rsc/adapters/vue.d.ts +80 -0
  131. package/dist/rsc/adapters/vue.js +3 -0
  132. package/dist/rsc/adapters/vue.js.map +1 -0
  133. package/dist/rsc/boundaries.d.ts +182 -0
  134. package/dist/rsc/boundaries.js +3 -0
  135. package/dist/rsc/boundaries.js.map +1 -0
  136. package/dist/rsc/context.d.ts +201 -0
  137. package/dist/rsc/context.js +3 -0
  138. package/dist/rsc/context.js.map +1 -0
  139. package/dist/rsc/index.d.ts +232 -0
  140. package/dist/rsc/index.js +15 -0
  141. package/dist/rsc/index.js.map +1 -0
  142. package/dist/rsc/legacy.d.ts +155 -0
  143. package/dist/rsc/legacy.js +3 -0
  144. package/dist/rsc/legacy.js.map +1 -0
  145. package/dist/rsc/payload.d.ts +262 -0
  146. package/dist/rsc/payload.js +3 -0
  147. package/dist/rsc/payload.js.map +1 -0
  148. package/dist/rsc/plugins/esbuild.d.ts +124 -0
  149. package/dist/rsc/plugins/esbuild.js +4 -0
  150. package/dist/rsc/plugins/esbuild.js.map +1 -0
  151. package/dist/rsc/plugins/index.d.ts +4 -0
  152. package/dist/rsc/plugins/index.js +6 -0
  153. package/dist/rsc/plugins/index.js.map +1 -0
  154. package/dist/rsc/plugins/rollup.d.ts +103 -0
  155. package/dist/rsc/plugins/rollup.js +4 -0
  156. package/dist/rsc/plugins/rollup.js.map +1 -0
  157. package/dist/rsc/renderer.d.ts +162 -0
  158. package/dist/rsc/renderer.js +5 -0
  159. package/dist/rsc/renderer.js.map +1 -0
  160. package/dist/rsc/stream.d.ts +129 -0
  161. package/dist/rsc/stream.js +3 -0
  162. package/dist/rsc/stream.js.map +1 -0
  163. package/dist/rsc/vite-plugin.d.ts +78 -0
  164. package/dist/rsc/vite-plugin.js +4 -0
  165. package/dist/rsc/vite-plugin.js.map +1 -0
  166. package/dist/server/index.d.ts +135 -0
  167. package/dist/server/index.js +6 -0
  168. package/dist/server/index.js.map +1 -0
  169. package/dist/streaming/adapters/index.d.ts +223 -0
  170. package/dist/streaming/adapters/index.js +3 -0
  171. package/dist/streaming/adapters/index.js.map +1 -0
  172. package/dist/streaming/conditional.d.ts +130 -0
  173. package/dist/streaming/conditional.js +3 -0
  174. package/dist/streaming/conditional.js.map +1 -0
  175. package/dist/streaming/index.d.ts +177 -0
  176. package/dist/streaming/index.js +3 -0
  177. package/dist/streaming/index.js.map +1 -0
  178. package/dist/streaming/observability.d.ts +201 -0
  179. package/dist/streaming/observability.js +4 -0
  180. package/dist/streaming/observability.js.map +1 -0
  181. package/dist/streaming/priority.d.ts +103 -0
  182. package/dist/streaming/priority.js +3 -0
  183. package/dist/streaming/priority.js.map +1 -0
  184. package/dist/utils/index.d.ts +42 -0
  185. package/dist/utils/index.js +4 -0
  186. package/dist/utils/index.js.map +1 -0
  187. package/package.json +228 -0
@@ -0,0 +1,743 @@
1
+ /**
2
+ * @flightdev/core - Action Middleware
3
+ *
4
+ * Agnostic middleware system for Server Actions.
5
+ * Flight provides the PRIMITIVES, you build YOUR solution.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Create your own auth middleware (Flight doesn't impose any auth provider)
10
+ * const withAuth = createActionMiddleware(async (ctx, next) => {
11
+ * const session = await yourAuthProvider.getSession(ctx.headers);
12
+ * if (!session) {
13
+ * return { success: false, error: 'UNAUTHORIZED' };
14
+ * }
15
+ * ctx.set('session', session);
16
+ * return next();
17
+ * });
18
+ *
19
+ * // Create your own rate limiter (Flight doesn't impose any rate limit provider)
20
+ * const withRateLimit = createActionMiddleware(async (ctx, next) => {
21
+ * const allowed = await yourRateLimiter.check(ctx.get('session').userId);
22
+ * if (!allowed) {
23
+ * return { success: false, error: 'RATE_LIMITED' };
24
+ * }
25
+ * return next();
26
+ * });
27
+ *
28
+ * // Compose them
29
+ * const protectedAction = pipeline(withAuth, withRateLimit)(myAction);
30
+ * ```
31
+ */
32
+ /**
33
+ * Action context - holds request data and middleware-set values
34
+ */
35
+ interface ActionContext {
36
+ /** Original request (if available) */
37
+ readonly request?: Request;
38
+ /** Request headers */
39
+ readonly headers: Headers;
40
+ /** Action ID being executed */
41
+ readonly actionId: string;
42
+ /** Action arguments */
43
+ readonly args: unknown[];
44
+ /** Abort signal for cancellation */
45
+ readonly signal?: AbortSignal;
46
+ /** Get a value set by previous middleware */
47
+ get<T = unknown>(key: string): T | undefined;
48
+ /** Set a value for subsequent middleware/action */
49
+ set<T = unknown>(key: string, value: T): void;
50
+ }
51
+ /**
52
+ * Action result following Flight conventions
53
+ */
54
+ interface ActionResult$1<T = unknown> {
55
+ success: boolean;
56
+ data?: T;
57
+ error?: string;
58
+ code?: string;
59
+ }
60
+ /**
61
+ * Next function to call the next middleware or action
62
+ */
63
+ type ActionNext<T = unknown> = () => Promise<ActionResult$1<T>>;
64
+ /**
65
+ * Middleware handler function
66
+ */
67
+ type ActionMiddlewareHandler<TContext extends ActionContext = ActionContext> = (ctx: TContext, next: ActionNext) => Promise<ActionResult$1> | ActionResult$1;
68
+ /**
69
+ * A middleware instance
70
+ */
71
+ interface ActionMiddleware {
72
+ /** Unique name for debugging */
73
+ readonly name: string;
74
+ /** The handler function */
75
+ readonly handler: ActionMiddlewareHandler;
76
+ }
77
+ /**
78
+ * An action function
79
+ */
80
+ type Action<TInput = unknown, TOutput = unknown> = (...args: TInput extends unknown[] ? TInput : [TInput]) => Promise<ActionResult$1<TOutput>>;
81
+ /**
82
+ * Options for creating middleware
83
+ */
84
+ interface CreateMiddlewareOptions {
85
+ /** Name for debugging/logging */
86
+ name?: string;
87
+ }
88
+ /**
89
+ * Create an action context from request or minimal data
90
+ */
91
+ declare function createActionContext(options: {
92
+ request?: Request;
93
+ headers?: Headers;
94
+ actionId: string;
95
+ args: unknown[];
96
+ signal?: AbortSignal;
97
+ }): ActionContext;
98
+ /**
99
+ * Create a reusable action middleware.
100
+ *
101
+ * Flight provides this PRIMITIVE - you define WHAT the middleware does.
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * // Authentication middleware (you choose the auth provider)
106
+ * const withAuth = createActionMiddleware(async (ctx, next) => {
107
+ * const token = ctx.headers.get('Authorization');
108
+ * const user = await myAuthLib.verify(token); // YOUR auth library
109
+ *
110
+ * if (!user) {
111
+ * return { success: false, error: 'Unauthorized', code: 'AUTH_ERROR' };
112
+ * }
113
+ *
114
+ * ctx.set('user', user);
115
+ * return next();
116
+ * });
117
+ *
118
+ * // Validation middleware (you choose the validator)
119
+ * const withValidation = (schema: ZodSchema) => createActionMiddleware(
120
+ * async (ctx, next) => {
121
+ * const result = schema.safeParse(ctx.args[0]);
122
+ * if (!result.success) {
123
+ * return { success: false, error: 'Validation failed', code: 'VALIDATION_ERROR' };
124
+ * }
125
+ * return next();
126
+ * },
127
+ * { name: 'validation' }
128
+ * );
129
+ * ```
130
+ */
131
+ declare function createActionMiddleware(handler: ActionMiddlewareHandler, options?: CreateMiddlewareOptions): ActionMiddleware;
132
+ /**
133
+ * Compose multiple middleware into a pipeline that wraps an action.
134
+ *
135
+ * Middleware executes in order: first middleware runs first.
136
+ * Each middleware can:
137
+ * - Short-circuit by returning a result without calling next()
138
+ * - Transform context for subsequent middleware
139
+ * - Wrap the next() call for timing/logging
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const protectedAction = pipeline(
144
+ * withAuth,
145
+ * withRateLimit,
146
+ * withValidation(UserSchema),
147
+ * )(createUserAction);
148
+ *
149
+ * // Now protectedAction has auth, rate-limit, and validation
150
+ * const result = await protectedAction(userData);
151
+ * ```
152
+ */
153
+ declare function pipeline<TInput, TOutput>(...middlewares: ActionMiddleware[]): (action: Action<TInput, TOutput>) => Action<TInput, TOutput>;
154
+ /**
155
+ * Execute an action with middleware, providing custom context.
156
+ *
157
+ * Use this when you need to provide request context (headers, etc.)
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * const result = await executeWithMiddleware(
162
+ * myAction,
163
+ * [arg1, arg2],
164
+ * [withAuth, withRateLimit],
165
+ * { request: incomingRequest }
166
+ * );
167
+ * ```
168
+ */
169
+ declare function executeWithMiddleware<TInput extends unknown[], TOutput>(action: (...args: TInput) => Promise<ActionResult$1<TOutput>>, args: TInput, middlewares: ActionMiddleware[], options?: {
170
+ request?: Request;
171
+ headers?: Headers;
172
+ signal?: AbortSignal;
173
+ }): Promise<ActionResult$1<TOutput>>;
174
+ /**
175
+ * Create a timing middleware for observability.
176
+ *
177
+ * You provide the reporter - Flight doesn't impose any observability provider.
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const withTiming = createTimingMiddleware((actionId, durationMs) => {
182
+ * myMetricsService.histogram('action.duration', durationMs, { actionId });
183
+ * });
184
+ * ```
185
+ */
186
+ declare function createTimingMiddleware(reporter: (actionId: string, durationMs: number, result: ActionResult$1) => void): ActionMiddleware;
187
+ /**
188
+ * Create a logging middleware.
189
+ *
190
+ * You provide the logger - Flight doesn't impose any logging library.
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const withLogging = createLoggingMiddleware({
195
+ * onStart: (ctx) => console.log(`[${ctx.actionId}] Starting...`),
196
+ * onComplete: (ctx, result, ms) => console.log(`[${ctx.actionId}] ${result.success ? 'OK' : 'FAIL'} in ${ms}ms`),
197
+ * });
198
+ * ```
199
+ */
200
+ declare function createLoggingMiddleware(options: {
201
+ onStart?: (ctx: ActionContext) => void;
202
+ onComplete?: (ctx: ActionContext, result: ActionResult$1, durationMs: number) => void;
203
+ onError?: (ctx: ActionContext, error: Error) => void;
204
+ }): ActionMiddleware;
205
+ /**
206
+ * Create a retry middleware.
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * const withRetry = createRetryMiddleware({
211
+ * maxAttempts: 3,
212
+ * delay: (attempt) => Math.pow(2, attempt) * 100, // Exponential backoff
213
+ * shouldRetry: (result) => result.code === 'TEMPORARY_ERROR',
214
+ * });
215
+ * ```
216
+ */
217
+ declare function createRetryMiddleware(options: {
218
+ maxAttempts: number;
219
+ delay?: (attempt: number) => number;
220
+ shouldRetry?: (result: ActionResult$1) => boolean;
221
+ }): ActionMiddleware;
222
+
223
+ /**
224
+ * @flightdev/core - Action Streaming
225
+ *
226
+ * Streamable actions using async generators.
227
+ * Flight provides the PRIMITIVES, you choose the transport.
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * // Create a streamable action for long-running operations
232
+ * const generateReport = createStreamableAction(async function* (params: ReportParams) {
233
+ * yield { type: 'progress', message: 'Fetching data...', progress: 0 };
234
+ * const data = await fetchData(params);
235
+ *
236
+ * yield { type: 'progress', message: 'Processing...', progress: 33 };
237
+ * const processed = await processData(data);
238
+ *
239
+ * yield { type: 'progress', message: 'Generating PDF...', progress: 66 };
240
+ * const pdf = await generatePDF(processed);
241
+ *
242
+ * yield { type: 'progress', message: 'Complete!', progress: 100 };
243
+ * return { success: true, data: pdf };
244
+ * });
245
+ *
246
+ * // Client consumption
247
+ * for await (const update of generateReport(params)) {
248
+ * if (update.type === 'progress') {
249
+ * setProgress(update.progress);
250
+ * } else if (update.type === 'result') {
251
+ * handleResult(update.data);
252
+ * }
253
+ * }
254
+ * ```
255
+ */
256
+ /**
257
+ * Progress update yielded during streaming
258
+ */
259
+ interface StreamProgress<TYield = unknown> {
260
+ type: 'progress';
261
+ data: TYield;
262
+ }
263
+ /**
264
+ * Final result of a streaming action
265
+ */
266
+ interface StreamResult<TReturn = unknown> {
267
+ type: 'result';
268
+ success: boolean;
269
+ data?: TReturn;
270
+ error?: string;
271
+ }
272
+ /**
273
+ * Union type for stream items
274
+ */
275
+ type StreamItem<TYield, TReturn> = StreamProgress<TYield> | StreamResult<TReturn>;
276
+ /**
277
+ * Streamable action generator function
278
+ */
279
+ type StreamableGenerator<TInput, TYield, TReturn> = (input: TInput, signal?: AbortSignal) => AsyncGenerator<TYield, TReturn>;
280
+ /**
281
+ * Options for creating a streamable action
282
+ */
283
+ interface StreamableActionOptions {
284
+ /** Name for debugging */
285
+ name?: string;
286
+ /** Timeout in milliseconds */
287
+ timeout?: number;
288
+ }
289
+ /**
290
+ * Controller for a running stream
291
+ */
292
+ interface StreamController<TYield, TReturn> {
293
+ /** Async iterator for consuming the stream */
294
+ [Symbol.asyncIterator](): AsyncIterator<StreamItem<TYield, TReturn>>;
295
+ /** Abort the stream */
296
+ abort(): void;
297
+ /** Promise that resolves when stream completes */
298
+ done: Promise<StreamResult<TReturn>>;
299
+ }
300
+ /**
301
+ * A streamable action function
302
+ */
303
+ type StreamableAction<TInput, TYield, TReturn> = (input: TInput) => StreamController<TYield, TReturn>;
304
+ /**
305
+ * Create a streamable action from an async generator.
306
+ *
307
+ * Flight provides this PRIMITIVE - you define the generator logic
308
+ * and choose how to transport the stream (HTTP, WebSocket, etc.)
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * // AI streaming response
313
+ * const streamChat = createStreamableAction(async function* (message: string) {
314
+ * const stream = await openai.chat.completions.create({
315
+ * model: 'gpt-4',
316
+ * messages: [{ role: 'user', content: message }],
317
+ * stream: true,
318
+ * });
319
+ *
320
+ * let fullResponse = '';
321
+ * for await (const chunk of stream) {
322
+ * const text = chunk.choices[0]?.delta?.content || '';
323
+ * fullResponse += text;
324
+ * yield { text, partial: true };
325
+ * }
326
+ *
327
+ * return { text: fullResponse, partial: false };
328
+ * });
329
+ * ```
330
+ */
331
+ declare function createStreamableAction<TInput, TYield, TReturn>(generator: StreamableGenerator<TInput, TYield, TReturn>, options?: StreamableActionOptions): StreamableAction<TInput, TYield, TReturn>;
332
+ /**
333
+ * Convert a streamable action result to an HTTP streaming response.
334
+ *
335
+ * This is ONE transport option - you can create others (WebSocket, SSE, etc.)
336
+ *
337
+ * @example
338
+ * ```typescript
339
+ * // In your API route
340
+ * export async function POST(request: Request) {
341
+ * const body = await request.json();
342
+ * const stream = generateReport(body);
343
+ * return streamToResponse(stream);
344
+ * }
345
+ * ```
346
+ */
347
+ declare function streamToResponse<TYield, TReturn>(controller: StreamController<TYield, TReturn>, options?: {
348
+ headers?: Record<string, string>;
349
+ }): Response;
350
+ /**
351
+ * Parse an HTTP streaming response back to a stream controller (client-side).
352
+ *
353
+ * @example
354
+ * ```typescript
355
+ * // Client-side consumption
356
+ * const response = await fetch('/api/generate-report', {
357
+ * method: 'POST',
358
+ * body: JSON.stringify(params),
359
+ * });
360
+ *
361
+ * const stream = responseToStream<Progress, Report>(response);
362
+ *
363
+ * for await (const item of stream) {
364
+ * if (item.type === 'progress') {
365
+ * setProgress(item.data);
366
+ * } else {
367
+ * setReport(item.data);
368
+ * }
369
+ * }
370
+ * ```
371
+ */
372
+ declare function responseToStream<TYield, TReturn>(response: Response): AsyncGenerator<StreamItem<TYield, TReturn>>;
373
+ /**
374
+ * Collect all items from a stream into an array.
375
+ *
376
+ * Useful for testing or when you want to wait for completion.
377
+ */
378
+ declare function collectStream<TYield, TReturn>(controller: StreamController<TYield, TReturn>): Promise<{
379
+ items: StreamItem<TYield, TReturn>[];
380
+ result: StreamResult<TReturn>;
381
+ }>;
382
+ /**
383
+ * Create a simple progress reporter for streams.
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * const onProgress = createProgressReporter<MyProgress>((data) => {
388
+ * console.log(`Progress: ${data.percent}%`);
389
+ * });
390
+ *
391
+ * for await (const item of myStream) {
392
+ * onProgress(item);
393
+ * }
394
+ * ```
395
+ */
396
+ declare function createProgressReporter<TYield, TReturn = unknown>(onProgress: (data: TYield) => void, onComplete?: (result: StreamResult<TReturn>) => void): (item: StreamItem<TYield, TReturn>) => void;
397
+
398
+ /**
399
+ * @flightdev/core - Action Queue
400
+ *
401
+ * Offline-first action queuing with pluggable storage.
402
+ * Flight provides the PRIMITIVES and INTERFACE, you choose the storage.
403
+ *
404
+ * @example
405
+ * ```typescript
406
+ * // 1. Use a storage adapter (install separately or create your own)
407
+ * import { indexedDBAdapter } from '@flightdev/queue-indexeddb';
408
+ * // OR create your own:
409
+ * const myAdapter: QueueStorageAdapter = { ... };
410
+ *
411
+ * // 2. Create a queued action
412
+ * const saveNote = createQueuedAction(
413
+ * async (note: Note) => {
414
+ * await api.saveNote(note);
415
+ * return { success: true };
416
+ * },
417
+ * {
418
+ * storage: indexedDBAdapter({ dbName: 'myapp' }),
419
+ * retryStrategy: exponentialBackoff({ maxAttempts: 5 }),
420
+ * onStatusChange: (status) => console.log('Queue status:', status),
421
+ * }
422
+ * );
423
+ *
424
+ * // 3. Use it - works offline!
425
+ * await saveNote({ title: 'My Note', content: '...' });
426
+ * // If offline: queued and synced later
427
+ * // If online: executed immediately
428
+ * ```
429
+ */
430
+ /**
431
+ * A queued action entry
432
+ */
433
+ interface QueuedActionEntry<TInput = unknown> {
434
+ /** Unique ID for this entry */
435
+ id: string;
436
+ /** Action identifier */
437
+ actionId: string;
438
+ /** Action arguments */
439
+ input: TInput;
440
+ /** When the action was queued */
441
+ queuedAt: number;
442
+ /** Number of execution attempts */
443
+ attempts: number;
444
+ /** Last error message if failed */
445
+ lastError?: string;
446
+ /** Status */
447
+ status: 'pending' | 'processing' | 'failed';
448
+ /** Optional metadata */
449
+ meta?: Record<string, unknown>;
450
+ }
451
+ /**
452
+ * Queue storage adapter interface.
453
+ *
454
+ * Flight does NOT provide storage implementations - you choose:
455
+ * - @flightdev/queue-indexeddb (browser)
456
+ * - @flightdev/queue-sqlite (mobile/desktop)
457
+ * - @flightdev/queue-memory (testing)
458
+ * - Your own implementation
459
+ */
460
+ interface QueueStorageAdapter {
461
+ /** Add an action to the queue */
462
+ enqueue<TInput>(entry: QueuedActionEntry<TInput>): Promise<void>;
463
+ /** Get and remove the next pending action */
464
+ dequeue(): Promise<QueuedActionEntry | null>;
465
+ /** Get all pending actions without removing */
466
+ peek(): Promise<QueuedActionEntry[]>;
467
+ /** Update an existing entry */
468
+ update(id: string, updates: Partial<QueuedActionEntry>): Promise<void>;
469
+ /** Remove an entry by ID */
470
+ remove(id: string): Promise<void>;
471
+ /** Clear all entries */
472
+ clear(): Promise<void>;
473
+ /** Get queue length */
474
+ length(): Promise<number>;
475
+ }
476
+ /**
477
+ * Retry strategy function
478
+ */
479
+ type RetryStrategy = (entry: QueuedActionEntry, error: Error) => {
480
+ shouldRetry: boolean;
481
+ delayMs: number;
482
+ };
483
+ /**
484
+ * Queue status for observability
485
+ */
486
+ interface QueueStatus {
487
+ /** Whether the queue processor is running */
488
+ isProcessing: boolean;
489
+ /** Number of pending actions */
490
+ pendingCount: number;
491
+ /** Number of failed actions */
492
+ failedCount: number;
493
+ /** Whether online */
494
+ isOnline: boolean;
495
+ }
496
+ /**
497
+ * Options for creating a queued action
498
+ */
499
+ interface QueuedActionOptions {
500
+ /** Storage adapter (required - Flight doesn't provide default) */
501
+ storage: QueueStorageAdapter;
502
+ /** Custom action ID */
503
+ actionId?: string;
504
+ /** Retry strategy */
505
+ retryStrategy?: RetryStrategy;
506
+ /** Check if online (default: navigator.onLine on browser) */
507
+ isOnline?: () => boolean | Promise<boolean>;
508
+ /** Called when queue status changes */
509
+ onStatusChange?: (status: QueueStatus) => void;
510
+ /** Called when an action is successfully processed */
511
+ onSuccess?: (entry: QueuedActionEntry, result: unknown) => void;
512
+ /** Called when an action fails permanently */
513
+ onFailure?: (entry: QueuedActionEntry, error: Error) => void;
514
+ }
515
+ /**
516
+ * Action result for queued actions
517
+ */
518
+ interface QueuedActionResult<TOutput = unknown> {
519
+ /** Whether immediately executed or queued */
520
+ queued: boolean;
521
+ /** Queue entry ID if queued */
522
+ entryId?: string;
523
+ /** Result if immediately executed */
524
+ result?: {
525
+ success: boolean;
526
+ data?: TOutput;
527
+ error?: string;
528
+ };
529
+ }
530
+ /**
531
+ * A queued action function
532
+ */
533
+ type QueuedAction<TInput, TOutput> = (input: TInput) => Promise<QueuedActionResult<TOutput>>;
534
+ /**
535
+ * Create an offline-capable queued action.
536
+ *
537
+ * Flight provides this PRIMITIVE - you provide the storage adapter.
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * // Create with your storage adapter
542
+ * const syncData = createQueuedAction(
543
+ * async (data: MyData) => {
544
+ * await api.sync(data);
545
+ * return { success: true };
546
+ * },
547
+ * {
548
+ * storage: myStorageAdapter,
549
+ * retryStrategy: exponentialBackoff(),
550
+ * }
551
+ * );
552
+ *
553
+ * // Use it - works offline automatically
554
+ * const result = await syncData({ items: [...] });
555
+ *
556
+ * if (result.queued) {
557
+ * console.log('Queued for later sync:', result.entryId);
558
+ * } else {
559
+ * console.log('Synced immediately:', result.result);
560
+ * }
561
+ * ```
562
+ */
563
+ declare function createQueuedAction<TInput, TOutput>(action: (input: TInput) => Promise<{
564
+ success: boolean;
565
+ data?: TOutput;
566
+ error?: string;
567
+ }>, options: QueuedActionOptions): QueuedAction<TInput, TOutput>;
568
+ /**
569
+ * Default retry strategy: 3 attempts with 1 second delay
570
+ */
571
+ declare const defaultRetryStrategy: RetryStrategy;
572
+ /**
573
+ * Create an exponential backoff retry strategy.
574
+ *
575
+ * @example
576
+ * ```typescript
577
+ * const retry = exponentialBackoff({
578
+ * maxAttempts: 5,
579
+ * baseDelayMs: 1000,
580
+ * maxDelayMs: 30000,
581
+ * });
582
+ * ```
583
+ */
584
+ declare function exponentialBackoff(options?: {
585
+ maxAttempts?: number;
586
+ baseDelayMs?: number;
587
+ maxDelayMs?: number;
588
+ }): RetryStrategy;
589
+ /**
590
+ * Create a fixed delay retry strategy.
591
+ */
592
+ declare function fixedDelay(options?: {
593
+ maxAttempts?: number;
594
+ delayMs?: number;
595
+ }): RetryStrategy;
596
+ /**
597
+ * In-memory queue storage adapter.
598
+ *
599
+ * ⚠️ FOR TESTING ONLY - data is lost on page refresh.
600
+ *
601
+ * For production, use:
602
+ * - @flightdev/queue-indexeddb (browser)
603
+ * - @flightdev/queue-sqlite (native apps)
604
+ * - Your own implementation
605
+ */
606
+ declare function createMemoryAdapter(): QueueStorageAdapter;
607
+ /**
608
+ * Create a queue manager to control multiple queued actions.
609
+ *
610
+ * @example
611
+ * ```typescript
612
+ * const queueManager = createQueueManager({
613
+ * storage: myStorageAdapter,
614
+ * });
615
+ *
616
+ * // Pause all processing
617
+ * queueManager.pause();
618
+ *
619
+ * // Resume
620
+ * queueManager.resume();
621
+ *
622
+ * // Get status
623
+ * const status = await queueManager.getStatus();
624
+ * ```
625
+ */
626
+ declare function createQueueManager(options: {
627
+ storage: QueueStorageAdapter;
628
+ }): {
629
+ pause: () => void;
630
+ resume: () => void;
631
+ getStatus: () => Promise<QueueStatus>;
632
+ clearFailed: () => Promise<void>;
633
+ retryFailed: () => Promise<void>;
634
+ };
635
+
636
+ /**
637
+ * @flightdev/core - Server Actions
638
+ *
639
+ * Implementation of React 19 style Server Actions.
640
+ * Functions marked with 'use server' run on the server.
641
+ */
642
+ /**
643
+ * Server action metadata
644
+ */
645
+ interface ServerAction {
646
+ /** Unique action ID */
647
+ id: string;
648
+ /** Original function name */
649
+ name: string;
650
+ /** File path where action is defined */
651
+ filePath: string;
652
+ /** The actual action function */
653
+ fn: (...args: unknown[]) => Promise<unknown>;
654
+ }
655
+ /**
656
+ * Server action result
657
+ */
658
+ interface ActionResult<T = unknown> {
659
+ success: boolean;
660
+ data?: T;
661
+ error?: string;
662
+ }
663
+ /**
664
+ * Form action data
665
+ */
666
+ interface FormActionData {
667
+ actionId: string;
668
+ formData: FormData;
669
+ }
670
+ /**
671
+ * Register a server action
672
+ */
673
+ declare function registerAction(action: ServerAction): void;
674
+ /**
675
+ * Get a registered action by ID
676
+ */
677
+ declare function getAction(id: string): ServerAction | undefined;
678
+ /**
679
+ * Get all registered actions
680
+ */
681
+ declare function getAllActions(): ServerAction[];
682
+ /**
683
+ * Clear all registered actions (useful for testing)
684
+ */
685
+ declare function clearActions(): void;
686
+ /**
687
+ * Execute a server action
688
+ */
689
+ declare function executeAction<T = unknown>(actionId: string, args: unknown[]): Promise<ActionResult<T>>;
690
+ /**
691
+ * Execute a form action
692
+ */
693
+ declare function executeFormAction<T = unknown>(actionId: string, formData: FormData): Promise<ActionResult<T>>;
694
+ /**
695
+ * Generate a unique action ID
696
+ */
697
+ declare function generateActionId(name: string, filePath: string): string;
698
+ /**
699
+ * Get cookies in server action context
700
+ */
701
+ declare function cookies(): {
702
+ get: (name: string) => string | undefined;
703
+ set: (name: string, value: string, options?: CookieOptions) => void;
704
+ delete: (name: string) => void;
705
+ };
706
+ interface CookieOptions {
707
+ maxAge?: number;
708
+ expires?: Date;
709
+ path?: string;
710
+ domain?: string;
711
+ secure?: boolean;
712
+ httpOnly?: boolean;
713
+ sameSite?: 'strict' | 'lax' | 'none';
714
+ }
715
+ /**
716
+ * Redirect in server action context
717
+ */
718
+ declare function redirect(url: string): never;
719
+ /**
720
+ * Special error for redirects
721
+ */
722
+ declare class RedirectError extends Error {
723
+ readonly url: string;
724
+ constructor(url: string);
725
+ }
726
+ /**
727
+ * Check if error is a redirect
728
+ */
729
+ declare function isRedirectError(error: unknown): error is RedirectError;
730
+ /**
731
+ * Parse form data to typed object
732
+ */
733
+ declare function parseFormData<T extends Record<string, string>>(formData: FormData): T;
734
+ /**
735
+ * Create action reference for form action attribute
736
+ */
737
+ declare function createActionReference(actionId: string): string;
738
+ /**
739
+ * Handle action request from client
740
+ */
741
+ declare function handleActionRequest(request: Request): Promise<Response>;
742
+
743
+ export { type Action, type ActionContext, type ActionMiddleware, type ActionMiddlewareHandler, type ActionNext, type ActionResult, type CookieOptions, type CreateMiddlewareOptions, type FormActionData, type QueueStatus, type QueueStorageAdapter, type QueuedAction, type QueuedActionEntry, type QueuedActionOptions, type QueuedActionResult, RedirectError, type RetryStrategy, type ServerAction, type StreamController, type StreamItem, type StreamProgress, type StreamResult, type StreamableAction, type StreamableActionOptions, type StreamableGenerator, clearActions, collectStream, cookies, createActionContext, createActionMiddleware, createActionReference, createLoggingMiddleware, createMemoryAdapter, createProgressReporter, createQueueManager, createQueuedAction, createRetryMiddleware, createStreamableAction, createTimingMiddleware, defaultRetryStrategy, executeAction, executeFormAction, executeWithMiddleware, exponentialBackoff, fixedDelay, generateActionId, getAction, getAllActions, handleActionRequest, isRedirectError, parseFormData, pipeline, redirect, registerAction, responseToStream, streamToResponse };