@remit/api-http-client 0.0.20 → 0.0.22
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/client/client.gen.ts +151 -185
- package/client/index.ts +2 -0
- package/client/types.gen.ts +22 -45
- package/client/utils.gen.ts +19 -35
- package/client.gen.ts +2 -2
- package/core/auth.gen.ts +8 -2
- package/core/bodySerializer.gen.ts +10 -28
- package/core/params.gen.ts +26 -24
- package/core/pathSerializer.gen.ts +10 -20
- package/core/queryKeySerializer.gen.ts +7 -26
- package/core/serverSentEvents.gen.ts +12 -36
- package/core/types.gen.ts +11 -19
- package/core/utils.gen.ts +6 -9
- package/package.json +1 -1
- package/sdk.gen.ts +60 -60
- package/types.gen.ts +12 -12
package/client/utils.gen.ts
CHANGED
|
@@ -14,8 +14,8 @@ import type { Client, ClientOptions, Config, RequestOptions } from './types.gen.
|
|
|
14
14
|
export const createQuerySerializer = <T = unknown>({
|
|
15
15
|
parameters = {},
|
|
16
16
|
...args
|
|
17
|
-
}: QuerySerializerOptions = {}) => {
|
|
18
|
-
const querySerializer = (queryParams: T) => {
|
|
17
|
+
}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {
|
|
18
|
+
const querySerializer = (queryParams: T): string => {
|
|
19
19
|
const search: string[] = [];
|
|
20
20
|
if (queryParams && typeof queryParams === 'object') {
|
|
21
21
|
for (const name in queryParams) {
|
|
@@ -65,9 +65,7 @@ export const createQuerySerializer = <T = unknown>({
|
|
|
65
65
|
/**
|
|
66
66
|
* Infers parseAs value from provided Content-Type header.
|
|
67
67
|
*/
|
|
68
|
-
export const getParseAs = (
|
|
69
|
-
contentType: string | null,
|
|
70
|
-
): Exclude<Config['parseAs'], 'auto'> => {
|
|
68
|
+
export const getParseAs = (contentType: string | null): Exclude<Config['parseAs'], 'auto'> => {
|
|
71
69
|
if (!contentType) {
|
|
72
70
|
// If no Content-Type header is provided, the best we can do is return the raw response body,
|
|
73
71
|
// which is effectively the same as the 'stream' option.
|
|
@@ -80,10 +78,7 @@ export const getParseAs = (
|
|
|
80
78
|
return;
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
if (
|
|
84
|
-
cleanContent.startsWith('application/json') ||
|
|
85
|
-
cleanContent.endsWith('+json')
|
|
86
|
-
) {
|
|
81
|
+
if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) {
|
|
87
82
|
return 'json';
|
|
88
83
|
}
|
|
89
84
|
|
|
@@ -92,9 +87,7 @@ export const getParseAs = (
|
|
|
92
87
|
}
|
|
93
88
|
|
|
94
89
|
if (
|
|
95
|
-
['application/', 'audio/', 'image/', 'video/'].some((type) =>
|
|
96
|
-
cleanContent.startsWith(type),
|
|
97
|
-
)
|
|
90
|
+
['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type))
|
|
98
91
|
) {
|
|
99
92
|
return 'blob';
|
|
100
93
|
}
|
|
@@ -125,14 +118,12 @@ const checkForExistence = (
|
|
|
125
118
|
return false;
|
|
126
119
|
};
|
|
127
120
|
|
|
128
|
-
export
|
|
129
|
-
security
|
|
130
|
-
...options
|
|
131
|
-
}: Pick<Required<RequestOptions>, 'security'> &
|
|
132
|
-
Pick<RequestOptions, 'auth' | 'query'> & {
|
|
121
|
+
export async function setAuthParams(
|
|
122
|
+
options: Pick<RequestOptions, 'auth' | 'query' | 'security'> & {
|
|
133
123
|
headers: Headers;
|
|
134
|
-
}
|
|
135
|
-
|
|
124
|
+
},
|
|
125
|
+
): Promise<void> {
|
|
126
|
+
for (const auth of options.security ?? []) {
|
|
136
127
|
if (checkForExistence(options, auth.name)) {
|
|
137
128
|
continue;
|
|
138
129
|
}
|
|
@@ -161,7 +152,7 @@ export const setAuthParams = async ({
|
|
|
161
152
|
break;
|
|
162
153
|
}
|
|
163
154
|
}
|
|
164
|
-
}
|
|
155
|
+
}
|
|
165
156
|
|
|
166
157
|
export const buildUrl: Client['buildUrl'] = (options) =>
|
|
167
158
|
getUrl({
|
|
@@ -201,10 +192,7 @@ export const mergeHeaders = (
|
|
|
201
192
|
continue;
|
|
202
193
|
}
|
|
203
194
|
|
|
204
|
-
const iterator =
|
|
205
|
-
header instanceof Headers
|
|
206
|
-
? headersEntries(header)
|
|
207
|
-
: Object.entries(header);
|
|
195
|
+
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
|
208
196
|
|
|
209
197
|
for (const [key, value] of iterator) {
|
|
210
198
|
if (value === null) {
|
|
@@ -214,7 +202,7 @@ export const mergeHeaders = (
|
|
|
214
202
|
mergedHeaders.append(key, v as string);
|
|
215
203
|
}
|
|
216
204
|
} else if (value !== undefined) {
|
|
217
|
-
// assume object headers are meant to be JSON stringified, i.e
|
|
205
|
+
// assume object headers are meant to be JSON stringified, i.e., their
|
|
218
206
|
// content value in OpenAPI specification is 'application/json'
|
|
219
207
|
mergedHeaders.set(
|
|
220
208
|
key,
|
|
@@ -228,15 +216,14 @@ export const mergeHeaders = (
|
|
|
228
216
|
|
|
229
217
|
type ErrInterceptor<Err, Res, Req, Options> = (
|
|
230
218
|
error: Err,
|
|
231
|
-
response
|
|
232
|
-
|
|
219
|
+
/** response may be undefined due to a network error where no response object is produced */
|
|
220
|
+
response: Res | undefined,
|
|
221
|
+
/** request may be undefined, because error may be from building the request object itself */
|
|
222
|
+
request: Req | undefined,
|
|
233
223
|
options: Options,
|
|
234
224
|
) => Err | Promise<Err>;
|
|
235
225
|
|
|
236
|
-
type ReqInterceptor<Req, Options> = (
|
|
237
|
-
request: Req,
|
|
238
|
-
options: Options,
|
|
239
|
-
) => Req | Promise<Req>;
|
|
226
|
+
type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;
|
|
240
227
|
|
|
241
228
|
type ResInterceptor<Res, Req, Options> = (
|
|
242
229
|
response: Res,
|
|
@@ -270,10 +257,7 @@ class Interceptors<Interceptor> {
|
|
|
270
257
|
return this.fns.indexOf(id);
|
|
271
258
|
}
|
|
272
259
|
|
|
273
|
-
update(
|
|
274
|
-
id: number | Interceptor,
|
|
275
|
-
fn: Interceptor,
|
|
276
|
-
): number | Interceptor | false {
|
|
260
|
+
update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false {
|
|
277
261
|
const index = this.getInterceptorIndex(id);
|
|
278
262
|
if (this.fns[index]) {
|
|
279
263
|
this.fns[index] = fn;
|
package/client.gen.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// This file is auto-generated by @hey-api/openapi-ts
|
|
2
2
|
|
|
3
|
-
import { type ClientOptions, type Config, createClient, createConfig } from './client/index.js';
|
|
3
|
+
import { type Client, type ClientOptions, type Config, createClient, createConfig } from './client/index.js';
|
|
4
4
|
import type { ClientOptions as ClientOptions2 } from './types.gen.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -13,4 +13,4 @@ import type { ClientOptions as ClientOptions2 } from './types.gen.js';
|
|
|
13
13
|
*/
|
|
14
14
|
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
|
|
15
15
|
|
|
16
|
-
export const client = createClient(createConfig<ClientOptions2>({ baseUrl: 'https://api.remit.example.com' }));
|
|
16
|
+
export const client: Client = createClient(createConfig<ClientOptions2>({ baseUrl: 'https://api.remit.example.com' }));
|
package/core/auth.gen.ts
CHANGED
|
@@ -9,6 +9,13 @@ export interface Auth {
|
|
|
9
9
|
* @default 'header'
|
|
10
10
|
*/
|
|
11
11
|
in?: 'header' | 'query' | 'cookie';
|
|
12
|
+
/**
|
|
13
|
+
* A unique identifier for the security scheme.
|
|
14
|
+
*
|
|
15
|
+
* Defined only when there are multiple security schemes whose `Auth`
|
|
16
|
+
* shape would otherwise be identical.
|
|
17
|
+
*/
|
|
18
|
+
key?: string;
|
|
12
19
|
/**
|
|
13
20
|
* Header or query parameter name.
|
|
14
21
|
*
|
|
@@ -23,8 +30,7 @@ export const getAuthToken = async (
|
|
|
23
30
|
auth: Auth,
|
|
24
31
|
callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,
|
|
25
32
|
): Promise<string | undefined> => {
|
|
26
|
-
const token =
|
|
27
|
-
typeof callback === 'function' ? await callback(auth) : callback;
|
|
33
|
+
const token = typeof callback === 'function' ? await callback(auth) : callback;
|
|
28
34
|
|
|
29
35
|
if (!token) {
|
|
30
36
|
return;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
// This file is auto-generated by @hey-api/openapi-ts
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
ArrayStyle,
|
|
5
|
-
ObjectStyle,
|
|
6
|
-
SerializerOptions,
|
|
7
|
-
} from './pathSerializer.gen.js';
|
|
3
|
+
import type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerializer.gen.js';
|
|
8
4
|
|
|
9
5
|
export type QuerySerializer = (query: Record<string, unknown>) => string;
|
|
10
6
|
|
|
11
|
-
export type BodySerializer = (body:
|
|
7
|
+
export type BodySerializer = (body: unknown) => unknown;
|
|
12
8
|
|
|
13
9
|
type QuerySerializerOptionsObject = {
|
|
14
10
|
allowReserved?: boolean;
|
|
@@ -24,11 +20,7 @@ export type QuerySerializerOptions = QuerySerializerOptionsObject & {
|
|
|
24
20
|
parameters?: Record<string, QuerySerializerOptionsObject>;
|
|
25
21
|
};
|
|
26
22
|
|
|
27
|
-
const serializeFormDataPair = (
|
|
28
|
-
data: FormData,
|
|
29
|
-
key: string,
|
|
30
|
-
value: unknown,
|
|
31
|
-
): void => {
|
|
23
|
+
const serializeFormDataPair = (data: FormData, key: string, value: unknown): void => {
|
|
32
24
|
if (typeof value === 'string' || value instanceof Blob) {
|
|
33
25
|
data.append(key, value);
|
|
34
26
|
} else if (value instanceof Date) {
|
|
@@ -38,11 +30,7 @@ const serializeFormDataPair = (
|
|
|
38
30
|
}
|
|
39
31
|
};
|
|
40
32
|
|
|
41
|
-
const serializeUrlSearchParamsPair = (
|
|
42
|
-
data: URLSearchParams,
|
|
43
|
-
key: string,
|
|
44
|
-
value: unknown,
|
|
45
|
-
): void => {
|
|
33
|
+
const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => {
|
|
46
34
|
if (typeof value === 'string') {
|
|
47
35
|
data.append(key, value);
|
|
48
36
|
} else {
|
|
@@ -51,12 +39,10 @@ const serializeUrlSearchParamsPair = (
|
|
|
51
39
|
};
|
|
52
40
|
|
|
53
41
|
export const formDataBodySerializer = {
|
|
54
|
-
bodySerializer:
|
|
55
|
-
body: T,
|
|
56
|
-
): FormData => {
|
|
42
|
+
bodySerializer: (body: unknown): FormData => {
|
|
57
43
|
const data = new FormData();
|
|
58
44
|
|
|
59
|
-
Object.entries(body).forEach(([key, value]) => {
|
|
45
|
+
Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {
|
|
60
46
|
if (value === undefined || value === null) {
|
|
61
47
|
return;
|
|
62
48
|
}
|
|
@@ -72,19 +58,15 @@ export const formDataBodySerializer = {
|
|
|
72
58
|
};
|
|
73
59
|
|
|
74
60
|
export const jsonBodySerializer = {
|
|
75
|
-
bodySerializer:
|
|
76
|
-
JSON.stringify(body, (_key, value) =>
|
|
77
|
-
typeof value === 'bigint' ? value.toString() : value,
|
|
78
|
-
),
|
|
61
|
+
bodySerializer: (body: unknown): string =>
|
|
62
|
+
JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)),
|
|
79
63
|
};
|
|
80
64
|
|
|
81
65
|
export const urlSearchParamsBodySerializer = {
|
|
82
|
-
bodySerializer:
|
|
83
|
-
body: T,
|
|
84
|
-
): string => {
|
|
66
|
+
bodySerializer: (body: unknown): string => {
|
|
85
67
|
const data = new URLSearchParams();
|
|
86
68
|
|
|
87
|
-
Object.entries(body).forEach(([key, value]) => {
|
|
69
|
+
Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {
|
|
88
70
|
if (value === undefined || value === null) {
|
|
89
71
|
return;
|
|
90
72
|
}
|
package/core/params.gen.ts
CHANGED
|
@@ -62,7 +62,7 @@ type KeyMap = Map<
|
|
|
62
62
|
}
|
|
63
63
|
>;
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
function buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {
|
|
66
66
|
if (!map) {
|
|
67
67
|
map = new Map();
|
|
68
68
|
}
|
|
@@ -85,36 +85,42 @@ const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
return map;
|
|
88
|
-
}
|
|
88
|
+
}
|
|
89
89
|
|
|
90
90
|
interface Params {
|
|
91
|
-
body
|
|
91
|
+
body?: unknown;
|
|
92
92
|
headers: Record<string, unknown>;
|
|
93
93
|
path: Record<string, unknown>;
|
|
94
94
|
query: Record<string, unknown>;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
function stripEmptySlots(params: Params): void {
|
|
98
98
|
for (const [slot, value] of Object.entries(params)) {
|
|
99
|
-
if (
|
|
99
|
+
if (slot === 'body') continue;
|
|
100
|
+
if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) {
|
|
100
101
|
delete params[slot as Slot];
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
|
-
}
|
|
104
|
+
}
|
|
104
105
|
|
|
105
|
-
export
|
|
106
|
-
args: ReadonlyArray<unknown>,
|
|
107
|
-
fields: FieldsConfig,
|
|
108
|
-
) => {
|
|
106
|
+
export function buildClientParams(args: ReadonlyArray<unknown>, fields: FieldsConfig): Params {
|
|
109
107
|
const params: Params = {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
query: {},
|
|
108
|
+
headers: Object.create(null),
|
|
109
|
+
path: Object.create(null),
|
|
110
|
+
query: Object.create(null),
|
|
114
111
|
};
|
|
115
112
|
|
|
116
113
|
const map = buildKeyMap(fields);
|
|
117
114
|
|
|
115
|
+
function writeSlot(slot: Slot, key: string, value: unknown): void {
|
|
116
|
+
let record = params[slot] as Record<string, unknown> | undefined;
|
|
117
|
+
if (record === undefined) {
|
|
118
|
+
record = Object.create(null) as Record<string, unknown>;
|
|
119
|
+
params[slot] = record;
|
|
120
|
+
}
|
|
121
|
+
record[key] = value;
|
|
122
|
+
}
|
|
123
|
+
|
|
118
124
|
let config: FieldsConfig[number] | undefined;
|
|
119
125
|
|
|
120
126
|
for (const [index, arg] of args.entries()) {
|
|
@@ -131,7 +137,7 @@ export const buildClientParams = (
|
|
|
131
137
|
const field = map.get(config.key)!;
|
|
132
138
|
const name = field.map || config.key;
|
|
133
139
|
if (field.in) {
|
|
134
|
-
(
|
|
140
|
+
writeSlot(field.in, name, arg);
|
|
135
141
|
}
|
|
136
142
|
} else {
|
|
137
143
|
params.body = arg;
|
|
@@ -143,24 +149,20 @@ export const buildClientParams = (
|
|
|
143
149
|
if (field) {
|
|
144
150
|
if (field.in) {
|
|
145
151
|
const name = field.map || key;
|
|
146
|
-
(
|
|
152
|
+
writeSlot(field.in, name, value);
|
|
147
153
|
} else {
|
|
148
154
|
params[field.map] = value;
|
|
149
155
|
}
|
|
150
156
|
} else {
|
|
151
|
-
const extra = extraPrefixes.find(([prefix]) =>
|
|
152
|
-
key.startsWith(prefix),
|
|
153
|
-
);
|
|
157
|
+
const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix));
|
|
154
158
|
|
|
155
159
|
if (extra) {
|
|
156
160
|
const [prefix, slot] = extra;
|
|
157
|
-
(
|
|
158
|
-
key.slice(prefix.length)
|
|
159
|
-
] = value;
|
|
161
|
+
writeSlot(slot, key.slice(prefix.length), value);
|
|
160
162
|
} else if ('allowExtra' in config && config.allowExtra) {
|
|
161
163
|
for (const [slot, allowed] of Object.entries(config.allowExtra)) {
|
|
162
164
|
if (allowed) {
|
|
163
|
-
(
|
|
165
|
+
writeSlot(slot as Slot, key, value);
|
|
164
166
|
break;
|
|
165
167
|
}
|
|
166
168
|
}
|
|
@@ -173,4 +175,4 @@ export const buildClientParams = (
|
|
|
173
175
|
stripEmptySlots(params);
|
|
174
176
|
|
|
175
177
|
return params;
|
|
176
|
-
}
|
|
178
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// This file is auto-generated by @hey-api/openapi-ts
|
|
2
2
|
|
|
3
|
-
interface SerializeOptions<T>
|
|
4
|
-
extends SerializePrimitiveOptions,
|
|
5
|
-
SerializerOptions<T> {}
|
|
3
|
+
interface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {}
|
|
6
4
|
|
|
7
5
|
interface SerializePrimitiveOptions {
|
|
8
6
|
allowReserved?: boolean;
|
|
@@ -27,7 +25,7 @@ interface SerializePrimitiveParam extends SerializePrimitiveOptions {
|
|
|
27
25
|
value: string;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
|
|
28
|
+
export const separatorArrayExplode = (style: ArraySeparatorStyle): '.' | ';' | ',' | '&' => {
|
|
31
29
|
switch (style) {
|
|
32
30
|
case 'label':
|
|
33
31
|
return '.';
|
|
@@ -40,7 +38,7 @@ export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
|
|
|
40
38
|
}
|
|
41
39
|
};
|
|
42
40
|
|
|
43
|
-
export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
|
|
41
|
+
export const separatorArrayNoExplode = (style: ArraySeparatorStyle): ',' | '|' | '%20' => {
|
|
44
42
|
switch (style) {
|
|
45
43
|
case 'form':
|
|
46
44
|
return ',';
|
|
@@ -53,7 +51,7 @@ export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
|
|
|
53
51
|
}
|
|
54
52
|
};
|
|
55
53
|
|
|
56
|
-
export const separatorObjectExplode = (style: ObjectSeparatorStyle) => {
|
|
54
|
+
export const separatorObjectExplode = (style: ObjectSeparatorStyle): '.' | ';' | ',' | '&' => {
|
|
57
55
|
switch (style) {
|
|
58
56
|
case 'label':
|
|
59
57
|
return '.';
|
|
@@ -74,7 +72,7 @@ export const serializeArrayParam = ({
|
|
|
74
72
|
value,
|
|
75
73
|
}: SerializeOptions<ArraySeparatorStyle> & {
|
|
76
74
|
value: unknown[];
|
|
77
|
-
}) => {
|
|
75
|
+
}): string => {
|
|
78
76
|
if (!explode) {
|
|
79
77
|
const joinedValues = (
|
|
80
78
|
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
|
|
@@ -105,16 +103,14 @@ export const serializeArrayParam = ({
|
|
|
105
103
|
});
|
|
106
104
|
})
|
|
107
105
|
.join(separator);
|
|
108
|
-
return style === 'label' || style === 'matrix'
|
|
109
|
-
? separator + joinedValues
|
|
110
|
-
: joinedValues;
|
|
106
|
+
return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
|
|
111
107
|
};
|
|
112
108
|
|
|
113
109
|
export const serializePrimitiveParam = ({
|
|
114
110
|
allowReserved,
|
|
115
111
|
name,
|
|
116
112
|
value,
|
|
117
|
-
}: SerializePrimitiveParam) => {
|
|
113
|
+
}: SerializePrimitiveParam): string => {
|
|
118
114
|
if (value === undefined || value === null) {
|
|
119
115
|
return '';
|
|
120
116
|
}
|
|
@@ -138,7 +134,7 @@ export const serializeObjectParam = ({
|
|
|
138
134
|
}: SerializeOptions<ObjectSeparatorStyle> & {
|
|
139
135
|
value: Record<string, unknown> | Date;
|
|
140
136
|
valueOnly?: boolean;
|
|
141
|
-
}) => {
|
|
137
|
+
}): string => {
|
|
142
138
|
if (value instanceof Date) {
|
|
143
139
|
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
|
144
140
|
}
|
|
@@ -146,11 +142,7 @@ export const serializeObjectParam = ({
|
|
|
146
142
|
if (style !== 'deepObject' && !explode) {
|
|
147
143
|
let values: string[] = [];
|
|
148
144
|
Object.entries(value).forEach(([key, v]) => {
|
|
149
|
-
values = [
|
|
150
|
-
...values,
|
|
151
|
-
key,
|
|
152
|
-
allowReserved ? (v as string) : encodeURIComponent(v as string),
|
|
153
|
-
];
|
|
145
|
+
values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)];
|
|
154
146
|
});
|
|
155
147
|
const joinedValues = values.join(',');
|
|
156
148
|
switch (style) {
|
|
@@ -175,7 +167,5 @@ export const serializeObjectParam = ({
|
|
|
175
167
|
}),
|
|
176
168
|
)
|
|
177
169
|
.join(separator);
|
|
178
|
-
return style === 'label' || style === 'matrix'
|
|
179
|
-
? separator + joinedValues
|
|
180
|
-
: joinedValues;
|
|
170
|
+
return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
|
|
181
171
|
};
|
|
@@ -14,12 +14,8 @@ export type JsonValue =
|
|
|
14
14
|
/**
|
|
15
15
|
* Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes.
|
|
16
16
|
*/
|
|
17
|
-
export const queryKeyJsonReplacer = (_key: string, value: unknown) => {
|
|
18
|
-
if (
|
|
19
|
-
value === undefined ||
|
|
20
|
-
typeof value === 'function' ||
|
|
21
|
-
typeof value === 'symbol'
|
|
22
|
-
) {
|
|
17
|
+
export const queryKeyJsonReplacer = (_key: string, value: unknown): unknown | undefined => {
|
|
18
|
+
if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
|
|
23
19
|
return undefined;
|
|
24
20
|
}
|
|
25
21
|
if (typeof value === 'bigint') {
|
|
@@ -61,9 +57,7 @@ const isPlainObject = (value: unknown): value is Record<string, unknown> => {
|
|
|
61
57
|
* Turns URLSearchParams into a sorted JSON object for deterministic keys.
|
|
62
58
|
*/
|
|
63
59
|
const serializeSearchParams = (params: URLSearchParams): JsonValue => {
|
|
64
|
-
const entries = Array.from(params.entries()).sort(([a], [b]) =>
|
|
65
|
-
a.localeCompare(b),
|
|
66
|
-
);
|
|
60
|
+
const entries = Array.from(params.entries()).sort(([a], [b]) => a.localeCompare(b));
|
|
67
61
|
const result: Record<string, JsonValue> = {};
|
|
68
62
|
|
|
69
63
|
for (const [key, value] of entries) {
|
|
@@ -86,26 +80,16 @@ const serializeSearchParams = (params: URLSearchParams): JsonValue => {
|
|
|
86
80
|
/**
|
|
87
81
|
* Normalizes any accepted value into a JSON-friendly shape for query keys.
|
|
88
82
|
*/
|
|
89
|
-
export const serializeQueryKeyValue = (
|
|
90
|
-
value: unknown,
|
|
91
|
-
): JsonValue | undefined => {
|
|
83
|
+
export const serializeQueryKeyValue = (value: unknown): JsonValue | undefined => {
|
|
92
84
|
if (value === null) {
|
|
93
85
|
return null;
|
|
94
86
|
}
|
|
95
87
|
|
|
96
|
-
if (
|
|
97
|
-
typeof value === 'string' ||
|
|
98
|
-
typeof value === 'number' ||
|
|
99
|
-
typeof value === 'boolean'
|
|
100
|
-
) {
|
|
88
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
101
89
|
return value;
|
|
102
90
|
}
|
|
103
91
|
|
|
104
|
-
if (
|
|
105
|
-
value === undefined ||
|
|
106
|
-
typeof value === 'function' ||
|
|
107
|
-
typeof value === 'symbol'
|
|
108
|
-
) {
|
|
92
|
+
if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
|
|
109
93
|
return undefined;
|
|
110
94
|
}
|
|
111
95
|
|
|
@@ -121,10 +105,7 @@ export const serializeQueryKeyValue = (
|
|
|
121
105
|
return stringifyToJsonValue(value);
|
|
122
106
|
}
|
|
123
107
|
|
|
124
|
-
if (
|
|
125
|
-
typeof URLSearchParams !== 'undefined' &&
|
|
126
|
-
value instanceof URLSearchParams
|
|
127
|
-
) {
|
|
108
|
+
if (typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams) {
|
|
128
109
|
return serializeSearchParams(value);
|
|
129
110
|
}
|
|
130
111
|
|
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { Config } from './types.gen.js';
|
|
4
4
|
|
|
5
|
-
export type ServerSentEventsOptions<TData = unknown> = Omit<
|
|
6
|
-
RequestInit,
|
|
7
|
-
'method'
|
|
8
|
-
> &
|
|
5
|
+
export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> &
|
|
9
6
|
Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & {
|
|
10
7
|
/**
|
|
11
8
|
* Fetch API implementation. You can use this option to provide a custom
|
|
@@ -74,11 +71,7 @@ export interface StreamEvent<TData = unknown> {
|
|
|
74
71
|
retry?: number;
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
export type ServerSentEventsResult<
|
|
78
|
-
TData = unknown,
|
|
79
|
-
TReturn = void,
|
|
80
|
-
TNext = unknown,
|
|
81
|
-
> = {
|
|
74
|
+
export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
|
|
82
75
|
stream: AsyncGenerator<
|
|
83
76
|
TData extends Record<string, unknown> ? TData[keyof TData] : TData,
|
|
84
77
|
TReturn,
|
|
@@ -86,7 +79,7 @@ export type ServerSentEventsResult<
|
|
|
86
79
|
>;
|
|
87
80
|
};
|
|
88
81
|
|
|
89
|
-
export
|
|
82
|
+
export function createSseClient<TData = unknown>({
|
|
90
83
|
onRequest,
|
|
91
84
|
onSseError,
|
|
92
85
|
onSseEvent,
|
|
@@ -98,12 +91,10 @@ export const createSseClient = <TData = unknown>({
|
|
|
98
91
|
sseSleepFn,
|
|
99
92
|
url,
|
|
100
93
|
...options
|
|
101
|
-
}: ServerSentEventsOptions): ServerSentEventsResult<TData>
|
|
94
|
+
}: ServerSentEventsOptions): ServerSentEventsResult<TData> {
|
|
102
95
|
let lastEventId: string | undefined;
|
|
103
96
|
|
|
104
|
-
const sleep =
|
|
105
|
-
sseSleepFn ??
|
|
106
|
-
((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
97
|
+
const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
107
98
|
|
|
108
99
|
const createStream = async function* () {
|
|
109
100
|
let retryDelay: number = sseDefaultRetryDelay ?? 3000;
|
|
@@ -141,16 +132,11 @@ export const createSseClient = <TData = unknown>({
|
|
|
141
132
|
const _fetch = options.fetch ?? globalThis.fetch;
|
|
142
133
|
const response = await _fetch(request);
|
|
143
134
|
|
|
144
|
-
if (!response.ok)
|
|
145
|
-
throw new Error(
|
|
146
|
-
`SSE failed: ${response.status} ${response.statusText}`,
|
|
147
|
-
);
|
|
135
|
+
if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
|
|
148
136
|
|
|
149
137
|
if (!response.body) throw new Error('No body in SSE response');
|
|
150
138
|
|
|
151
|
-
const reader = response.body
|
|
152
|
-
.pipeThrough(new TextDecoderStream())
|
|
153
|
-
.getReader();
|
|
139
|
+
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
154
140
|
|
|
155
141
|
let buffer = '';
|
|
156
142
|
|
|
@@ -169,8 +155,7 @@ export const createSseClient = <TData = unknown>({
|
|
|
169
155
|
const { done, value } = await reader.read();
|
|
170
156
|
if (done) break;
|
|
171
157
|
buffer += value;
|
|
172
|
-
|
|
173
|
-
buffer = buffer.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
158
|
+
buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings
|
|
174
159
|
|
|
175
160
|
const chunks = buffer.split('\n\n');
|
|
176
161
|
buffer = chunks.pop() ?? '';
|
|
@@ -188,10 +173,7 @@ export const createSseClient = <TData = unknown>({
|
|
|
188
173
|
} else if (line.startsWith('id:')) {
|
|
189
174
|
lastEventId = line.replace(/^id:\s*/, '');
|
|
190
175
|
} else if (line.startsWith('retry:')) {
|
|
191
|
-
const parsed = Number.parseInt(
|
|
192
|
-
line.replace(/^retry:\s*/, ''),
|
|
193
|
-
10,
|
|
194
|
-
);
|
|
176
|
+
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ''), 10);
|
|
195
177
|
if (!Number.isNaN(parsed)) {
|
|
196
178
|
retryDelay = parsed;
|
|
197
179
|
}
|
|
@@ -243,18 +225,12 @@ export const createSseClient = <TData = unknown>({
|
|
|
243
225
|
// connection failed or aborted; retry after delay
|
|
244
226
|
onSseError?.(error);
|
|
245
227
|
|
|
246
|
-
if (
|
|
247
|
-
sseMaxRetryAttempts !== undefined &&
|
|
248
|
-
attempt >= sseMaxRetryAttempts
|
|
249
|
-
) {
|
|
228
|
+
if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
|
|
250
229
|
break; // stop after firing error
|
|
251
230
|
}
|
|
252
231
|
|
|
253
232
|
// exponential backoff: double retry each attempt, cap at 30s
|
|
254
|
-
const backoff = Math.min(
|
|
255
|
-
retryDelay * 2 ** (attempt - 1),
|
|
256
|
-
sseMaxRetryDelay ?? 30000,
|
|
257
|
-
);
|
|
233
|
+
const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
|
|
258
234
|
await sleep(backoff);
|
|
259
235
|
}
|
|
260
236
|
}
|
|
@@ -263,4 +239,4 @@ export const createSseClient = <TData = unknown>({
|
|
|
263
239
|
const stream = createStream();
|
|
264
240
|
|
|
265
241
|
return { stream };
|
|
266
|
-
}
|
|
242
|
+
}
|