@spfn/core 0.2.0-beta.5 → 0.2.0-beta.50

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 (64) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +181 -1281
  3. package/dist/{boss-BO8ty33K.d.ts → boss-Cxqc-Oiw.d.ts} +37 -7
  4. package/dist/cache/index.js +32 -29
  5. package/dist/cache/index.js.map +1 -1
  6. package/dist/codegen/index.d.ts +55 -8
  7. package/dist/codegen/index.js +179 -5
  8. package/dist/codegen/index.js.map +1 -1
  9. package/dist/config/index.d.ts +168 -6
  10. package/dist/config/index.js +29 -5
  11. package/dist/config/index.js.map +1 -1
  12. package/dist/db/index.d.ts +218 -4
  13. package/dist/db/index.js +351 -57
  14. package/dist/db/index.js.map +1 -1
  15. package/dist/env/index.d.ts +2 -1
  16. package/dist/env/index.js +2 -1
  17. package/dist/env/index.js.map +1 -1
  18. package/dist/env/loader.d.ts +26 -19
  19. package/dist/env/loader.js +32 -25
  20. package/dist/env/loader.js.map +1 -1
  21. package/dist/errors/index.js.map +1 -1
  22. package/dist/event/index.d.ts +33 -3
  23. package/dist/event/index.js +17 -1
  24. package/dist/event/index.js.map +1 -1
  25. package/dist/event/sse/client.d.ts +42 -3
  26. package/dist/event/sse/client.js +128 -45
  27. package/dist/event/sse/client.js.map +1 -1
  28. package/dist/event/sse/index.d.ts +12 -5
  29. package/dist/event/sse/index.js +188 -20
  30. package/dist/event/sse/index.js.map +1 -1
  31. package/dist/event/ws/client.d.ts +59 -0
  32. package/dist/event/ws/client.js +273 -0
  33. package/dist/event/ws/client.js.map +1 -0
  34. package/dist/event/ws/index.d.ts +94 -0
  35. package/dist/event/ws/index.js +213 -0
  36. package/dist/event/ws/index.js.map +1 -0
  37. package/dist/job/index.d.ts +23 -8
  38. package/dist/job/index.js +154 -44
  39. package/dist/job/index.js.map +1 -1
  40. package/dist/logger/index.d.ts +5 -0
  41. package/dist/logger/index.js +14 -0
  42. package/dist/logger/index.js.map +1 -1
  43. package/dist/middleware/index.d.ts +23 -1
  44. package/dist/middleware/index.js +58 -5
  45. package/dist/middleware/index.js.map +1 -1
  46. package/dist/nextjs/index.d.ts +2 -2
  47. package/dist/nextjs/index.js +77 -31
  48. package/dist/nextjs/index.js.map +1 -1
  49. package/dist/nextjs/server.d.ts +44 -23
  50. package/dist/nextjs/server.js +83 -65
  51. package/dist/nextjs/server.js.map +1 -1
  52. package/dist/route/index.d.ts +158 -4
  53. package/dist/route/index.js +238 -22
  54. package/dist/route/index.js.map +1 -1
  55. package/dist/server/index.d.ts +308 -17
  56. package/dist/server/index.js +1128 -261
  57. package/dist/server/index.js.map +1 -1
  58. package/dist/{router-Di7ENoah.d.ts → token-manager-CyG7la3p.d.ts} +116 -1
  59. package/dist/{types-D_N_U-Py.d.ts → types-7Mhoxnnt.d.ts} +21 -1
  60. package/dist/types-C1jMLGwK.d.ts +257 -0
  61. package/dist/types-Cfj--lfr.d.ts +151 -0
  62. package/docs/file-upload.md +717 -0
  63. package/package.json +18 -5
  64. package/dist/types-B-e_f2dQ.d.ts +0 -121
@@ -148,4 +148,119 @@ type InferEventPayloads<T extends EventRouterDef<any>> = T['_types'];
148
148
  */
149
149
  declare function defineEventRouter<TEvents extends Record<string, EventDef<any>>>(events: TEvents): EventRouterDef<TEvents>;
150
150
 
151
- export { type EventRouterDef as E, type InferEventNames as I, type JobQueueSender as J, type PubSubCache as P, type EventDef as a, type InferEventPayload as b, type InferEventPayloads as c, defineEventRouter as d, type EventHandler as e, type InferEventPayload$1 as f };
151
+ /**
152
+ * SSE Token Manager
153
+ *
154
+ * Auth-agnostic token issuance and verification for SSE connections.
155
+ * Issues one-time-use tokens with TTL for Token Exchange pattern.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const manager = new SSETokenManager({ ttl: 30000 });
160
+ *
161
+ * // Issue token for authenticated user
162
+ * const token = await manager.issue('user-123');
163
+ *
164
+ * // Verify and consume token (one-time use)
165
+ * const subject = await manager.verify(token); // 'user-123'
166
+ * const again = await manager.verify(token); // null (already consumed)
167
+ *
168
+ * // Cleanup on shutdown
169
+ * manager.destroy();
170
+ * ```
171
+ */
172
+ /**
173
+ * Minimal cache client interface (compatible with ioredis Redis | Cluster)
174
+ */
175
+ type CacheClient = {
176
+ set(key: string, value: string, ...args: any[]): Promise<any>;
177
+ getdel?(key: string): Promise<string | null>;
178
+ get(key: string): Promise<string | null>;
179
+ del(...keys: string[]): Promise<number>;
180
+ };
181
+ /**
182
+ * Stored SSE token data
183
+ */
184
+ interface SSEToken {
185
+ token: string;
186
+ subject: string;
187
+ expiresAt: number;
188
+ }
189
+ /**
190
+ * Token storage interface
191
+ *
192
+ * Implement this for custom storage backends (e.g., Redis for multi-instance).
193
+ */
194
+ interface SSETokenStore {
195
+ /** Store a token */
196
+ set(token: string, data: SSEToken): Promise<void>;
197
+ /** Get and delete a token (one-time use) */
198
+ consume(token: string): Promise<SSEToken | null>;
199
+ /** Remove expired tokens */
200
+ cleanup(): Promise<void>;
201
+ }
202
+ /**
203
+ * SSETokenManager configuration
204
+ */
205
+ interface SSETokenManagerConfig {
206
+ /**
207
+ * Token time-to-live in milliseconds
208
+ * @default 30000
209
+ */
210
+ ttl?: number;
211
+ /**
212
+ * Custom token store (default: in-memory Map)
213
+ */
214
+ store?: SSETokenStore;
215
+ /**
216
+ * Cleanup interval in milliseconds
217
+ * @default 60000
218
+ */
219
+ cleanupInterval?: number;
220
+ }
221
+ /**
222
+ * Redis/Valkey-backed token store for multi-instance deployments.
223
+ *
224
+ * Uses SET EX for automatic TTL expiry and GETDEL for atomic one-time consumption.
225
+ * No cleanup needed — Redis handles expiration automatically.
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * import { getCache } from '@spfn/core/cache';
230
+ *
231
+ * const cache = getCache();
232
+ * if (cache) {
233
+ * const store = new CacheTokenStore(cache);
234
+ * const manager = new SSETokenManager({ store });
235
+ * }
236
+ * ```
237
+ */
238
+ declare class CacheTokenStore implements SSETokenStore {
239
+ private cache;
240
+ private prefix;
241
+ constructor(cache: CacheClient);
242
+ set(token: string, data: SSEToken): Promise<void>;
243
+ consume(token: string): Promise<SSEToken | null>;
244
+ cleanup(): Promise<void>;
245
+ }
246
+ declare class SSETokenManager {
247
+ private store;
248
+ private ttl;
249
+ private cleanupTimer;
250
+ constructor(config?: SSETokenManagerConfig);
251
+ /**
252
+ * Issue a new one-time-use token for the given subject
253
+ */
254
+ issue(subject: string): Promise<string>;
255
+ /**
256
+ * Verify and consume a token
257
+ * @returns subject string if valid, null if invalid/expired/already consumed
258
+ */
259
+ verify(token: string): Promise<string | null>;
260
+ /**
261
+ * Cleanup timer and resources
262
+ */
263
+ destroy(): void;
264
+ }
265
+
266
+ export { CacheTokenStore as C, type EventRouterDef as E, type InferEventNames as I, type JobQueueSender as J, type PubSubCache as P, SSETokenManager as S, type EventDef as a, type InferEventPayload as b, type InferEventPayloads as c, defineEventRouter as d, type EventHandler as e, type InferEventPayload$1 as f, type SSEToken as g, type SSETokenStore as h, type SSETokenManagerConfig as i };
@@ -2,6 +2,20 @@ import { TSchema, Static } from '@sinclair/typebox';
2
2
  import { ErrorRegistry, ErrorRegistryInput } from '@spfn/core/errors';
3
3
  import { RouteDef, RouteInput } from '@spfn/core/route';
4
4
 
5
+ /**
6
+ * Convert File types in schema to actual File for client usage
7
+ *
8
+ * TypeBox File schemas become actual File objects on the client side.
9
+ */
10
+ type ConvertFileTypes<T> = T extends File ? File : T extends File[] ? File[] : T;
11
+ /**
12
+ * Extract form data input type with File support
13
+ *
14
+ * Maps schema types to runtime types, converting FileSchema to File.
15
+ */
16
+ type FormDataInput<T> = {
17
+ [K in keyof T]: ConvertFileTypes<T[K]>;
18
+ };
5
19
  /**
6
20
  * Extract structured input from RouteInput
7
21
  *
@@ -11,6 +25,7 @@ type StructuredInput<TInput extends RouteInput> = {
11
25
  params: TInput['params'] extends TSchema ? Static<TInput['params']> : {};
12
26
  query: TInput['query'] extends TSchema ? Static<TInput['query']> : {};
13
27
  body: TInput['body'] extends TSchema ? Static<TInput['body']> : {};
28
+ formData: TInput['formData'] extends TSchema ? FormDataInput<Static<TInput['formData']>> : {};
14
29
  headers: TInput['headers'] extends TSchema ? Static<TInput['headers']> : {};
15
30
  cookies: TInput['cookies'] extends TSchema ? Static<TInput['cookies']> : {};
16
31
  };
@@ -144,7 +159,7 @@ interface ApiConfig {
144
159
  /**
145
160
  * Request timeout in milliseconds
146
161
  *
147
- * @default 30000
162
+ * @default env.SERVER_TIMEOUT (120000)
148
163
  */
149
164
  timeout?: number;
150
165
  /**
@@ -187,6 +202,11 @@ interface ApiConfig {
187
202
  * Per-call options
188
203
  */
189
204
  interface CallOptions {
205
+ /**
206
+ * Request timeout in milliseconds
207
+ * Overrides the global timeout set in ApiConfig
208
+ */
209
+ timeout?: number;
190
210
  /**
191
211
  * Additional headers for this request
192
212
  */
@@ -0,0 +1,257 @@
1
+ import { Context } from 'hono';
2
+ import { h as SSETokenStore, S as SSETokenManager, E as EventRouterDef, I as InferEventNames, b as InferEventPayload } from './token-manager-CyG7la3p.js';
3
+
4
+ /**
5
+ * SSE Types
6
+ *
7
+ * Type definitions for Server-Sent Events
8
+ */
9
+
10
+ /**
11
+ * SSE message sent from server
12
+ */
13
+ interface SSEMessage<TEvent extends string = string, TPayload = unknown> {
14
+ /** Event name */
15
+ event: TEvent;
16
+ /** Event payload */
17
+ data: TPayload;
18
+ /** Optional message ID for reconnection */
19
+ id?: string;
20
+ }
21
+ /**
22
+ * SSE auth configuration (internal, non-generic)
23
+ *
24
+ * Stored in SSEHandlerConfig. Generic user-facing version is SSEAuthConfig.
25
+ */
26
+ interface SSEHandlerAuthConfig {
27
+ /**
28
+ * Enable SSE token authentication
29
+ * @default false
30
+ */
31
+ enabled?: boolean;
32
+ /**
33
+ * Token TTL in milliseconds
34
+ * @default 30000
35
+ */
36
+ tokenTtl?: number;
37
+ /**
38
+ * Custom token store (e.g., Redis for multi-instance)
39
+ */
40
+ store?: SSETokenStore;
41
+ /**
42
+ * External token manager instance or lazy resolver.
43
+ *
44
+ * When provided, the SSE system uses this manager instead of creating its own.
45
+ * Useful for sharing a single token manager with auth package's one-time token system.
46
+ *
47
+ * Use a function when the manager is not available at module load time
48
+ * (e.g. initialized in a lifecycle hook that runs after config evaluation).
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * import { getOneTimeTokenManager } from '@spfn/auth/server';
53
+ *
54
+ * // Lazy resolver (recommended — avoids timing issues)
55
+ * .events(eventRouter, {
56
+ * auth: {
57
+ * enabled: true,
58
+ * tokenManager: () => getOneTimeTokenManager(),
59
+ * },
60
+ * })
61
+ * ```
62
+ */
63
+ tokenManager?: SSETokenManager | (() => SSETokenManager);
64
+ /**
65
+ * Extract subject (user ID) from Hono context
66
+ * @default (c) => c.get('auth')?.userId ?? null
67
+ */
68
+ getSubject?: (c: Context) => string | null;
69
+ /**
70
+ * Subscription authorization hook (called once on connect)
71
+ *
72
+ * Return allowed events subset. Empty array = 403 rejection.
73
+ */
74
+ authorize?: (subject: string, events: string[]) => Promise<string[]> | string[];
75
+ /**
76
+ * Per-event payload filter map (called on every event emission)
77
+ *
78
+ * Return false to skip sending the event to this user.
79
+ */
80
+ filter?: Record<string, (subject: string, payload: unknown) => boolean>;
81
+ }
82
+ /**
83
+ * SSE auth configuration (user-facing, generic)
84
+ *
85
+ * Provides type-safe event names and payload inference from EventRouter.
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * .events(eventRouter, {
90
+ * auth: {
91
+ * enabled: true,
92
+ * authorize: async (subject, events) => {
93
+ * // events: ('userCreated' | 'orderUpdated')[]
94
+ * return events.filter(e => hasPermission(subject, e));
95
+ * },
96
+ * filter: {
97
+ * orderUpdated: (subject, payload) => {
98
+ * // payload: { orderId: string; userId: string }
99
+ * return payload.userId === subject;
100
+ * },
101
+ * },
102
+ * },
103
+ * })
104
+ * ```
105
+ */
106
+ interface SSEAuthConfig<TRouter extends EventRouterDef<any>> {
107
+ enabled?: boolean;
108
+ tokenTtl?: number;
109
+ store?: SSETokenStore;
110
+ tokenManager?: SSETokenManager | (() => SSETokenManager);
111
+ getSubject?: (c: Context) => string | null;
112
+ authorize?: (subject: string, events: InferEventNames<TRouter>[]) => Promise<InferEventNames<TRouter>[]> | InferEventNames<TRouter>[];
113
+ filter?: {
114
+ [K in InferEventNames<TRouter>]?: (subject: string, payload: InferEventPayload<TRouter, K>) => boolean;
115
+ };
116
+ }
117
+ /**
118
+ * SSE Handler configuration
119
+ */
120
+ interface SSEHandlerConfig {
121
+ /**
122
+ * Keep-alive ping interval in milliseconds
123
+ * @default 30000
124
+ */
125
+ pingInterval?: number;
126
+ /**
127
+ * Custom headers for SSE response
128
+ */
129
+ headers?: Record<string, string>;
130
+ /**
131
+ * Authentication and authorization configuration
132
+ */
133
+ auth?: SSEHandlerAuthConfig;
134
+ }
135
+ /**
136
+ * SSE Client configuration
137
+ */
138
+ interface SSEClientConfig {
139
+ /**
140
+ * Backend API host URL
141
+ * @default NEXT_PUBLIC_SPFN_API_URL || 'http://localhost:8790'
142
+ * @example 'http://localhost:8790'
143
+ * @example 'https://api.example.com'
144
+ */
145
+ host?: string;
146
+ /**
147
+ * SSE endpoint pathname
148
+ * @default '/events/stream'
149
+ */
150
+ pathname?: string;
151
+ /**
152
+ * Full URL (overrides host + pathname)
153
+ * @deprecated Use host and pathname instead
154
+ * @example 'http://localhost:8790/events/stream'
155
+ */
156
+ url?: string;
157
+ /**
158
+ * Auto reconnect on disconnect
159
+ * @default true
160
+ */
161
+ reconnect?: boolean;
162
+ /**
163
+ * Reconnect delay in milliseconds
164
+ * @default 3000
165
+ */
166
+ reconnectDelay?: number;
167
+ /**
168
+ * Maximum reconnect attempts (0 = infinite)
169
+ * @default 0
170
+ */
171
+ maxReconnectAttempts?: number;
172
+ /**
173
+ * Include credentials (cookies) in request
174
+ * @default false
175
+ */
176
+ withCredentials?: boolean;
177
+ /**
178
+ * Acquire a one-time SSE token before connecting.
179
+ *
180
+ * Called on every (re)connect. The returned token is appended
181
+ * to the SSE URL as `?token=...`.
182
+ *
183
+ * For automatic token acquisition via RPC proxy, use `createAuthSSEClient` instead.
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * // Recommended: use createAuthSSEClient for automatic token handling
188
+ * import { createAuthSSEClient } from '@spfn/core/event/sse/client';
189
+ * const client = createAuthSSEClient<EventRouter>();
190
+ *
191
+ * // Manual: provide acquireToken directly
192
+ * acquireToken: async () => {
193
+ * const res = await fetch('/api/rpc/eventsToken', {
194
+ * method: 'POST',
195
+ * credentials: 'include',
196
+ * });
197
+ * const data = await res.json();
198
+ * return data.token;
199
+ * }
200
+ * ```
201
+ */
202
+ acquireToken?: () => Promise<string>;
203
+ }
204
+ /**
205
+ * Event handler function
206
+ */
207
+ type SSEEventHandler<TPayload> = (payload: TPayload) => void;
208
+ /**
209
+ * Event handlers map for EventRouter
210
+ */
211
+ type SSEEventHandlers<TRouter extends EventRouterDef<any>> = {
212
+ [K in InferEventNames<TRouter>]?: SSEEventHandler<InferEventPayload<TRouter, K>>;
213
+ };
214
+ /**
215
+ * Subscription options
216
+ */
217
+ interface SSESubscribeOptions<TRouter extends EventRouterDef<any>> {
218
+ /**
219
+ * Events to subscribe
220
+ */
221
+ events: InferEventNames<TRouter>[];
222
+ /**
223
+ * Event handlers
224
+ */
225
+ handlers: SSEEventHandlers<TRouter>;
226
+ /**
227
+ * Called when connection opens
228
+ */
229
+ onOpen?: () => void;
230
+ /**
231
+ * Called on connection error
232
+ */
233
+ onError?: (error: Event) => void;
234
+ /**
235
+ * Called when connection is permanently closed
236
+ *
237
+ * Triggered when:
238
+ * - unsubscribe() is called
239
+ * - client.close() is called
240
+ * - Max reconnect attempts exceeded
241
+ */
242
+ onClose?: () => void;
243
+ /**
244
+ * Called when reconnecting
245
+ */
246
+ onReconnect?: (attempt: number) => void;
247
+ }
248
+ /**
249
+ * SSE connection state
250
+ */
251
+ type SSEConnectionState = 'connecting' | 'open' | 'closed' | 'error';
252
+ /**
253
+ * Unsubscribe function
254
+ */
255
+ type SSEUnsubscribe = () => void;
256
+
257
+ export type { SSEHandlerConfig as S, SSEAuthConfig as a, SSEMessage as b, SSEHandlerAuthConfig as c, SSEClientConfig as d, SSEEventHandler as e, SSEEventHandlers as f, SSESubscribeOptions as g, SSEConnectionState as h, SSEUnsubscribe as i };
@@ -0,0 +1,151 @@
1
+ import { Context } from 'hono';
2
+ import { a as EventDef, E as EventRouterDef, h as SSETokenStore, S as SSETokenManager, I as InferEventNames, b as InferEventPayload } from './token-manager-CyG7la3p.js';
3
+
4
+ /**
5
+ * WebSocket Types
6
+ */
7
+
8
+ /**
9
+ * WebSocket Router Definition
10
+ *
11
+ * Extends EventRouterDef with client→server message handlers.
12
+ */
13
+ interface WSRouterDef<TEvents extends Record<string, EventDef<any>>, TMessages extends WSMessageHandlers = WSMessageHandlers> extends EventRouterDef<TEvents> {
14
+ messages: TMessages;
15
+ }
16
+ /**
17
+ * Low-level WS connection handle passed to message handlers
18
+ */
19
+ interface WSRawConnection {
20
+ send(type: string, payload: unknown): void;
21
+ close(code?: number, reason?: string): void;
22
+ }
23
+ /**
24
+ * Context passed to each client→server message handler
25
+ */
26
+ interface WSMessageContext<TPayload = unknown> {
27
+ payload: TPayload;
28
+ subject?: string;
29
+ ws: WSRawConnection;
30
+ }
31
+ /**
32
+ * Single message handler function
33
+ */
34
+ type WSMessageHandlerFn<TPayload = unknown> = (ctx: WSMessageContext<TPayload>) => void | Promise<void>;
35
+ /**
36
+ * Map of message type name → handler
37
+ */
38
+ type WSMessageHandlers = Record<string, WSMessageHandlerFn<any>>;
39
+ /**
40
+ * WebSocket auth configuration (internal, non-generic)
41
+ */
42
+ interface WSHandlerAuthConfig {
43
+ enabled?: boolean;
44
+ tokenTtl?: number;
45
+ store?: SSETokenStore;
46
+ tokenManager?: SSETokenManager | (() => SSETokenManager);
47
+ /**
48
+ * Extract subject from Hono context (used on token-issue endpoint)
49
+ * @default (c) => c.get('auth')?.userId ?? null
50
+ */
51
+ getSubject?: (c: Context) => string | null;
52
+ /**
53
+ * Authorize event subscriptions on connect
54
+ * Return allowed events subset. Empty array = 403 rejection.
55
+ */
56
+ authorize?: (subject: string, events: string[]) => Promise<string[]> | string[];
57
+ /**
58
+ * Per-event payload filter (called on every emission)
59
+ * Return false to skip sending the event to this client.
60
+ */
61
+ filter?: Record<string, (subject: string, payload: unknown) => boolean>;
62
+ }
63
+ /**
64
+ * WebSocket auth configuration (user-facing, generic)
65
+ */
66
+ interface WSAuthConfig<TRouter extends WSRouterDef<any, any>> {
67
+ enabled?: boolean;
68
+ tokenTtl?: number;
69
+ store?: SSETokenStore;
70
+ tokenManager?: SSETokenManager | (() => SSETokenManager);
71
+ getSubject?: (c: Context) => string | null;
72
+ authorize?: (subject: string, events: InferEventNames<TRouter>[]) => Promise<InferEventNames<TRouter>[]> | InferEventNames<TRouter>[];
73
+ filter?: {
74
+ [K in InferEventNames<TRouter>]?: (subject: string, payload: InferEventPayload<TRouter, K>) => boolean;
75
+ };
76
+ }
77
+ /**
78
+ * Configuration for the WebSocket server handler
79
+ */
80
+ interface WSHandlerConfig {
81
+ /**
82
+ * Keep-alive ping interval in ms
83
+ * @default 30000
84
+ */
85
+ pingInterval?: number;
86
+ /**
87
+ * Authentication and authorization configuration
88
+ */
89
+ auth?: WSHandlerAuthConfig;
90
+ }
91
+ /**
92
+ * WebSocket client configuration
93
+ */
94
+ interface WSClientConfig {
95
+ /**
96
+ * Backend API host URL (ws:// or wss://)
97
+ * @default derived from NEXT_PUBLIC_SPFN_API_URL
98
+ */
99
+ host?: string;
100
+ /**
101
+ * WS endpoint pathname
102
+ * @default '/ws'
103
+ */
104
+ pathname?: string;
105
+ /**
106
+ * Auto reconnect on disconnect
107
+ * @default true
108
+ */
109
+ reconnect?: boolean;
110
+ /**
111
+ * Reconnect delay in ms
112
+ * @default 3000
113
+ */
114
+ reconnectDelay?: number;
115
+ /**
116
+ * Maximum reconnect attempts (0 = infinite)
117
+ * @default 0
118
+ */
119
+ maxReconnectAttempts?: number;
120
+ /**
121
+ * Acquire a one-time token before connecting
122
+ */
123
+ acquireToken?: () => Promise<string>;
124
+ }
125
+ /**
126
+ * WebSocket connection state
127
+ */
128
+ type WSConnectionState = 'connecting' | 'open' | 'closed' | 'error';
129
+ /**
130
+ * Event handlers map for WSRouterDef
131
+ */
132
+ type WSEventHandlers<TRouter extends WSRouterDef<any, any>> = {
133
+ [K in InferEventNames<TRouter>]?: (payload: InferEventPayload<TRouter, K>) => void;
134
+ };
135
+ /**
136
+ * Subscribe options
137
+ */
138
+ interface WSSubscribeOptions<TRouter extends WSRouterDef<any, any>> {
139
+ events: InferEventNames<TRouter>[];
140
+ handlers: WSEventHandlers<TRouter>;
141
+ onOpen?: () => void;
142
+ onError?: (error: Event) => void;
143
+ onClose?: () => void;
144
+ onReconnect?: (attempt: number) => void;
145
+ }
146
+ /**
147
+ * Unsubscribe function
148
+ */
149
+ type WSUnsubscribe = () => void;
150
+
151
+ export type { WSRouterDef as W, WSHandlerConfig as a, WSMessageHandlers as b, WSAuthConfig as c, WSHandlerAuthConfig as d, WSMessageContext as e, WSMessageHandlerFn as f, WSRawConnection as g, WSClientConfig as h, WSConnectionState as i, WSEventHandlers as j, WSSubscribeOptions as k, WSUnsubscribe as l };