@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.
- package/LICENSE +21 -0
- package/README.md +541 -0
- package/dist/actions/index.d.ts +743 -0
- package/dist/actions/index.js +3 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/adapters/index.d.ts +502 -0
- package/dist/adapters/index.js +3 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/cache/index.d.ts +191 -0
- package/dist/cache/index.js +3 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/chunk-62HISNA3.js +354 -0
- package/dist/chunk-62HISNA3.js.map +1 -0
- package/dist/chunk-63LWTEDQ.js +341 -0
- package/dist/chunk-63LWTEDQ.js.map +1 -0
- package/dist/chunk-63SCEXD7.js +3 -0
- package/dist/chunk-63SCEXD7.js.map +1 -0
- package/dist/chunk-72MYOTUB.js +667 -0
- package/dist/chunk-72MYOTUB.js.map +1 -0
- package/dist/chunk-7CNW24MQ.js +257 -0
- package/dist/chunk-7CNW24MQ.js.map +1 -0
- package/dist/chunk-7WIEAUJT.js +300 -0
- package/dist/chunk-7WIEAUJT.js.map +1 -0
- package/dist/chunk-7ZZF4ULK.js +259 -0
- package/dist/chunk-7ZZF4ULK.js.map +1 -0
- package/dist/chunk-AE3JTS73.js +222 -0
- package/dist/chunk-AE3JTS73.js.map +1 -0
- package/dist/chunk-AP5NLUSB.js +258 -0
- package/dist/chunk-AP5NLUSB.js.map +1 -0
- package/dist/chunk-C37YQQI7.js +221 -0
- package/dist/chunk-C37YQQI7.js.map +1 -0
- package/dist/chunk-DCLVXFVH.js +225 -0
- package/dist/chunk-DCLVXFVH.js.map +1 -0
- package/dist/chunk-DZMWWDFD.js +223 -0
- package/dist/chunk-DZMWWDFD.js.map +1 -0
- package/dist/chunk-GCQZ4FHI.js +245 -0
- package/dist/chunk-GCQZ4FHI.js.map +1 -0
- package/dist/chunk-IPP44XY6.js +47 -0
- package/dist/chunk-IPP44XY6.js.map +1 -0
- package/dist/chunk-IW7FTQQX.js +267 -0
- package/dist/chunk-IW7FTQQX.js.map +1 -0
- package/dist/chunk-JX4YSCBH.js +428 -0
- package/dist/chunk-JX4YSCBH.js.map +1 -0
- package/dist/chunk-KX6UYWWR.js +229 -0
- package/dist/chunk-KX6UYWWR.js.map +1 -0
- package/dist/chunk-LWVETFJV.js +46 -0
- package/dist/chunk-LWVETFJV.js.map +1 -0
- package/dist/chunk-MCL2MCA2.js +285 -0
- package/dist/chunk-MCL2MCA2.js.map +1 -0
- package/dist/chunk-MZXCF35B.js +205 -0
- package/dist/chunk-MZXCF35B.js.map +1 -0
- package/dist/chunk-NCGPUFWV.js +96 -0
- package/dist/chunk-NCGPUFWV.js.map +1 -0
- package/dist/chunk-OEJMIE2Q.js +351 -0
- package/dist/chunk-OEJMIE2Q.js.map +1 -0
- package/dist/chunk-OYF2OAKS.js +394 -0
- package/dist/chunk-OYF2OAKS.js.map +1 -0
- package/dist/chunk-P6S43FYZ.js +316 -0
- package/dist/chunk-P6S43FYZ.js.map +1 -0
- package/dist/chunk-PL37KFRJ.js +3 -0
- package/dist/chunk-PL37KFRJ.js.map +1 -0
- package/dist/chunk-Q7BS5QC5.js +197 -0
- package/dist/chunk-Q7BS5QC5.js.map +1 -0
- package/dist/chunk-SDYPG3JD.js +288 -0
- package/dist/chunk-SDYPG3JD.js.map +1 -0
- package/dist/chunk-SUG56SZO.js +256 -0
- package/dist/chunk-SUG56SZO.js.map +1 -0
- package/dist/chunk-UVH5XJRP.js +164 -0
- package/dist/chunk-UVH5XJRP.js.map +1 -0
- package/dist/chunk-WZIJKCL3.js +282 -0
- package/dist/chunk-WZIJKCL3.js.map +1 -0
- package/dist/chunk-Y22AMGTM.js +3 -0
- package/dist/chunk-Y22AMGTM.js.map +1 -0
- package/dist/chunk-Z7G23XWU.js +200 -0
- package/dist/chunk-Z7G23XWU.js.map +1 -0
- package/dist/chunk-ZJU5M4IB.js +125 -0
- package/dist/chunk-ZJU5M4IB.js.map +1 -0
- package/dist/chunk-ZVC3ZWLM.js +52 -0
- package/dist/chunk-ZVC3ZWLM.js.map +1 -0
- package/dist/chunk-ZZZML7Y3.js +310 -0
- package/dist/chunk-ZZZML7Y3.js.map +1 -0
- package/dist/client.d.ts +25 -0
- package/dist/client.js +16 -0
- package/dist/client.js.map +1 -0
- package/dist/config/index.d.ts +170 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/errors/index.d.ts +267 -0
- package/dist/errors/index.js +4 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/file-router/index.d.ts +184 -0
- package/dist/file-router/index.js +3 -0
- package/dist/file-router/index.js.map +1 -0
- package/dist/file-router/streaming-hints.d.ts +129 -0
- package/dist/file-router/streaming-hints.js +3 -0
- package/dist/file-router/streaming-hints.js.map +1 -0
- package/dist/handlers/index.d.ts +59 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/index.d.ts +588 -0
- package/dist/index.js +886 -0
- package/dist/index.js.map +1 -0
- package/dist/islands/index.d.ts +234 -0
- package/dist/islands/index.js +3 -0
- package/dist/islands/index.js.map +1 -0
- package/dist/middleware/index.d.ts +305 -0
- package/dist/middleware/index.js +3 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/react/index.d.ts +73 -0
- package/dist/react/index.js +52 -0
- package/dist/react/index.js.map +1 -0
- package/dist/render/index.d.ts +131 -0
- package/dist/render/index.js +3 -0
- package/dist/render/index.js.map +1 -0
- package/dist/router/index.d.ts +65 -0
- package/dist/router/index.js +3 -0
- package/dist/router/index.js.map +1 -0
- package/dist/rsc/adapters/index.d.ts +8 -0
- package/dist/rsc/adapters/index.js +7 -0
- package/dist/rsc/adapters/index.js.map +1 -0
- package/dist/rsc/adapters/preact.d.ts +97 -0
- package/dist/rsc/adapters/preact.js +3 -0
- package/dist/rsc/adapters/preact.js.map +1 -0
- package/dist/rsc/adapters/react.d.ts +82 -0
- package/dist/rsc/adapters/react.js +3 -0
- package/dist/rsc/adapters/react.js.map +1 -0
- package/dist/rsc/adapters/solid.d.ts +84 -0
- package/dist/rsc/adapters/solid.js +3 -0
- package/dist/rsc/adapters/solid.js.map +1 -0
- package/dist/rsc/adapters/vue.d.ts +80 -0
- package/dist/rsc/adapters/vue.js +3 -0
- package/dist/rsc/adapters/vue.js.map +1 -0
- package/dist/rsc/boundaries.d.ts +182 -0
- package/dist/rsc/boundaries.js +3 -0
- package/dist/rsc/boundaries.js.map +1 -0
- package/dist/rsc/context.d.ts +201 -0
- package/dist/rsc/context.js +3 -0
- package/dist/rsc/context.js.map +1 -0
- package/dist/rsc/index.d.ts +232 -0
- package/dist/rsc/index.js +15 -0
- package/dist/rsc/index.js.map +1 -0
- package/dist/rsc/legacy.d.ts +155 -0
- package/dist/rsc/legacy.js +3 -0
- package/dist/rsc/legacy.js.map +1 -0
- package/dist/rsc/payload.d.ts +262 -0
- package/dist/rsc/payload.js +3 -0
- package/dist/rsc/payload.js.map +1 -0
- package/dist/rsc/plugins/esbuild.d.ts +124 -0
- package/dist/rsc/plugins/esbuild.js +4 -0
- package/dist/rsc/plugins/esbuild.js.map +1 -0
- package/dist/rsc/plugins/index.d.ts +4 -0
- package/dist/rsc/plugins/index.js +6 -0
- package/dist/rsc/plugins/index.js.map +1 -0
- package/dist/rsc/plugins/rollup.d.ts +103 -0
- package/dist/rsc/plugins/rollup.js +4 -0
- package/dist/rsc/plugins/rollup.js.map +1 -0
- package/dist/rsc/renderer.d.ts +162 -0
- package/dist/rsc/renderer.js +5 -0
- package/dist/rsc/renderer.js.map +1 -0
- package/dist/rsc/stream.d.ts +129 -0
- package/dist/rsc/stream.js +3 -0
- package/dist/rsc/stream.js.map +1 -0
- package/dist/rsc/vite-plugin.d.ts +78 -0
- package/dist/rsc/vite-plugin.js +4 -0
- package/dist/rsc/vite-plugin.js.map +1 -0
- package/dist/server/index.d.ts +135 -0
- package/dist/server/index.js +6 -0
- package/dist/server/index.js.map +1 -0
- package/dist/streaming/adapters/index.d.ts +223 -0
- package/dist/streaming/adapters/index.js +3 -0
- package/dist/streaming/adapters/index.js.map +1 -0
- package/dist/streaming/conditional.d.ts +130 -0
- package/dist/streaming/conditional.js +3 -0
- package/dist/streaming/conditional.js.map +1 -0
- package/dist/streaming/index.d.ts +177 -0
- package/dist/streaming/index.js +3 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming/observability.d.ts +201 -0
- package/dist/streaming/observability.js +4 -0
- package/dist/streaming/observability.js.map +1 -0
- package/dist/streaming/priority.d.ts +103 -0
- package/dist/streaming/priority.js +3 -0
- package/dist/streaming/priority.js.map +1 -0
- package/dist/utils/index.d.ts +42 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- 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 };
|