@spfn/core 0.3.0-beta.3 → 0.3.0-beta.30
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/README.md +301 -10
- package/dist/app-config/index.d.ts +39 -1
- package/dist/app-config/index.js.map +1 -1
- package/dist/authz/index.js +47 -391
- package/dist/authz/index.js.map +1 -1
- package/dist/{boss-D16fO2oG.d.ts → boss-BiDCbbAQ.d.ts} +60 -7
- package/dist/codegen/index.d.ts +157 -16
- package/dist/codegen/index.js +772 -166
- package/dist/codegen/index.js.map +1 -1
- package/dist/config/index.js +4 -4
- package/dist/config/index.js.map +1 -1
- package/dist/contract/index.d.ts +39 -16
- package/dist/contract/index.js +147 -23
- package/dist/contract/index.js.map +1 -1
- package/dist/db/index.d.ts +230 -35
- package/dist/db/index.js +316 -160
- package/dist/db/index.js.map +1 -1
- package/dist/env/index.d.ts +6 -442
- package/dist/env/index.js +13 -16
- package/dist/env/index.js.map +1 -1
- package/dist/env/loader.js +24 -1
- package/dist/env/loader.js.map +1 -1
- package/dist/error-CIZlYJlL.d.ts +157 -0
- package/dist/errors/index.d.ts +18 -1
- package/dist/errors/index.js +47 -391
- package/dist/errors/index.js.map +1 -1
- package/dist/event/index.d.ts +5 -5
- package/dist/event/index.js +202 -3
- package/dist/event/index.js.map +1 -1
- package/dist/event/sse/client.d.ts +18 -4
- package/dist/event/sse/client.js +94 -18
- package/dist/event/sse/client.js.map +1 -1
- package/dist/event/sse/index.d.ts +18 -5
- package/dist/event/sse/index.js +452 -114
- package/dist/event/sse/index.js.map +1 -1
- package/dist/event/ws/client.d.ts +3 -2
- package/dist/event/ws/index.d.ts +4 -3
- package/dist/job/index.d.ts +48 -3
- package/dist/job/index.js +131 -52
- package/dist/job/index.js.map +1 -1
- package/dist/logger/index.js +0 -12
- package/dist/logger/index.js.map +1 -1
- package/dist/middleware/index.js +52 -397
- package/dist/middleware/index.js.map +1 -1
- package/dist/nextjs/index.d.ts +75 -14
- package/dist/nextjs/index.js +200 -84
- package/dist/nextjs/index.js.map +1 -1
- package/dist/nextjs/server.d.ts +46 -8
- package/dist/nextjs/server.js +15 -1
- package/dist/nextjs/server.js.map +1 -1
- package/dist/ops/index.d.ts +61 -42
- package/dist/ops/index.js +648 -97
- package/dist/ops/index.js.map +1 -1
- package/dist/registry-C2KQCh0m.d.ts +473 -0
- package/dist/route/index.d.ts +5 -2
- package/dist/route/index.js +107 -28
- package/dist/route/index.js.map +1 -1
- package/dist/route/types.d.ts +7 -1
- package/dist/{router-Cy7rAfmj.d.ts → route-builder-DRW-MSCJ.d.ts} +51 -126
- package/dist/router-C57y-vz1.d.ts +184 -0
- package/dist/router-CX5uVjmU.d.ts +406 -0
- package/dist/server/index.d.ts +130 -7
- package/dist/server/index.js +1174 -164
- package/dist/server/index.js.map +1 -1
- package/dist/state/client.d.ts +206 -0
- package/dist/state/client.js +678 -0
- package/dist/state/client.js.map +1 -0
- package/dist/state/index.d.ts +443 -0
- package/dist/state/index.js +644 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/react.d.ts +49 -0
- package/dist/state/react.js +50 -0
- package/dist/state/react.js.map +1 -0
- package/dist/surface/index.d.ts +115 -0
- package/dist/surface/index.js +1013 -0
- package/dist/surface/index.js.map +1 -0
- package/dist/token-manager-Ckjt2-qq.d.ts +122 -0
- package/dist/{types-CfYVhIQ9.d.ts → types-5Rl11_Nb.d.ts} +43 -4
- package/dist/types-CKH0D3Dy.d.ts +441 -0
- package/dist/{types-ZQODsBft.d.ts → types-CurMab2Q.d.ts} +52 -2
- package/dist/{types-2AbaW4Ie.d.ts → types-DncqXfWN.d.ts} +4 -3
- package/docs/file-upload.md +195 -333
- package/package.json +39 -9
- package/src/cache/README.md +330 -0
- package/src/codegen/README.md +721 -0
- package/src/config/README.md +333 -0
- package/src/contract/README.md +442 -0
- package/src/db/README.md +589 -0
- package/src/db/manager/README.md +500 -0
- package/src/db/schema/README.md +354 -0
- package/src/db/transaction/README.md +845 -0
- package/src/env/README.md +787 -0
- package/src/errors/README.md +445 -0
- package/src/event/README.md +994 -0
- package/src/job/README.md +613 -0
- package/src/logger/README.md +321 -0
- package/src/middleware/README.md +634 -0
- package/src/nextjs/README.md +756 -0
- package/src/route/README.md +763 -0
- package/src/security/README.md +100 -0
- package/src/server/README.md +704 -0
- package/src/state/README.md +806 -0
- package/dist/token-manager-BT5EnUAR.d.ts +0 -278
- package/dist/types-9oszaJqp.d.ts +0 -250
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import { TSchema } from '@sinclair/typebox';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Event System Types
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Pub/Sub capable cache interface for multi-instance events
|
|
9
|
-
*/
|
|
10
|
-
interface PubSubCache {
|
|
11
|
-
/**
|
|
12
|
-
* Publish a message to a channel
|
|
13
|
-
*/
|
|
14
|
-
publish(channel: string, message: unknown): Promise<void>;
|
|
15
|
-
/**
|
|
16
|
-
* Subscribe to a channel
|
|
17
|
-
*/
|
|
18
|
-
subscribe(channel: string, handler: (message: unknown) => void | Promise<void>): Promise<void>;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Event handler function type
|
|
22
|
-
*/
|
|
23
|
-
type EventHandler<TPayload> = (payload: TPayload) => void | Promise<void>;
|
|
24
|
-
/**
|
|
25
|
-
* Job queue sender function type (used by job module)
|
|
26
|
-
*/
|
|
27
|
-
type JobQueueSender = (queueName: string, payload: unknown) => Promise<void>;
|
|
28
|
-
/**
|
|
29
|
-
* Event definition interface
|
|
30
|
-
*/
|
|
31
|
-
interface EventDef<TPayload = void> {
|
|
32
|
-
/**
|
|
33
|
-
* Unique event name
|
|
34
|
-
*/
|
|
35
|
-
readonly name: string;
|
|
36
|
-
/**
|
|
37
|
-
* TypeBox payload schema (optional)
|
|
38
|
-
*/
|
|
39
|
-
readonly schema?: TSchema;
|
|
40
|
-
/**
|
|
41
|
-
* Subscribe to this event (in-memory handler)
|
|
42
|
-
*/
|
|
43
|
-
subscribe: (handler: EventHandler<TPayload>) => () => void;
|
|
44
|
-
/**
|
|
45
|
-
* Unsubscribe all handlers
|
|
46
|
-
*/
|
|
47
|
-
unsubscribeAll: () => void;
|
|
48
|
-
/**
|
|
49
|
-
* Emit the event (triggers all subscribers and queued jobs)
|
|
50
|
-
*/
|
|
51
|
-
emit: TPayload extends void ? () => Promise<void> : (payload: TPayload) => Promise<void>;
|
|
52
|
-
/**
|
|
53
|
-
* Enable cache-based pub/sub for multi-instance support
|
|
54
|
-
* Must await before emitting events to ensure subscription is ready
|
|
55
|
-
*/
|
|
56
|
-
useCache: (cache: PubSubCache) => Promise<EventDef<TPayload>>;
|
|
57
|
-
/**
|
|
58
|
-
* Internal: Register a job queue to receive this event
|
|
59
|
-
* Called by job registration system
|
|
60
|
-
*/
|
|
61
|
-
_registerJobQueue: (queueName: string, sender: JobQueueSender) => void;
|
|
62
|
-
/**
|
|
63
|
-
* Internal: Drop the cache binding (cache + subscribed flag).
|
|
64
|
-
* Called by the event cache transport on shutdown so a later useCache can
|
|
65
|
-
* rebind a fresh cache in the same process.
|
|
66
|
-
*/
|
|
67
|
-
_resetCache: () => void;
|
|
68
|
-
/**
|
|
69
|
-
* Type inference helper
|
|
70
|
-
*/
|
|
71
|
-
_payload: TPayload;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Infer payload type from EventDef
|
|
75
|
-
*/
|
|
76
|
-
type InferEventPayload$1<TEvent> = TEvent extends EventDef<infer TPayload> ? TPayload : never;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Event Router
|
|
80
|
-
*
|
|
81
|
-
* Type-safe event router for SSE subscription
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* ```typescript
|
|
85
|
-
* import { defineEvent, defineEventRouter } from '@spfn/core/event';
|
|
86
|
-
* import { Type } from '@sinclair/typebox';
|
|
87
|
-
*
|
|
88
|
-
* const userCreated = defineEvent('user.created', Type.Object({
|
|
89
|
-
* userId: Type.String(),
|
|
90
|
-
* }));
|
|
91
|
-
*
|
|
92
|
-
* const orderPlaced = defineEvent('order.placed', Type.Object({
|
|
93
|
-
* orderId: Type.String(),
|
|
94
|
-
* amount: Type.Number(),
|
|
95
|
-
* }));
|
|
96
|
-
*
|
|
97
|
-
* export const eventRouter = defineEventRouter({
|
|
98
|
-
* userCreated,
|
|
99
|
-
* orderPlaced,
|
|
100
|
-
* });
|
|
101
|
-
*
|
|
102
|
-
* export type EventRouter = typeof eventRouter;
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Event Router Definition
|
|
108
|
-
*/
|
|
109
|
-
interface EventRouterDef<TEvents extends Record<string, EventDef<any>>> {
|
|
110
|
-
/**
|
|
111
|
-
* Event definitions
|
|
112
|
-
*/
|
|
113
|
-
readonly events: TEvents;
|
|
114
|
-
/**
|
|
115
|
-
* Event names as array
|
|
116
|
-
*/
|
|
117
|
-
readonly eventNames: (keyof TEvents)[];
|
|
118
|
-
/**
|
|
119
|
-
* Type inference helper - payload types by event name
|
|
120
|
-
*/
|
|
121
|
-
readonly _types: {
|
|
122
|
-
[K in keyof TEvents]: TEvents[K]['_payload'];
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Infer event names from EventRouter
|
|
127
|
-
*/
|
|
128
|
-
type InferEventNames<T> = T extends EventRouterDef<infer E> ? keyof E & string : never;
|
|
129
|
-
/**
|
|
130
|
-
* Infer payload type for specific event
|
|
131
|
-
*/
|
|
132
|
-
type InferEventPayload<T extends EventRouterDef<any>, K extends InferEventNames<T>> = T['_types'][K];
|
|
133
|
-
/**
|
|
134
|
-
* Infer all event payloads map
|
|
135
|
-
*/
|
|
136
|
-
type InferEventPayloads<T extends EventRouterDef<any>> = T['_types'];
|
|
137
|
-
/**
|
|
138
|
-
* Define an event router for SSE subscription
|
|
139
|
-
*
|
|
140
|
-
* @example
|
|
141
|
-
* ```typescript
|
|
142
|
-
* export const eventRouter = defineEventRouter({
|
|
143
|
-
* userCreated,
|
|
144
|
-
* orderPlaced,
|
|
145
|
-
* });
|
|
146
|
-
*
|
|
147
|
-
* // Type inference
|
|
148
|
-
* type Names = InferEventNames<typeof eventRouter>;
|
|
149
|
-
* // 'userCreated' | 'orderPlaced'
|
|
150
|
-
*
|
|
151
|
-
* type Payload = InferEventPayload<typeof eventRouter, 'userCreated'>;
|
|
152
|
-
* // { userId: string }
|
|
153
|
-
* ```
|
|
154
|
-
*/
|
|
155
|
-
declare function defineEventRouter<TEvents extends Record<string, EventDef<any>>>(events: TEvents): EventRouterDef<TEvents>;
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* SSE Token Manager
|
|
159
|
-
*
|
|
160
|
-
* Auth-agnostic token issuance and verification for SSE connections.
|
|
161
|
-
* Issues one-time-use tokens with TTL for Token Exchange pattern.
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```typescript
|
|
165
|
-
* const manager = new SSETokenManager({ ttl: 30000 });
|
|
166
|
-
*
|
|
167
|
-
* // Issue token for authenticated user
|
|
168
|
-
* const token = await manager.issue('user-123');
|
|
169
|
-
*
|
|
170
|
-
* // Verify and consume token (one-time use)
|
|
171
|
-
* const subject = await manager.verify(token); // 'user-123'
|
|
172
|
-
* const again = await manager.verify(token); // null (already consumed)
|
|
173
|
-
*
|
|
174
|
-
* // Cleanup on shutdown
|
|
175
|
-
* manager.destroy();
|
|
176
|
-
* ```
|
|
177
|
-
*/
|
|
178
|
-
/**
|
|
179
|
-
* Minimal cache client interface (compatible with ioredis Redis | Cluster)
|
|
180
|
-
*/
|
|
181
|
-
type CacheClient = {
|
|
182
|
-
set(key: string, value: string, ...args: any[]): Promise<any>;
|
|
183
|
-
getdel?(key: string): Promise<string | null>;
|
|
184
|
-
get(key: string): Promise<string | null>;
|
|
185
|
-
del(...keys: string[]): Promise<number>;
|
|
186
|
-
};
|
|
187
|
-
/**
|
|
188
|
-
* Stored SSE token data
|
|
189
|
-
*/
|
|
190
|
-
interface SSEToken {
|
|
191
|
-
subject: string;
|
|
192
|
-
expiresAt: number;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Token storage interface
|
|
196
|
-
*
|
|
197
|
-
* Implement this for custom storage backends (e.g., Redis for multi-instance).
|
|
198
|
-
*/
|
|
199
|
-
interface SSETokenStore {
|
|
200
|
-
/** Store a token */
|
|
201
|
-
set(token: string, data: SSEToken): Promise<void>;
|
|
202
|
-
/** Get and delete a token (one-time use) */
|
|
203
|
-
consume(token: string): Promise<SSEToken | null>;
|
|
204
|
-
/** Remove expired tokens */
|
|
205
|
-
cleanup(): Promise<void>;
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* SSETokenManager configuration
|
|
209
|
-
*/
|
|
210
|
-
interface SSETokenManagerConfig {
|
|
211
|
-
/**
|
|
212
|
-
* Token time-to-live in milliseconds
|
|
213
|
-
* @default 30000
|
|
214
|
-
*/
|
|
215
|
-
ttl?: number;
|
|
216
|
-
/**
|
|
217
|
-
* Custom token store (default: in-memory Map)
|
|
218
|
-
*/
|
|
219
|
-
store?: SSETokenStore;
|
|
220
|
-
/**
|
|
221
|
-
* Cleanup interval in milliseconds
|
|
222
|
-
* @default 60000
|
|
223
|
-
*/
|
|
224
|
-
cleanupInterval?: number;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Redis/Valkey-backed token store for multi-instance deployments.
|
|
228
|
-
*
|
|
229
|
-
* Uses SET EX for automatic TTL expiry and GETDEL for atomic one-time consumption.
|
|
230
|
-
* No cleanup needed — Redis handles expiration automatically.
|
|
231
|
-
*
|
|
232
|
-
* @example
|
|
233
|
-
* ```typescript
|
|
234
|
-
* import { getCache } from '@spfn/core/cache';
|
|
235
|
-
*
|
|
236
|
-
* const cache = getCache();
|
|
237
|
-
* if (cache) {
|
|
238
|
-
* const store = new CacheTokenStore(cache);
|
|
239
|
-
* const manager = new SSETokenManager({ store });
|
|
240
|
-
* }
|
|
241
|
-
* ```
|
|
242
|
-
*/
|
|
243
|
-
declare class CacheTokenStore implements SSETokenStore {
|
|
244
|
-
private cache;
|
|
245
|
-
private prefix;
|
|
246
|
-
constructor(cache: CacheClient);
|
|
247
|
-
set(token: string, data: SSEToken): Promise<void>;
|
|
248
|
-
consume(token: string): Promise<SSEToken | null>;
|
|
249
|
-
cleanup(): Promise<void>;
|
|
250
|
-
}
|
|
251
|
-
declare class SSETokenManager {
|
|
252
|
-
private store;
|
|
253
|
-
private ttl;
|
|
254
|
-
private cleanupTimer;
|
|
255
|
-
constructor(config?: SSETokenManagerConfig);
|
|
256
|
-
/**
|
|
257
|
-
* How long an issued token stays valid, in milliseconds.
|
|
258
|
-
*
|
|
259
|
-
* Exposed so a caller that has to report an expiry to its client computes the same
|
|
260
|
-
* number this manager stamps on the token, instead of assuming the default.
|
|
261
|
-
*/
|
|
262
|
-
get ttlMs(): number;
|
|
263
|
-
/**
|
|
264
|
-
* Issue a new one-time-use token for the given subject
|
|
265
|
-
*/
|
|
266
|
-
issue(subject: string): Promise<string>;
|
|
267
|
-
/**
|
|
268
|
-
* Verify and consume a token
|
|
269
|
-
* @returns subject string if valid, null if invalid/expired/already consumed
|
|
270
|
-
*/
|
|
271
|
-
verify(token: string): Promise<string | null>;
|
|
272
|
-
/**
|
|
273
|
-
* Cleanup timer and resources
|
|
274
|
-
*/
|
|
275
|
-
destroy(): void;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
export { CacheTokenStore as C, type EventDef as E, type InferEventNames as I, type JobQueueSender as J, type PubSubCache as P, SSETokenManager as S, type EventHandler as a, type EventRouterDef as b, type InferEventPayload$1 as c, type InferEventPayloads as d, type InferEventPayload as e, defineEventRouter as f, type SSEToken as g, type SSETokenManagerConfig as h, type SSETokenStore as i };
|
package/dist/types-9oszaJqp.d.ts
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import { TSchema, Static } from '@sinclair/typebox';
|
|
2
|
-
import { ErrorRegistry, ErrorRegistryInput } from '@spfn/core/errors';
|
|
3
|
-
import { RouteDef, RouteInput } from '@spfn/core/route';
|
|
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
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Extract structured input from RouteInput
|
|
21
|
-
*
|
|
22
|
-
* Converts TypeBox schemas to their static types for each input field.
|
|
23
|
-
*/
|
|
24
|
-
type StructuredInput<TInput extends RouteInput> = {
|
|
25
|
-
params: TInput['params'] extends TSchema ? Static<TInput['params']> : {};
|
|
26
|
-
query: TInput['query'] extends TSchema ? Static<TInput['query']> : {};
|
|
27
|
-
body: TInput['body'] extends TSchema ? Static<TInput['body']> : {};
|
|
28
|
-
formData: TInput['formData'] extends TSchema ? FormDataInput<Static<TInput['formData']>> : {};
|
|
29
|
-
headers: TInput['headers'] extends TSchema ? Static<TInput['headers']> : {};
|
|
30
|
-
cookies: TInput['cookies'] extends TSchema ? Static<TInput['cookies']> : {};
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Infer route input type from RouteDef
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```typescript
|
|
37
|
-
* // Server route definition
|
|
38
|
-
* const getUser = route.get('/users/:id')
|
|
39
|
-
* .input({ params: Type.Object({ id: Type.String() }) })
|
|
40
|
-
* .handler(...);
|
|
41
|
-
*
|
|
42
|
-
* // Client: extract input type
|
|
43
|
-
* type Input = InferRouteInput<typeof getUser>;
|
|
44
|
-
* // { params: { id: string }, query: {}, body: {}, ... }
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
type InferRouteInput<TRoute> = TRoute extends RouteDef<infer TInput, any, any> ? StructuredInput<TInput> : never;
|
|
48
|
-
/**
|
|
49
|
-
* Infer route output type from RouteDef
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```typescript
|
|
53
|
-
* // Server route definition
|
|
54
|
-
* const getUser = route.get('/users/:id')
|
|
55
|
-
* .handler(async (c) => {
|
|
56
|
-
* return { id: '1', name: 'John' };
|
|
57
|
-
* });
|
|
58
|
-
*
|
|
59
|
-
* // Client: extract output type
|
|
60
|
-
* type Output = InferRouteOutput<typeof getUser>;
|
|
61
|
-
* // { id: string, name: string }
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
|
-
type InferRouteOutput<TRoute> = TRoute extends RouteDef<any, any, infer TResponse> ? TResponse : never;
|
|
65
|
-
/**
|
|
66
|
-
* Extract routes from Router type
|
|
67
|
-
* Router<TRoutes> has routes in `_routes` property
|
|
68
|
-
*/
|
|
69
|
-
type ExtractRoutes<TRouter> = TRouter extends {
|
|
70
|
-
_routes: infer TRoutes;
|
|
71
|
-
} ? TRoutes : TRouter;
|
|
72
|
-
/**
|
|
73
|
-
* Extract output type for a specific route from router
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```typescript
|
|
77
|
-
* import type { RouterOutput } from '@spfn/core/nextjs';
|
|
78
|
-
* import type { AppRouter } from '@/server/router';
|
|
79
|
-
*
|
|
80
|
-
* // Get output type for a specific route
|
|
81
|
-
* type ListData = RouterOutput<AppRouter, 'listExamples'>;
|
|
82
|
-
*
|
|
83
|
-
* // Use in props
|
|
84
|
-
* interface Props {
|
|
85
|
-
* data: RouterOutput<AppRouter, 'listExamples'>;
|
|
86
|
-
* }
|
|
87
|
-
*
|
|
88
|
-
* // Extract item type from paginated response
|
|
89
|
-
* type Example = RouterOutput<AppRouter, 'listExamples'>['items'][number];
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
type RouterOutput<TRouter, K extends keyof ExtractRoutes<TRouter>> = InferRouteOutput<ExtractRoutes<TRouter>[K]>;
|
|
93
|
-
/**
|
|
94
|
-
* Extract input type for a specific route from router
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* ```typescript
|
|
98
|
-
* import type { RouterInput } from '@spfn/core/nextjs';
|
|
99
|
-
* import type { AppRouter } from '@/server/router';
|
|
100
|
-
*
|
|
101
|
-
* // Get input type for a specific route
|
|
102
|
-
* type CreateInput = RouterInput<AppRouter, 'createExample'>;
|
|
103
|
-
*
|
|
104
|
-
* // Use in function parameter
|
|
105
|
-
* function submitForm(data: RouterInput<AppRouter, 'createExample'>['body']) {
|
|
106
|
-
* // ...
|
|
107
|
-
* }
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
type RouterInput<TRouter, K extends keyof ExtractRoutes<TRouter>> = InferRouteInput<ExtractRoutes<TRouter>[K]>;
|
|
111
|
-
/**
|
|
112
|
-
* Cookie options for setCookie
|
|
113
|
-
*/
|
|
114
|
-
interface CookieOptions {
|
|
115
|
-
httpOnly?: boolean;
|
|
116
|
-
secure?: boolean;
|
|
117
|
-
sameSite?: 'strict' | 'lax' | 'none';
|
|
118
|
-
maxAge?: number;
|
|
119
|
-
path?: string;
|
|
120
|
-
domain?: string;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Cookie to set in response
|
|
124
|
-
*/
|
|
125
|
-
interface SetCookie {
|
|
126
|
-
name: string;
|
|
127
|
-
value: string;
|
|
128
|
-
options?: CookieOptions;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Request interceptor - called before fetch
|
|
132
|
-
*/
|
|
133
|
-
type RequestInterceptor = (url: string, init: RequestInit) => Promise<RequestInit> | RequestInit;
|
|
134
|
-
/**
|
|
135
|
-
* Response interceptor - called after fetch
|
|
136
|
-
*/
|
|
137
|
-
type ResponseInterceptor = (response: Response, body: any) => Promise<{
|
|
138
|
-
response: Response;
|
|
139
|
-
body: any;
|
|
140
|
-
}> | {
|
|
141
|
-
response: Response;
|
|
142
|
-
body: any;
|
|
143
|
-
};
|
|
144
|
-
/**
|
|
145
|
-
* Client configuration
|
|
146
|
-
*/
|
|
147
|
-
interface ApiConfig {
|
|
148
|
-
/**
|
|
149
|
-
* Base URL for RPC endpoint
|
|
150
|
-
*
|
|
151
|
-
* @default '/api/rpc'
|
|
152
|
-
* @example '/api/rpc', 'http://localhost:3000/api/rpc'
|
|
153
|
-
*/
|
|
154
|
-
baseUrl?: string;
|
|
155
|
-
/**
|
|
156
|
-
* Default headers for all requests
|
|
157
|
-
*/
|
|
158
|
-
headers?: Record<string, string>;
|
|
159
|
-
/**
|
|
160
|
-
* Request timeout in milliseconds
|
|
161
|
-
*
|
|
162
|
-
* @default env.SERVER_TIMEOUT (120000)
|
|
163
|
-
*/
|
|
164
|
-
timeout?: number;
|
|
165
|
-
/**
|
|
166
|
-
* Custom fetch implementation
|
|
167
|
-
*/
|
|
168
|
-
fetch?: typeof fetch;
|
|
169
|
-
/**
|
|
170
|
-
* Global request interceptor
|
|
171
|
-
*/
|
|
172
|
-
onRequest?: RequestInterceptor;
|
|
173
|
-
/**
|
|
174
|
-
* Global response interceptor
|
|
175
|
-
*/
|
|
176
|
-
onResponse?: ResponseInterceptor;
|
|
177
|
-
/**
|
|
178
|
-
* Custom error registry for deserialization
|
|
179
|
-
*
|
|
180
|
-
* Core HTTP errors are automatically registered. Use this to add your custom application errors.
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* ```typescript
|
|
184
|
-
* import { errorRegistry } from '@spfn/core/errors';
|
|
185
|
-
* import { authErrorRegistry } from '@myapp/auth/errors';
|
|
186
|
-
* import { PaymentFailedError } from '@/server/errors';
|
|
187
|
-
*
|
|
188
|
-
* const api = createApi<AppRouter>({
|
|
189
|
-
* errorRegistry: [errorRegistry, authErrorRegistry, PaymentFailedError]
|
|
190
|
-
* });
|
|
191
|
-
* ```
|
|
192
|
-
*/
|
|
193
|
-
errorRegistry?: ErrorRegistry | ErrorRegistryInput[];
|
|
194
|
-
/**
|
|
195
|
-
* Enable debug logging
|
|
196
|
-
*
|
|
197
|
-
* @default false
|
|
198
|
-
*/
|
|
199
|
-
debug?: boolean;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Per-call options
|
|
203
|
-
*/
|
|
204
|
-
interface CallOptions {
|
|
205
|
-
/**
|
|
206
|
-
* Request timeout in milliseconds
|
|
207
|
-
* Overrides the global timeout set in ApiConfig
|
|
208
|
-
*/
|
|
209
|
-
timeout?: number;
|
|
210
|
-
/**
|
|
211
|
-
* Additional headers for this request
|
|
212
|
-
*/
|
|
213
|
-
headers?: Record<string, string>;
|
|
214
|
-
/**
|
|
215
|
-
* Override cookies for this request
|
|
216
|
-
*
|
|
217
|
-
* Note: Cookies are automatically forwarded by the proxy.
|
|
218
|
-
* Use this only when you need to override them.
|
|
219
|
-
*/
|
|
220
|
-
cookies?: Record<string, string>;
|
|
221
|
-
/**
|
|
222
|
-
* Request-specific interceptor
|
|
223
|
-
*/
|
|
224
|
-
onRequest?: RequestInterceptor;
|
|
225
|
-
/**
|
|
226
|
-
* Response-specific interceptor
|
|
227
|
-
*/
|
|
228
|
-
onResponse?: ResponseInterceptor;
|
|
229
|
-
/**
|
|
230
|
-
* Next.js-specific fetch options
|
|
231
|
-
*
|
|
232
|
-
* @example
|
|
233
|
-
* // Time-based revalidation
|
|
234
|
-
* { next: { revalidate: 60 } }
|
|
235
|
-
*
|
|
236
|
-
* // Disable cache
|
|
237
|
-
* { cache: 'no-store' }
|
|
238
|
-
*
|
|
239
|
-
* // Tag-based revalidation
|
|
240
|
-
* { next: { tags: ['users'] } }
|
|
241
|
-
*/
|
|
242
|
-
fetchOptions?: RequestInit & {
|
|
243
|
-
next?: {
|
|
244
|
-
revalidate?: number | false;
|
|
245
|
-
tags?: string[];
|
|
246
|
-
};
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export type { ApiConfig as A, CallOptions as C, InferRouteInput as I, RequestInterceptor as R, SetCookie as S, ResponseInterceptor as a, InferRouteOutput as b, CookieOptions as c, RouterInput as d, RouterOutput as e, StructuredInput as f };
|