@fluojs/http 1.0.0-beta.1 → 1.0.0-beta.11
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.ko.md +39 -5
- package/README.md +39 -5
- package/dist/adapter.d.ts +31 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +37 -0
- package/dist/adapters/binding.d.ts +6 -0
- package/dist/adapters/binding.d.ts.map +1 -1
- package/dist/adapters/binding.js +54 -55
- package/dist/adapters/dto-binding-plan.d.ts +22 -0
- package/dist/adapters/dto-binding-plan.d.ts.map +1 -0
- package/dist/adapters/dto-binding-plan.js +86 -0
- package/dist/adapters/dto-validation-adapter.d.ts +3 -1
- package/dist/adapters/dto-validation-adapter.d.ts.map +1 -1
- package/dist/adapters/dto-validation-adapter.js +10 -16
- package/dist/context/request-context-node-store.d.ts +25 -0
- package/dist/context/request-context-node-store.d.ts.map +1 -0
- package/dist/context/request-context-node-store.js +32 -0
- package/dist/context/request-context-stack-store.d.ts +8 -0
- package/dist/context/request-context-stack-store.d.ts.map +1 -0
- package/dist/context/request-context-stack-store.js +29 -0
- package/dist/context/request-context-store.d.ts +7 -0
- package/dist/context/request-context-store.d.ts.map +1 -0
- package/dist/context/request-context-store.js +1 -0
- package/dist/context/request-context.d.ts +7 -3
- package/dist/context/request-context.d.ts.map +1 -1
- package/dist/context/request-context.js +17 -5
- package/dist/context/sse.d.ts +38 -0
- package/dist/context/sse.d.ts.map +1 -1
- package/dist/context/sse.js +50 -2
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +262 -53
- package/dist/dispatch/dispatch-content-negotiation.d.ts +17 -0
- package/dist/dispatch/dispatch-content-negotiation.d.ts.map +1 -1
- package/dist/dispatch/dispatch-content-negotiation.js +21 -0
- package/dist/dispatch/dispatch-error-policy.d.ts +8 -0
- package/dist/dispatch/dispatch-error-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-error-policy.js +9 -0
- package/dist/dispatch/dispatch-handler-policy.d.ts +11 -1
- package/dist/dispatch/dispatch-handler-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-handler-policy.js +17 -5
- package/dist/dispatch/dispatch-response-policy.d.ts +11 -1
- package/dist/dispatch/dispatch-response-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-response-policy.js +44 -2
- package/dist/dispatch/dispatch-routing-policy.d.ts +13 -0
- package/dist/dispatch/dispatch-routing-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-routing-policy.js +49 -4
- package/dist/dispatch/dispatcher.d.ts +24 -7
- package/dist/dispatch/dispatcher.d.ts.map +1 -1
- package/dist/dispatch/dispatcher.js +464 -48
- package/dist/dispatch/fast-path/debug-visibility.d.ts +18 -0
- package/dist/dispatch/fast-path/debug-visibility.d.ts.map +1 -0
- package/dist/dispatch/fast-path/debug-visibility.js +39 -0
- package/dist/dispatch/fast-path/eligibility-checker.d.ts +22 -0
- package/dist/dispatch/fast-path/eligibility-checker.d.ts.map +1 -0
- package/dist/dispatch/fast-path/eligibility-checker.js +107 -0
- package/dist/dispatch/fast-path/eligibility.d.ts +61 -0
- package/dist/dispatch/fast-path/eligibility.d.ts.map +1 -0
- package/dist/dispatch/fast-path/eligibility.js +23 -0
- package/dist/dispatch/fast-path/fast-path-executor.d.ts +21 -0
- package/dist/dispatch/fast-path/fast-path-executor.d.ts.map +1 -0
- package/dist/dispatch/fast-path/fast-path-executor.js +80 -0
- package/dist/dispatch/fast-path/index.d.ts +6 -0
- package/dist/dispatch/fast-path/index.d.ts.map +1 -0
- package/dist/dispatch/fast-path/index.js +4 -0
- package/dist/dispatch/native-route-handoff.d.ts +53 -0
- package/dist/dispatch/native-route-handoff.d.ts.map +1 -0
- package/dist/dispatch/native-route-handoff.js +97 -0
- package/dist/errors.d.ts +3 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -0
- package/dist/guards.d.ts +7 -0
- package/dist/guards.d.ts.map +1 -1
- package/dist/guards.js +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/input-error-detail.d.ts +9 -0
- package/dist/input-error-detail.d.ts.map +1 -1
- package/dist/input-error-detail.js +10 -0
- package/dist/interceptors.d.ts +8 -0
- package/dist/interceptors.d.ts.map +1 -1
- package/dist/interceptors.js +14 -1
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +3 -1
- package/dist/mapping.d.ts +7 -0
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +93 -11
- package/dist/middleware/correlation.d.ts +5 -0
- package/dist/middleware/correlation.d.ts.map +1 -1
- package/dist/middleware/correlation.js +14 -2
- package/dist/middleware/cors.d.ts +9 -0
- package/dist/middleware/cors.d.ts.map +1 -1
- package/dist/middleware/cors.js +11 -0
- package/dist/middleware/middleware.d.ts +34 -0
- package/dist/middleware/middleware.d.ts.map +1 -1
- package/dist/middleware/middleware.js +47 -0
- package/dist/middleware/security-headers.d.ts +9 -0
- package/dist/middleware/security-headers.d.ts.map +1 -1
- package/dist/middleware/security-headers.js +11 -0
- package/dist/route-path.d.ts +41 -0
- package/dist/route-path.d.ts.map +1 -1
- package/dist/route-path.js +50 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RequestContextStore } from './request-context-store.js';
|
|
2
|
+
type AsyncLocalStorageConstructor = new () => RequestContextStore;
|
|
3
|
+
type NodeAsyncHooksModule = {
|
|
4
|
+
AsyncLocalStorage?: AsyncLocalStorageConstructor;
|
|
5
|
+
};
|
|
6
|
+
type AsyncLocalStorageResolutionHost = {
|
|
7
|
+
AsyncLocalStorage?: AsyncLocalStorageConstructor;
|
|
8
|
+
process?: {
|
|
9
|
+
getBuiltinModule?(id: 'node:async_hooks'): NodeAsyncHooksModule;
|
|
10
|
+
versions?: {
|
|
11
|
+
node?: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
type NodeAsyncHooksLoader = () => Promise<NodeAsyncHooksModule>;
|
|
16
|
+
/**
|
|
17
|
+
* Resolves the host `AsyncLocalStorage` constructor without eagerly importing Node built-ins.
|
|
18
|
+
*
|
|
19
|
+
* @param host Host global-like object to inspect for async-context support.
|
|
20
|
+
* @param loadNodeAsyncHooks Lazy loader for Node's `node:async_hooks` module.
|
|
21
|
+
* @returns The resolved `AsyncLocalStorage` constructor, or `undefined` when unavailable.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveAsyncLocalStorageConstructor(host?: AsyncLocalStorageResolutionHost, loadNodeAsyncHooks?: NodeAsyncHooksLoader): Promise<AsyncLocalStorageConstructor | undefined>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=request-context-node-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context-node-store.d.ts","sourceRoot":"","sources":["../../src/context/request-context-node-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,KAAK,4BAA4B,GAAG,UAAU,mBAAmB,CAAC;AAElE,KAAK,oBAAoB,GAAG;IAC1B,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;CAClD,CAAC;AAEF,KAAK,+BAA+B,GAAG;IACrC,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;IACjD,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,CAAC,EAAE,EAAE,kBAAkB,GAAG,oBAAoB,CAAC;QAChE,QAAQ,CAAC,EAAE;YACT,IAAI,CAAC,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH,CAAC;AAEF,KAAK,oBAAoB,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEhE;;;;;;GAMG;AACH,wBAAsB,mCAAmC,CACvD,IAAI,GAAE,+BAA4C,EAClD,kBAAkB,GAAE,oBAA2C,GAC9D,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC,CAsBnD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the host `AsyncLocalStorage` constructor without eagerly importing Node built-ins.
|
|
3
|
+
*
|
|
4
|
+
* @param host Host global-like object to inspect for async-context support.
|
|
5
|
+
* @param loadNodeAsyncHooks Lazy loader for Node's `node:async_hooks` module.
|
|
6
|
+
* @returns The resolved `AsyncLocalStorage` constructor, or `undefined` when unavailable.
|
|
7
|
+
*/
|
|
8
|
+
export async function resolveAsyncLocalStorageConstructor(host = globalThis, loadNodeAsyncHooks = importNodeAsyncHooks) {
|
|
9
|
+
if (typeof host.AsyncLocalStorage === 'function') {
|
|
10
|
+
return host.AsyncLocalStorage;
|
|
11
|
+
}
|
|
12
|
+
const builtinAsyncLocalStorage = host.process?.getBuiltinModule?.('node:async_hooks').AsyncLocalStorage;
|
|
13
|
+
if (typeof builtinAsyncLocalStorage === 'function') {
|
|
14
|
+
return builtinAsyncLocalStorage;
|
|
15
|
+
}
|
|
16
|
+
if (!isNodeHost(host)) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const nodeAsyncHooks = await loadNodeAsyncHooks();
|
|
21
|
+
return nodeAsyncHooks.AsyncLocalStorage;
|
|
22
|
+
} catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function isNodeHost(host) {
|
|
27
|
+
return typeof host.process?.versions?.node === 'string';
|
|
28
|
+
}
|
|
29
|
+
function importNodeAsyncHooks() {
|
|
30
|
+
const nodeAsyncHooksSpecifier = `node:${'async_hooks'}`;
|
|
31
|
+
return import(nodeAsyncHooksSpecifier);
|
|
32
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RequestContextStore } from './request-context-store.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates the synchronous fallback request-context store used when no async-context primitive exists.
|
|
4
|
+
*
|
|
5
|
+
* @returns A stack-backed request-context store scoped to synchronous callback frames.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createStackRequestContextStore(): RequestContextStore;
|
|
8
|
+
//# sourceMappingURL=request-context-stack-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context-stack-store.d.ts","sourceRoot":"","sources":["../../src/context/request-context-stack-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,mBAAmB,CAmBpE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the synchronous fallback request-context store used when no async-context primitive exists.
|
|
3
|
+
*
|
|
4
|
+
* @returns A stack-backed request-context store scoped to synchronous callback frames.
|
|
5
|
+
*/
|
|
6
|
+
export function createStackRequestContextStore() {
|
|
7
|
+
const stack = [];
|
|
8
|
+
return {
|
|
9
|
+
getStore() {
|
|
10
|
+
return stack.at(-1);
|
|
11
|
+
},
|
|
12
|
+
run(context, callback) {
|
|
13
|
+
stack.push(context);
|
|
14
|
+
try {
|
|
15
|
+
return callback();
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw error;
|
|
18
|
+
} finally {
|
|
19
|
+
removeStackContext(stack, context);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function removeStackContext(stack, context) {
|
|
25
|
+
const index = stack.lastIndexOf(context);
|
|
26
|
+
if (index >= 0) {
|
|
27
|
+
stack.splice(index, 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RequestContext } from '../types.js';
|
|
2
|
+
/** Store abstraction shared by host async-context implementations and the synchronous fallback. */
|
|
3
|
+
export type RequestContextStore = {
|
|
4
|
+
getStore(): RequestContext | undefined;
|
|
5
|
+
run<T>(context: RequestContext, callback: () => T): T;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=request-context-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context-store.d.ts","sourceRoot":"","sources":["../../src/context/request-context-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,mGAAmG;AACnG,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,IAAI,cAAc,GAAG,SAAS,CAAC;IACvC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CACvD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { ContextKey, RequestContext } from '../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Runs a callback inside the request-scoped
|
|
3
|
+
* Runs a callback inside the request-scoped async context.
|
|
4
|
+
*
|
|
5
|
+
* Hosts with `AsyncLocalStorage` preserve the context across awaited work. Hosts without an async
|
|
6
|
+
* context primitive use a stack fallback that keeps the context only for the synchronous callback
|
|
7
|
+
* frame and clears it before awaited continuations resume.
|
|
4
8
|
*
|
|
5
9
|
* @param context Request context snapshot to bind to the current async execution chain.
|
|
6
10
|
* @param callback Callback executed with `context` available through request-context helpers.
|
|
@@ -21,9 +25,9 @@ export declare function getCurrentRequestContext(): RequestContext | undefined;
|
|
|
21
25
|
*/
|
|
22
26
|
export declare function assertRequestContext(): RequestContext;
|
|
23
27
|
/**
|
|
24
|
-
* Creates a defensive clone of a request context for
|
|
28
|
+
* Creates a defensive clone of a request context for async-context storage.
|
|
25
29
|
*
|
|
26
|
-
* @param context Request context to clone before storing in
|
|
30
|
+
* @param context Request context to clone before storing in the active async-context store.
|
|
27
31
|
* @returns A shallow clone with copied metadata map to avoid cross-request mutation.
|
|
28
32
|
*/
|
|
29
33
|
export declare function createRequestContext(context: RequestContext): RequestContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/context/request-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/context/request-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAO9D;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,GAAG,SAAS,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAUrD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAK5E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAE7F;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAE9F"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
1
|
import { FluoError } from '@fluojs/core';
|
|
3
|
-
|
|
2
|
+
import { resolveAsyncLocalStorageConstructor } from './request-context-node-store.js';
|
|
3
|
+
import { createStackRequestContextStore } from './request-context-stack-store.js';
|
|
4
|
+
const requestContextStore = await createRequestContextStore();
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Runs a callback inside the request-scoped
|
|
7
|
+
* Runs a callback inside the request-scoped async context.
|
|
8
|
+
*
|
|
9
|
+
* Hosts with `AsyncLocalStorage` preserve the context across awaited work. Hosts without an async
|
|
10
|
+
* context primitive use a stack fallback that keeps the context only for the synchronous callback
|
|
11
|
+
* frame and clears it before awaited continuations resume.
|
|
7
12
|
*
|
|
8
13
|
* @param context Request context snapshot to bind to the current async execution chain.
|
|
9
14
|
* @param callback Callback executed with `context` available through request-context helpers.
|
|
@@ -39,9 +44,9 @@ export function assertRequestContext() {
|
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
/**
|
|
42
|
-
* Creates a defensive clone of a request context for
|
|
47
|
+
* Creates a defensive clone of a request context for async-context storage.
|
|
43
48
|
*
|
|
44
|
-
* @param context Request context to clone before storing in
|
|
49
|
+
* @param context Request context to clone before storing in the active async-context store.
|
|
45
50
|
* @returns A shallow clone with copied metadata map to avoid cross-request mutation.
|
|
46
51
|
*/
|
|
47
52
|
export function createRequestContext(context) {
|
|
@@ -86,4 +91,11 @@ export function getContextValue(context, key) {
|
|
|
86
91
|
*/
|
|
87
92
|
export function setContextValue(context, key, value) {
|
|
88
93
|
context.metadata[key.id] = value;
|
|
94
|
+
}
|
|
95
|
+
async function createRequestContextStore() {
|
|
96
|
+
const AsyncLocalStorage = await resolveAsyncLocalStorageConstructor();
|
|
97
|
+
if (typeof AsyncLocalStorage === 'function') {
|
|
98
|
+
return new AsyncLocalStorage();
|
|
99
|
+
}
|
|
100
|
+
return createStackRequestContextStore();
|
|
89
101
|
}
|
package/dist/context/sse.d.ts
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
import type { RequestContext } from '../types.js';
|
|
2
|
+
/** Options that customize the fields emitted for one server-sent event frame. */
|
|
2
3
|
export interface SseSendOptions {
|
|
4
|
+
/** Optional SSE event name. Newline characters are stripped before writing. */
|
|
3
5
|
event?: string;
|
|
6
|
+
/** Optional SSE event id. Newline characters are stripped before writing. */
|
|
4
7
|
id?: string | number;
|
|
8
|
+
/** Optional client retry delay in milliseconds. Non-finite or negative values are ignored. */
|
|
5
9
|
retry?: number;
|
|
6
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Encodes a comment as a canonical server-sent event comment frame.
|
|
13
|
+
*
|
|
14
|
+
* @param comment Comment text to split into SSE comment lines.
|
|
15
|
+
* @returns A complete SSE comment frame ending in a blank line.
|
|
16
|
+
*/
|
|
7
17
|
export declare function encodeSseComment(comment: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Encodes data and optional event fields as a server-sent event message frame.
|
|
20
|
+
*
|
|
21
|
+
* @param data Payload to write. Strings are sent as-is; other values are JSON serialized.
|
|
22
|
+
* @param options Optional event metadata fields.
|
|
23
|
+
* @returns A complete SSE message frame ending in a blank line.
|
|
24
|
+
* @throws {TypeError} When `data` cannot be represented as an SSE data field.
|
|
25
|
+
*/
|
|
8
26
|
export declare function encodeSseMessage(data: unknown, options?: SseSendOptions): string;
|
|
27
|
+
/**
|
|
28
|
+
* Response helper for server-sent event streams backed by an adapter-provided response stream.
|
|
29
|
+
*
|
|
30
|
+
* The helper commits SSE headers immediately, closes idempotently on request abort
|
|
31
|
+
* or raw stream close, and removes all registered close/abort listeners during cleanup.
|
|
32
|
+
*/
|
|
9
33
|
export declare class SseResponse {
|
|
10
34
|
private readonly context;
|
|
11
35
|
private closed;
|
|
@@ -13,8 +37,22 @@ export declare class SseResponse {
|
|
|
13
37
|
private removeCloseListener?;
|
|
14
38
|
private readonly onAbort;
|
|
15
39
|
constructor(context: RequestContext);
|
|
40
|
+
/**
|
|
41
|
+
* Writes one SSE data message when the stream is still open.
|
|
42
|
+
*
|
|
43
|
+
* @param data Payload to encode into `data:` lines.
|
|
44
|
+
* @param options Optional event metadata fields.
|
|
45
|
+
* @returns `true` when the underlying stream accepted the frame without backpressure.
|
|
46
|
+
*/
|
|
16
47
|
send(data: unknown, options?: SseSendOptions): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Writes one SSE comment frame when the stream is still open.
|
|
50
|
+
*
|
|
51
|
+
* @param comment Comment text to encode.
|
|
52
|
+
* @returns `true` when the underlying stream accepted the frame without backpressure.
|
|
53
|
+
*/
|
|
17
54
|
comment(comment: string): boolean;
|
|
55
|
+
/** Closes the SSE stream and removes registered abort/close listeners exactly once. */
|
|
18
56
|
close(): void;
|
|
19
57
|
private writeFrame;
|
|
20
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/context/sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8C,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9F,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoCD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,CAoBpF;AAED,qBAAa,WAAW;IASV,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,mBAAmB,CAAC,CAAa;IAEzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAEtB;gBAE2B,OAAO,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/context/sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8C,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9F,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,CAoBpF;AAED;;;;;GAKG;AACH,qBAAa,WAAW;IASV,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,mBAAmB,CAAC,CAAa;IAEzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAEtB;gBAE2B,OAAO,EAAE,cAAc;IAmCpD;;;;;;OAMG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO;IAI1D;;;;;OAKG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIjC,uFAAuF;IACvF,KAAK,IAAI,IAAI;IAiBb,OAAO,CAAC,UAAU;CAYnB"}
|
package/dist/context/sse.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Options that customize the fields emitted for one server-sent event frame. */
|
|
2
|
+
|
|
1
3
|
function sanitizeSseField(value) {
|
|
2
4
|
return value.replace(/\r/g, '').replace(/\n/g, '');
|
|
3
5
|
}
|
|
@@ -23,11 +25,27 @@ function resolveSseStream(response) {
|
|
|
23
25
|
}
|
|
24
26
|
return response.stream;
|
|
25
27
|
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Encodes a comment as a canonical server-sent event comment frame.
|
|
31
|
+
*
|
|
32
|
+
* @param comment Comment text to split into SSE comment lines.
|
|
33
|
+
* @returns A complete SSE comment frame ending in a blank line.
|
|
34
|
+
*/
|
|
26
35
|
export function encodeSseComment(comment) {
|
|
27
36
|
const lines = splitSseLines(comment);
|
|
28
37
|
const encoded = lines.map(line => line.length === 0 ? ':' : `: ${line}`);
|
|
29
38
|
return `${encoded.join('\n')}\n\n`;
|
|
30
39
|
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Encodes data and optional event fields as a server-sent event message frame.
|
|
43
|
+
*
|
|
44
|
+
* @param data Payload to write. Strings are sent as-is; other values are JSON serialized.
|
|
45
|
+
* @param options Optional event metadata fields.
|
|
46
|
+
* @returns A complete SSE message frame ending in a blank line.
|
|
47
|
+
* @throws {TypeError} When `data` cannot be represented as an SSE data field.
|
|
48
|
+
*/
|
|
31
49
|
export function encodeSseMessage(data, options = {}) {
|
|
32
50
|
const lines = [];
|
|
33
51
|
if (options.event !== undefined) {
|
|
@@ -44,6 +62,13 @@ export function encodeSseMessage(data, options = {}) {
|
|
|
44
62
|
}
|
|
45
63
|
return `${lines.join('\n')}\n\n`;
|
|
46
64
|
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Response helper for server-sent event streams backed by an adapter-provided response stream.
|
|
68
|
+
*
|
|
69
|
+
* The helper commits SSE headers immediately, closes idempotently on request abort
|
|
70
|
+
* or raw stream close, and removes all registered close/abort listeners during cleanup.
|
|
71
|
+
*/
|
|
47
72
|
export class SseResponse {
|
|
48
73
|
closed = false;
|
|
49
74
|
stream;
|
|
@@ -70,16 +95,39 @@ export class SseResponse {
|
|
|
70
95
|
context.request.signal?.addEventListener('abort', this.onAbort, {
|
|
71
96
|
once: true
|
|
72
97
|
});
|
|
73
|
-
|
|
74
|
-
|
|
98
|
+
const removeCloseListener = this.stream.onClose?.(this.onAbort) ?? undefined;
|
|
99
|
+
if (this.closed) {
|
|
100
|
+
removeCloseListener?.();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.removeCloseListener = removeCloseListener;
|
|
104
|
+
if (this.stream.closed) {
|
|
105
|
+
this.close();
|
|
75
106
|
}
|
|
76
107
|
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Writes one SSE data message when the stream is still open.
|
|
111
|
+
*
|
|
112
|
+
* @param data Payload to encode into `data:` lines.
|
|
113
|
+
* @param options Optional event metadata fields.
|
|
114
|
+
* @returns `true` when the underlying stream accepted the frame without backpressure.
|
|
115
|
+
*/
|
|
77
116
|
send(data, options = {}) {
|
|
78
117
|
return this.writeFrame(encodeSseMessage(data, options));
|
|
79
118
|
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Writes one SSE comment frame when the stream is still open.
|
|
122
|
+
*
|
|
123
|
+
* @param comment Comment text to encode.
|
|
124
|
+
* @returns `true` when the underlying stream accepted the frame without backpressure.
|
|
125
|
+
*/
|
|
80
126
|
comment(comment) {
|
|
81
127
|
return this.writeFrame(encodeSseComment(comment));
|
|
82
128
|
}
|
|
129
|
+
|
|
130
|
+
/** Closes the SSE stream and removes registered abort/close listeners exactly once. */
|
|
83
131
|
close() {
|
|
84
132
|
if (this.closed) {
|
|
85
133
|
return;
|
package/dist/decorators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EAEzB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EAEzB,MAAM,cAAc,CAAC;AAgBtB,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAc,eAAe,EAAE,MAAM,YAAY,CAAC;AAGxF,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,wBAAwB,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;AAI1H,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AACnD,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;AACrD,KAAK,0BAA0B,GAAG,wBAAwB,GAAG,yBAAyB,CAAC;AACvF,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AAqUnD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,QAAQ,SAAK,GAAG,kBAAkB,CAa5D;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,0BAA0B,CAuBnE;AAED;;;;;GAKG;AACH,eAAO,MAAM,GAAG,SAxHA,MAAM,KAAG,mBAwHqB,CAAC;AAC/C;;;;;GAKG;AACH,eAAO,MAAM,IAAI,SA/HD,MAAM,KAAG,mBA+HuB,CAAC;AACjD;;;;;GAKG;AACH,eAAO,MAAM,GAAG,SAtIA,MAAM,KAAG,mBAsIqB,CAAC;AAC/C;;;;;GAKG;AACH,eAAO,MAAM,KAAK,SA7IF,MAAM,KAAG,mBA6IyB,CAAC;AACnD;;;;;GAKG;AACH,eAAO,MAAM,MAAM,SApJH,MAAM,KAAG,mBAoJ2B,CAAC;AACrD;;;;;GAKG;AACH,eAAO,MAAM,OAAO,SA3JJ,MAAM,KAAG,mBA2J6B,CAAC;AACvD;;;;;GAKG;AACH,eAAO,MAAM,IAAI,SAlKD,MAAM,KAAG,mBAkKuB,CAAC;AACjD;;;;;GAKG;AACH,eAAO,MAAM,GAAG,SAzKA,MAAM,KAAG,mBAyKqB,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,UAAU,0BA5JF,mBA8JnB,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAIrE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,qBAlLA,mBAoLnB,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,mBAAmB,GAAG,MAAM,EAAE,GAAG,SAAS,CAM7H;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,SAxLL,MAAM,KAAG,kBAwL8B,CAAC;AACxD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,SA/LN,MAAM,KAAG,kBA+LgC,CAAC;AAC1D;;;;;GAKG;AACH,eAAO,MAAM,UAAU,SAtMP,MAAM,KAAG,kBAsMkC,CAAC;AAC5D;;;;;GAKG;AACH,eAAO,MAAM,UAAU,SA7MP,MAAM,KAAG,kBA6MkC,CAAC;AAC5D;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,SApNL,MAAM,KAAG,kBAoN8B,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,kBAAkB,CAa7C;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,aAAa,GAAG,kBAAkB,CAapE;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAcvE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAa9E;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,0BAA0B,CAyB5E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,YAAY,EAAE,eAAe,EAAE,GAAG,0BAA0B,CAyB9F"}
|