@loutrejs/loutre 0.5.0 → 0.7.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 +63 -32
- package/dist/adapters/aws-lambda.d.ts +5 -3
- package/dist/adapters/aws-lambda.js +53 -23
- package/dist/adapters/bun.d.ts +7 -4
- package/dist/adapters/bun.js +52 -42
- package/dist/adapters/cloudflare-workers.d.ts +5 -3
- package/dist/adapters/cloudflare-workers.js +23 -28
- package/dist/adapters/deno.d.ts +7 -4
- package/dist/adapters/deno.js +94 -57
- package/dist/adapters/electron.d.ts +13 -5
- package/dist/adapters/electron.js +76 -28
- package/dist/application/definition.d.ts +31 -0
- package/dist/application/definition.js +16 -0
- package/dist/application/index.d.ts +4 -63
- package/dist/application/index.js +2 -11
- package/dist/application/kernel-internal.d.ts +2 -0
- package/dist/application/kernel-internal.js +10 -0
- package/dist/application/kernel.d.ts +22 -0
- package/dist/application/kernel.js +65 -0
- package/dist/core/diagnostic.d.ts +9 -0
- package/dist/core/diagnostic.js +9 -0
- package/dist/core/extension.d.ts +118 -0
- package/dist/core/extension.js +73 -0
- package/dist/core/generic-layer.d.ts +26 -0
- package/dist/core/generic-layer.js +116 -0
- package/dist/core/index.d.ts +32 -15
- package/dist/core/index.js +15 -15
- package/dist/core/injection.d.ts +4 -13
- package/dist/core/injection.js +63 -0
- package/dist/core/instrumentation.d.ts +36 -0
- package/dist/core/model/context.d.ts +18 -0
- package/dist/core/model/context.js +34 -0
- package/dist/core/model/lifecycle.d.ts +5 -0
- package/dist/core/model/lifecycle.js +44 -0
- package/dist/core/model/modules.d.ts +2 -0
- package/dist/core/model/modules.js +101 -0
- package/dist/core/model/providers.d.ts +4 -0
- package/dist/core/model/providers.js +74 -0
- package/dist/core/model/snapshot.d.ts +6 -0
- package/dist/core/model/snapshot.js +31 -0
- package/dist/core/model/types.d.ts +78 -0
- package/dist/core/model/types.js +1 -0
- package/dist/core/model/validation.d.ts +4 -0
- package/dist/core/model/validation.js +40 -0
- package/dist/core/model/visibility.d.ts +4 -0
- package/dist/core/model/visibility.js +20 -0
- package/dist/core/model.d.ts +10 -0
- package/dist/core/model.js +346 -0
- package/dist/core/module.d.ts +8 -13
- package/dist/core/source-location.d.ts +8 -0
- package/dist/core/source-location.js +31 -0
- package/dist/core/token-internal.d.ts +3 -0
- package/dist/core/token-internal.js +4 -0
- package/dist/core/type.d.ts +7 -0
- package/dist/core/type.js +4 -0
- package/dist/devtools/capsule.d.ts +51 -0
- package/dist/devtools/capsule.js +245 -0
- package/dist/devtools/index.d.ts +11 -0
- package/dist/devtools/index.js +6 -0
- package/dist/devtools/inspector.d.ts +57 -0
- package/dist/devtools/inspector.js +1 -0
- package/dist/devtools/module.d.ts +18 -0
- package/dist/devtools/module.js +26 -0
- package/dist/devtools/observer.d.ts +77 -0
- package/dist/devtools/observer.js +10 -0
- package/dist/devtools/protocol.d.ts +1 -0
- package/dist/devtools/protocol.js +1 -0
- package/dist/devtools/provider-instrumentation.d.ts +14 -0
- package/dist/devtools/provider-instrumentation.js +117 -0
- package/dist/devtools/runtime.d.ts +20 -0
- package/dist/devtools/runtime.js +519 -0
- package/dist/devtools/values.d.ts +35 -0
- package/dist/devtools/values.js +175 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/graph/index.d.ts +2 -3
- package/dist/graph/index.js +1 -3
- package/dist/graph/model.d.ts +34 -0
- package/dist/graph/model.js +127 -0
- package/dist/http/auth.d.ts +46 -0
- package/dist/http/auth.js +96 -0
- package/dist/http/client.d.ts +28 -31
- package/dist/http/client.js +58 -44
- package/dist/http/cors-internal.d.ts +29 -0
- package/dist/http/cors-internal.js +160 -0
- package/dist/http/cors.d.ts +5 -8
- package/dist/http/cors.js +7 -165
- package/dist/http/extension.d.ts +348 -0
- package/dist/http/extension.js +1061 -0
- package/dist/http/index.d.ts +9 -7
- package/dist/http/index.js +5 -7
- package/dist/{application → http}/openapi.d.ts +12 -3
- package/dist/{application → http}/openapi.js +164 -102
- package/dist/http/path.d.ts +1 -42
- package/dist/http/path.js +1 -2
- package/dist/http/runtime/request.d.ts +17 -0
- package/dist/http/runtime/request.js +109 -0
- package/dist/http/runtime/response.d.ts +18 -0
- package/dist/http/runtime/response.js +108 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/message-port/extension.d.ts +66 -0
- package/dist/message-port/extension.js +411 -0
- package/dist/message-port/index.d.ts +4 -73
- package/dist/message-port/index.js +2 -189
- package/dist/message-port/transport.d.ts +11 -0
- package/dist/message-port/transport.js +45 -0
- package/dist/runtime/async-iterator-lifecycle.d.ts +12 -0
- package/dist/runtime/async-iterator-lifecycle.js +95 -0
- package/dist/runtime/capability.d.ts +11 -11
- package/dist/runtime/capability.js +3 -3
- package/dist/runtime/di.d.ts +5 -21
- package/dist/runtime/di.js +22 -289
- package/dist/runtime/execution-tracker.d.ts +8 -0
- package/dist/runtime/execution-tracker.js +54 -0
- package/dist/runtime/index.d.ts +15 -9
- package/dist/runtime/index.js +9 -9
- package/dist/runtime/ingress-gate.d.ts +7 -0
- package/dist/runtime/ingress-gate.js +33 -0
- package/dist/runtime/kernel.d.ts +25 -0
- package/dist/runtime/kernel.js +447 -0
- package/dist/runtime/logger.d.ts +2 -0
- package/dist/runtime/logger.js +2 -0
- package/dist/runtime/node-capabilities.d.ts +1 -1
- package/dist/runtime/node-capabilities.js +1 -1
- package/dist/runtime/server-port.d.ts +2 -0
- package/dist/runtime/server-port.js +11 -0
- package/dist/tasks/extension.d.ts +144 -0
- package/dist/tasks/extension.js +525 -0
- package/dist/tasks/index.d.ts +2 -0
- package/dist/tasks/index.js +1 -0
- package/dist/tasks/runtime/cron.d.ts +6 -0
- package/dist/tasks/runtime/cron.js +89 -0
- package/dist/websocket/errors.d.ts +9 -0
- package/dist/websocket/errors.js +18 -0
- package/dist/websocket/extension.d.ts +154 -0
- package/dist/websocket/extension.js +533 -0
- package/dist/websocket/index.d.ts +3 -0
- package/dist/websocket/index.js +2 -0
- package/package.json +16 -16
- package/dist/application/binding.d.ts +0 -33
- package/dist/application/binding.js +0 -295
- package/dist/application/host.d.ts +0 -8
- package/dist/application/host.js +0 -14
- package/dist/application/queue.d.ts +0 -3
- package/dist/application/queue.js +0 -4
- package/dist/application/scheduler.d.ts +0 -2
- package/dist/application/scheduler.js +0 -45
- package/dist/core/context-key.d.ts +0 -16
- package/dist/core/context-key.js +0 -17
- package/dist/core/contract-internal.d.ts +0 -22
- package/dist/core/contract-internal.js +0 -61
- package/dist/core/contract.d.ts +0 -96
- package/dist/core/contract.js +0 -88
- package/dist/core/execution.d.ts +0 -78
- package/dist/core/execution.js +0 -61
- package/dist/core/implementation.d.ts +0 -44
- package/dist/core/implementation.js +0 -35
- package/dist/core/layer.d.ts +0 -137
- package/dist/core/layer.js +0 -81
- package/dist/graph/compiler.d.ts +0 -4
- package/dist/graph/compiler.js +0 -228
- package/dist/graph/graph.d.ts +0 -18
- package/dist/graph/graph.js +0 -1118
- package/dist/graph/ir.d.ts +0 -175
- package/dist/http/application.d.ts +0 -18
- package/dist/http/application.js +0 -515
- package/dist/http/basic-auth.d.ts +0 -37
- package/dist/http/basic-auth.js +0 -67
- package/dist/http/definitions.d.ts +0 -363
- package/dist/http/definitions.js +0 -310
- package/dist/http/hosted-protocol.d.ts +0 -4
- package/dist/http/hosted-protocol.js +0 -4
- package/dist/http/internal.d.ts +0 -8
- package/dist/http/internal.js +0 -1
- package/dist/http/params.d.ts +0 -2
- package/dist/http/params.js +0 -19
- package/dist/http/request-body.d.ts +0 -4
- package/dist/http/request-body.js +0 -6
- package/dist/http/validate.d.ts +0 -20
- package/dist/http/validate.js +0 -6
- package/dist/message-port/environment.d.ts +0 -2
- package/dist/message-port/environment.js +0 -4
- package/dist/runtime/application.d.ts +0 -38
- package/dist/runtime/application.js +0 -339
- package/dist/runtime/pipeline.d.ts +0 -11
- package/dist/runtime/pipeline.js +0 -161
- /package/dist/{graph/ir.js → core/instrumentation.js} +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { validateSchema } from '../../core/index.js';
|
|
2
|
+
export async function validateResponseHeaders(schema, headers) {
|
|
3
|
+
if (!schema) {
|
|
4
|
+
if (headers !== undefined) {
|
|
5
|
+
throw new Error('Undeclared HTTP response header was returned');
|
|
6
|
+
}
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const validated = await validateSchema(schema, headers);
|
|
10
|
+
if (validated === undefined)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (!isHttpHeaders(validated)) {
|
|
13
|
+
throw new Error('HTTP response header schema produced an invalid value');
|
|
14
|
+
}
|
|
15
|
+
return validated;
|
|
16
|
+
}
|
|
17
|
+
export function responseHeadersSchema(headers) {
|
|
18
|
+
if (isStandardSchema(headers))
|
|
19
|
+
return headers;
|
|
20
|
+
if (isResponseHeadersWithDefaults(headers))
|
|
21
|
+
return headers.schema;
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
export function responseHeadersDefaults(headers) {
|
|
25
|
+
if (headers === undefined || isStandardSchema(headers))
|
|
26
|
+
return undefined;
|
|
27
|
+
if (isResponseHeadersWithDefaults(headers))
|
|
28
|
+
return headers.defaults;
|
|
29
|
+
return headers;
|
|
30
|
+
}
|
|
31
|
+
export function isStandardSchema(value) {
|
|
32
|
+
return typeof value === 'object' && value !== null && '~standard' in value;
|
|
33
|
+
}
|
|
34
|
+
export function isResponseHeadersWithDefaults(value) {
|
|
35
|
+
return (typeof value === 'object' &&
|
|
36
|
+
value !== null &&
|
|
37
|
+
'schema' in value &&
|
|
38
|
+
isStandardSchema(value.schema));
|
|
39
|
+
}
|
|
40
|
+
export function mergeResponseHeaders(defaults, dynamic) {
|
|
41
|
+
const headers = new Headers();
|
|
42
|
+
applyResponseHeaders(headers, defaults);
|
|
43
|
+
applyResponseHeaders(headers, dynamic);
|
|
44
|
+
return headers;
|
|
45
|
+
}
|
|
46
|
+
export function applyResponseHeaders(headers, source) {
|
|
47
|
+
if (!source)
|
|
48
|
+
return;
|
|
49
|
+
for (const [name, value] of Object.entries(source)) {
|
|
50
|
+
if (value === undefined)
|
|
51
|
+
continue;
|
|
52
|
+
headers.delete(name);
|
|
53
|
+
if (typeof value === 'string') {
|
|
54
|
+
headers.set(name, value);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
for (const item of value)
|
|
58
|
+
headers.append(name, item);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function applyFrameworkHeadersToResponse(response, source) {
|
|
62
|
+
if (!source)
|
|
63
|
+
return response;
|
|
64
|
+
const headers = new Headers(response.headers);
|
|
65
|
+
applyFrameworkResponseHeaders(headers, Object.fromEntries(source.entries()));
|
|
66
|
+
return new Response(response.body, {
|
|
67
|
+
status: response.status,
|
|
68
|
+
statusText: response.statusText,
|
|
69
|
+
headers,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export function applyFrameworkResponseHeaders(headers, source) {
|
|
73
|
+
if (!source)
|
|
74
|
+
return;
|
|
75
|
+
for (const [name, value] of Object.entries(source)) {
|
|
76
|
+
if (value === undefined)
|
|
77
|
+
continue;
|
|
78
|
+
if (name.toLowerCase() === 'vary') {
|
|
79
|
+
const values = typeof value === 'string' ? [value] : value;
|
|
80
|
+
for (const item of values.flatMap((header) => header.split(','))) {
|
|
81
|
+
appendVary(headers, item.trim());
|
|
82
|
+
}
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
applyResponseHeaders(headers, { [name]: value });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function isHttpHeaders(value) {
|
|
89
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
return Object.values(value).every((header) => header === undefined ||
|
|
93
|
+
typeof header === 'string' ||
|
|
94
|
+
(Array.isArray(header) &&
|
|
95
|
+
header.every((item) => typeof item === 'string')));
|
|
96
|
+
}
|
|
97
|
+
function appendVary(headers, value) {
|
|
98
|
+
if (value.length === 0)
|
|
99
|
+
return;
|
|
100
|
+
const values = (headers.get('vary') ?? '')
|
|
101
|
+
.split(',')
|
|
102
|
+
.map((item) => item.trim())
|
|
103
|
+
.filter(Boolean);
|
|
104
|
+
if (!values.some((item) => item.toLowerCase() === value.toLowerCase())) {
|
|
105
|
+
values.push(value);
|
|
106
|
+
}
|
|
107
|
+
headers.set('vary', values.join(', '));
|
|
108
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
export * from './core/index.js';
|
|
2
2
|
export * from './application/index.js';
|
|
3
|
+
export { projectApplicationModel } from './graph/model.js';
|
|
4
|
+
export type { ApplicationModelGraphIR, GraphEdgeIR, GraphNodeIR, JsonValue, } from './graph/model.js';
|
|
5
|
+
export { ApplicationKernelRuntime } from './runtime/kernel.js';
|
|
6
|
+
export type { ApplicationKernelRuntimeOptions } from './runtime/kernel.js';
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type ExecutionDefinition, type ExecutionExtension, type ExecutionExtensionDrainContext, type SchemaOutput, type StandardSchemaV1 } from '../core/index.js';
|
|
2
|
+
export interface MessagePortServerStreamResponseDefinition {
|
|
3
|
+
readonly body: StandardSchemaV1;
|
|
4
|
+
readonly stream: 'server';
|
|
5
|
+
}
|
|
6
|
+
export type MessagePortResponseDefinition = StandardSchemaV1 | MessagePortServerStreamResponseDefinition;
|
|
7
|
+
export interface MessagePortRouteDefinition {
|
|
8
|
+
readonly input?: StandardSchemaV1;
|
|
9
|
+
readonly responses: Readonly<Record<string, MessagePortResponseDefinition>>;
|
|
10
|
+
}
|
|
11
|
+
export interface MessagePortContract<TRoutes extends Readonly<Record<string, MessagePortRouteDefinition>> = Readonly<Record<string, MessagePortRouteDefinition>>> {
|
|
12
|
+
readonly kind: 'message-port-contract';
|
|
13
|
+
readonly routes: TRoutes;
|
|
14
|
+
}
|
|
15
|
+
export interface MessagePortResult<TVariant extends string = string, TValue = unknown> {
|
|
16
|
+
readonly kind: 'message-port-result';
|
|
17
|
+
readonly response: TVariant;
|
|
18
|
+
readonly value: TValue;
|
|
19
|
+
}
|
|
20
|
+
type MessagePortResponseValue<TResponse extends MessagePortResponseDefinition> = TResponse extends MessagePortServerStreamResponseDefinition ? AsyncIterable<SchemaOutput<TResponse['body']>> : TResponse extends StandardSchemaV1 ? SchemaOutput<TResponse> : never;
|
|
21
|
+
type ResponseHelpers<TRoute extends MessagePortRouteDefinition> = {
|
|
22
|
+
readonly [TVariant in keyof TRoute['responses'] & string]: (value: MessagePortResponseValue<TRoute['responses'][TVariant]>) => MessagePortResult<TVariant, MessagePortResponseValue<TRoute['responses'][TVariant]>>;
|
|
23
|
+
};
|
|
24
|
+
export interface MessagePortContext<TRoute extends MessagePortRouteDefinition = MessagePortRouteDefinition> {
|
|
25
|
+
readonly input: TRoute['input'] extends StandardSchemaV1 ? SchemaOutput<TRoute['input']> : unknown;
|
|
26
|
+
readonly response: ResponseHelpers<TRoute>;
|
|
27
|
+
readonly signal: AbortSignal;
|
|
28
|
+
}
|
|
29
|
+
export type MessagePortHandlers<TContract extends MessagePortContract> = {
|
|
30
|
+
readonly [TName in keyof TContract['routes']]: (context: MessagePortContext<TContract['routes'][TName]>) => MessagePortResult | Promise<MessagePortResult>;
|
|
31
|
+
};
|
|
32
|
+
export interface MessagePortImplementationData<TContract extends MessagePortContract = MessagePortContract> {
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly contract: TContract;
|
|
35
|
+
readonly factory: () => MessagePortHandlers<TContract>;
|
|
36
|
+
}
|
|
37
|
+
interface CompiledMessagePortExecution {
|
|
38
|
+
readonly routes: MessagePortContract['routes'];
|
|
39
|
+
readonly factory: () => Readonly<Record<string, (context: MessagePortContext) => MessagePortResult | Promise<MessagePortResult>>>;
|
|
40
|
+
}
|
|
41
|
+
export interface MessagePortExtensionRuntime {
|
|
42
|
+
invoke(method: string, input?: unknown): Promise<MessagePortResult>;
|
|
43
|
+
drain(context: ExecutionExtensionDrainContext): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
export interface MessagePortHostApi {
|
|
46
|
+
invoke(method: string, input?: unknown): Promise<MessagePortResult>;
|
|
47
|
+
}
|
|
48
|
+
declare const messagePortExecutionExtensionIdentity: unique symbol;
|
|
49
|
+
export declare const messagePortExtension: ExecutionExtension<MessagePortImplementationData & ExecutionDefinition, CompiledMessagePortExecution, 'messagePort', MessagePortHostApi, MessagePortExtensionRuntime> & {
|
|
50
|
+
readonly [messagePortExecutionExtensionIdentity]: true;
|
|
51
|
+
};
|
|
52
|
+
export type MessagePortExecutionDefinition<TContract extends MessagePortContract = MessagePortContract> = MessagePortImplementationData<TContract> & ExecutionDefinition<typeof messagePortExtension>;
|
|
53
|
+
export declare function defineMessagePortContract<const TRoutes extends Readonly<Record<string, MessagePortRouteDefinition>>>(routes: TRoutes): MessagePortContract<TRoutes>;
|
|
54
|
+
export declare function defineMessagePortImplementation<const TContract extends MessagePortContract>(definition: {
|
|
55
|
+
readonly name?: string;
|
|
56
|
+
readonly contract: TContract;
|
|
57
|
+
readonly factory: MessagePortImplementationData<TContract>['factory'];
|
|
58
|
+
}): MessagePortExecutionDefinition<TContract>;
|
|
59
|
+
export declare const messagePort: Readonly<{
|
|
60
|
+
contract: typeof defineMessagePortContract;
|
|
61
|
+
implementation: typeof defineMessagePortImplementation;
|
|
62
|
+
extension: ExecutionExtension<MessagePortImplementationData<MessagePortContract<Readonly<Record<string, MessagePortRouteDefinition>>>> & ExecutionDefinition<import("../core/extension.js").AnyExecutionExtension>, CompiledMessagePortExecution, "messagePort", MessagePortHostApi, MessagePortExtensionRuntime> & {
|
|
63
|
+
readonly [messagePortExecutionExtensionIdentity]: true;
|
|
64
|
+
};
|
|
65
|
+
}>;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { collectInjectedDependencies, defineExecution, defineExecutionExtension, runInInjectionContext, validateSchema, } from '../core/index.js';
|
|
2
|
+
import { IngressGate } from '../runtime/ingress-gate.js';
|
|
3
|
+
import { AsyncIteratorCleanupDeadlineError, AsyncIteratorLifecycle, } from '../runtime/async-iterator-lifecycle.js';
|
|
4
|
+
export const messagePortExtension = defineExecutionExtension({
|
|
5
|
+
kind: 'execution-extension',
|
|
6
|
+
abiVersion: '1',
|
|
7
|
+
name: 'loutre:message-port',
|
|
8
|
+
compile(definition, context) {
|
|
9
|
+
return {
|
|
10
|
+
kind: 'execution',
|
|
11
|
+
id: definition.name ||
|
|
12
|
+
`${context.moduleId}.message-port.${context.definitionIndex}`,
|
|
13
|
+
executionKind: 'message-port.invocation',
|
|
14
|
+
dependencies: collectInjectedDependencies({
|
|
15
|
+
kind: 'execution',
|
|
16
|
+
id: `message-port:${definition.name || `${context.moduleId}.message-port.${context.definitionIndex}`}`,
|
|
17
|
+
name: definition.name ||
|
|
18
|
+
`${context.moduleId}.message-port.${context.definitionIndex}`,
|
|
19
|
+
}, () => definition.factory()),
|
|
20
|
+
capabilities: [],
|
|
21
|
+
compiled: Object.freeze({
|
|
22
|
+
routes: snapshotMessagePortRoutes(definition.contract.routes),
|
|
23
|
+
factory: definition.factory,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
validate({ executions }) {
|
|
28
|
+
const methods = new Set();
|
|
29
|
+
return executions.flatMap((execution) => Object.keys(execution.compiled.routes).flatMap((method) => {
|
|
30
|
+
if (!methods.has(method)) {
|
|
31
|
+
methods.add(method);
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
code: 'LUTRE_MESSAGE_PORT_DUPLICATE_METHOD',
|
|
37
|
+
message: `MessagePort method ${method} is declared more than once.`,
|
|
38
|
+
path: execution.id,
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
}));
|
|
42
|
+
},
|
|
43
|
+
createRuntime({ executions, applicationRuntime }) {
|
|
44
|
+
return createMessagePortRuntime(executions, applicationRuntime);
|
|
45
|
+
},
|
|
46
|
+
projectGraph: ({ execution }) => ({
|
|
47
|
+
methods: Object.keys(execution.compiled.routes),
|
|
48
|
+
}),
|
|
49
|
+
host: {
|
|
50
|
+
namespace: 'messagePort',
|
|
51
|
+
create: ({ runtime }) => ({
|
|
52
|
+
invoke: (method, input) => runtime.invoke(method, input),
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
export function defineMessagePortContract(routes) {
|
|
57
|
+
return Object.freeze({ kind: 'message-port-contract', routes });
|
|
58
|
+
}
|
|
59
|
+
export function defineMessagePortImplementation(definition) {
|
|
60
|
+
return defineExecution(messagePortExtension, {
|
|
61
|
+
name: definition.name ?? '',
|
|
62
|
+
contract: definition.contract,
|
|
63
|
+
factory: definition.factory,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export const messagePort = Object.freeze({
|
|
67
|
+
contract: defineMessagePortContract,
|
|
68
|
+
implementation: defineMessagePortImplementation,
|
|
69
|
+
extension: messagePortExtension,
|
|
70
|
+
});
|
|
71
|
+
function snapshotMessagePortRoutes(routes) {
|
|
72
|
+
return Object.freeze(Object.fromEntries(Object.entries(routes).map(([name, route]) => [
|
|
73
|
+
name,
|
|
74
|
+
Object.freeze({
|
|
75
|
+
...(route.input === undefined ? {} : { input: route.input }),
|
|
76
|
+
responses: Object.freeze(Object.fromEntries(Object.entries(route.responses).map(([response, definition]) => [
|
|
77
|
+
response,
|
|
78
|
+
isMessagePortServerStreamResponse(definition)
|
|
79
|
+
? Object.freeze({ ...definition })
|
|
80
|
+
: definition,
|
|
81
|
+
]))),
|
|
82
|
+
}),
|
|
83
|
+
])));
|
|
84
|
+
}
|
|
85
|
+
function createMessagePortRuntime(executions, applicationRuntime) {
|
|
86
|
+
const routes = new Map();
|
|
87
|
+
const ingress = new IngressGate();
|
|
88
|
+
const activeStreams = new Set();
|
|
89
|
+
for (const execution of executions) {
|
|
90
|
+
const handlers = runInInjectionContext({
|
|
91
|
+
consumer: {
|
|
92
|
+
kind: 'execution',
|
|
93
|
+
id: `message-port:${execution.id}`,
|
|
94
|
+
name: execution.id,
|
|
95
|
+
},
|
|
96
|
+
resolve: (token) => applicationRuntime.resolve(token, execution.id),
|
|
97
|
+
}, () => execution.compiled.factory());
|
|
98
|
+
for (const [method, definition] of Object.entries(execution.compiled.routes)) {
|
|
99
|
+
const handler = handlers[method];
|
|
100
|
+
if (handler) {
|
|
101
|
+
routes.set(method, {
|
|
102
|
+
executionId: execution.id,
|
|
103
|
+
route: definition,
|
|
104
|
+
handler,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
async invoke(method, input) {
|
|
111
|
+
const completePendingIngress = ingress.enter();
|
|
112
|
+
if (!completePendingIngress) {
|
|
113
|
+
throw new Error('LUTRE_MESSAGE_PORT_DRAINING');
|
|
114
|
+
}
|
|
115
|
+
const route = routes.get(method);
|
|
116
|
+
if (!route) {
|
|
117
|
+
completePendingIngress();
|
|
118
|
+
throw new Error(`LUTRE_MESSAGE_PORT_METHOD_NOT_FOUND: ${method}`);
|
|
119
|
+
}
|
|
120
|
+
let lease;
|
|
121
|
+
try {
|
|
122
|
+
lease = applicationRuntime.beginExecution({
|
|
123
|
+
executionId: route.executionId,
|
|
124
|
+
executionKind: 'message-port.invocation',
|
|
125
|
+
graphNodeId: route.executionId,
|
|
126
|
+
name: method,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
completePendingIngress();
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
let executionOwnedByStream = false;
|
|
134
|
+
try {
|
|
135
|
+
const value = route.route.input
|
|
136
|
+
? await validateSchema(route.route.input, input)
|
|
137
|
+
: input;
|
|
138
|
+
const response = Object.fromEntries(Object.keys(route.route.responses).map((name) => [
|
|
139
|
+
name,
|
|
140
|
+
(result) => ({
|
|
141
|
+
kind: 'message-port-result',
|
|
142
|
+
response: name,
|
|
143
|
+
value: result,
|
|
144
|
+
}),
|
|
145
|
+
]));
|
|
146
|
+
const invoke = () => route.handler({
|
|
147
|
+
input: value,
|
|
148
|
+
response,
|
|
149
|
+
signal: lease.signal,
|
|
150
|
+
});
|
|
151
|
+
const result = await (lease.run ? lease.run(invoke) : invoke());
|
|
152
|
+
const schema = route.route.responses[result.response];
|
|
153
|
+
if (!schema) {
|
|
154
|
+
throw new Error(`LUTRE_MESSAGE_PORT_RESPONSE_UNDECLARED: ${result.response}`);
|
|
155
|
+
}
|
|
156
|
+
if (isMessagePortServerStreamResponse(schema)) {
|
|
157
|
+
if (!isAsyncIterable(result.value)) {
|
|
158
|
+
throw new TypeError('LUTRE_MESSAGE_PORT_STREAM_REQUIRED');
|
|
159
|
+
}
|
|
160
|
+
const stream = createLeasedMessagePortStream(schema.body, result.value, lease, activeStreams);
|
|
161
|
+
executionOwnedByStream = true;
|
|
162
|
+
return { ...result, value: stream };
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
...result,
|
|
166
|
+
value: await validateSchema(schema, result.value),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
lease.fail?.(error);
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
if (!executionOwnedByStream)
|
|
175
|
+
lease.complete();
|
|
176
|
+
completePendingIngress();
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
async drain({ timeoutMs }) {
|
|
180
|
+
ingress.stopAccepting();
|
|
181
|
+
const deadline = Date.now() + timeoutMs;
|
|
182
|
+
await ingress.waitForIdle();
|
|
183
|
+
const reason = new Error('LUTRE_MESSAGE_PORT_DRAINING');
|
|
184
|
+
const results = await Promise.allSettled([...activeStreams].map((stream) => stream.abort(reason, deadline)));
|
|
185
|
+
const errors = results.flatMap((result) => result.status === 'rejected' ? [result.reason] : []);
|
|
186
|
+
if (errors.length > 0) {
|
|
187
|
+
throw new AggregateError(errors, 'MessagePort stream drain failed.');
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function createLeasedMessagePortStream(schema, source, lease, activeStreams) {
|
|
193
|
+
const iterator = new AsyncIteratorLifecycle(source[Symbol.asyncIterator]());
|
|
194
|
+
let finished = false;
|
|
195
|
+
let completed = false;
|
|
196
|
+
let inFlightOperations = 0;
|
|
197
|
+
let cancellationSettled = true;
|
|
198
|
+
let cancellation;
|
|
199
|
+
let iteratorCleanup;
|
|
200
|
+
let iteratorCleanupDeadline;
|
|
201
|
+
let iteratorCleanupComplete = false;
|
|
202
|
+
let resolveCompleted;
|
|
203
|
+
const completedPromise = new Promise((resolve) => {
|
|
204
|
+
resolveCompleted = resolve;
|
|
205
|
+
});
|
|
206
|
+
let control;
|
|
207
|
+
const markFinished = () => {
|
|
208
|
+
if (finished)
|
|
209
|
+
return false;
|
|
210
|
+
finished = true;
|
|
211
|
+
lease.signal.removeEventListener('abort', onAbort);
|
|
212
|
+
return true;
|
|
213
|
+
};
|
|
214
|
+
const completeIfSafe = () => {
|
|
215
|
+
if (completed ||
|
|
216
|
+
!finished ||
|
|
217
|
+
!cancellationSettled ||
|
|
218
|
+
inFlightOperations > 0) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
completed = true;
|
|
222
|
+
activeStreams.delete(control);
|
|
223
|
+
try {
|
|
224
|
+
lease.complete();
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
resolveCompleted();
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
const startIteratorCleanup = (reason, deadline) => {
|
|
231
|
+
if (iteratorCleanup) {
|
|
232
|
+
if (deadline !== undefined) {
|
|
233
|
+
iteratorCleanupDeadline = Math.min(iteratorCleanupDeadline ?? deadline, deadline);
|
|
234
|
+
}
|
|
235
|
+
return iteratorCleanup;
|
|
236
|
+
}
|
|
237
|
+
if (deadline !== undefined)
|
|
238
|
+
iteratorCleanupDeadline = deadline;
|
|
239
|
+
markFinished();
|
|
240
|
+
if (iteratorCleanupComplete)
|
|
241
|
+
return Promise.resolve();
|
|
242
|
+
cancellationSettled = false;
|
|
243
|
+
const operation = (async () => {
|
|
244
|
+
try {
|
|
245
|
+
await iterator.drain(reason, () => iteratorCleanupDeadline, 'MessagePort iterator cleanup exceeded the drain deadline.');
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
if (error instanceof AsyncIteratorCleanupDeadlineError)
|
|
249
|
+
throw error;
|
|
250
|
+
iteratorCleanupComplete = true;
|
|
251
|
+
cancellationSettled = true;
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
if (iterator.done)
|
|
256
|
+
iteratorCleanupComplete = true;
|
|
257
|
+
if (iteratorCleanupComplete)
|
|
258
|
+
cancellationSettled = true;
|
|
259
|
+
completeIfSafe();
|
|
260
|
+
}
|
|
261
|
+
})();
|
|
262
|
+
iteratorCleanup = operation;
|
|
263
|
+
void operation.then(() => {
|
|
264
|
+
if (iteratorCleanup === operation)
|
|
265
|
+
iteratorCleanup = undefined;
|
|
266
|
+
}, () => {
|
|
267
|
+
if (iteratorCleanup === operation)
|
|
268
|
+
iteratorCleanup = undefined;
|
|
269
|
+
});
|
|
270
|
+
return operation;
|
|
271
|
+
};
|
|
272
|
+
const cancel = (reason) => {
|
|
273
|
+
if (cancellation)
|
|
274
|
+
return cancellation;
|
|
275
|
+
cancellation = (async () => {
|
|
276
|
+
let cleanupError;
|
|
277
|
+
try {
|
|
278
|
+
await startIteratorCleanup(reason);
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
cleanupError = error;
|
|
282
|
+
}
|
|
283
|
+
await completedPromise;
|
|
284
|
+
if (cleanupError !== undefined)
|
|
285
|
+
throw cleanupError;
|
|
286
|
+
})();
|
|
287
|
+
return cancellation;
|
|
288
|
+
};
|
|
289
|
+
const onAbort = () => {
|
|
290
|
+
// AbortSignalはasync cleanup errorを返せないため、error伝播が必要なdrainはcontrol.abort()を直接awaitする。
|
|
291
|
+
void cancel(lease.signal.reason).catch(() => undefined);
|
|
292
|
+
};
|
|
293
|
+
control = {
|
|
294
|
+
async abort(reason, deadline) {
|
|
295
|
+
iteratorCleanupDeadline = deadline;
|
|
296
|
+
lease.abort(reason);
|
|
297
|
+
const cleanup = startIteratorCleanup(reason, deadline);
|
|
298
|
+
await cleanup;
|
|
299
|
+
await completedPromise;
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
activeStreams.add(control);
|
|
303
|
+
if (lease.signal.aborted)
|
|
304
|
+
onAbort();
|
|
305
|
+
else
|
|
306
|
+
lease.signal.addEventListener('abort', onAbort, { once: true });
|
|
307
|
+
const closeAfterError = async (error) => {
|
|
308
|
+
lease.fail?.(error);
|
|
309
|
+
let cleanupError;
|
|
310
|
+
try {
|
|
311
|
+
await startIteratorCleanup(error);
|
|
312
|
+
}
|
|
313
|
+
catch (caught) {
|
|
314
|
+
cleanupError = caught;
|
|
315
|
+
}
|
|
316
|
+
if (cleanupError !== undefined) {
|
|
317
|
+
throw new AggregateError([error, cleanupError], 'MessagePort stream validation and cleanup failed.', { cause: error });
|
|
318
|
+
}
|
|
319
|
+
throw error;
|
|
320
|
+
};
|
|
321
|
+
const validateResult = async (result) => {
|
|
322
|
+
if (result.done) {
|
|
323
|
+
markFinished();
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
return {
|
|
328
|
+
done: false,
|
|
329
|
+
value: await validateSchema(schema, result.value),
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
return closeAfterError(error);
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const wrapped = {
|
|
337
|
+
async next() {
|
|
338
|
+
if (finished)
|
|
339
|
+
return { done: true, value: undefined };
|
|
340
|
+
inFlightOperations += 1;
|
|
341
|
+
try {
|
|
342
|
+
return await validateResult(await iterator.next());
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
if (finished)
|
|
346
|
+
throw error;
|
|
347
|
+
return await closeAfterError(error);
|
|
348
|
+
}
|
|
349
|
+
finally {
|
|
350
|
+
inFlightOperations -= 1;
|
|
351
|
+
completeIfSafe();
|
|
352
|
+
}
|
|
353
|
+
},
|
|
354
|
+
async return(reason) {
|
|
355
|
+
if (finished)
|
|
356
|
+
return { done: true, value: reason };
|
|
357
|
+
inFlightOperations += 1;
|
|
358
|
+
try {
|
|
359
|
+
const result = await iterator.return(reason);
|
|
360
|
+
if (result.done) {
|
|
361
|
+
markFinished();
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
markFinished();
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
inFlightOperations -= 1;
|
|
371
|
+
completeIfSafe();
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
async throw(error) {
|
|
375
|
+
if (finished)
|
|
376
|
+
throw error;
|
|
377
|
+
inFlightOperations += 1;
|
|
378
|
+
try {
|
|
379
|
+
return await validateResult(await iterator.throw(error));
|
|
380
|
+
}
|
|
381
|
+
catch (caught) {
|
|
382
|
+
if (finished)
|
|
383
|
+
throw caught;
|
|
384
|
+
return await closeAfterError(caught);
|
|
385
|
+
}
|
|
386
|
+
finally {
|
|
387
|
+
inFlightOperations -= 1;
|
|
388
|
+
completeIfSafe();
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
return {
|
|
393
|
+
[Symbol.asyncIterator]() {
|
|
394
|
+
return wrapped;
|
|
395
|
+
},
|
|
396
|
+
cancel,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function isMessagePortServerStreamResponse(response) {
|
|
400
|
+
return (typeof response === 'object' &&
|
|
401
|
+
response !== null &&
|
|
402
|
+
'stream' in response &&
|
|
403
|
+
response.stream === 'server' &&
|
|
404
|
+
'body' in response);
|
|
405
|
+
}
|
|
406
|
+
function isAsyncIterable(value) {
|
|
407
|
+
return (typeof value === 'object' &&
|
|
408
|
+
value !== null &&
|
|
409
|
+
Symbol.asyncIterator in value &&
|
|
410
|
+
typeof value[Symbol.asyncIterator] === 'function');
|
|
411
|
+
}
|
|
@@ -1,73 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
readonly body: StandardSchemaV1;
|
|
6
|
-
readonly stream?: 'server';
|
|
7
|
-
}
|
|
8
|
-
export interface MessagePortProtocolDefinition {
|
|
9
|
-
readonly interaction?: 'unary' | 'server-stream';
|
|
10
|
-
readonly responses: Readonly<Record<string, MessagePortResponseDefinition>>;
|
|
11
|
-
readonly pipeline: readonly PipelineItem[];
|
|
12
|
-
}
|
|
13
|
-
export interface MessagePortProtocol<TDefinition extends MessagePortProtocolDefinition = MessagePortProtocolDefinition> extends ProtocolDescriptor<'messagePort', MessagePortHandlerContextDefinition<TDefinition>, LogicalMessagePortResult> {
|
|
14
|
-
readonly definition: TDefinition;
|
|
15
|
-
}
|
|
16
|
-
declare function defineMessagePort<const TDefinition extends MessagePortProtocolDefinition>(definition: TDefinition & MessagePortPipelineConstraint<TDefinition>): MessagePortProtocol<TDefinition>;
|
|
17
|
-
type MessagePortPipelineConstraint<TDefinition extends MessagePortProtocolDefinition> = IsValidProtocolPipeline<TDefinition['pipeline'], 'messagePort'> extends true ? unknown : {
|
|
18
|
-
readonly pipeline: never;
|
|
19
|
-
};
|
|
20
|
-
type MessagePortProtocolGroup<TDefinitions extends Record<string, MessagePortProtocolDefinition>> = ProtocolGroup<'messagePort', {
|
|
21
|
-
[K in keyof TDefinitions]: MessagePortProtocol<TDefinitions[K]>;
|
|
22
|
-
}>;
|
|
23
|
-
type MessagePortDefinitionsConstraint<TDefinitions extends Record<string, MessagePortProtocolDefinition>> = {
|
|
24
|
-
[K in keyof TDefinitions]: TDefinitions[K] & MessagePortPipelineConstraint<TDefinitions[K]>;
|
|
25
|
-
};
|
|
26
|
-
export interface MessagePortProtocolFactory extends ProtocolFactory<'messagePort'> {
|
|
27
|
-
<const TDefinitions extends Record<string, MessagePortProtocolDefinition>>(definitions: TDefinitions & MessagePortDefinitionsConstraint<TDefinitions>): MessagePortProtocolGroup<TDefinitions>;
|
|
28
|
-
readonly route: typeof defineMessagePort;
|
|
29
|
-
readonly handler: TerminalLayerDescriptor<'messagePort'>;
|
|
30
|
-
}
|
|
31
|
-
export declare const messagePort: MessagePortProtocolFactory;
|
|
32
|
-
export interface LogicalMessagePortResult<TVariant extends string = string, TValue = unknown> {
|
|
33
|
-
readonly kind: 'message-port-result';
|
|
34
|
-
readonly variant: TVariant;
|
|
35
|
-
readonly value: TValue;
|
|
36
|
-
}
|
|
37
|
-
type ProceduresForMessagePort<TContract extends ContractDefinition> = {
|
|
38
|
-
[K in keyof TContract['procedures']]: 'messagePort' extends keyof TContract['procedures'][K]['protocols'] ? K : never;
|
|
39
|
-
}[keyof TContract['procedures']] & string;
|
|
40
|
-
type ProtocolAt<TContract extends ContractDefinition, TProcedure extends keyof TContract['procedures']> = TContract['procedures'][TProcedure]['protocols']['messagePort' & keyof TContract['procedures'][TProcedure]['protocols']] extends infer TProtocol ? TProtocol extends MessagePortProtocol ? TProtocol : never : never;
|
|
41
|
-
type MessageHelpers<TProtocol extends MessagePortProtocol> = {
|
|
42
|
-
[TVariant in keyof TProtocol['definition']['responses'] & string]: (value: TProtocol['definition']['responses'][TVariant] extends {
|
|
43
|
-
readonly stream: 'server';
|
|
44
|
-
} ? AsyncIterable<SchemaOutput<TProtocol['definition']['responses'][TVariant]['body']>> : SchemaOutput<TProtocol['definition']['responses'][TVariant]['body']>) => LogicalMessagePortResult;
|
|
45
|
-
};
|
|
46
|
-
type MessagePortHandlerContextDefinition<TDefinition extends MessagePortProtocolDefinition> = {
|
|
47
|
-
readonly input: unknown;
|
|
48
|
-
readonly message: MessageHelpers<MessagePortProtocol<TDefinition>>;
|
|
49
|
-
readonly logger: Logger;
|
|
50
|
-
} & ContextProvidedBeforeTerminal<TDefinition['pipeline']>;
|
|
51
|
-
export type MessagePortHandlerContext<TProtocol extends MessagePortProtocol> = MessagePortHandlerContextDefinition<TProtocol['definition']>;
|
|
52
|
-
export type HandlerOf<TContract extends ContractDefinition, TProtocol extends 'messagePort', TProcedures extends ProceduresForMessagePort<TContract> = ProceduresForMessagePort<TContract>> = TProtocol extends 'messagePort' ? {
|
|
53
|
-
[K in TProcedures]: (context: MessagePortHandlerContext<ProtocolAt<TContract, K>>) => LogicalMessagePortResult | Promise<LogicalMessagePortResult>;
|
|
54
|
-
} : never;
|
|
55
|
-
export type MessageContextOf<THandler, TProcedure extends keyof THandler> = THandler[TProcedure] extends (context: infer TContext, ...args: any[]) => any ? TContext : never;
|
|
56
|
-
export interface MessagePortProtocolExecution {
|
|
57
|
-
readonly graph: ApplicationGraphIR;
|
|
58
|
-
initialize(): Promise<void>;
|
|
59
|
-
shutdown(signal?: string): Promise<void>;
|
|
60
|
-
invoke(procedure: string, input?: unknown): Promise<LogicalMessagePortResult>;
|
|
61
|
-
}
|
|
62
|
-
export declare function createMessagePortExecution(options: {
|
|
63
|
-
readonly runtime: ApplicationRuntime;
|
|
64
|
-
readonly graph: ApplicationGraphIR;
|
|
65
|
-
readonly logger?: Logger;
|
|
66
|
-
}): MessagePortProtocolExecution;
|
|
67
|
-
export interface MessagePortLike {
|
|
68
|
-
postMessage(value: unknown): void;
|
|
69
|
-
addEventListener(type: string, listener: (event: any) => void): void;
|
|
70
|
-
start?(): void;
|
|
71
|
-
}
|
|
72
|
-
export declare function attachMessagePort(application: MessagePortProtocolExecution, port: MessagePortLike): void;
|
|
73
|
-
export {};
|
|
1
|
+
export { defineMessagePortContract, defineMessagePortImplementation, messagePort, messagePortExtension, } from './extension.js';
|
|
2
|
+
export { attachMessagePort } from './transport.js';
|
|
3
|
+
export type { MessagePortContext, MessagePortContract, MessagePortExecutionDefinition, MessagePortExtensionRuntime, MessagePortHandlers, MessagePortHostApi, MessagePortImplementationData, MessagePortResponseDefinition, MessagePortResult, MessagePortRouteDefinition, MessagePortServerStreamResponseDefinition, } from './extension.js';
|
|
4
|
+
export type { MessagePortHost, MessagePortLike } from './transport.js';
|