@kaito-http/core 3.0.0-beta.20 → 3.0.0-beta.21
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/dist/index.cjs +17 -23
- package/dist/index.d.cts +1 -18
- package/dist/index.d.ts +1 -18
- package/dist/index.js +17 -23
- package/dist/stream/stream.cjs +35 -3
- package/dist/stream/stream.d.cts +24 -20
- package/dist/stream/stream.d.ts +24 -20
- package/dist/stream/stream.js +34 -3
- package/package.json +3 -3
- package/src/router/router.ts +5 -8
- package/src/server.ts +2 -27
- package/src/stream/stream.ts +6 -5
package/dist/index.cjs
CHANGED
|
@@ -128,19 +128,6 @@ var KaitoResponse = class {
|
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
// src/util.ts
|
|
132
|
-
function createUtilities(getContext) {
|
|
133
|
-
return {
|
|
134
|
-
getContext,
|
|
135
|
-
router: () => Router.create()
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
function parsable(parse) {
|
|
139
|
-
return {
|
|
140
|
-
parse
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
131
|
// src/router/router.ts
|
|
145
132
|
var Router = class _Router {
|
|
146
133
|
state;
|
|
@@ -153,9 +140,10 @@ var Router = class _Router {
|
|
|
153
140
|
return {};
|
|
154
141
|
}
|
|
155
142
|
const result = {};
|
|
156
|
-
for (const
|
|
143
|
+
for (const key in schema) {
|
|
144
|
+
if (!schema.hasOwnProperty(key)) continue;
|
|
157
145
|
const value = url.searchParams.get(key);
|
|
158
|
-
result[key] =
|
|
146
|
+
result[key] = schema[key].parse(value);
|
|
159
147
|
}
|
|
160
148
|
return result;
|
|
161
149
|
}
|
|
@@ -246,9 +234,6 @@ var Router = class _Router {
|
|
|
246
234
|
params
|
|
247
235
|
});
|
|
248
236
|
if (result instanceof Response) {
|
|
249
|
-
if (server.enableClientResponseHints) {
|
|
250
|
-
result.headers.set("x-kaito-is-response", "1");
|
|
251
|
-
}
|
|
252
237
|
return result;
|
|
253
238
|
}
|
|
254
239
|
return response.toResponse({
|
|
@@ -294,11 +279,7 @@ var Router = class _Router {
|
|
|
294
279
|
};
|
|
295
280
|
|
|
296
281
|
// src/server.ts
|
|
297
|
-
function createKaitoHandler(
|
|
298
|
-
const config = {
|
|
299
|
-
enableClientResponseHints: true,
|
|
300
|
-
...userConfig
|
|
301
|
-
};
|
|
282
|
+
function createKaitoHandler(config) {
|
|
302
283
|
const handle = config.router.freeze(config);
|
|
303
284
|
return async (request) => {
|
|
304
285
|
if (config.before) {
|
|
@@ -313,6 +294,19 @@ function createKaitoHandler(userConfig) {
|
|
|
313
294
|
return response;
|
|
314
295
|
};
|
|
315
296
|
}
|
|
297
|
+
|
|
298
|
+
// src/util.ts
|
|
299
|
+
function createUtilities(getContext) {
|
|
300
|
+
return {
|
|
301
|
+
getContext,
|
|
302
|
+
router: () => Router.create()
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function parsable(parse) {
|
|
306
|
+
return {
|
|
307
|
+
parse
|
|
308
|
+
};
|
|
309
|
+
}
|
|
316
310
|
// Annotate the CommonJS export names for ESM import in node:
|
|
317
311
|
0 && (module.exports = {
|
|
318
312
|
KaitoError,
|
package/dist/index.d.cts
CHANGED
|
@@ -126,25 +126,8 @@ type ServerConfig<ContextFrom> = {
|
|
|
126
126
|
* ```
|
|
127
127
|
*/
|
|
128
128
|
transform?: (req: Request, res: Response) => Promise<Response | void | undefined>;
|
|
129
|
-
/**
|
|
130
|
-
* Controls whether the server includes a header to indicate non-JSON responses.
|
|
131
|
-
*
|
|
132
|
-
* When a route handler returns a `Response` object, this setting determines if
|
|
133
|
-
* the server adds a header indicating the response should not be parsed as JSON.
|
|
134
|
-
*
|
|
135
|
-
* The `@kaito-http/client` package checks for this header's presence:
|
|
136
|
-
* - If present: Returns the raw Response object
|
|
137
|
-
* - If absent: Attempts to parse the response as JSON
|
|
138
|
-
*
|
|
139
|
-
* You might want to disable this feature when:
|
|
140
|
-
* 1. Using a custom client that doesn't recognize this header
|
|
141
|
-
* 2. Security requirements prevent exposing framework details in headers
|
|
142
|
-
*
|
|
143
|
-
* @default true
|
|
144
|
-
*/
|
|
145
|
-
enableClientResponseHints: boolean;
|
|
146
129
|
};
|
|
147
|
-
declare function createKaitoHandler<Context>(
|
|
130
|
+
declare function createKaitoHandler<Context>(config: ServerConfig<Context>): (request: Request) => Promise<Response>;
|
|
148
131
|
|
|
149
132
|
type PrefixRoutesPathInner<R extends AnyRoute, Prefix extends `/${string}`> = R extends Route<infer ContextFrom, infer ContextTo, infer Result, infer Path, infer Method, infer Query, infer BodyOutput> ? Route<ContextFrom, ContextTo, Result, `${Prefix}${Path}`, Method, Query, BodyOutput> : never;
|
|
150
133
|
type PrefixRoutesPath<Prefix extends `/${string}`, R extends AnyRoute> = R extends R ? PrefixRoutesPathInner<R, Prefix> : never;
|
package/dist/index.d.ts
CHANGED
|
@@ -126,25 +126,8 @@ type ServerConfig<ContextFrom> = {
|
|
|
126
126
|
* ```
|
|
127
127
|
*/
|
|
128
128
|
transform?: (req: Request, res: Response) => Promise<Response | void | undefined>;
|
|
129
|
-
/**
|
|
130
|
-
* Controls whether the server includes a header to indicate non-JSON responses.
|
|
131
|
-
*
|
|
132
|
-
* When a route handler returns a `Response` object, this setting determines if
|
|
133
|
-
* the server adds a header indicating the response should not be parsed as JSON.
|
|
134
|
-
*
|
|
135
|
-
* The `@kaito-http/client` package checks for this header's presence:
|
|
136
|
-
* - If present: Returns the raw Response object
|
|
137
|
-
* - If absent: Attempts to parse the response as JSON
|
|
138
|
-
*
|
|
139
|
-
* You might want to disable this feature when:
|
|
140
|
-
* 1. Using a custom client that doesn't recognize this header
|
|
141
|
-
* 2. Security requirements prevent exposing framework details in headers
|
|
142
|
-
*
|
|
143
|
-
* @default true
|
|
144
|
-
*/
|
|
145
|
-
enableClientResponseHints: boolean;
|
|
146
129
|
};
|
|
147
|
-
declare function createKaitoHandler<Context>(
|
|
130
|
+
declare function createKaitoHandler<Context>(config: ServerConfig<Context>): (request: Request) => Promise<Response>;
|
|
148
131
|
|
|
149
132
|
type PrefixRoutesPathInner<R extends AnyRoute, Prefix extends `/${string}`> = R extends Route<infer ContextFrom, infer ContextTo, infer Result, infer Path, infer Method, infer Query, infer BodyOutput> ? Route<ContextFrom, ContextTo, Result, `${Prefix}${Path}`, Method, Query, BodyOutput> : never;
|
|
150
133
|
type PrefixRoutesPath<Prefix extends `/${string}`, R extends AnyRoute> = R extends R ? PrefixRoutesPathInner<R, Prefix> : never;
|
package/dist/index.js
CHANGED
|
@@ -96,19 +96,6 @@ var KaitoResponse = class {
|
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
-
// src/util.ts
|
|
100
|
-
function createUtilities(getContext) {
|
|
101
|
-
return {
|
|
102
|
-
getContext,
|
|
103
|
-
router: () => Router.create()
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
function parsable(parse) {
|
|
107
|
-
return {
|
|
108
|
-
parse
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
99
|
// src/router/router.ts
|
|
113
100
|
var Router = class _Router {
|
|
114
101
|
state;
|
|
@@ -121,9 +108,10 @@ var Router = class _Router {
|
|
|
121
108
|
return {};
|
|
122
109
|
}
|
|
123
110
|
const result = {};
|
|
124
|
-
for (const
|
|
111
|
+
for (const key in schema) {
|
|
112
|
+
if (!schema.hasOwnProperty(key)) continue;
|
|
125
113
|
const value = url.searchParams.get(key);
|
|
126
|
-
result[key] =
|
|
114
|
+
result[key] = schema[key].parse(value);
|
|
127
115
|
}
|
|
128
116
|
return result;
|
|
129
117
|
}
|
|
@@ -214,9 +202,6 @@ var Router = class _Router {
|
|
|
214
202
|
params
|
|
215
203
|
});
|
|
216
204
|
if (result instanceof Response) {
|
|
217
|
-
if (server.enableClientResponseHints) {
|
|
218
|
-
result.headers.set("x-kaito-is-response", "1");
|
|
219
|
-
}
|
|
220
205
|
return result;
|
|
221
206
|
}
|
|
222
207
|
return response.toResponse({
|
|
@@ -262,11 +247,7 @@ var Router = class _Router {
|
|
|
262
247
|
};
|
|
263
248
|
|
|
264
249
|
// src/server.ts
|
|
265
|
-
function createKaitoHandler(
|
|
266
|
-
const config = {
|
|
267
|
-
enableClientResponseHints: true,
|
|
268
|
-
...userConfig
|
|
269
|
-
};
|
|
250
|
+
function createKaitoHandler(config) {
|
|
270
251
|
const handle = config.router.freeze(config);
|
|
271
252
|
return async (request) => {
|
|
272
253
|
if (config.before) {
|
|
@@ -281,6 +262,19 @@ function createKaitoHandler(userConfig) {
|
|
|
281
262
|
return response;
|
|
282
263
|
};
|
|
283
264
|
}
|
|
265
|
+
|
|
266
|
+
// src/util.ts
|
|
267
|
+
function createUtilities(getContext) {
|
|
268
|
+
return {
|
|
269
|
+
getContext,
|
|
270
|
+
router: () => Router.create()
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function parsable(parse) {
|
|
274
|
+
return {
|
|
275
|
+
parse
|
|
276
|
+
};
|
|
277
|
+
}
|
|
284
278
|
export {
|
|
285
279
|
KaitoError,
|
|
286
280
|
KaitoRequest,
|
package/dist/stream/stream.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(stream_exports, {
|
|
|
25
25
|
SSEController: () => SSEController,
|
|
26
26
|
sse: () => sse,
|
|
27
27
|
sseEventToString: () => sseEventToString,
|
|
28
|
+
sseFromAnyReadable: () => sseFromAnyReadable,
|
|
28
29
|
stream: () => stream
|
|
29
30
|
});
|
|
30
31
|
module.exports = __toCommonJS(stream_exports);
|
|
@@ -63,8 +64,8 @@ function sseEventToString(event) {
|
|
|
63
64
|
result += `retry:${event.retry}
|
|
64
65
|
`;
|
|
65
66
|
}
|
|
66
|
-
if (event.data) {
|
|
67
|
-
result += `data:${event.data}`;
|
|
67
|
+
if (event.data !== void 0) {
|
|
68
|
+
result += `data:${JSON.stringify(event.data)}`;
|
|
68
69
|
}
|
|
69
70
|
return result;
|
|
70
71
|
}
|
|
@@ -79,8 +80,11 @@ var SSEController = class {
|
|
|
79
80
|
close() {
|
|
80
81
|
this.controller.close();
|
|
81
82
|
}
|
|
83
|
+
[Symbol.dispose]() {
|
|
84
|
+
this.close();
|
|
85
|
+
}
|
|
82
86
|
};
|
|
83
|
-
function
|
|
87
|
+
function sseFromSource(source) {
|
|
84
88
|
const start = source.start;
|
|
85
89
|
const pull = source.pull;
|
|
86
90
|
const cancel = source.cancel;
|
|
@@ -99,6 +103,33 @@ function sse(source) {
|
|
|
99
103
|
});
|
|
100
104
|
return new KaitoSSEResponse(readable);
|
|
101
105
|
}
|
|
106
|
+
function sse(source) {
|
|
107
|
+
const evaluated = typeof source === "function" ? source() : source;
|
|
108
|
+
if ("next" in evaluated) {
|
|
109
|
+
const generator = evaluated;
|
|
110
|
+
return sseFromSource({
|
|
111
|
+
async start(controller) {
|
|
112
|
+
try {
|
|
113
|
+
for await (const event of generator) {
|
|
114
|
+
controller.enqueue(event);
|
|
115
|
+
}
|
|
116
|
+
} finally {
|
|
117
|
+
controller.close();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
return sseFromSource(evaluated);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function sseFromAnyReadable(stream2, transform) {
|
|
126
|
+
const transformer = new TransformStream({
|
|
127
|
+
transform: (chunk, controller) => {
|
|
128
|
+
controller.enqueue(transform(chunk));
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return sse(stream2.pipeThrough(transformer));
|
|
132
|
+
}
|
|
102
133
|
// Annotate the CommonJS export names for ESM import in node:
|
|
103
134
|
0 && (module.exports = {
|
|
104
135
|
KaitoSSEResponse,
|
|
@@ -106,5 +137,6 @@ function sse(source) {
|
|
|
106
137
|
SSEController,
|
|
107
138
|
sse,
|
|
108
139
|
sseEventToString,
|
|
140
|
+
sseFromAnyReadable,
|
|
109
141
|
stream
|
|
110
142
|
});
|
package/dist/stream/stream.d.cts
CHANGED
|
@@ -1,35 +1,39 @@
|
|
|
1
|
-
declare class KaitoStreamResponse<
|
|
2
|
-
constructor(body: ReadableStream<
|
|
1
|
+
declare class KaitoStreamResponse<R> extends Response {
|
|
2
|
+
constructor(body: ReadableStream<R>);
|
|
3
3
|
[Symbol.asyncIterator](): AsyncGenerator<Uint8Array<ArrayBufferLike>, void, unknown>;
|
|
4
4
|
}
|
|
5
|
-
declare class KaitoSSEResponse extends KaitoStreamResponse<string> {
|
|
5
|
+
declare class KaitoSSEResponse<_ClientType> extends KaitoStreamResponse<string> {
|
|
6
6
|
}
|
|
7
|
-
declare function stream<
|
|
8
|
-
type SSEEvent = ({
|
|
9
|
-
data:
|
|
10
|
-
event
|
|
7
|
+
declare function stream<R>(body: UnderlyingDefaultSource<R>): KaitoStreamResponse<R>;
|
|
8
|
+
type SSEEvent<T, E extends string> = ({
|
|
9
|
+
data: T;
|
|
10
|
+
event?: E | undefined;
|
|
11
11
|
} | {
|
|
12
|
-
data
|
|
13
|
-
event
|
|
14
|
-
} | {
|
|
15
|
-
data?: string | undefined;
|
|
16
|
-
event: string;
|
|
12
|
+
data?: T | undefined;
|
|
13
|
+
event: E;
|
|
17
14
|
}) & {
|
|
18
15
|
retry?: number;
|
|
19
16
|
id?: string;
|
|
20
17
|
};
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Converts an SSE Event into a string, ready for sending to the client
|
|
20
|
+
* @param event The SSE Event
|
|
21
|
+
* @returns A stringified version
|
|
22
|
+
*/
|
|
23
|
+
declare function sseEventToString(event: SSEEvent<unknown, string>): string;
|
|
24
|
+
declare class SSEController<U, E extends string> implements Disposable {
|
|
23
25
|
private readonly controller;
|
|
24
26
|
constructor(controller: ReadableStreamDefaultController<string>);
|
|
25
|
-
enqueue(event: SSEEvent): void;
|
|
27
|
+
enqueue(event: SSEEvent<U, E>): void;
|
|
26
28
|
close(): void;
|
|
29
|
+
[Symbol.dispose](): void;
|
|
27
30
|
}
|
|
28
|
-
interface SSESource {
|
|
31
|
+
interface SSESource<U, E extends string> {
|
|
29
32
|
cancel?: UnderlyingSourceCancelCallback;
|
|
30
|
-
start?(controller: SSEController): Promise<void>;
|
|
31
|
-
pull?(controller: SSEController): Promise<void>;
|
|
33
|
+
start?(controller: SSEController<U, E>): Promise<void>;
|
|
34
|
+
pull?(controller: SSEController<U, E>): Promise<void>;
|
|
32
35
|
}
|
|
33
|
-
declare function sse(source: SSESource): KaitoSSEResponse
|
|
36
|
+
declare function sse<U, E extends string, T extends SSEEvent<U, E>>(source: SSESource<U, E> | AsyncGenerator<T, unknown, unknown> | (() => AsyncGenerator<T, unknown, unknown>)): KaitoSSEResponse<T>;
|
|
37
|
+
declare function sseFromAnyReadable<R, U, E extends string>(stream: ReadableStream<R>, transform: (chunk: R) => SSEEvent<U, E>): KaitoSSEResponse<SSEEvent<U, E>>;
|
|
34
38
|
|
|
35
|
-
export { KaitoSSEResponse, KaitoStreamResponse, SSEController, type SSEEvent, type SSESource, sse, sseEventToString, stream };
|
|
39
|
+
export { KaitoSSEResponse, KaitoStreamResponse, SSEController, type SSEEvent, type SSESource, sse, sseEventToString, sseFromAnyReadable, stream };
|
package/dist/stream/stream.d.ts
CHANGED
|
@@ -1,35 +1,39 @@
|
|
|
1
|
-
declare class KaitoStreamResponse<
|
|
2
|
-
constructor(body: ReadableStream<
|
|
1
|
+
declare class KaitoStreamResponse<R> extends Response {
|
|
2
|
+
constructor(body: ReadableStream<R>);
|
|
3
3
|
[Symbol.asyncIterator](): AsyncGenerator<Uint8Array<ArrayBufferLike>, void, unknown>;
|
|
4
4
|
}
|
|
5
|
-
declare class KaitoSSEResponse extends KaitoStreamResponse<string> {
|
|
5
|
+
declare class KaitoSSEResponse<_ClientType> extends KaitoStreamResponse<string> {
|
|
6
6
|
}
|
|
7
|
-
declare function stream<
|
|
8
|
-
type SSEEvent = ({
|
|
9
|
-
data:
|
|
10
|
-
event
|
|
7
|
+
declare function stream<R>(body: UnderlyingDefaultSource<R>): KaitoStreamResponse<R>;
|
|
8
|
+
type SSEEvent<T, E extends string> = ({
|
|
9
|
+
data: T;
|
|
10
|
+
event?: E | undefined;
|
|
11
11
|
} | {
|
|
12
|
-
data
|
|
13
|
-
event
|
|
14
|
-
} | {
|
|
15
|
-
data?: string | undefined;
|
|
16
|
-
event: string;
|
|
12
|
+
data?: T | undefined;
|
|
13
|
+
event: E;
|
|
17
14
|
}) & {
|
|
18
15
|
retry?: number;
|
|
19
16
|
id?: string;
|
|
20
17
|
};
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Converts an SSE Event into a string, ready for sending to the client
|
|
20
|
+
* @param event The SSE Event
|
|
21
|
+
* @returns A stringified version
|
|
22
|
+
*/
|
|
23
|
+
declare function sseEventToString(event: SSEEvent<unknown, string>): string;
|
|
24
|
+
declare class SSEController<U, E extends string> implements Disposable {
|
|
23
25
|
private readonly controller;
|
|
24
26
|
constructor(controller: ReadableStreamDefaultController<string>);
|
|
25
|
-
enqueue(event: SSEEvent): void;
|
|
27
|
+
enqueue(event: SSEEvent<U, E>): void;
|
|
26
28
|
close(): void;
|
|
29
|
+
[Symbol.dispose](): void;
|
|
27
30
|
}
|
|
28
|
-
interface SSESource {
|
|
31
|
+
interface SSESource<U, E extends string> {
|
|
29
32
|
cancel?: UnderlyingSourceCancelCallback;
|
|
30
|
-
start?(controller: SSEController): Promise<void>;
|
|
31
|
-
pull?(controller: SSEController): Promise<void>;
|
|
33
|
+
start?(controller: SSEController<U, E>): Promise<void>;
|
|
34
|
+
pull?(controller: SSEController<U, E>): Promise<void>;
|
|
32
35
|
}
|
|
33
|
-
declare function sse(source: SSESource): KaitoSSEResponse
|
|
36
|
+
declare function sse<U, E extends string, T extends SSEEvent<U, E>>(source: SSESource<U, E> | AsyncGenerator<T, unknown, unknown> | (() => AsyncGenerator<T, unknown, unknown>)): KaitoSSEResponse<T>;
|
|
37
|
+
declare function sseFromAnyReadable<R, U, E extends string>(stream: ReadableStream<R>, transform: (chunk: R) => SSEEvent<U, E>): KaitoSSEResponse<SSEEvent<U, E>>;
|
|
34
38
|
|
|
35
|
-
export { KaitoSSEResponse, KaitoStreamResponse, SSEController, type SSEEvent, type SSESource, sse, sseEventToString, stream };
|
|
39
|
+
export { KaitoSSEResponse, KaitoStreamResponse, SSEController, type SSEEvent, type SSESource, sse, sseEventToString, sseFromAnyReadable, stream };
|
package/dist/stream/stream.js
CHANGED
|
@@ -34,8 +34,8 @@ function sseEventToString(event) {
|
|
|
34
34
|
result += `retry:${event.retry}
|
|
35
35
|
`;
|
|
36
36
|
}
|
|
37
|
-
if (event.data) {
|
|
38
|
-
result += `data:${event.data}`;
|
|
37
|
+
if (event.data !== void 0) {
|
|
38
|
+
result += `data:${JSON.stringify(event.data)}`;
|
|
39
39
|
}
|
|
40
40
|
return result;
|
|
41
41
|
}
|
|
@@ -50,8 +50,11 @@ var SSEController = class {
|
|
|
50
50
|
close() {
|
|
51
51
|
this.controller.close();
|
|
52
52
|
}
|
|
53
|
+
[Symbol.dispose]() {
|
|
54
|
+
this.close();
|
|
55
|
+
}
|
|
53
56
|
};
|
|
54
|
-
function
|
|
57
|
+
function sseFromSource(source) {
|
|
55
58
|
const start = source.start;
|
|
56
59
|
const pull = source.pull;
|
|
57
60
|
const cancel = source.cancel;
|
|
@@ -70,11 +73,39 @@ function sse(source) {
|
|
|
70
73
|
});
|
|
71
74
|
return new KaitoSSEResponse(readable);
|
|
72
75
|
}
|
|
76
|
+
function sse(source) {
|
|
77
|
+
const evaluated = typeof source === "function" ? source() : source;
|
|
78
|
+
if ("next" in evaluated) {
|
|
79
|
+
const generator = evaluated;
|
|
80
|
+
return sseFromSource({
|
|
81
|
+
async start(controller) {
|
|
82
|
+
try {
|
|
83
|
+
for await (const event of generator) {
|
|
84
|
+
controller.enqueue(event);
|
|
85
|
+
}
|
|
86
|
+
} finally {
|
|
87
|
+
controller.close();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
} else {
|
|
92
|
+
return sseFromSource(evaluated);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function sseFromAnyReadable(stream2, transform) {
|
|
96
|
+
const transformer = new TransformStream({
|
|
97
|
+
transform: (chunk, controller) => {
|
|
98
|
+
controller.enqueue(transform(chunk));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return sse(stream2.pipeThrough(transformer));
|
|
102
|
+
}
|
|
73
103
|
export {
|
|
74
104
|
KaitoSSEResponse,
|
|
75
105
|
KaitoStreamResponse,
|
|
76
106
|
SSEController,
|
|
77
107
|
sse,
|
|
78
108
|
sseEventToString,
|
|
109
|
+
sseFromAnyReadable,
|
|
79
110
|
stream
|
|
80
111
|
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaito-http/core",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Alistair Smith <hi@alistair.sh>",
|
|
6
6
|
"description": "Functional HTTP Framework for TypeScript",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsup",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
9
|
+
"attw": "attw --profile node16 --pack .",
|
|
10
|
+
"test": "node --test --import=tsx ./src/**/*.test.ts"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
"./package.json": "./package.json",
|
package/src/router/router.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {KaitoRequest} from '../request.ts';
|
|
|
4
4
|
import {KaitoResponse} from '../response.ts';
|
|
5
5
|
import type {AnyQueryDefinition, AnyRoute, Route} from '../route.ts';
|
|
6
6
|
import type {ServerConfig} from '../server.ts';
|
|
7
|
-
import type {ErroredAPIResponse,
|
|
7
|
+
import type {ErroredAPIResponse, Parsable} from '../util.ts';
|
|
8
8
|
import type {KaitoMethod} from './types.ts';
|
|
9
9
|
|
|
10
10
|
type PrefixRoutesPathInner<R extends AnyRoute, Prefix extends `/${string}`> =
|
|
@@ -46,9 +46,10 @@ export class Router<ContextFrom, ContextTo, R extends AnyRoute> {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const result: Record<PropertyKey, unknown> = {};
|
|
49
|
-
for (const
|
|
49
|
+
for (const key in schema) {
|
|
50
|
+
if (!schema.hasOwnProperty(key)) continue;
|
|
50
51
|
const value = url.searchParams.get(key);
|
|
51
|
-
result[key] =
|
|
52
|
+
result[key] = (schema[key] as Parsable).parse(value);
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
return result as {
|
|
@@ -111,7 +112,7 @@ export class Router<ContextFrom, ContextTo, R extends AnyRoute> {
|
|
|
111
112
|
});
|
|
112
113
|
};
|
|
113
114
|
|
|
114
|
-
public freeze = (server: Omit<
|
|
115
|
+
public freeze = (server: Omit<ServerConfig<ContextFrom>, 'router'>) => {
|
|
115
116
|
const routes = new Map<string, Map<KaitoMethod, AnyRoute>>();
|
|
116
117
|
|
|
117
118
|
for (const route of this.state.routes) {
|
|
@@ -187,10 +188,6 @@ export class Router<ContextFrom, ContextTo, R extends AnyRoute> {
|
|
|
187
188
|
});
|
|
188
189
|
|
|
189
190
|
if (result instanceof Response) {
|
|
190
|
-
if (server.enableClientResponseHints) {
|
|
191
|
-
result.headers.set('x-kaito-is-response', '1');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
191
|
return result;
|
|
195
192
|
}
|
|
196
193
|
|
package/src/server.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {KaitoError} from './error.ts';
|
|
2
2
|
import type {KaitoRequest} from './request.ts';
|
|
3
3
|
import type {Router} from './router/router.ts';
|
|
4
|
-
import type {GetContext
|
|
4
|
+
import type {GetContext} from './util.ts';
|
|
5
5
|
|
|
6
6
|
export type Before = (req: Request) => Promise<Response | void | undefined>;
|
|
7
7
|
|
|
@@ -64,34 +64,9 @@ export type ServerConfig<ContextFrom> = {
|
|
|
64
64
|
* ```
|
|
65
65
|
*/
|
|
66
66
|
transform?: (req: Request, res: Response) => Promise<Response | void | undefined>;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Controls whether the server includes a header to indicate non-JSON responses.
|
|
70
|
-
*
|
|
71
|
-
* When a route handler returns a `Response` object, this setting determines if
|
|
72
|
-
* the server adds a header indicating the response should not be parsed as JSON.
|
|
73
|
-
*
|
|
74
|
-
* The `@kaito-http/client` package checks for this header's presence:
|
|
75
|
-
* - If present: Returns the raw Response object
|
|
76
|
-
* - If absent: Attempts to parse the response as JSON
|
|
77
|
-
*
|
|
78
|
-
* You might want to disable this feature when:
|
|
79
|
-
* 1. Using a custom client that doesn't recognize this header
|
|
80
|
-
* 2. Security requirements prevent exposing framework details in headers
|
|
81
|
-
*
|
|
82
|
-
* @default true
|
|
83
|
-
*/
|
|
84
|
-
enableClientResponseHints: boolean;
|
|
85
67
|
};
|
|
86
68
|
|
|
87
|
-
export function createKaitoHandler<Context>(
|
|
88
|
-
userConfig: MakeOptional<ServerConfig<Context>, 'enableClientResponseHints'>,
|
|
89
|
-
) {
|
|
90
|
-
const config: ServerConfig<Context> = {
|
|
91
|
-
enableClientResponseHints: true,
|
|
92
|
-
...userConfig,
|
|
93
|
-
};
|
|
94
|
-
|
|
69
|
+
export function createKaitoHandler<Context>(config: ServerConfig<Context>) {
|
|
95
70
|
const handle = config.router.freeze(config);
|
|
96
71
|
|
|
97
72
|
return async (request: Request): Promise<Response> => {
|
package/src/stream/stream.ts
CHANGED
|
@@ -129,12 +129,13 @@ export function sse<U, E extends string, T extends SSEEvent<U, E>>(
|
|
|
129
129
|
// TODO: use `using` once Node.js supports it
|
|
130
130
|
// // ensures close is called on controller when we're done
|
|
131
131
|
// using c = controller;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
try {
|
|
133
|
+
for await (const event of generator) {
|
|
134
|
+
controller.enqueue(event);
|
|
135
|
+
}
|
|
136
|
+
} finally {
|
|
137
|
+
controller.close();
|
|
135
138
|
}
|
|
136
|
-
|
|
137
|
-
controller.close();
|
|
138
139
|
},
|
|
139
140
|
});
|
|
140
141
|
} else {
|