@defjs/core 0.4.0 → 0.6.0
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 +25 -71
- package/index.d.ts +387 -525
- package/index.js +742 -995
- package/index.min.js +20 -20
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -37,8 +37,8 @@ interface HttpProgressEvent {
|
|
|
37
37
|
* Callbacks may be async and are awaited before the next chunk is processed. A
|
|
38
38
|
* callback that throws or rejects fails the call with `EXT_OBSERVER_FAILED`,
|
|
39
39
|
* with the thrown value as `cause`, for downloads and uploads alike. Caller
|
|
40
|
-
* cancellation
|
|
41
|
-
*
|
|
40
|
+
* cancellation still takes precedence and reports `NET_ABORTED`, or `NET_TIMEOUT`
|
|
41
|
+
* when the abort reason is a timeout.
|
|
42
42
|
*
|
|
43
43
|
* Upload progress for a `Blob`, `File`, `ArrayBuffer`, or `FormData` body is
|
|
44
44
|
* reported only where the runtime can stream request bodies (Bun, Node). In
|
|
@@ -48,8 +48,8 @@ interface HttpProgressEvent {
|
|
|
48
48
|
*
|
|
49
49
|
* On server runtimes, FormData with `onUploadProgress` reads its serialized
|
|
50
50
|
* stream directly, keeps its multipart boundary, and is sent without a
|
|
51
|
-
* library-generated `Content-Length` (chunked over HTTP/1.1), so progress
|
|
52
|
-
*
|
|
51
|
+
* library-generated `Content-Length` (chunked over HTTP/1.1), so progress
|
|
52
|
+
* and abort work without buffering the whole body. It reports an
|
|
53
53
|
* unknown total unless a valid explicit `Content-Length` supplies it. For an
|
|
54
54
|
* endpoint that requires `Content-Length`, such as some presigned upload
|
|
55
55
|
* targets, omit `onUploadProgress`; platform Fetch then sends FormData with its
|
|
@@ -78,7 +78,7 @@ type HttpProgressFn = (event: HttpProgressEvent) => Promise<void> | void;
|
|
|
78
78
|
* @group http
|
|
79
79
|
*/
|
|
80
80
|
interface HttpRequest {
|
|
81
|
-
|
|
81
|
+
signal?: AbortSignal;
|
|
82
82
|
/** Trusted absolute base; its origin and directory bound the resolved endpoint path. */
|
|
83
83
|
baseEndpoint?: string;
|
|
84
84
|
body?: Blob | ArrayBuffer | FormData | URLSearchParams | ReadableStream<Uint8Array> | object | string | number | boolean | null;
|
|
@@ -111,7 +111,6 @@ interface HttpRequest {
|
|
|
111
111
|
* unread and does not fall back to `responseType`.
|
|
112
112
|
*/
|
|
113
113
|
readonly errorResponseType?: HttpResponseType;
|
|
114
|
-
timeout?: number;
|
|
115
114
|
uploadProgress?: HttpProgressFn;
|
|
116
115
|
withCredentials?: boolean;
|
|
117
116
|
xsrf?: {
|
|
@@ -501,7 +500,7 @@ interface PreservedStruct<T, I, O, OO extends boolean> extends Struct<I, O, OO>,
|
|
|
501
500
|
/**
|
|
502
501
|
* Broad struct constraint that accepts any struct, for endpoint and client generics.
|
|
503
502
|
*
|
|
504
|
-
* Used by generics such as `defineRequest
|
|
503
|
+
* Used by generics such as `defineRequest` and `Fault`. Prefer a concrete `Struct<…>` when you need precise input and output inference.
|
|
505
504
|
*
|
|
506
505
|
* @group struct
|
|
507
506
|
*/
|
|
@@ -655,7 +654,7 @@ interface IntersectionStruct<T extends readonly StructLike<unknown, unknown, boo
|
|
|
655
654
|
* | Class | Meaning |
|
|
656
655
|
* | ------ | -------------------------------------------------------------- |
|
|
657
656
|
* | `HTTP` | The peer answered with a non-2xx status. |
|
|
658
|
-
* | `REQ` | The request never left: input,
|
|
657
|
+
* | `REQ` | The request never left: input, request options, or build. |
|
|
659
658
|
* | `NET` | No usable response: cancel, timeout, connect, truncated body. |
|
|
660
659
|
* | `RES` | A response arrived but could not be read as declared. |
|
|
661
660
|
* | `EXT` | Code you attached to the pipeline threw. |
|
|
@@ -762,7 +761,7 @@ export type PreflightFault = Error & {
|
|
|
762
761
|
response?: HttpMeta;
|
|
763
762
|
};
|
|
764
763
|
/**
|
|
765
|
-
* Any failure returned by
|
|
764
|
+
* Any failure returned by an operation, expressed by its decoded error-body type.
|
|
766
765
|
*
|
|
767
766
|
* `Fault<TErr>` is `FaultOf` applied to `Infer<TErr>`, and `HttpAwaitResult` uses
|
|
768
767
|
* `FaultOf<TErrorData>`. Pass a decoded type, not a struct: write
|
|
@@ -773,7 +772,7 @@ export type PreflightFault = Error & {
|
|
|
773
772
|
*/
|
|
774
773
|
export type FaultOf<TData = undefined> = DecodeFault | HttpStatusFaultOf<TData> | PreflightFault;
|
|
775
774
|
/**
|
|
776
|
-
* Union of every failure
|
|
775
|
+
* Union of every failure an operation can return, discriminated by `code`.
|
|
777
776
|
*
|
|
778
777
|
* `Fault<TErr>` is {@link FaultOf} applied to the decoded body type, so it is the
|
|
779
778
|
* union of {@link DecodeFault}, {@link HttpStatusFault}<TErr>, and
|
|
@@ -1380,7 +1379,7 @@ interface EventStreamMessage {
|
|
|
1380
1379
|
/**
|
|
1381
1380
|
* Metadata available once an SSE response has opened.
|
|
1382
1381
|
*
|
|
1383
|
-
* `response` is the handshake response and `url` is the resolved request URL. It is the third element of a successful
|
|
1382
|
+
* `response` is the handshake response and `url` is the resolved request URL. It is the third element of a successful event-stream result and the value of `EventStreamHandle.open`.
|
|
1384
1383
|
*
|
|
1385
1384
|
* @group sse
|
|
1386
1385
|
*/
|
|
@@ -1420,7 +1419,7 @@ type EventStreamCloseInfo = (EventStreamCloseInfoBase & {
|
|
|
1420
1419
|
/**
|
|
1421
1420
|
* Open SSE stream: iterate events, read open metadata, and close early.
|
|
1422
1421
|
*
|
|
1423
|
-
* `EventStreamMessage` is the raw `{ id: string; event: string; data: string }` message. Handles returned by
|
|
1422
|
+
* `EventStreamMessage` is the raw `{ id: string; event: string; data: string }` message. Handles returned by an event-stream operation carry parsed {@link EventStreamData}.
|
|
1424
1423
|
*
|
|
1425
1424
|
* `open` is the startup snapshot ({@link EventStreamOpenInfo}); after a reconnect it can change, so read `stream.open` again. `closed` resolves with an {@link EventStreamCloseInfo} when the stream ends.
|
|
1426
1425
|
*
|
|
@@ -1443,16 +1442,8 @@ interface EventStreamHandle<TEvent = EventStreamMessage> extends AsyncIterable<T
|
|
|
1443
1442
|
close(reason?: unknown): void;
|
|
1444
1443
|
[Symbol.asyncDispose](): PromiseLike<void>;
|
|
1445
1444
|
}
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
timeout?: never;
|
|
1449
|
-
} | {
|
|
1450
|
-
abort?: never;
|
|
1451
|
-
timeout?: number;
|
|
1452
|
-
};
|
|
1453
|
-
type EndpointInput<TInput extends AnyStruct | undefined> = TInput extends AnyStruct ? StructInput<TInput> : unknown;
|
|
1454
|
-
type IsEndpointInputOptional<TInput extends AnyStruct | undefined> = [TInput] extends [undefined] ? true : undefined extends EndpointInput<TInput> ? true : false;
|
|
1455
|
-
type EndpointCallable<TInput extends AnyStruct | undefined, TCommand> = [TInput] extends [undefined] ? () => TCommand : IsEndpointInputOptional<TInput> extends true ? (input?: EndpointInput<TInput>) => TCommand : (input: EndpointInput<TInput>) => TCommand;
|
|
1445
|
+
/** Argument list after the client, decided by the input struct. */
|
|
1446
|
+
type EndpointArgs<S extends AnyStruct | undefined> = [S] extends [undefined] ? [] : undefined extends StructInput<S> ? [input?: StructInput<S>] : [input: StructInput<S>];
|
|
1456
1447
|
/** Object produced by endpoint input parsing. The symbol points at the struct that produced the node. */
|
|
1457
1448
|
type Typed = {
|
|
1458
1449
|
readonly [STRUCT]: AnyStruct;
|
|
@@ -1570,359 +1561,14 @@ type BuilderInput<S> = S extends CarriedStruct<infer Inner> ? NullishBuilderInpu
|
|
|
1570
1561
|
[key: string]: BuilderInput<Value>;
|
|
1571
1562
|
} : S extends TupleStruct<infer Items> ? { [K in keyof Items]: Items[K] extends StructLike<unknown, unknown, boolean> ? BuilderInput<Items[K]> : Items[K]; } : S extends ArrayStruct<infer Item> ? BuilderInput<Item>[] : S extends ObjectStruct<infer Shape> ? { [K in keyof Shape]: BuilderInput<Shape[K]>; } & Typed : Infer<S>;
|
|
1572
1563
|
type BuilderField<TInput, TShape> = [TInput] extends [undefined] ? {
|
|
1573
|
-
/** Pure, synchronous request builder, evaluated when the
|
|
1564
|
+
/** Pure, synchronous request builder, evaluated when the operation runs. Optional without input. */
|
|
1574
1565
|
builder?: () => TShape;
|
|
1575
1566
|
} : {
|
|
1576
|
-
/** Pure, synchronous function that explicitly places parsed input on the request when the
|
|
1567
|
+
/** Pure, synchronous function that explicitly places parsed input on the request when the operation runs. */
|
|
1577
1568
|
builder: (input: BuilderInput<TInput>) => TShape;
|
|
1578
1569
|
};
|
|
1579
1570
|
/** Accepts any concrete builder. `never` keeps the parameter contravariant. */
|
|
1580
1571
|
type OutboundBuilder = (input: never) => unknown;
|
|
1581
|
-
/**
|
|
1582
|
-
* Per-request options for HTTP execution: progress callbacks and cancellation.
|
|
1583
|
-
*
|
|
1584
|
-
* The HTTP-specific part of {@link HttpExecuteOptions}, which adds `signal`.
|
|
1585
|
-
* `onDownloadProgress` and `onUploadProgress` are {@link HttpProgressFn}
|
|
1586
|
-
* callbacks. They receive an {@link HttpProgressEvent} with `loaded`, `total`,
|
|
1587
|
-
* and `lengthComputable`.
|
|
1588
|
-
*
|
|
1589
|
-
* Cancellation is either `abort` or `timeout`, never both. The type rejects
|
|
1590
|
-
* both, and at runtime passing both fails with a `REQ_OPTIONS_INVALID` fault.
|
|
1591
|
-
* `timeout` must be a positive safe integer no greater than `2_147_483_647`.
|
|
1592
|
-
* It replaces the default set by {@link withTimeout} for that call. `abort`
|
|
1593
|
-
* combines with that default instead.
|
|
1594
|
-
*
|
|
1595
|
-
* @group http
|
|
1596
|
-
*/
|
|
1597
|
-
export type UseRequestConfig = {
|
|
1598
|
-
onDownloadProgress?: HttpProgressFn;
|
|
1599
|
-
onUploadProgress?: HttpProgressFn;
|
|
1600
|
-
} & UseCancellationConfig;
|
|
1601
|
-
/**
|
|
1602
|
-
* Opaque executable HTTP command produced by a `defineRequest` endpoint.
|
|
1603
|
-
*
|
|
1604
|
-
* Created by calling a `RequestEndpoint` with input. It carries the request
|
|
1605
|
-
* definition and optional typed input for `client.execute`. Treat it as opaque
|
|
1606
|
-
* and pass it to `client.execute`.
|
|
1607
|
-
*
|
|
1608
|
-
* @group http
|
|
1609
|
-
*/
|
|
1610
|
-
export interface HttpCommand<TInput extends AnyStruct | undefined, TOutput extends AnyStruct | undefined, TError extends AnyStruct | undefined = undefined> extends BaseCommand<typeof HTTP_COMMAND> {
|
|
1611
|
-
readonly definition: RequestDefinition<TInput, TOutput, TError>;
|
|
1612
|
-
readonly input: EndpointInput<TInput> | undefined;
|
|
1613
|
-
}
|
|
1614
|
-
/**
|
|
1615
|
-
* Options passed to `client.execute` or `executeHttpCommand` for one HTTP call: progress, `abort` or `timeout`, and `signal`.
|
|
1616
|
-
*
|
|
1617
|
-
* Cancellation is `abort` or `timeout`, not both (`abort` XOR `timeout`).
|
|
1618
|
-
* `signal` combines with either; it is not an alias for `abort`. Valid shapes:
|
|
1619
|
-
* `{ timeout }`, `{ abort }`, `{ signal, timeout }`, `{ signal, abort }`.
|
|
1620
|
-
* `{ abort, timeout }` is invalid and makes the call resolve with a
|
|
1621
|
-
* `REQ_OPTIONS_INVALID` fault. `timeout` must be a positive safe integer in
|
|
1622
|
-
* `1..2_147_483_647`.
|
|
1623
|
-
*
|
|
1624
|
-
* When `timeout` is omitted, the client's `withTimeout` default applies;
|
|
1625
|
-
* `abort` combines with that default.
|
|
1626
|
-
*
|
|
1627
|
-
* @group http
|
|
1628
|
-
*/
|
|
1629
|
-
export type HttpExecuteOptions = UseRequestConfig & {
|
|
1630
|
-
signal?: AbortSignal;
|
|
1631
|
-
};
|
|
1632
|
-
/**
|
|
1633
|
-
* Callable endpoint returned by `defineRequest`.
|
|
1634
|
-
*
|
|
1635
|
-
* Call it to get an `HttpCommand`: with no arguments when the endpoint declares
|
|
1636
|
-
* no `input`, with an optional argument when the input struct accepts
|
|
1637
|
-
* `undefined`, and otherwise with the struct's input value.
|
|
1638
|
-
*
|
|
1639
|
-
* @group http
|
|
1640
|
-
*/
|
|
1641
|
-
export type RequestEndpoint<TInput extends AnyStruct | undefined, TOutput extends AnyStruct | undefined, TError extends AnyStruct | undefined = undefined> = EndpointCallable<TInput, HttpCommand<TInput, TOutput, TError>>;
|
|
1642
|
-
type DeclaredBody<TStruct> = [TStruct] extends [undefined] ? undefined : Infer<TStruct>;
|
|
1643
|
-
type DeclaredResponse<TStruct> = [TStruct] extends [undefined] ? HttpMeta : DecodedResponse<Infer<TStruct>>;
|
|
1644
|
-
/**
|
|
1645
|
-
* Decoded success body for the declared `output` struct, or `undefined` when none is declared.
|
|
1646
|
-
*
|
|
1647
|
-
* @group http
|
|
1648
|
-
*/
|
|
1649
|
-
export type RequestSuccessData<TOutput extends AnyStruct | undefined> = DeclaredBody<TOutput>;
|
|
1650
|
-
/**
|
|
1651
|
-
* Decoded error body for the declared `error` struct, or `undefined` when none is declared.
|
|
1652
|
-
*
|
|
1653
|
-
* @group http
|
|
1654
|
-
*/
|
|
1655
|
-
export type RequestErrorData<TError extends AnyStruct | undefined> = DeclaredBody<TError>;
|
|
1656
|
-
type ResponseDeclaration<TOutput extends AnyStruct | undefined, TError extends AnyStruct | undefined> = ([TOutput] extends [undefined] ? {
|
|
1657
|
-
output?: never;
|
|
1658
|
-
} : {
|
|
1659
|
-
output: TOutput;
|
|
1660
|
-
}) & ([TError] extends [undefined] ? {
|
|
1661
|
-
error?: never;
|
|
1662
|
-
} : {
|
|
1663
|
-
error: TError;
|
|
1664
|
-
});
|
|
1665
|
-
/**
|
|
1666
|
-
* Contract for an HTTP endpoint: method, path, optional input, and the structs that decode its bodies.
|
|
1667
|
-
*
|
|
1668
|
-
* Declaring `input` requires an explicit `builder` to place the parsed value on
|
|
1669
|
-
* the request. `input` only defines the parameters; the builder alone decides
|
|
1670
|
-
* where each value goes. Only definitions without `input` may omit `builder`.
|
|
1671
|
-
* `output` declares the body for a 2xx response, `error` the body for anything
|
|
1672
|
-
* else. Only one of the two ever runs, and omitting one means that body is never
|
|
1673
|
-
* read. `ResponseDeclaration` is an internal helper type: `output` and `error`
|
|
1674
|
-
* are required only when the matching type parameter is a struct. There is no
|
|
1675
|
-
* `responseType`: the struct kind selects how a declared body is read. Pass to
|
|
1676
|
-
* `defineRequest` to get a typed endpoint.
|
|
1677
|
-
*
|
|
1678
|
-
* @group http
|
|
1679
|
-
*/
|
|
1680
|
-
export type RequestDefinition<TInput extends AnyStruct | undefined = undefined, TOutput extends AnyStruct | undefined = undefined, TError extends AnyStruct | undefined = undefined> = ResponseDeclaration<TOutput, TError> & {
|
|
1681
|
-
builder?: OutboundBuilder;
|
|
1682
|
-
input?: TInput;
|
|
1683
|
-
method: string;
|
|
1684
|
-
operation?: string;
|
|
1685
|
-
path: string;
|
|
1686
|
-
};
|
|
1687
|
-
/**
|
|
1688
|
-
* Await-result tuple for an HTTP call: success is `[null, data, response]`, and failure is `[fault, undefined, undefined]`.
|
|
1689
|
-
*
|
|
1690
|
-
* `TData` and `TErrorData` are decoded body types. On success the third slot
|
|
1691
|
-
* carries `body` only when `output` was declared. On failure it is `undefined`,
|
|
1692
|
-
* because the fault already holds whatever response metadata existed.
|
|
1693
|
-
*
|
|
1694
|
-
* @group http
|
|
1695
|
-
*/
|
|
1696
|
-
export type HttpAwaitResult<TData = undefined, TErrorData = undefined> = [error: null, result: TData, response: [TData] extends [undefined] ? HttpMeta : DecodedResponse<TData>] | [error: FaultOf<TErrorData>, result: undefined, response: undefined];
|
|
1697
|
-
type HttpExecuteAwaitResult<TOutput extends AnyStruct | undefined, TError extends AnyStruct | undefined> = [error: null, result: RequestSuccessData<TOutput>, response: DeclaredResponse<TOutput>] | [error: Fault<TError>, result: undefined, response: undefined];
|
|
1698
|
-
/**
|
|
1699
|
-
* Declares a typed HTTP request endpoint.
|
|
1700
|
-
*
|
|
1701
|
-
* Pass method, path, an optional input struct, and the single `output` and
|
|
1702
|
-
* `error` structs. Call the returned endpoint with input to get an `HttpCommand`
|
|
1703
|
-
* for `client.execute`.
|
|
1704
|
-
*
|
|
1705
|
-
* The contract is `method`, `path`, an optional `input` struct, optional
|
|
1706
|
-
* `output` and `error` structs, and an optional `operation`. A declared `input`
|
|
1707
|
-
* always requires an explicit `builder`. `input` only defines the parameters;
|
|
1708
|
-
* the builder alone decides where each value goes. Only definitions without
|
|
1709
|
-
* `input` may omit `builder`. `ResponseDeclaration` and `BuilderField` are
|
|
1710
|
-
* internal helper types: `output` and `error` are required only when the
|
|
1711
|
-
* matching type parameter is a struct, and `builder` is
|
|
1712
|
-
* `(input: BuilderInput<TInput>) => HttpRequestShape` when `input` is declared.
|
|
1713
|
-
*
|
|
1714
|
-
* `output` is one struct for the 2xx body; `error` is one struct for every
|
|
1715
|
-
* non-2xx body. Neither is keyed by status. A declaration is an assertion:
|
|
1716
|
-
* omitting one means that body is never read.
|
|
1717
|
-
*
|
|
1718
|
-
* @param definition - Request contract (method, path, input, builder, output).
|
|
1719
|
-
* @returns An endpoint that creates `HttpCommand` values from input.
|
|
1720
|
-
*
|
|
1721
|
-
* The checked example file passes the whole input object as `path`. This snippet maps individual fields into `path` and `query` instead:
|
|
1722
|
-
*
|
|
1723
|
-
* @example
|
|
1724
|
-
* ```ts
|
|
1725
|
-
* const getUser = defineRequest({
|
|
1726
|
-
* method: 'GET',
|
|
1727
|
-
* path: '/users/:id',
|
|
1728
|
-
* input: struct.object({ id: struct.number(), verbose: struct.boolean() }),
|
|
1729
|
-
* builder: (input) => ({ path: { id: input.id }, query: { verbose: input.verbose } }),
|
|
1730
|
-
* output: struct.object({ id: struct.number(), name: struct.string() }),
|
|
1731
|
-
* })
|
|
1732
|
-
* ```
|
|
1733
|
-
* @group http
|
|
1734
|
-
* @exampleFile examples/api/define-request.ts#example
|
|
1735
|
-
*/
|
|
1736
|
-
export declare function defineRequest<const M extends string, const P extends string, TInput extends AnyStruct | undefined = undefined, TOutput extends AnyStruct | undefined = undefined, TError extends AnyStruct | undefined = undefined>(definition: ResponseDeclaration<TOutput, TError> & {
|
|
1737
|
-
input?: TInput;
|
|
1738
|
-
method: M;
|
|
1739
|
-
operation?: string;
|
|
1740
|
-
path: P;
|
|
1741
|
-
} & BuilderField<NoInfer<TInput>, HttpRequestShape<NoInfer<P>, NoInfer<M>>>): RequestEndpoint<TInput, TOutput, TError>;
|
|
1742
|
-
/**
|
|
1743
|
-
* Runs an `HttpCommand` against client config: validate input, send the request, and parse the response.
|
|
1744
|
-
*
|
|
1745
|
-
* Low-level entry used by `client.execute`. Prefer `client.execute(command, options)`
|
|
1746
|
-
* in application code. `HttpClientConfig` is the HTTP part of `ClientConfig`, so
|
|
1747
|
-
* a `ClientConfig` is accepted. `HttpExecuteAwaitResult` is the internal result
|
|
1748
|
-
* tuple.
|
|
1749
|
-
*
|
|
1750
|
-
* The result is `[null, data, response]` or `[fault, undefined, undefined]`.
|
|
1751
|
-
* `data` is the decoded `output` body, or `undefined` when none is declared.
|
|
1752
|
-
* `response` is `DecodedResponse` when `output` is declared and `HttpMeta`
|
|
1753
|
-
* otherwise. The fault is `Fault<TError>`. A non-2xx status is `HTTP_STATUS`
|
|
1754
|
-
* when no `error` struct is declared (its `data` is `undefined`) or when the
|
|
1755
|
-
* declared body decodes (its `data` is that body). When a declared `error` body
|
|
1756
|
-
* cannot be read, the fault is a `RES_*` decode fault instead. On failure the
|
|
1757
|
-
* tuple's third slot is `undefined`; the fault carries the response metadata.
|
|
1758
|
-
* `options.timeout` falls back to the client's `withTimeout` default when omitted.
|
|
1759
|
-
*
|
|
1760
|
-
* @param clientConfig - Resolved HTTP client configuration (endpoint, interceptors, handler).
|
|
1761
|
-
* @param command - Command from a `defineRequest` endpoint.
|
|
1762
|
-
* @param options - Per-request progress and cancellation options.
|
|
1763
|
-
* @returns An await-result tuple of success body or typed request error.
|
|
1764
|
-
* @group http
|
|
1765
|
-
*/
|
|
1766
|
-
export declare function executeHttpCommand<TInput extends AnyStruct | undefined, TOutput extends AnyStruct | undefined, TError extends AnyStruct | undefined>(clientConfig: HttpClientConfig, command: HttpCommand<TInput, TOutput, TError>, options?: HttpExecuteOptions): Promise<HttpExecuteAwaitResult<TOutput, TError>>;
|
|
1767
|
-
/**
|
|
1768
|
-
* Map from SSE event names to the structs that decode their data.
|
|
1769
|
-
*
|
|
1770
|
-
* An event with no `event:` field is named `message`. An event whose name has no own entry uses the `default` struct; with neither, the event is skipped and `onInvalidEvent` is called. Declare the event name `__proto__` with a computed own key.
|
|
1771
|
-
*
|
|
1772
|
-
* A `string` event struct keeps the raw `data` text. Every other kind is JSON text: `JSON.parse`, then the struct. A bare `struct.literal` therefore needs JSON text, not an unquoted token.
|
|
1773
|
-
*
|
|
1774
|
-
* Reconnect lives on the client (`withSSEReconnect`). SSE `jitter` is a **0-1 multiplicative factor**, same as WebSocket.
|
|
1775
|
-
*
|
|
1776
|
-
* @group sse
|
|
1777
|
-
*/
|
|
1778
|
-
export type EventStructs = {
|
|
1779
|
-
[key: string]: AnyStruct;
|
|
1780
|
-
};
|
|
1781
|
-
type EventName<TKey extends string | number> = `${TKey}`;
|
|
1782
|
-
type KnownEventUnion<TEvents extends EventStructs> = { [K in keyof TEvents & (number | string)]: EventName<K> extends "default" ? never : {
|
|
1783
|
-
data: Infer<TEvents[K]>;
|
|
1784
|
-
event: EventName<K>;
|
|
1785
|
-
id?: string;
|
|
1786
|
-
}; }[keyof TEvents & (number | string)];
|
|
1787
|
-
type DefaultEventUnion<TEvents extends EventStructs> = "default" extends keyof TEvents ? {
|
|
1788
|
-
data: Infer<TEvents["default"]>;
|
|
1789
|
-
event: string;
|
|
1790
|
-
id?: string;
|
|
1791
|
-
} : never;
|
|
1792
|
-
/**
|
|
1793
|
-
* Union of parsed SSE events inferred from an EventStructs map.
|
|
1794
|
-
*
|
|
1795
|
-
* For each declared event name except `default`, the union has `{ event: <name>; data: Infer<TEvents[name]>; id?: string }`. When a `default` struct is declared, it adds `{ event: string; data: Infer<TEvents['default']>; id?: string }` for every event name that has no struct of its own. `KnownEventUnion` and `DefaultEventUnion` are internal helper types.
|
|
1796
|
-
*
|
|
1797
|
-
* @group sse
|
|
1798
|
-
*/
|
|
1799
|
-
export type EventStreamData<TEvents extends EventStructs> = TEvents extends EventStructs ? KnownEventUnion<TEvents> | DefaultEventUnion<TEvents> : never;
|
|
1800
|
-
interface EventStreamDefinitionBase<TEvents extends EventStructs = EventStructs> {
|
|
1801
|
-
events: TEvents;
|
|
1802
|
-
maxBufferSize: number;
|
|
1803
|
-
maxQueueSize: number;
|
|
1804
|
-
method?: string;
|
|
1805
|
-
operation?: string;
|
|
1806
|
-
path: string;
|
|
1807
|
-
}
|
|
1808
|
-
/** Makes `error` required only when an error struct is declared, so omission stays `Fault<undefined>`. */
|
|
1809
|
-
type EventStreamErrorField<TError extends AnyStruct | undefined> = [TError] extends [undefined] ? {
|
|
1810
|
-
error?: never;
|
|
1811
|
-
} : {
|
|
1812
|
-
error: TError;
|
|
1813
|
-
};
|
|
1814
|
-
/**
|
|
1815
|
-
* Contract that describes an SSE endpoint for defineEventStream.
|
|
1816
|
-
*
|
|
1817
|
-
* The composed members are:
|
|
1818
|
-
*
|
|
1819
|
-
* - `events`, `maxBufferSize`, and `maxQueueSize` (both limits are required positive safe integers), optional `method`, `operation`, and a required `path`.
|
|
1820
|
-
*
|
|
1821
|
-
* - `error`, required only when `TError` is a struct. It decodes the body of a failed handshake (a non-2xx response). The kind rule is the same as for HTTP: `string` is text, `blob` and `file` are blobs, `arrayBuffer` is bytes, and everything else is JSON.
|
|
1822
|
-
*
|
|
1823
|
-
* - `input` and `builder`. The request shape matches HTTP, including `body`; `GET` and `HEAD` cannot return a body. A declared `input` always requires an explicit `builder`. `input` only defines the parameters; the builder alone decides where each value goes. Only definitions without `input` may omit `builder`.
|
|
1824
|
-
*
|
|
1825
|
-
* `EventStreamDefinitionBase` and `EventStreamErrorField` are internal helper types.
|
|
1826
|
-
*
|
|
1827
|
-
* @group sse
|
|
1828
|
-
*/
|
|
1829
|
-
export type EventStreamDefinition<TInput extends AnyStruct | undefined = undefined, TEvents extends EventStructs = EventStructs, TError extends AnyStruct | undefined = undefined> = EventStreamDefinitionBase<TEvents> & EventStreamErrorField<TError> & {
|
|
1830
|
-
builder?: OutboundBuilder;
|
|
1831
|
-
input?: TInput;
|
|
1832
|
-
};
|
|
1833
|
-
/**
|
|
1834
|
-
* Await-result tuple from opening an SSE stream via `client.execute`.
|
|
1835
|
-
*
|
|
1836
|
-
* - On success: `[null, stream, open]`. `open` is the returned connection's first successful handshake snapshot for native Defjs handles or wrappers forwarding the same live `open` object; custom handles or wrappers overriding `open` use their current public `open` even after reconnect, while `stream.open` stays live.
|
|
1837
|
-
*
|
|
1838
|
-
* - On failure: `[fault, undefined, open]`. `open` carries the response snapshot when the failure happened after a response arrived, for example a non-2xx handshake, and is `undefined` otherwise.
|
|
1839
|
-
*
|
|
1840
|
-
* - `TError` is the declared `error` struct. It types the decoded error body on the fault.
|
|
1841
|
-
*
|
|
1842
|
-
* @group sse
|
|
1843
|
-
*/
|
|
1844
|
-
export type StreamAwaitResult<TEvent, TError extends AnyStruct | undefined = undefined> = [error: null, stream: EventStreamHandle<TEvent>, open: EventStreamOpenInfo] | [error: Fault<TError>, stream: undefined, open: EventStreamOpenInfo | undefined];
|
|
1845
|
-
/**
|
|
1846
|
-
* Opaque executable SSE command produced by an `EventStreamEndpoint`.
|
|
1847
|
-
*
|
|
1848
|
-
* Created by calling an `EventStreamEndpoint` with input. It also has internal symbol-keyed members that identify and run the command. Treat it as opaque and pass it to `client.execute`. `endpoint` is the definition plus `method`, which is always a string (it defaults to `'GET'` when the definition omits it). `ResolvedEventStreamDefinition` names that shape and is not exported.
|
|
1849
|
-
*
|
|
1850
|
-
* @group sse
|
|
1851
|
-
*/
|
|
1852
|
-
export interface EventStreamCommand<TInput extends AnyStruct | undefined, TEvents extends EventStructs, TError extends AnyStruct | undefined = undefined> extends BaseCommand<typeof EVENT_STREAM_COMMAND> {
|
|
1853
|
-
readonly endpoint: ResolvedEventStreamDefinition<TInput, TEvents, TError>;
|
|
1854
|
-
readonly input: EndpointInput<TInput> | undefined;
|
|
1855
|
-
}
|
|
1856
|
-
/**
|
|
1857
|
-
* Per-call options for opening an SSE stream: abort or timeout, plus an optional signal.
|
|
1858
|
-
*
|
|
1859
|
-
* Cancellation is `abort` **or** `timeout`, not both; passing both makes the call resolve with a `REQ_OPTIONS_INVALID` fault. `signal` combines with either and is not an alias for `abort`. `timeout` must be a positive safe integer up to 2147483647.
|
|
1860
|
-
*
|
|
1861
|
-
* For SSE, `timeout` is a startup deadline. It covers input parsing, the builder, the interceptors, and opening the connection, and stops applying once the stream is open. The client-level `withTimeout` default does not apply to SSE.
|
|
1862
|
-
*
|
|
1863
|
-
* @group sse
|
|
1864
|
-
*/
|
|
1865
|
-
export type EventStreamExecuteOptions = UseCancellationConfig & {
|
|
1866
|
-
signal?: AbortSignal;
|
|
1867
|
-
};
|
|
1868
|
-
/**
|
|
1869
|
-
* Callable endpoint returned by defineEventStream.
|
|
1870
|
-
*
|
|
1871
|
-
* Returned by `defineEventStream`. Call it to get an `EventStreamCommand`: with no arguments when the endpoint declares no `input`, with an optional argument when the input struct accepts `undefined`, and otherwise with the struct's input value.
|
|
1872
|
-
*
|
|
1873
|
-
* @group sse
|
|
1874
|
-
*/
|
|
1875
|
-
export type EventStreamEndpoint<TInput extends AnyStruct | undefined, TEvents extends EventStructs, TError extends AnyStruct | undefined = undefined> = EndpointCallable<TInput, EventStreamCommand<TInput, TEvents, TError>>;
|
|
1876
|
-
type ResolvedEventStreamDefinition<TInput extends AnyStruct | undefined = undefined, TEvents extends EventStructs = EventStructs, TError extends AnyStruct | undefined = undefined> = EventStreamDefinition<TInput, TEvents, TError> & {
|
|
1877
|
-
readonly method: string;
|
|
1878
|
-
};
|
|
1879
|
-
/**
|
|
1880
|
-
* Declare a typed Server-Sent Events endpoint.
|
|
1881
|
-
*
|
|
1882
|
-
* Pass path, event structs, and buffer/queue limits. Call the returned endpoint
|
|
1883
|
-
* with input to get an `EventStreamCommand` for `client.execute`.
|
|
1884
|
-
*
|
|
1885
|
-
* - **definition** — `path`, an `events` map, and the required `maxBufferSize` and `maxQueueSize` limits (positive safe integers). Optional `method` (default `'GET'`), `operation`, `input`, and `error`. A declared `input` always requires an explicit `builder`. `input` only defines the parameters; the builder alone decides where each value goes. Only definitions without `input` may omit `builder`.
|
|
1886
|
-
*
|
|
1887
|
-
* `EventStreamDefinitionBase`, `EventStreamErrorField`, and `BuilderField` are internal helper types: `error` is required only when `TError` is a struct, and `builder` is `(input: BuilderInput<TInput>) => EventStreamRequestShape` when `input` is declared.
|
|
1888
|
-
*
|
|
1889
|
-
* @param definition - SSE contract (path, events, buffer limits, optional input).
|
|
1890
|
-
* @returns An endpoint that creates `EventStreamCommand` values from input.
|
|
1891
|
-
*
|
|
1892
|
-
* @group sse
|
|
1893
|
-
* @exampleFile examples/api/define-event-stream.ts#example
|
|
1894
|
-
*/
|
|
1895
|
-
export declare function defineEventStream<const P extends string, const M extends string = "GET", TInput extends AnyStruct | undefined = undefined, TEvents extends EventStructs = EventStructs, TError extends AnyStruct | undefined = undefined>(definition: Omit<EventStreamDefinitionBase<TEvents>, "method" | "path"> & EventStreamErrorField<TError> & {
|
|
1896
|
-
input?: TInput;
|
|
1897
|
-
method?: M;
|
|
1898
|
-
path: P;
|
|
1899
|
-
} & BuilderField<NoInfer<TInput>, EventStreamRequestShape<NoInfer<P>, NoInfer<M>>>): EventStreamEndpoint<TInput, TEvents, TError>;
|
|
1900
|
-
/**
|
|
1901
|
-
* Open an SSE command against the given client config.
|
|
1902
|
-
*
|
|
1903
|
-
* Prefer `client.execute(command)` in application code; this is the low-level entry used by the client.
|
|
1904
|
-
*
|
|
1905
|
-
* The result is `[null, stream, open]` or `[fault, undefined, open | undefined]`. The fault is `Fault<TError>`: the decoded handshake body is on `data` when `error` is declared, and `Fault<undefined>` otherwise.
|
|
1906
|
-
*
|
|
1907
|
-
* @param clientConfig - Resolved client configuration.
|
|
1908
|
-
* @param command - SSE command from an `EventStreamEndpoint`.
|
|
1909
|
-
* @param options - Optional execute options (abort, timeout).
|
|
1910
|
-
* @returns Await-result tuple of `[error, stream, open]`.
|
|
1911
|
-
* @group sse
|
|
1912
|
-
*/
|
|
1913
|
-
export declare function executeEventStreamCommand<TInput extends AnyStruct | undefined, TEvents extends EventStructs, TError extends AnyStruct | undefined = undefined>(clientConfig: ClientConfig, command: EventStreamCommand<TInput, TEvents, TError>, options?: EventStreamExecuteOptions): Promise<StreamAwaitResult<EventStreamData<TEvents>, TError>>;
|
|
1914
|
-
declare const COMMAND_TYPE: unique symbol;
|
|
1915
|
-
declare const HTTP_COMMAND: unique symbol;
|
|
1916
|
-
declare const EVENT_STREAM_COMMAND: unique symbol;
|
|
1917
|
-
declare const WEB_SOCKET_COMMAND: unique symbol;
|
|
1918
|
-
/** The command's own runner, so `client.execute` never imports a transport the app does not use. */
|
|
1919
|
-
declare const COMMAND_EXECUTE: unique symbol;
|
|
1920
|
-
type CommandExecutor = (config: ClientConfig, command: never, options?: never) => Promise<unknown>;
|
|
1921
|
-
type CommandType = typeof HTTP_COMMAND | typeof EVENT_STREAM_COMMAND | typeof WEB_SOCKET_COMMAND;
|
|
1922
|
-
interface BaseCommand<TCommandType extends CommandType> {
|
|
1923
|
-
readonly [COMMAND_EXECUTE]: CommandExecutor;
|
|
1924
|
-
readonly [COMMAND_TYPE]: TCommandType;
|
|
1925
|
-
}
|
|
1926
1572
|
interface WebSocketCloseSnapshot {
|
|
1927
1573
|
cause?: unknown;
|
|
1928
1574
|
code?: number;
|
|
@@ -1940,7 +1586,7 @@ interface WebSocketCloseSnapshot {
|
|
|
1940
1586
|
* | `reconnecting` | Preparing or waiting for a replacement socket after a close |
|
|
1941
1587
|
* | `closing` | Closure was requested with `session.close()` or disposal |
|
|
1942
1588
|
* | `closed` | Terminal: the session ended without an error or cancellation |
|
|
1943
|
-
* | `aborted` | Terminal: the session was cancelled through `
|
|
1589
|
+
* | `aborted` | Terminal: the session was cancelled through `signal` |
|
|
1944
1590
|
* | `error` | Terminal: the session failed, including a startup failure or `timeout` |
|
|
1945
1591
|
*
|
|
1946
1592
|
* Observe it with `session.state` and `session.onStateChange`.
|
|
@@ -1982,13 +1628,13 @@ interface WebSocketDefinitionBase<TIncoming extends AnyStruct = AnyStruct, TOutg
|
|
|
1982
1628
|
*
|
|
1983
1629
|
* - `maxIncomingQueueSize` is required and must be a positive safe integer. `maxOutgoingQueueSize` must be a non-negative safe integer; it defaults to `0`, which disables queueing of messages sent while the session is `reconnecting`.
|
|
1984
1630
|
*
|
|
1985
|
-
* - `protocols` is the static default subprotocol list.
|
|
1631
|
+
* - `protocols` is the static default subprotocol list. `RequestOptions.protocols` and {@link withWebSocketProtocols} override it.
|
|
1986
1632
|
*
|
|
1987
1633
|
* - `operation` is a static, low-cardinality name for telemetry.
|
|
1988
1634
|
*
|
|
1989
|
-
* - `input` is the struct for the
|
|
1635
|
+
* - `input` is the struct for the operation input. A declared `input` always requires an explicit `builder`. `input` only defines the parameters; the builder alone decides where each value goes. Only definitions without `input` may omit `builder`. The builder may return `path` and `query` only; see {@link WebSocketRequestShape}.
|
|
1990
1636
|
*
|
|
1991
|
-
* Invalid queue limits are reported when the
|
|
1637
|
+
* Invalid queue limits are reported when the operation runs, as a `REQ_OPTIONS_INVALID` fault.
|
|
1992
1638
|
*
|
|
1993
1639
|
* @group web-socket
|
|
1994
1640
|
*/
|
|
@@ -2005,7 +1651,7 @@ export type WebSocketDefinition<TInput extends AnyStruct | undefined = undefined
|
|
|
2005
1651
|
*
|
|
2006
1652
|
* - `generation` counts the physical sockets that reached `open`: `1` after the first open, one more after each reconnect. A snapshot taken before any open has `0`.
|
|
2007
1653
|
*
|
|
2008
|
-
* `session.connection` exposes the session's current public connection info. The `connection` in the
|
|
1654
|
+
* `session.connection` exposes the session's current public connection info. The `connection` in the operation result preserves the first successful snapshot only for a native Defjs session or a wrapper forwarding the same live `connection` object. Custom sessions and wrappers that transform `connection` instead return their current public `connection`. Sharing `closed` cannot bypass URL sanitization or metadata filtering, and Defjs does not reconstruct first-connection metadata from arbitrary transformations.
|
|
2009
1655
|
*
|
|
2010
1656
|
* @group web-socket
|
|
2011
1657
|
*/
|
|
@@ -2093,7 +1739,7 @@ export interface WebSocketSession<TIncoming = unknown, TOutgoing = never> extend
|
|
|
2093
1739
|
send(message: TOutgoing): void;
|
|
2094
1740
|
}
|
|
2095
1741
|
/**
|
|
2096
|
-
* Await-result tuple from opening a WebSocket
|
|
1742
|
+
* Await-result tuple from opening a WebSocket.
|
|
2097
1743
|
*
|
|
2098
1744
|
* - On success: `[null, session, connection]`. `session.connection` moves forward on reconnect. The tuple's `connection` preserves the first successful snapshot only for a native Defjs session or a wrapper forwarding the same live `connection` object. Custom sessions and wrappers that transform `connection` instead return their current public `connection`. Sharing `closed` cannot bypass URL sanitization or metadata filtering, and Defjs does not reconstruct first-connection metadata from arbitrary transformations.
|
|
2099
1745
|
*
|
|
@@ -2111,83 +1757,33 @@ interface UseWebSocketBaseConfig<TIncoming = unknown, TOutgoing = unknown> {
|
|
|
2111
1757
|
reconnect?: ClientWebSocketOptions["reconnect"];
|
|
2112
1758
|
}
|
|
2113
1759
|
/**
|
|
2114
|
-
* WebSocket
|
|
1760
|
+
* WebSocket fields of {@link RequestOptions}, plus `signal`.
|
|
2115
1761
|
*
|
|
2116
|
-
*
|
|
1762
|
+
* `beforeConnect`, `heartbeat`, `protocols`, and `reconnect` override the client-level options for one call. `signal` covers the whole session, including after it opens. There is no startup-only deadline and no `abort` field.
|
|
2117
1763
|
*
|
|
2118
|
-
*
|
|
1764
|
+
* @group web-socket
|
|
1765
|
+
*/
|
|
1766
|
+
export type UseWebSocketConfig<TIncoming = unknown, TOutgoing = unknown> = UseWebSocketBaseConfig<TIncoming, TOutgoing> & {
|
|
1767
|
+
/** Aborts the session, including after it is open. */
|
|
1768
|
+
signal?: AbortSignal;
|
|
1769
|
+
};
|
|
1770
|
+
/**
|
|
1771
|
+
* WebSocket fields read from {@link RequestOptions} for one call.
|
|
2119
1772
|
*
|
|
2120
|
-
*
|
|
1773
|
+
* See {@link UseWebSocketConfig}. `heartbeat` callbacks are not inferred from the operation; narrow `unknown` messages yourself.
|
|
2121
1774
|
*
|
|
2122
1775
|
* @group web-socket
|
|
1776
|
+
* @see {@link WebSocketHeartbeatConfig}
|
|
2123
1777
|
*/
|
|
2124
|
-
export type
|
|
1778
|
+
export type WebSocketExecuteOptions<TIncoming = unknown, TOutgoing = unknown> = UseWebSocketConfig<TIncoming, TOutgoing>;
|
|
2125
1779
|
/**
|
|
2126
|
-
*
|
|
1780
|
+
* Operation returned by `defineWebSocket`.
|
|
2127
1781
|
*
|
|
2128
|
-
* {@link
|
|
2129
|
-
*
|
|
2130
|
-
* ```ts
|
|
2131
|
-
* type WebSocketExecuteOptions<TIncoming = unknown, TOutgoing = unknown> = {
|
|
2132
|
-
* beforeConnect?: (context: {
|
|
2133
|
-
* attempt: number;
|
|
2134
|
-
* signal: AbortSignal;
|
|
2135
|
-
* }) => void | Promise<void>;
|
|
2136
|
-
* heartbeat?: WebSocketHeartbeatConfig<TIncoming, TOutgoing>;
|
|
2137
|
-
* protocols?: readonly string[];
|
|
2138
|
-
* reconnect?: ClientWebSocketOptions["reconnect"];
|
|
2139
|
-
* signal?: AbortSignal;
|
|
2140
|
-
* } & (
|
|
2141
|
-
* { abort?: AbortSignal; timeout?: never } | { abort?: never; timeout?: number }
|
|
2142
|
-
* );
|
|
2143
|
-
* ```
|
|
2144
|
-
*
|
|
2145
|
-
* - `abort` and `timeout` are mutually exclusive. The type rejects both, and at runtime passing both fails with a `REQ_OPTIONS_INVALID` fault.
|
|
2146
|
-
*
|
|
2147
|
-
* - `signal` combines with either one; it is not an alias for `abort`.
|
|
2148
|
-
*
|
|
2149
|
-
* - `timeout` must be a positive safe integer no greater than `2_147_483_647`. It limits how long opening the session may take and is not applied again on reconnect.
|
|
2150
|
-
*
|
|
2151
|
-
* - `beforeConnect`, `heartbeat`, `protocols`, and `reconnect` override the client-level options for this call.
|
|
2152
|
-
*
|
|
2153
|
-
* - When `reconnect` is set, `attempts` defaults to `3` per outage; `0` disables. Successful `open` resets the budget and backoff exponent. Omitting `attempts` does not give unlimited retries within one outage. See {@link withWebSocketReconnect} for validation and final delay caps.
|
|
2154
|
-
*
|
|
2155
|
-
* See {@link WebSocketHeartbeatConfig}.
|
|
1782
|
+
* The first argument is a {@link Client}. Further arguments are the input only. Calling it opens the session and returns the existing error-first tuple.
|
|
2156
1783
|
*
|
|
2157
1784
|
* @group web-socket
|
|
2158
1785
|
*/
|
|
2159
|
-
export type
|
|
2160
|
-
signal?: AbortSignal;
|
|
2161
|
-
};
|
|
2162
|
-
/**
|
|
2163
|
-
* Executable command created by calling a WebSocketEndpoint.
|
|
2164
|
-
*
|
|
2165
|
-
* Created by calling a {@link WebSocketEndpoint}. It holds the endpoint definition and the unparsed input. Pass it to `client.execute` to open a session; nothing connects until then.
|
|
2166
|
-
*
|
|
2167
|
-
* `BaseCommand` carries symbol-keyed members that route the command to the right transport. They are internal, so treat the command as opaque.
|
|
2168
|
-
*
|
|
2169
|
-
* @group web-socket
|
|
2170
|
-
*/
|
|
2171
|
-
export interface WebSocketCommand<TInput extends AnyStruct | undefined, TIncoming extends AnyStruct, TOutgoing extends AnyStruct | undefined> extends BaseCommand<typeof WEB_SOCKET_COMMAND> {
|
|
2172
|
-
readonly endpoint: WebSocketDefinition<TInput, TIncoming, TOutgoing>;
|
|
2173
|
-
readonly input: EndpointInput<TInput> | undefined;
|
|
2174
|
-
}
|
|
2175
|
-
/**
|
|
2176
|
-
* Callable returned by defineWebSocket.
|
|
2177
|
-
*
|
|
2178
|
-
* Returned by {@link defineWebSocket}. Calling it creates a {@link WebSocketCommand} that you pass to `client.execute`. The call signature depends on `input`:
|
|
2179
|
-
*
|
|
2180
|
-
* - No `input` declared: `() => WebSocketCommand`.
|
|
2181
|
-
*
|
|
2182
|
-
* - `input` accepts `undefined`: `(input?: StructInput<TInput>) => WebSocketCommand`.
|
|
2183
|
-
*
|
|
2184
|
-
* - Otherwise: `(input: StructInput<TInput>) => WebSocketCommand`.
|
|
2185
|
-
*
|
|
2186
|
-
* Calling the endpoint does not connect. The input is parsed when the command is executed.
|
|
2187
|
-
*
|
|
2188
|
-
* @group web-socket
|
|
2189
|
-
*/
|
|
2190
|
-
export type WebSocketEndpoint<TInput extends AnyStruct | undefined, TIncoming extends AnyStruct, TOutgoing extends AnyStruct | undefined> = EndpointCallable<TInput, WebSocketCommand<TInput, TIncoming, TOutgoing>>;
|
|
1786
|
+
export type WebSocketEndpoint<Args extends unknown[], Incoming, Outgoing = never> = (client: Client, ...args: Args) => Promise<SocketAwaitResult<Incoming, Outgoing>>;
|
|
2191
1787
|
/**
|
|
2192
1788
|
* Close code and reason recorded when a session is closed with session.close.
|
|
2193
1789
|
*
|
|
@@ -2215,7 +1811,7 @@ export type ManualSocketCloseReason = {
|
|
|
2215
1811
|
*
|
|
2216
1812
|
* - `intervalMs` and `timeoutMs` must be positive, finite, and at most `2_147_483_647`.
|
|
2217
1813
|
*
|
|
2218
|
-
* Set it with {@link withWebSocketHeartbeat} or the `heartbeat`
|
|
1814
|
+
* Set it with {@link withWebSocketHeartbeat} or the `heartbeat` request option.
|
|
2219
1815
|
*
|
|
2220
1816
|
* @group web-socket
|
|
2221
1817
|
*/
|
|
@@ -2229,14 +1825,14 @@ export interface WebSocketHeartbeatConfig<TIncoming = unknown, TOutgoing = unkno
|
|
|
2229
1825
|
* Declare a typed WebSocket endpoint.
|
|
2230
1826
|
*
|
|
2231
1827
|
* Pass path, incoming (and optional outgoing) message structs, and queue limits.
|
|
2232
|
-
* Call the returned
|
|
1828
|
+
* Call the returned operation with a client and, when declared, the input.
|
|
2233
1829
|
*
|
|
2234
1830
|
* - **definition** — `path`, one `incoming` struct, and the required `maxIncomingQueueSize` (a positive safe integer). Optional `outgoing` and `input` structs, static `protocols`, `maxOutgoingQueueSize` (a non-negative safe integer), and `operation`. A declared `input` always requires an explicit `builder`. `input` only defines the parameters; the builder alone decides where each value goes. Only definitions without `input` may omit `builder`.
|
|
2235
1831
|
*
|
|
2236
1832
|
* A WebSocket `builder` may return `path` and `query` only; `headers` and `body` are rejected. `WebSocketDefinitionBase` and `BuilderField` are internal helper types.
|
|
2237
1833
|
*
|
|
2238
1834
|
* @param definition - WebSocket contract (path, structs, queue limits, optional input).
|
|
2239
|
-
* @returns An
|
|
1835
|
+
* @returns An operation `(client, ...input) => Promise<error-first tuple>`.
|
|
2240
1836
|
*
|
|
2241
1837
|
* @group web-socket
|
|
2242
1838
|
* @exampleFile examples/api/define-web-socket.ts#example
|
|
@@ -2244,23 +1840,7 @@ export interface WebSocketHeartbeatConfig<TIncoming = unknown, TOutgoing = unkno
|
|
|
2244
1840
|
export declare function defineWebSocket<const P extends string, TInput extends AnyStruct | undefined = undefined, TIncoming extends AnyStruct = AnyStruct, TOutgoing extends AnyStruct | undefined = undefined>(definition: Omit<WebSocketDefinitionBase<TIncoming, TOutgoing>, "path"> & {
|
|
2245
1841
|
input?: TInput;
|
|
2246
1842
|
path: P;
|
|
2247
|
-
} & BuilderField<NoInfer<TInput>, WebSocketRequestShape<NoInfer<P>>>): WebSocketEndpoint<TInput
|
|
2248
|
-
/**
|
|
2249
|
-
* Open a WebSocket command against the given client config.
|
|
2250
|
-
*
|
|
2251
|
-
* Prefer `client.execute(command)` in application code; this is the low-level entry used by the client.
|
|
2252
|
-
*
|
|
2253
|
-
* The result is `[null, session, connection]` or `[fault, undefined, connection | undefined]`, where the fault is `Fault<undefined>`.
|
|
2254
|
-
*
|
|
2255
|
-
* WebSocket execute options can override the client's `beforeConnect`, `heartbeat`, `protocols`, and `reconnect`.
|
|
2256
|
-
*
|
|
2257
|
-
* @param clientConfig - Resolved client configuration.
|
|
2258
|
-
* @param command - WebSocket command from a `WebSocketEndpoint`.
|
|
2259
|
-
* @param options - Optional execute options (heartbeat, reconnect, abort).
|
|
2260
|
-
* @returns Await-result tuple of `[error, socket, connection]`.
|
|
2261
|
-
* @group web-socket
|
|
2262
|
-
*/
|
|
2263
|
-
export declare function executeWebSocketCommand<TInput extends AnyStruct | undefined, TIncoming extends AnyStruct, TOutgoing extends AnyStruct | undefined>(clientConfig: ClientConfig, command: WebSocketCommand<TInput, TIncoming, TOutgoing>, options?: WebSocketExecuteOptions<WebSocketIncomingData<TIncoming>, WebSocketOutgoingData<TOutgoing>>): Promise<SocketAwaitResult<WebSocketIncomingData<TIncoming>, WebSocketOutgoingData<TOutgoing>>>;
|
|
1843
|
+
} & BuilderField<NoInfer<TInput>, WebSocketRequestShape<NoInfer<P>>>): WebSocketEndpoint<EndpointArgs<TInput>, WebSocketIncomingData<TIncoming>, WebSocketOutgoingData<TOutgoing>>;
|
|
2264
1844
|
/**
|
|
2265
1845
|
* The outcome of a **single connect attempt**, not the final result of the session.
|
|
2266
1846
|
*
|
|
@@ -2288,8 +1868,8 @@ export type SocketLifecycleOutcome = {
|
|
|
2288
1868
|
* Continuation that runs the rest of the HTTP interceptor chain, or the handler.
|
|
2289
1869
|
*
|
|
2290
1870
|
* `next(req)` only goes inward: the interceptors registered after this one, then
|
|
2291
|
-
* the Fetch handler. It is not a
|
|
2292
|
-
*
|
|
1871
|
+
* the Fetch handler. It is not a new operation call from outside the chain.
|
|
1872
|
+
* Call `next` again for a safe
|
|
2293
1873
|
* replay (for example one 401 refresh) from the same interceptor; outer layers
|
|
2294
1874
|
* do not run a second time. Once the chain has settled, calling `next` rejects
|
|
2295
1875
|
* with `HTTP interceptor next() cannot be called after the chain has settled`.
|
|
@@ -2324,10 +1904,10 @@ interface HttpInterceptor {
|
|
|
2324
1904
|
* Returns `{ kind: 'http', fn }`. Call `next(req)` (optionally with a modified
|
|
2325
1905
|
* request) or short-circuit with `makeResponse`. `next` runs only the
|
|
2326
1906
|
* interceptors registered after this one and then the fetch handler. HTTP
|
|
2327
|
-
* interceptors do not run for SSE or WebSocket
|
|
1907
|
+
* interceptors do not run for SSE or WebSocket operations.
|
|
2328
1908
|
*
|
|
2329
1909
|
* A deterministic URL error from `next(req)` rejects the returned promise, so
|
|
2330
|
-
* `.then` or `.catch` recovery runs; if it is not recovered,
|
|
1910
|
+
* `.then` or `.catch` recovery runs; if it is not recovered, the operation
|
|
2331
1911
|
* still reports `REQ_BUILD_FAILED`.
|
|
2332
1912
|
*
|
|
2333
1913
|
* @param fn - HTTP interceptor function.
|
|
@@ -2369,7 +1949,7 @@ type SSEInterceptorFn = (req: HttpRequest, next: SSEHandler) => Promise<EventStr
|
|
|
2369
1949
|
*
|
|
2370
1950
|
* Created by `createSSEInterceptor`. The `kind` tag lets `withInterceptors`
|
|
2371
1951
|
* accept HTTP, SSE, and WebSocket interceptors in one list; only `kind: 'sse'`
|
|
2372
|
-
* interceptors run for SSE
|
|
1952
|
+
* interceptors run for SSE operations.
|
|
2373
1953
|
*
|
|
2374
1954
|
* @group interceptors
|
|
2375
1955
|
*/
|
|
@@ -2380,12 +1960,12 @@ interface SSEInterceptor {
|
|
|
2380
1960
|
/**
|
|
2381
1961
|
* Wraps an `SSEInterceptorFn` as a tagged `SSEInterceptor`.
|
|
2382
1962
|
*
|
|
2383
|
-
* Returns `{ kind: 'sse', fn }`. SSE interceptors run only for SSE
|
|
1963
|
+
* Returns `{ kind: 'sse', fn }`. SSE interceptors run only for SSE operations, in
|
|
2384
1964
|
* registration order; `next(req)` opens the stream through the remaining
|
|
2385
1965
|
* interceptors.
|
|
2386
1966
|
*
|
|
2387
1967
|
* A deterministic URL error from `next(req)` rejects the returned promise, so
|
|
2388
|
-
* `.then` or `.catch` recovery runs; if it is not recovered,
|
|
1968
|
+
* `.then` or `.catch` recovery runs; if it is not recovered, the operation
|
|
2389
1969
|
* still reports `REQ_BUILD_FAILED`.
|
|
2390
1970
|
*
|
|
2391
1971
|
* `EventStreamHandle` extends `AsyncDisposable`. A structural short-circuit
|
|
@@ -2448,7 +2028,7 @@ type WebSocketHandler = (req: HttpRequest) => Promise<WebSocketSessionLike>;
|
|
|
2448
2028
|
* {@link WebSocketSessionLike} to short-circuit. Wrap it with
|
|
2449
2029
|
* `createWebSocketInterceptor` to register it through `withInterceptors`.
|
|
2450
2030
|
*
|
|
2451
|
-
* The chain runs once per
|
|
2031
|
+
* The chain runs once per operation. Reconnects happen inside the session it
|
|
2452
2032
|
* returns and do not run it again.
|
|
2453
2033
|
*
|
|
2454
2034
|
* @group interceptors
|
|
@@ -2459,7 +2039,7 @@ type WebSocketInterceptorFn = (req: HttpRequest, next: WebSocketHandler) => Prom
|
|
|
2459
2039
|
*
|
|
2460
2040
|
* Created by `createWebSocketInterceptor`. The `kind` tag lets
|
|
2461
2041
|
* `withInterceptors` accept HTTP, SSE, and WebSocket interceptors in one list;
|
|
2462
|
-
* only `kind: 'web-socket'` interceptors run for WebSocket
|
|
2042
|
+
* only `kind: 'web-socket'` interceptors run for WebSocket operations.
|
|
2463
2043
|
*
|
|
2464
2044
|
* @group interceptors
|
|
2465
2045
|
*/
|
|
@@ -2471,7 +2051,7 @@ interface WebSocketInterceptor {
|
|
|
2471
2051
|
* Wraps a `WebSocketInterceptorFn` as a tagged `WebSocketInterceptor`.
|
|
2472
2052
|
*
|
|
2473
2053
|
* Returns `{ kind: 'web-socket', fn }`. WebSocket interceptors run only for
|
|
2474
|
-
* WebSocket
|
|
2054
|
+
* WebSocket operations. `next` and the interceptor return a
|
|
2475
2055
|
* {@link WebSocketSessionLike}, the interceptor-facing session. A wrapper or
|
|
2476
2056
|
* short-circuit session must forward its `[Symbol.asyncDispose]()` teardown.
|
|
2477
2057
|
*
|
|
@@ -2483,7 +2063,7 @@ export declare function createWebSocketInterceptor(fn: WebSocketInterceptorFn):
|
|
|
2483
2063
|
/**
|
|
2484
2064
|
* Any tagged interceptor accepted by client interceptor options.
|
|
2485
2065
|
*
|
|
2486
|
-
* `kind` (`'http'`, `'sse'`, or `'web-socket'`) selects which
|
|
2066
|
+
* `kind` (`'http'`, `'sse'`, or `'web-socket'`) selects which operations an
|
|
2487
2067
|
* interceptor runs for. `withInterceptors` accepts any mix; each transport runs
|
|
2488
2068
|
* only its own kind, in registration order.
|
|
2489
2069
|
*
|
|
@@ -2603,7 +2183,7 @@ interface ClientWebSocketOptions {
|
|
|
2603
2183
|
* - **onInvalidEvent** — Called when an event has no matching struct and no `default` struct (`'missing-struct'`), or its data fails validation (`'validation-failed'`). The event is skipped. An error thrown by the hook does not close the stream.
|
|
2604
2184
|
* - **reconnect** — Opt-in. Without it the stream never reconnects. `attempts` defaults to **3** per outage; `attempts: 0` disables retry. A successful handshake resets the budget, callback `attempt`, and backoff exponent. `delayMs` is the first base delay, 1000 by default, and a server-sent `retry:` value replaces it. `factor` defaults to 1. `jitter` is a 0–1 multiplicative factor and defaults to 0. `maxDelayMs` caps the final delay after jitter and rounding; without a configured cap, the platform limit of `2_147_483_647` ms still applies. A zero base stays zero; valid-number overflow saturates at the caps. Without `shouldReconnect` only `GET`, `HEAD`, `OPTIONS`, `PUT`, and `DELETE` reconnect; with it, its result decides for every method and its context carries `method`. A `ReadableStream` request body never reconnects. Reconnect sends the latest ID as UTF-8 bytes in `Last-Event-ID`; an empty ID clears it and an ID containing NUL is ignored.
|
|
2605
2185
|
*
|
|
2606
|
-
* Reconnect options are validated before interceptors or Fetch: `attempts` is a non-negative safe integer; `delayMs` must be finite and non-negative; `maxDelayMs` must be a non-negative finite number or positive `Infinity`, which removes the configured cap but not the platform limit of `2_147_483_647` ms; `factor` is finite and positive; `jitter` is finite and within 0–1. Invalid values return `REQ_OPTIONS_INVALID`
|
|
2186
|
+
* Reconnect options are validated before interceptors or Fetch: `attempts` is a non-negative safe integer; `delayMs` must be finite and non-negative; `maxDelayMs` must be a non-negative finite number or positive `Infinity`, which removes the configured cap but not the platform limit of `2_147_483_647` ms; `factor` is finite and positive; `jitter` is finite and within 0–1. Invalid values return `REQ_OPTIONS_INVALID` when the operation runs.
|
|
2607
2187
|
*
|
|
2608
2188
|
* Set these with `withSSEHandle`, `withSSEOnInvalidEvent`, and `withSSEReconnect`. Omitting `withSSEReconnect` disables retry.
|
|
2609
2189
|
*
|
|
@@ -2670,7 +2250,7 @@ interface ClientSSEConfig extends ClientSSEOptions {
|
|
|
2670
2250
|
interface HttpClientOptions {
|
|
2671
2251
|
/** Base URL prepended to relative request paths. */
|
|
2672
2252
|
endpoint: string;
|
|
2673
|
-
/** Static default headers merged under
|
|
2253
|
+
/** Static default headers merged under headers returned by the builder for HTTP/SSE. */
|
|
2674
2254
|
headers?: Headers;
|
|
2675
2255
|
/** HTTP transport overrides; the default resolves global `fetch` on each call. */
|
|
2676
2256
|
http?: {
|
|
@@ -2680,8 +2260,6 @@ interface HttpClientOptions {
|
|
|
2680
2260
|
interceptors?: Interceptor[];
|
|
2681
2261
|
/** Serializes encoded query objects. Omit to use `URLSearchParams`. */
|
|
2682
2262
|
querySerializer?: QuerySerializer;
|
|
2683
|
-
/** Default HTTP execute timeout in milliseconds (SSE/WebSocket ignore this). */
|
|
2684
|
-
timeout?: number;
|
|
2685
2263
|
/** XSRF cookie/header mapping and optional token provider. */
|
|
2686
2264
|
xsrf?: {
|
|
2687
2265
|
/** Cookie name that stores the XSRF token. */
|
|
@@ -2699,7 +2277,7 @@ interface HttpClientOptions {
|
|
|
2699
2277
|
/**
|
|
2700
2278
|
* Input-shaped client options, including SSE and WebSocket, that mirror what the option helpers configure.
|
|
2701
2279
|
*
|
|
2702
|
-
* The user-facing shape of the settings before defaults are applied. `createClient` does not accept this object; configure a client with option helpers such as `withEndpoint
|
|
2280
|
+
* The user-facing shape of the settings before defaults are applied. `createClient` does not accept this object; configure a client with option helpers such as `withEndpoint`. {@link ClientConfig} is the resolved counterpart. The HTTP members come from the non-exported `HttpClientOptions` base and are shown inline.
|
|
2703
2281
|
*
|
|
2704
2282
|
* @group client
|
|
2705
2283
|
*/
|
|
@@ -2713,7 +2291,7 @@ interface ClientOptions extends HttpClientOptions {
|
|
|
2713
2291
|
interface HttpClientConfig {
|
|
2714
2292
|
/** Base URL prepended to relative request paths. */
|
|
2715
2293
|
endpoint: string;
|
|
2716
|
-
/** Static default headers merged under
|
|
2294
|
+
/** Static default headers merged under headers returned by the builder for HTTP/SSE. */
|
|
2717
2295
|
headers?: Headers;
|
|
2718
2296
|
/** HTTP transport with a required fetch handle. */
|
|
2719
2297
|
http: {
|
|
@@ -2723,8 +2301,6 @@ interface HttpClientConfig {
|
|
|
2723
2301
|
interceptors: Interceptor[];
|
|
2724
2302
|
/** Serializes encoded query objects. Omit to use `URLSearchParams`. */
|
|
2725
2303
|
querySerializer?: QuerySerializer;
|
|
2726
|
-
/** Default HTTP execute timeout in milliseconds (SSE/WebSocket ignore this). */
|
|
2727
|
-
timeout?: number;
|
|
2728
2304
|
/** Resolved XSRF settings when enabled. */
|
|
2729
2305
|
xsrf?: {
|
|
2730
2306
|
/** Cookie name that stores the XSRF token. */
|
|
@@ -2766,7 +2342,7 @@ type ClientOption = (config: ClientConfig) => void;
|
|
|
2766
2342
|
/**
|
|
2767
2343
|
* Sets the valid absolute base URL prepended to relative request paths.
|
|
2768
2344
|
*
|
|
2769
|
-
* The default is an empty string, so execution requires an explicit endpoint. Its pathname is kept as a directory; its query and hash are discarded. For WebSocket
|
|
2345
|
+
* The default is an empty string, so execution requires an explicit endpoint. Its pathname is kept as a directory; its query and hash are discarded. For WebSocket operations, an `http:` base becomes `ws:` and `https:` becomes `wss:`.
|
|
2770
2346
|
*
|
|
2771
2347
|
* A missing, relative, or invalid endpoint, or an illegal request path, fails with `REQ_BUILD_FAILED` during building, before any interceptor or transport runs, even when an interceptor would short-circuit. HTTP, SSE, and WebSocket share this rule. The resolved request must keep the base origin and stay under its directory; C0 control characters (including tab, CR, and LF), backslashes, `?`, `#`, and directory escapes in a path are rejected. Scheme-like and protocol-relative forms are rejected even with leading spaces; a plain inner space is allowed and sent as `%20`. An interceptor's final `req.endpoint` is checked against its final `req.baseEndpoint` with the same rule, but it may deliberately replace the base with another valid absolute URL. Deterministic URL errors are never retried.
|
|
2772
2348
|
*
|
|
@@ -2789,22 +2365,10 @@ export declare function withEndpoint(endpoint: string): ClientOption;
|
|
|
2789
2365
|
* @group client
|
|
2790
2366
|
*/
|
|
2791
2367
|
export declare function withHeaders(headers: HeadersInit): ClientOption;
|
|
2792
|
-
/**
|
|
2793
|
-
* Sets the default timeout, in milliseconds, for HTTP `execute` only.
|
|
2794
|
-
*
|
|
2795
|
-
* SSE and WebSocket ignore it. `ms` must be a positive safe integer no greater than `2_147_483_647`. Anything else throws `RangeError` immediately, when `withTimeout` is called, not when the client executes.
|
|
2796
|
-
*
|
|
2797
|
-
* The timer starts before the interceptor chain runs. When it fires, the call returns a `NET_TIMEOUT` fault. Execute `{ timeout }` replaces this default for that call. Execute `{ abort }` combines with the default: an abort gives `NET_ABORTED`, the timer gives `NET_TIMEOUT`. Passing both `abort` and `timeout` to the same `execute` call is still rejected.
|
|
2798
|
-
*
|
|
2799
|
-
* @param ms - Positive safe integer timeout in milliseconds.
|
|
2800
|
-
* @returns An option that writes `config.timeout`.
|
|
2801
|
-
* @group client
|
|
2802
|
-
*/
|
|
2803
|
-
export declare function withTimeout(ms: number): ClientOption;
|
|
2804
2368
|
/**
|
|
2805
2369
|
* Appends interceptors to the client interceptor chain.
|
|
2806
2370
|
*
|
|
2807
|
-
* Calling it again appends more; it never replaces earlier ones. The first registered interceptor is the outermost layer. HTTP, SSE, and WebSocket interceptors can be mixed in one call.
|
|
2371
|
+
* Calling it again appends more; it never replaces earlier ones. The first registered interceptor is the outermost layer. HTTP, SSE, and WebSocket interceptors can be mixed in one call. When an operation runs, only the interceptors of that transport run, in their registration order.
|
|
2808
2372
|
*
|
|
2809
2373
|
* @param interceptors - Interceptors applied in registration order.
|
|
2810
2374
|
* @returns An option that pushes onto `config.interceptors`.
|
|
@@ -2848,7 +2412,7 @@ export declare function withSSEHandle(fetchImpl: FetchHandle): ClientOption;
|
|
|
2848
2412
|
/**
|
|
2849
2413
|
* Replaces the WebSocket constructor used for socket connections.
|
|
2850
2414
|
*
|
|
2851
|
-
* The default is `globalThis.WebSocket`. `WebSocketImpl` is a {@link WebSocketHandleConstructor} that returns a {@link WebSocketHandle}. If no constructor is available,
|
|
2415
|
+
* The default is `globalThis.WebSocket`. `WebSocketImpl` is a {@link WebSocketHandleConstructor} that returns a {@link WebSocketHandle}. If no constructor is available, a WebSocket operation fails with an `ENV_UNSUPPORTED` fault.
|
|
2852
2416
|
*
|
|
2853
2417
|
* @param WebSocketImpl - Constructor that returns a `WebSocketHandle`.
|
|
2854
2418
|
* @returns An option that sets `config.webSocket.handle`.
|
|
@@ -2867,7 +2431,7 @@ export declare function withWebSocketHandle(WebSocketImpl: WebSocketHandleConstr
|
|
|
2867
2431
|
* - `attempt` is `0` for the first connect and grows by one for each reconnect.
|
|
2868
2432
|
* - Pass `signal` into token refreshes and other async work so cancelling the session stops them.
|
|
2869
2433
|
* - If the hook throws, the attempt fails with an `EXT_HOOK_FAILED` fault.
|
|
2870
|
-
* - A `beforeConnect` in the
|
|
2434
|
+
* - A `beforeConnect` in the request options replaces this one for that call.
|
|
2871
2435
|
*
|
|
2872
2436
|
* @param beforeConnect - Hook receiving attempt index and abort signal.
|
|
2873
2437
|
* @returns An option that sets `config.webSocket.beforeConnect`.
|
|
@@ -2879,7 +2443,7 @@ export declare function withWebSocketBeforeConnect(beforeConnect: ClientWebSocke
|
|
|
2879
2443
|
*
|
|
2880
2444
|
* They are passed as the second argument to the `WebSocket` constructor only when the list is not empty, so the platform can run the RFC 6455 subprotocol negotiation. They matter only when the server requires a specific subprotocol, for example `['json']` or `['v1']`.
|
|
2881
2445
|
*
|
|
2882
|
-
* Precedence, highest first: the `protocols`
|
|
2446
|
+
* Precedence, highest first: the `protocols` request option, this client option, then `protocols` on the endpoint definition.
|
|
2883
2447
|
*
|
|
2884
2448
|
* @param protocols - Subprotocol list for the WebSocket constructor.
|
|
2885
2449
|
* @returns An option that sets `config.webSocket.protocols`.
|
|
@@ -2904,8 +2468,8 @@ export declare function withWebSocketProtocols(protocols: readonly string[]): Cl
|
|
|
2904
2468
|
* - With `timeoutMs`, an acknowledgement is expected after each heartbeat. `isAck` receives the decoded incoming message; when it returns `true`, the timer is cleared and that message is **not** delivered to `receive`.
|
|
2905
2469
|
* - If no ack arrives within `timeoutMs`, or a heartbeat cannot be sent, the session fails. This does not trigger a reconnect.
|
|
2906
2470
|
* - Heartbeat uses the same JSON guard as `session.send`: a value JSON cannot represent after struct encoding causes `TypeError` and ends the logical session.
|
|
2907
|
-
* - `intervalMs` and `timeoutMs` must be positive, finite, and at most `2_147_483_647`; otherwise
|
|
2908
|
-
* - A `heartbeat` in the
|
|
2471
|
+
* - `intervalMs` and `timeoutMs` must be positive, finite, and at most `2_147_483_647`; otherwise the operation fails with `REQ_OPTIONS_INVALID`.
|
|
2472
|
+
* - A `heartbeat` in the request options replaces this one for that call.
|
|
2909
2473
|
*
|
|
2910
2474
|
* @param options - Heartbeat interval, payload, timeout, and ACK predicate.
|
|
2911
2475
|
* @returns An option that sets `config.webSocket.heartbeat`.
|
|
@@ -2931,8 +2495,8 @@ export declare function withWebSocketHeartbeat(options: ClientWebSocketOptions["
|
|
|
2931
2495
|
* - `attempts` is the retry budget for each outage. It defaults to `3`, and `0` disables reconnection. Successful `open` resets the budget and backoff exponent; the next outage starts at retry 1. Omitting it does not give unlimited retries within one outage. A socket that successfully opens and is immediately closed again by the server can keep reconnecting at the base delay (subject to jitter and caps), because every open resets the budget; use `shouldReconnect` to stop it.
|
|
2932
2496
|
* - `delayMs` defaults to `1000`, `factor` to `2`, `maxDelayMs` to `30000`, and `jitter` (0 to 1) to `0`. Retry _n_ starts with `delayMs * factor^(n-1)`, capped at `maxDelayMs`; jitter and rounding follow, then the final delay is capped again at `maxDelayMs` and `2_147_483_647` ms. A zero base stays zero; valid-number overflow saturates at those caps.
|
|
2933
2497
|
* - `shouldReconnect` can return `false` to end the session instead. Without it every close is retried while the budget lasts. It is not called for a manual `session.close()`.
|
|
2934
|
-
* - Reconnect options are validated before connecting: `attempts` must be a non-negative safe integer; `delayMs` must be finite and non-negative; `maxDelayMs` must be a non-negative finite number or positive `Infinity`, which removes the configured cap but not the platform limit of `2_147_483_647` ms; `factor` must be finite and positive; `jitter` must be finite and within 0–1. Invalid values make
|
|
2935
|
-
* - A `reconnect` in the
|
|
2498
|
+
* - Reconnect options are validated before connecting: `attempts` must be a non-negative safe integer; `delayMs` must be finite and non-negative; `maxDelayMs` must be a non-negative finite number or positive `Infinity`, which removes the configured cap but not the platform limit of `2_147_483_647` ms; `factor` must be finite and positive; `jitter` must be finite and within 0–1. Invalid values make the operation fail with `REQ_OPTIONS_INVALID` before connecting. `attempts: 0` disables subsequent retries, but all explicitly supplied reconnect fields are still validated before the initial connection.
|
|
2499
|
+
* - A `reconnect` in the request options replaces this one for that call.
|
|
2936
2500
|
*
|
|
2937
2501
|
* @param options - Retry budget, backoff, and `shouldReconnect` gate.
|
|
2938
2502
|
* @returns An option that sets `config.webSocket.reconnect`.
|
|
@@ -2993,7 +2557,7 @@ export declare function withSSEOnInvalidEvent(handler: ClientSSEOptions["onInval
|
|
|
2993
2557
|
* - `delayMs`, `factor`, `jitter` (0 to 1), and `maxDelayMs` shape the backoff. `factor` defaults to `1` and `jitter` to `0`. `maxDelayMs` caps the final delay after jitter and rounding. Without a configured cap, the platform timer limit of `2_147_483_647` ms still applies. A zero base stays zero; valid-number overflow saturates at the caps.
|
|
2994
2558
|
* - `delayMs` is only the starting base delay (`1000` by default). A server `retry:` field (digits only, in milliseconds) replaces it for later attempts.
|
|
2995
2559
|
* - The last event id is sent again as UTF-8 bytes in `Last-Event-ID` on the next attempt. An empty `id:` clears it; an ID containing NUL is ignored.
|
|
2996
|
-
* - Reconnect options are validated before interceptors or Fetch: `attempts` must be a non-negative safe integer; `delayMs` must be finite and non-negative; `maxDelayMs` must be a non-negative finite number or positive `Infinity`, which removes the configured cap but not the platform limit of `2_147_483_647` ms; `factor` must be finite and positive; `jitter` must be finite and within 0–1. Invalid values return `REQ_OPTIONS_INVALID`
|
|
2560
|
+
* - Reconnect options are validated before interceptors or Fetch: `attempts` must be a non-negative safe integer; `delayMs` must be finite and non-negative; `maxDelayMs` must be a non-negative finite number or positive `Infinity`, which removes the configured cap but not the platform limit of `2_147_483_647` ms; `factor` must be finite and positive; `jitter` must be finite and within 0–1. Invalid values return `REQ_OPTIONS_INVALID` when the operation runs.
|
|
2997
2561
|
*
|
|
2998
2562
|
* @param options - Retry budget, backoff, and `shouldReconnect` gate.
|
|
2999
2563
|
* @returns An option that sets `config.sse.reconnect`.
|
|
@@ -3024,41 +2588,221 @@ export declare function withXSRF(options?: HttpClientOptions["xsrf"]): ClientOpt
|
|
|
3024
2588
|
* @group client
|
|
3025
2589
|
*/
|
|
3026
2590
|
export declare function withCredentials(value: boolean): ClientOption;
|
|
2591
|
+
/**
|
|
2592
|
+
* Internal symbol key for a client's base configuration and request options.
|
|
2593
|
+
*
|
|
2594
|
+
* Application code passes the client to an operation. It does not call the client or read this property.
|
|
2595
|
+
*
|
|
2596
|
+
* @group client
|
|
2597
|
+
*/
|
|
3027
2598
|
declare const CLIENT: unique symbol;
|
|
3028
2599
|
/**
|
|
3029
|
-
*
|
|
2600
|
+
* Flat per-call options. Each protocol reads the fields it understands and ignores the rest.
|
|
2601
|
+
*
|
|
2602
|
+
* SSE reads only `signal` from request options. SSE reconnect comes from client configuration (`withSSEReconnect`), so `client({ reconnect })` affects WebSocket only.
|
|
3030
2603
|
*
|
|
3031
|
-
*
|
|
2604
|
+
* `signal` cancels HTTP, SSE, and WebSocket calls. `onUploadProgress` and `onDownloadProgress` apply to HTTP. `beforeConnect`, `protocols`, `heartbeat`, and `reconnect` apply to WebSocket and replace the client setting for that call as a whole value. There is no `timeout` or `abort` field. Pass `AbortSignal.timeout(ms)` as `signal` when a call needs a deadline.
|
|
3032
2605
|
*
|
|
3033
2606
|
* @group client
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
2607
|
+
*/
|
|
2608
|
+
type RequestOptions = {
|
|
2609
|
+
/** Aborts the call. An already aborted signal fails the call before transport. */
|
|
2610
|
+
signal?: AbortSignal;
|
|
2611
|
+
/** Observes HTTP upload progress. */
|
|
2612
|
+
onUploadProgress?: HttpProgressFn;
|
|
2613
|
+
/** Observes HTTP download progress. */
|
|
2614
|
+
onDownloadProgress?: HttpProgressFn;
|
|
2615
|
+
/** Runs before each WebSocket connect attempt for this call. */
|
|
2616
|
+
beforeConnect?: ClientWebSocketOptions["beforeConnect"];
|
|
2617
|
+
/** WebSocket subprotocols for this call. Replaces the client list; it is not appended. */
|
|
2618
|
+
protocols?: readonly string[];
|
|
2619
|
+
/** WebSocket heartbeat for this call. Replaces the client heartbeat as a whole value. */
|
|
2620
|
+
heartbeat?: ClientWebSocketOptions["heartbeat"];
|
|
2621
|
+
/** WebSocket reconnect policy for this call. Replaces the client policy as a whole value. */
|
|
2622
|
+
reconnect?: ClientWebSocketOptions["reconnect"];
|
|
3047
2623
|
};
|
|
2624
|
+
interface ClientState {
|
|
2625
|
+
readonly config: ClientConfig;
|
|
2626
|
+
readonly options: RequestOptions;
|
|
2627
|
+
}
|
|
3048
2628
|
/**
|
|
3049
|
-
*
|
|
2629
|
+
* Client value that operations accept.
|
|
2630
|
+
*
|
|
2631
|
+
* A client value carries the base configuration and one call's request options. Operations accept it. It is not callable; create one by calling the factory returned by `createClient`. Calling a client value throws a `TypeError` at runtime and fails to compile.
|
|
3050
2632
|
*
|
|
3051
|
-
*
|
|
2633
|
+
* Create a client value per call. Reusing a value that carries `signal` shares that signal between calls.
|
|
2634
|
+
*
|
|
2635
|
+
* @group client
|
|
2636
|
+
* @see {@link createClient}
|
|
2637
|
+
* @see {@link RequestOptions}
|
|
2638
|
+
*/
|
|
2639
|
+
interface Client {
|
|
2640
|
+
/** Internal state. Not part of the call surface. */
|
|
2641
|
+
readonly [CLIENT]: ClientState;
|
|
2642
|
+
}
|
|
2643
|
+
/**
|
|
2644
|
+
* Callable root client returned by `createClient`.
|
|
2645
|
+
*
|
|
2646
|
+
* A factory is a {@link Client} that carries no request options, so it can be passed to an operation directly. Calling it with {@link RequestOptions} returns a plain, non-callable `Client` value for one call and performs no I/O. That value cannot be called again: `client()()` fails to compile and throws a `TypeError` at runtime. The seven known fields are copied from the argument into a fresh options object, unknown fields are ignored, and fields whose value is `undefined` are omitted. Nested `heartbeat`, `protocols`, and `reconnect` values are kept by reference. There is no parent overlay: `client()`, `client(undefined)`, and `client({})` all return a client with no request options. A getter that throws escapes the call and is not converted into a fault; the factory stays usable.
|
|
2647
|
+
*
|
|
2648
|
+
* @group client
|
|
2649
|
+
* @see {@link createClient}
|
|
2650
|
+
* @see {@link Client}
|
|
2651
|
+
* @see {@link RequestOptions}
|
|
2652
|
+
*/
|
|
2653
|
+
interface DerivableClient extends Client {
|
|
2654
|
+
/** Returns a client value that carries `options` for one call. */
|
|
2655
|
+
(options?: RequestOptions): Client;
|
|
2656
|
+
}
|
|
2657
|
+
/**
|
|
2658
|
+
* Creates a Defjs {@link DerivableClient} from option helpers.
|
|
2659
|
+
*
|
|
2660
|
+
* Options apply in order: a later option overwrites an earlier one for the same setting, and interceptors accumulate. Prefer creating the client inside the request boundary when interceptors close over auth or tenants. Default HTTP/SSE fetch availability is checked when an operation invokes transport.
|
|
2661
|
+
*
|
|
2662
|
+
* The returned factory is a function. Calling it with {@link RequestOptions} returns a {@link Client} value for one call and performs no I/O; see {@link DerivableClient} for the snapshot rules. The factory itself is also a `Client` and carries no request options, so it can be passed to an operation directly. The base configuration is shared by every client value and is not frozen at runtime. It is fixed by convention: nothing in the library changes it, and applications should not either.
|
|
3052
2663
|
*
|
|
3053
2664
|
* @param options - Client option helpers such as `withEndpoint`.
|
|
3054
|
-
* @returns A
|
|
2665
|
+
* @returns A callable factory that carries the resolved base configuration.
|
|
3055
2666
|
*
|
|
3056
2667
|
* @group client
|
|
2668
|
+
* @see {@link DerivableClient}
|
|
3057
2669
|
* @see {@link Client}
|
|
3058
2670
|
* @see {@link ClientOption}
|
|
2671
|
+
* @see {@link RequestOptions}
|
|
3059
2672
|
* @exampleFile examples/api/create-client.ts#example
|
|
3060
2673
|
*/
|
|
3061
|
-
export declare function createClient(...options: ClientOption[]):
|
|
2674
|
+
export declare function createClient(...options: ClientOption[]): DerivableClient;
|
|
2675
|
+
/**
|
|
2676
|
+
* HTTP fields of {@link RequestOptions}: progress callbacks and `signal`.
|
|
2677
|
+
*
|
|
2678
|
+
* `onDownloadProgress` and `onUploadProgress` are {@link HttpProgressFn}
|
|
2679
|
+
* callbacks. They receive an {@link HttpProgressEvent} with `loaded`, `total`,
|
|
2680
|
+
* and `lengthComputable`. Other request fields are ignored by HTTP.
|
|
2681
|
+
*
|
|
2682
|
+
* @group http
|
|
2683
|
+
*/
|
|
2684
|
+
export type UseRequestConfig = {
|
|
2685
|
+
/** Aborts the call. */
|
|
2686
|
+
signal?: AbortSignal;
|
|
2687
|
+
/** Observes download progress. */
|
|
2688
|
+
onDownloadProgress?: HttpProgressFn;
|
|
2689
|
+
/** Observes upload progress. */
|
|
2690
|
+
onUploadProgress?: HttpProgressFn;
|
|
2691
|
+
};
|
|
2692
|
+
/**
|
|
2693
|
+
* HTTP fields read from {@link RequestOptions} for one call.
|
|
2694
|
+
*
|
|
2695
|
+
* Progress callbacks and `signal`. There is no `timeout` or `abort`.
|
|
2696
|
+
*
|
|
2697
|
+
* @group http
|
|
2698
|
+
*/
|
|
2699
|
+
export type HttpExecuteOptions = UseRequestConfig;
|
|
2700
|
+
/**
|
|
2701
|
+
* Operation returned by `defineRequest`.
|
|
2702
|
+
*
|
|
2703
|
+
* The first argument is a {@link Client}. Further arguments are the input, and only the input: none when the definition declares no `input`, optional when the input struct accepts `undefined`, and required otherwise. Calling it starts the request and returns the error-first tuple.
|
|
2704
|
+
*
|
|
2705
|
+
* @group http
|
|
2706
|
+
*/
|
|
2707
|
+
export type RequestEndpoint<Args extends unknown[], Data, ErrorData, Response extends HttpMeta> = (client: Client, ...args: Args) => Promise<[error: null, result: Data, response: Response] | [error: FaultOf<ErrorData>, result: undefined, response: undefined]>;
|
|
2708
|
+
type DeclaredBody<TStruct> = [TStruct] extends [undefined] ? undefined : Infer<TStruct>;
|
|
2709
|
+
type DeclaredResponse<TStruct> = [TStruct] extends [undefined] ? HttpMeta : DecodedResponse<Infer<TStruct>>;
|
|
2710
|
+
/**
|
|
2711
|
+
* Decoded success body for the declared `output` struct, or `undefined` when none is declared.
|
|
2712
|
+
*
|
|
2713
|
+
* @group http
|
|
2714
|
+
*/
|
|
2715
|
+
export type RequestSuccessData<TOutput extends AnyStruct | undefined> = DeclaredBody<TOutput>;
|
|
2716
|
+
/**
|
|
2717
|
+
* Decoded error body for the declared `error` struct, or `undefined` when none is declared.
|
|
2718
|
+
*
|
|
2719
|
+
* @group http
|
|
2720
|
+
*/
|
|
2721
|
+
export type RequestErrorData<TError extends AnyStruct | undefined> = DeclaredBody<TError>;
|
|
2722
|
+
type ResponseDeclaration<TOutput extends AnyStruct | undefined, TError extends AnyStruct | undefined> = ([TOutput] extends [undefined] ? {
|
|
2723
|
+
output?: never;
|
|
2724
|
+
} : {
|
|
2725
|
+
output: TOutput;
|
|
2726
|
+
}) & ([TError] extends [undefined] ? {
|
|
2727
|
+
error?: never;
|
|
2728
|
+
} : {
|
|
2729
|
+
error: TError;
|
|
2730
|
+
});
|
|
2731
|
+
/**
|
|
2732
|
+
* Contract for an HTTP endpoint: method, path, optional input, and the structs that decode its bodies.
|
|
2733
|
+
*
|
|
2734
|
+
* Declaring `input` requires an explicit `builder` to place the parsed value on
|
|
2735
|
+
* the request. `input` only defines the parameters; the builder alone decides
|
|
2736
|
+
* where each value goes. Only definitions without `input` may omit `builder`.
|
|
2737
|
+
* `output` declares the body for a 2xx response, `error` the body for anything
|
|
2738
|
+
* else. Only one of the two ever runs, and omitting one means that body is never
|
|
2739
|
+
* read. `ResponseDeclaration` is an internal helper type: `output` and `error`
|
|
2740
|
+
* are required only when the matching type parameter is a struct. There is no
|
|
2741
|
+
* `responseType`: the struct kind selects how a declared body is read. Pass to
|
|
2742
|
+
* `defineRequest` to get a typed endpoint.
|
|
2743
|
+
*
|
|
2744
|
+
* @group http
|
|
2745
|
+
*/
|
|
2746
|
+
export type RequestDefinition<TInput extends AnyStruct | undefined = undefined, TOutput extends AnyStruct | undefined = undefined, TError extends AnyStruct | undefined = undefined> = ResponseDeclaration<TOutput, TError> & {
|
|
2747
|
+
builder?: OutboundBuilder;
|
|
2748
|
+
input?: TInput;
|
|
2749
|
+
method: string;
|
|
2750
|
+
operation?: string;
|
|
2751
|
+
path: string;
|
|
2752
|
+
};
|
|
2753
|
+
/**
|
|
2754
|
+
* Await-result tuple for an HTTP call: success is `[null, data, response]`, and failure is `[fault, undefined, undefined]`.
|
|
2755
|
+
*
|
|
2756
|
+
* `TData` and `TErrorData` are decoded body types. On success the third slot
|
|
2757
|
+
* carries `body` only when `output` was declared. On failure it is `undefined`,
|
|
2758
|
+
* because the fault already holds whatever response metadata existed.
|
|
2759
|
+
*
|
|
2760
|
+
* @group http
|
|
2761
|
+
*/
|
|
2762
|
+
export type HttpAwaitResult<TData = undefined, TErrorData = undefined> = [error: null, result: TData, response: [TData] extends [undefined] ? HttpMeta : DecodedResponse<TData>] | [error: FaultOf<TErrorData>, result: undefined, response: undefined];
|
|
2763
|
+
/**
|
|
2764
|
+
* Declares a typed HTTP request endpoint.
|
|
2765
|
+
*
|
|
2766
|
+
* Pass method, path, an optional input struct, and the single `output` and
|
|
2767
|
+
* `error` structs. Call the returned operation with a client and, when declared, the input.
|
|
2768
|
+
*
|
|
2769
|
+
* The contract is `method`, `path`, an optional `input` struct, optional
|
|
2770
|
+
* `output` and `error` structs, and an optional `operation`. A declared `input`
|
|
2771
|
+
* always requires an explicit `builder`. `input` only defines the parameters;
|
|
2772
|
+
* the builder alone decides where each value goes. Only definitions without
|
|
2773
|
+
* `input` may omit `builder`. `ResponseDeclaration` and `BuilderField` are
|
|
2774
|
+
* internal helper types: `output` and `error` are required only when the
|
|
2775
|
+
* matching type parameter is a struct, and `builder` is
|
|
2776
|
+
* `(input: BuilderInput<TInput>) => HttpRequestShape` when `input` is declared.
|
|
2777
|
+
*
|
|
2778
|
+
* `output` is one struct for the 2xx body; `error` is one struct for every
|
|
2779
|
+
* non-2xx body. Neither is keyed by status. A declaration is an assertion:
|
|
2780
|
+
* omitting one means that body is never read.
|
|
2781
|
+
*
|
|
2782
|
+
* @param definition - Request contract (method, path, input, builder, output).
|
|
2783
|
+
* @returns An operation `(client, ...input) => Promise<error-first tuple>`.
|
|
2784
|
+
*
|
|
2785
|
+
* The checked example file passes the whole input object as `path`. This snippet maps individual fields into `path` and `query` instead:
|
|
2786
|
+
*
|
|
2787
|
+
* @example
|
|
2788
|
+
* ```ts
|
|
2789
|
+
* const getUser = defineRequest({
|
|
2790
|
+
* method: 'GET',
|
|
2791
|
+
* path: '/users/:id',
|
|
2792
|
+
* input: struct.object({ id: struct.number(), verbose: struct.boolean() }),
|
|
2793
|
+
* builder: (input) => ({ path: { id: input.id }, query: { verbose: input.verbose } }),
|
|
2794
|
+
* output: struct.object({ id: struct.number(), name: struct.string() }),
|
|
2795
|
+
* })
|
|
2796
|
+
* ```
|
|
2797
|
+
* @group http
|
|
2798
|
+
* @exampleFile examples/api/define-request.ts#example
|
|
2799
|
+
*/
|
|
2800
|
+
export declare function defineRequest<const M extends string, const P extends string, TInput extends AnyStruct | undefined = undefined, TOutput extends AnyStruct | undefined = undefined, TError extends AnyStruct | undefined = undefined>(definition: ResponseDeclaration<TOutput, TError> & {
|
|
2801
|
+
input?: TInput;
|
|
2802
|
+
method: M;
|
|
2803
|
+
operation?: string;
|
|
2804
|
+
path: P;
|
|
2805
|
+
} & BuilderField<NoInfer<TInput>, HttpRequestShape<NoInfer<P>, NoInfer<M>>>): RequestEndpoint<EndpointArgs<TInput>, RequestSuccessData<TOutput>, RequestErrorData<TError>, DeclaredResponse<TOutput>>;
|
|
3062
2806
|
/**
|
|
3063
2807
|
* Default HTTP transport: perform `httpRequest` with `fetch` and return an `HttpResponse`.
|
|
3064
2808
|
*
|
|
@@ -3067,7 +2811,7 @@ export declare function createClient(...options: ClientOption[]): Client;
|
|
|
3067
2811
|
* global `fetch` resolved at send time. It rejects, rather than resolving with
|
|
3068
2812
|
* a synthetic response, when no response reached the client.
|
|
3069
2813
|
*
|
|
3070
|
-
* @param httpRequest - Normalized request (URL, headers, body,
|
|
2814
|
+
* @param httpRequest - Normalized request (URL, headers, body, signal, progress hooks).
|
|
3071
2815
|
* @param fetchImpl - Fetch implementation; defaults to global `fetch`. The library default handle is called as
|
|
3072
2816
|
* `(url, init)` while the global is untouched, and its body is read in one piece unless download progress is observed. Any other handle receives a
|
|
3073
2817
|
* `Request` and its body is read chunk by chunk.
|
|
@@ -3079,7 +2823,7 @@ export declare function fetchHandler(httpRequest: HttpRequest, fetchImpl?: Fetch
|
|
|
3079
2823
|
/**
|
|
3080
2824
|
* Resolves a relative definition path under the base endpoint's origin and directory into a URL.
|
|
3081
2825
|
*
|
|
3082
|
-
* During
|
|
2826
|
+
* During an operation, a missing, relative, or invalid base or an illegal
|
|
3083
2827
|
* path becomes `REQ_BUILD_FAILED` before any interceptor or transport runs,
|
|
3084
2828
|
* including a short-circuiting interceptor, for HTTP, SSE, and WebSocket alike.
|
|
3085
2829
|
* An interceptor's final `req.endpoint` is also validated against its final
|
|
@@ -3122,7 +2866,7 @@ type BasicAuthInterceptorOptions = {
|
|
|
3122
2866
|
* `encode`, calling `basicAuthHttpInterceptor` throws
|
|
3123
2867
|
* `Error: BasicAuthInterceptor is not supported in this environment` when `btoa`
|
|
3124
2868
|
* is not available in the runtime. Use {@link basicAuthSSEInterceptor} for SSE
|
|
3125
|
-
*
|
|
2869
|
+
* operations.
|
|
3126
2870
|
*
|
|
3127
2871
|
* @param fn - Factory returning username/password for each request.
|
|
3128
2872
|
* @param options - Optional custom encoder (defaults to `btoa`).
|
|
@@ -3144,4 +2888,122 @@ export declare function basicAuthHttpInterceptor(fn: () => BasicCredential, opti
|
|
|
3144
2888
|
* @group interceptors
|
|
3145
2889
|
*/
|
|
3146
2890
|
export declare function basicAuthSSEInterceptor(fn: () => BasicCredential, options?: BasicAuthInterceptorOptions): SSEInterceptor;
|
|
3147
|
-
|
|
2891
|
+
/**
|
|
2892
|
+
* Map from SSE event names to the structs that decode their data.
|
|
2893
|
+
*
|
|
2894
|
+
* An event with no `event:` field is named `message`. An event whose name has no own entry uses the `default` struct; with neither, the event is skipped and `onInvalidEvent` is called. Declare the event name `__proto__` with a computed own key.
|
|
2895
|
+
*
|
|
2896
|
+
* A `string` event struct keeps the raw `data` text. Every other kind is JSON text: `JSON.parse`, then the struct. A bare `struct.literal` therefore needs JSON text, not an unquoted token.
|
|
2897
|
+
*
|
|
2898
|
+
* Reconnect lives on the client (`withSSEReconnect`). SSE `jitter` is a **0-1 multiplicative factor**, same as WebSocket.
|
|
2899
|
+
*
|
|
2900
|
+
* @group sse
|
|
2901
|
+
*/
|
|
2902
|
+
export type EventStructs = {
|
|
2903
|
+
[key: string]: AnyStruct;
|
|
2904
|
+
};
|
|
2905
|
+
type EventName<TKey extends string | number> = `${TKey}`;
|
|
2906
|
+
type KnownEventUnion<TEvents extends EventStructs> = { [K in keyof TEvents & (number | string)]: EventName<K> extends "default" ? never : {
|
|
2907
|
+
data: Infer<TEvents[K]>;
|
|
2908
|
+
event: EventName<K>;
|
|
2909
|
+
id?: string;
|
|
2910
|
+
}; }[keyof TEvents & (number | string)];
|
|
2911
|
+
type DefaultEventUnion<TEvents extends EventStructs> = "default" extends keyof TEvents ? {
|
|
2912
|
+
data: Infer<TEvents["default"]>;
|
|
2913
|
+
event: string;
|
|
2914
|
+
id?: string;
|
|
2915
|
+
} : never;
|
|
2916
|
+
/**
|
|
2917
|
+
* Union of parsed SSE events inferred from an EventStructs map.
|
|
2918
|
+
*
|
|
2919
|
+
* For each declared event name except `default`, the union has `{ event: <name>; data: Infer<TEvents[name]>; id?: string }`. When a `default` struct is declared, it adds `{ event: string; data: Infer<TEvents['default']>; id?: string }` for every event name that has no struct of its own. `KnownEventUnion` and `DefaultEventUnion` are internal helper types.
|
|
2920
|
+
*
|
|
2921
|
+
* @group sse
|
|
2922
|
+
*/
|
|
2923
|
+
export type EventStreamData<TEvents extends EventStructs> = TEvents extends EventStructs ? KnownEventUnion<TEvents> | DefaultEventUnion<TEvents> : never;
|
|
2924
|
+
interface EventStreamDefinitionBase<TEvents extends EventStructs = EventStructs> {
|
|
2925
|
+
events: TEvents;
|
|
2926
|
+
maxBufferSize: number;
|
|
2927
|
+
maxQueueSize: number;
|
|
2928
|
+
method?: string;
|
|
2929
|
+
operation?: string;
|
|
2930
|
+
path: string;
|
|
2931
|
+
}
|
|
2932
|
+
/** Makes `error` required only when an error struct is declared, so omission stays `Fault<undefined>`. */
|
|
2933
|
+
type EventStreamErrorField<TError extends AnyStruct | undefined> = [TError] extends [undefined] ? {
|
|
2934
|
+
error?: never;
|
|
2935
|
+
} : {
|
|
2936
|
+
error: TError;
|
|
2937
|
+
};
|
|
2938
|
+
/**
|
|
2939
|
+
* Contract that describes an SSE endpoint for defineEventStream.
|
|
2940
|
+
*
|
|
2941
|
+
* The composed members are:
|
|
2942
|
+
*
|
|
2943
|
+
* - `events`, `maxBufferSize`, and `maxQueueSize` (both limits are required positive safe integers), optional `method`, `operation`, and a required `path`.
|
|
2944
|
+
*
|
|
2945
|
+
* - `error`, required only when `TError` is a struct. It decodes the body of a failed handshake (a non-2xx response). The kind rule is the same as for HTTP: `string` is text, `blob` and `file` are blobs, `arrayBuffer` is bytes, and everything else is JSON.
|
|
2946
|
+
*
|
|
2947
|
+
* - `input` and `builder`. The request shape matches HTTP, including `body`; `GET` and `HEAD` cannot return a body. A declared `input` always requires an explicit `builder`. `input` only defines the parameters; the builder alone decides where each value goes. Only definitions without `input` may omit `builder`.
|
|
2948
|
+
*
|
|
2949
|
+
* `EventStreamDefinitionBase` and `EventStreamErrorField` are internal helper types.
|
|
2950
|
+
*
|
|
2951
|
+
* @group sse
|
|
2952
|
+
*/
|
|
2953
|
+
export type EventStreamDefinition<TInput extends AnyStruct | undefined = undefined, TEvents extends EventStructs = EventStructs, TError extends AnyStruct | undefined = undefined> = EventStreamDefinitionBase<TEvents> & EventStreamErrorField<TError> & {
|
|
2954
|
+
builder?: OutboundBuilder;
|
|
2955
|
+
input?: TInput;
|
|
2956
|
+
};
|
|
2957
|
+
/**
|
|
2958
|
+
* Await-result tuple from opening an SSE stream.
|
|
2959
|
+
*
|
|
2960
|
+
* - On success: `[null, stream, open]`. `open` is the returned connection's first successful handshake snapshot for native Defjs handles or wrappers forwarding the same live `open` object; custom handles or wrappers overriding `open` use their current public `open` even after reconnect, while `stream.open` stays live.
|
|
2961
|
+
*
|
|
2962
|
+
* - On failure: `[fault, undefined, open]`. `open` carries the response snapshot when the failure happened after a response arrived, for example a non-2xx handshake, and is `undefined` otherwise.
|
|
2963
|
+
*
|
|
2964
|
+
* - `TError` is the declared `error` struct. It types the decoded error body on the fault.
|
|
2965
|
+
*
|
|
2966
|
+
* @group sse
|
|
2967
|
+
*/
|
|
2968
|
+
export type StreamAwaitResult<TEvent, TError extends AnyStruct | undefined = undefined> = [error: null, stream: EventStreamHandle<TEvent>, open: EventStreamOpenInfo] | [error: Fault<TError>, stream: undefined, open: EventStreamOpenInfo | undefined];
|
|
2969
|
+
/**
|
|
2970
|
+
* SSE field of {@link RequestOptions}. HTTP progress and WebSocket fields are ignored.
|
|
2971
|
+
*
|
|
2972
|
+
* `signal` covers the whole stream, including after it opens. There is no startup-only deadline.
|
|
2973
|
+
*
|
|
2974
|
+
* @group sse
|
|
2975
|
+
*/
|
|
2976
|
+
export type EventStreamExecuteOptions = {
|
|
2977
|
+
/** Aborts the stream, including after it is open. */
|
|
2978
|
+
signal?: AbortSignal;
|
|
2979
|
+
};
|
|
2980
|
+
/**
|
|
2981
|
+
* Operation returned by `defineEventStream`.
|
|
2982
|
+
*
|
|
2983
|
+
* The first argument is a {@link Client}. Further arguments are the input only. Calling it opens the stream and returns the existing error-first tuple.
|
|
2984
|
+
*
|
|
2985
|
+
* @group sse
|
|
2986
|
+
*/
|
|
2987
|
+
export type EventStreamEndpoint<Args extends unknown[], Event, TError extends AnyStruct | undefined = undefined> = (client: Client, ...args: Args) => Promise<StreamAwaitResult<Event, TError>>;
|
|
2988
|
+
/**
|
|
2989
|
+
* Declare a typed Server-Sent Events endpoint.
|
|
2990
|
+
*
|
|
2991
|
+
* Pass path, event structs, and buffer/queue limits. Call the returned operation
|
|
2992
|
+
* with a client and, when declared, the input.
|
|
2993
|
+
*
|
|
2994
|
+
* - **definition** — `path`, an `events` map, and the required `maxBufferSize` and `maxQueueSize` limits (positive safe integers). Optional `method` (default `'GET'`), `operation`, `input`, and `error`. A declared `input` always requires an explicit `builder`. `input` only defines the parameters; the builder alone decides where each value goes. Only definitions without `input` may omit `builder`.
|
|
2995
|
+
*
|
|
2996
|
+
* `EventStreamDefinitionBase`, `EventStreamErrorField`, and `BuilderField` are internal helper types: `error` is required only when `TError` is a struct, and `builder` is `(input: BuilderInput<TInput>) => EventStreamRequestShape` when `input` is declared.
|
|
2997
|
+
*
|
|
2998
|
+
* @param definition - SSE contract (path, events, buffer limits, optional input).
|
|
2999
|
+
* @returns An operation `(client, ...input) => Promise<error-first tuple>`.
|
|
3000
|
+
*
|
|
3001
|
+
* @group sse
|
|
3002
|
+
* @exampleFile examples/api/define-event-stream.ts#example
|
|
3003
|
+
*/
|
|
3004
|
+
export declare function defineEventStream<const P extends string, const M extends string = "GET", TInput extends AnyStruct | undefined = undefined, TEvents extends EventStructs = EventStructs, TError extends AnyStruct | undefined = undefined>(definition: Omit<EventStreamDefinitionBase<TEvents>, "method" | "path"> & EventStreamErrorField<TError> & {
|
|
3005
|
+
input?: TInput;
|
|
3006
|
+
method?: M;
|
|
3007
|
+
path: P;
|
|
3008
|
+
} & BuilderField<NoInfer<TInput>, EventStreamRequestShape<NoInfer<P>, NoInfer<M>>>): EventStreamEndpoint<EndpointArgs<TInput>, EventStreamData<TEvents>, TError>;
|
|
3009
|
+
export type { AnyStruct, BasicAuthInterceptorOptions, BuilderInput, Client, ClientConfig, ClientOption, ClientOptions, ClientSSEConfig, ClientSSEOptions, ClientWebSocketOptions, DecodedResponse, DerivableClient, ErrorMap, EventStreamCloseInfo, EventStreamFaultCode, EventStreamHandle, EventStreamOpenInfo, EventStreamRequestShape, FetchHandle, FlattenedStructError, FormattedStructError, HttpInterceptor, HttpInterceptorNext, HttpMeta, HttpProgressEvent, HttpProgressFn, HttpRequest, HttpRequestShape, HttpResponse, HttpResponseType, Infer, Interceptor, InterceptorFn, MakeResponseOptions, ObjectStruct, ParseResult, QuerySerializer, RequestOptions, SSEHandler, SSEInterceptor, SSEInterceptorFn, STRUCT, Struct, StructInput, StructIssue, StructLike, StructMethods, WebSocketHandle, WebSocketHandleConstructor, WebSocketHandler, WebSocketInterceptor, WebSocketInterceptorFn, WebSocketRequestShape, WebSocketSessionLike };
|