@astrale-os/kernel-client 0.6.0-beta.55 → 0.6.0-beta.57
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/auth/credential.js +2 -2
- package/dist/client/admission.js +8 -1
- package/dist/client/request.d.ts +3 -2
- package/dist/client/request.js +3 -0
- package/dist/graph/domain/domain.typecheck.js +1 -0
- package/dist/graph/domain/project.js +10 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/session/reference.d.ts +3 -4
- package/dist/session/reference.js +5 -3
- package/dist/session/routing/cache.d.ts +1 -2
- package/dist/session/routing/cache.js +2 -8
- package/dist/session/routing/dispatch.d.ts +1 -2
- package/dist/session/routing/dispatch.js +14 -14
- package/dist/session/routing/index.d.ts +0 -1
- package/dist/session/session.js +14 -6
- package/dist/session/session.typecheck.js +9 -1
- package/dist/transport/auto/fallback.d.ts +2 -1
- package/dist/transport/auto/fallback.js +2 -1
- package/dist/transport/http/transport.js +0 -1
- package/package.json +5 -5
- package/dist/session/routing/expectation.d.ts +0 -6
- package/dist/session/routing/expectation.js +0 -1
package/dist/auth/credential.js
CHANGED
|
@@ -8,8 +8,8 @@ export function credentialApi(call) {
|
|
|
8
8
|
return credential(await call(IDENTITY_MINT_PATH, input, options));
|
|
9
9
|
},
|
|
10
10
|
async delegate(principal, input, options) {
|
|
11
|
-
const target = Path.
|
|
12
|
-
return credential(await call(target, input, options));
|
|
11
|
+
const target = Path.staticMethod(identityOwner, identity.delegate.name).raw;
|
|
12
|
+
return credential(await call(target, { ...input, principal }, options));
|
|
13
13
|
},
|
|
14
14
|
});
|
|
15
15
|
}
|
package/dist/client/admission.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Target } from '@astrale-os/kernel-core/callable';
|
|
1
2
|
import { Path } from '@astrale-os/kernel-core/path';
|
|
2
3
|
import * as portable from '@astrale-os/kernel-dsl/value';
|
|
3
4
|
/** Parent-private Call acceptance shared by Client and Client Session. */
|
|
@@ -5,7 +6,13 @@ export function acceptCall(input) {
|
|
|
5
6
|
if (input === null || typeof input !== 'object' || Array.isArray(input)) {
|
|
6
7
|
throw new TypeError('Client call must be an object.');
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
+
const target = input.target;
|
|
10
|
+
return Object.freeze({
|
|
11
|
+
target: typeof target === 'object' && target !== null && 'callable' in target
|
|
12
|
+
? Target(target)
|
|
13
|
+
: admitPath(target),
|
|
14
|
+
input: admitInput(input.input),
|
|
15
|
+
});
|
|
9
16
|
}
|
|
10
17
|
function admitPath(input) {
|
|
11
18
|
try {
|
package/dist/client/request.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { Target } from '@astrale-os/kernel-core/callable';
|
|
1
2
|
import type { PathLike } from '@astrale-os/kernel-core/path';
|
|
2
3
|
import type * as protocol from '@astrale-os/kernel-protocol/invocation';
|
|
3
4
|
import type { RequestOptions, TransportRequest } from '../transport/index.js';
|
|
4
5
|
import type { Input } from './result.js';
|
|
5
6
|
/** One portable call before Path canonicalization, correlation, and credential binding. */
|
|
6
7
|
export interface Call {
|
|
7
|
-
readonly target: PathLike;
|
|
8
|
+
readonly target: PathLike | Target;
|
|
8
9
|
readonly input: Input;
|
|
9
10
|
}
|
|
10
11
|
export interface ClientDispatchOptions extends RequestOptions {
|
|
@@ -21,6 +22,6 @@ export interface AdmittedRequest {
|
|
|
21
22
|
readonly schema?: protocol.SchemaTarget;
|
|
22
23
|
readonly options: RequestOptions;
|
|
23
24
|
}
|
|
24
|
-
export declare function call(target: PathLike, input: Input): Call;
|
|
25
|
+
export declare function call(target: PathLike | Target, input: Input): Call;
|
|
25
26
|
export declare function admitRequest(input: Call, options: ClientDispatchOptions | undefined, lifecycle: AbortSignal): AdmittedRequest;
|
|
26
27
|
export declare function invocation(request: AdmittedRequest, credential?: string, trace?: protocol.Trace): TransportRequest;
|
package/dist/client/request.js
CHANGED
|
@@ -45,6 +45,9 @@ function admitRequestOptions(input) {
|
|
|
45
45
|
if (input === null || typeof input !== 'object' || Array.isArray(input)) {
|
|
46
46
|
throw new TypeError('Client request options must be an object.');
|
|
47
47
|
}
|
|
48
|
+
if (Reflect.ownKeys(input).some((field) => !['signal', 'timeoutMs', 'idempotencyKey', 'delegate', 'routing', 'schema'].includes(String(field)))) {
|
|
49
|
+
throw new TypeError('Client request options contain unsupported fields.');
|
|
50
|
+
}
|
|
48
51
|
if (input.timeoutMs !== undefined &&
|
|
49
52
|
(!Number.isSafeInteger(input.timeoutMs) ||
|
|
50
53
|
input.timeoutMs < 1 ||
|
|
@@ -62,6 +62,7 @@ const source = Query.from({ nodes: [Work.classes.Resource] });
|
|
|
62
62
|
const query = source.select({ kind: 'nodes', projection: { kind: 'value' } });
|
|
63
63
|
const prototypeSource = Query.from({ nodes: [Work.classes.PrototypeMembers] });
|
|
64
64
|
const prototypeQuery = prototypeSource.select({ kind: 'nodes', projection: { kind: 'value' } });
|
|
65
|
+
// @ts-expect-error Concrete Method shortcuts are absent from a child-selected projection.
|
|
65
66
|
const resourceAcceptsDocument = documentProjection;
|
|
66
67
|
void resourceAcceptsDocument;
|
|
67
68
|
const resourceReceiverAcceptsDocument = documentProjection;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { MethodKey, PropertyKey } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
2
|
import { retainProjectedProvenance } from './provenance.js';
|
|
3
3
|
export function projectNode(selected, node, provenance, call) {
|
|
4
|
+
const invoke = async (receiver, method, input) => {
|
|
5
|
+
if (receiver.class !== method.owner.key) {
|
|
6
|
+
throw new TypeError(`Method ${method.key} requires an exact ${method.owner.key} receiver.`);
|
|
7
|
+
}
|
|
8
|
+
return call(receiver, method, input);
|
|
9
|
+
};
|
|
4
10
|
const property = propertyAccessor(selected, node.props);
|
|
5
|
-
const method = methodAccessor(selected, node,
|
|
11
|
+
const method = methodAccessor(selected, node, invoke);
|
|
6
12
|
const value = {
|
|
7
13
|
id: node.id,
|
|
8
14
|
class: node.class,
|
|
@@ -11,7 +17,7 @@ export function projectNode(selected, node, provenance, call) {
|
|
|
11
17
|
method,
|
|
12
18
|
};
|
|
13
19
|
installPropertyShortcuts(value, selected, node.props, NODE_RESERVED);
|
|
14
|
-
installMethodShortcuts(value, selected, node,
|
|
20
|
+
installMethodShortcuts(value, selected, node, invoke, NODE_RESERVED);
|
|
15
21
|
const projected = Object.freeze(value);
|
|
16
22
|
retainProjectedProvenance(projected, provenance);
|
|
17
23
|
return projected;
|
|
@@ -41,7 +47,7 @@ function propertyAccessor(selected, props) {
|
|
|
41
47
|
function methodAccessor(selected, node, call) {
|
|
42
48
|
return (input) => {
|
|
43
49
|
const method = resolveMethod(selected, input);
|
|
44
|
-
if (method.
|
|
50
|
+
if (method.abstract === true) {
|
|
45
51
|
throw new TypeError(`Abstract Method ${method.key} cannot be invoked.`);
|
|
46
52
|
}
|
|
47
53
|
return (value) => call(node, method, value);
|
|
@@ -98,9 +104,7 @@ function installPropertyShortcuts(target, selected, props, reserved) {
|
|
|
98
104
|
}
|
|
99
105
|
function installMethodShortcuts(target, selected, node, call, reserved) {
|
|
100
106
|
for (const member of selected.methods) {
|
|
101
|
-
if (member.
|
|
102
|
-
reserved.has(member.name) ||
|
|
103
|
-
hasOwn(target, member.name))
|
|
107
|
+
if (member.abstract === true || reserved.has(member.name) || hasOwn(target, member.name))
|
|
104
108
|
continue;
|
|
105
109
|
if (named(selected.methods, member.name) !== member)
|
|
106
110
|
continue;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { Target, targetPath } from '@astrale-os/kernel-core/callable';
|
|
1
2
|
export { Client, call, type AuthenticatedClient, type Call, type ClientDispatchOptions, type ClientOptions, type Binary, type BinaryResponse, type Input, type RemoteCredential, type Result, type Stream, type StreamResult, type ValueResult, } from './client/index.js';
|
|
2
3
|
export * from './errors/index.js';
|
|
3
4
|
export { type RequestOptions, type MissControl, type StaleControl, type Transport, type TransportRequest, type TransportResult, } from './transport/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Path as PathValue, PathLike } from '@astrale-os/kernel-core/path';
|
|
2
|
-
import type { CallableInputOf, CallableOutputOf, CallableResultOf, Domain,
|
|
2
|
+
import type { CallableInputOf, CallableOutputOf, CallableResultOf, Domain, ResolvedFunction, ResolvedMethod } from '@astrale-os/kernel-dsl/v1';
|
|
3
3
|
import type { Revision } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
4
4
|
import { type Key as KeyType } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
5
5
|
import type { Binary, Input } from '../client/index.js';
|
|
@@ -25,9 +25,8 @@ export type InputOfReference<Reference extends CallableReference> = Reference ex
|
|
|
25
25
|
export type OutputOfReference<Reference extends CallableReference> = Reference extends CallableReference<infer _Input, infer Output> ? Output : never;
|
|
26
26
|
type ReferenceInput<Callable> = unknown extends CallableInputOf<Callable> ? Input : Extract<CallableInputOf<Callable>, Input>;
|
|
27
27
|
type ReferenceOutput<Callable> = unknown extends CallableOutputOf<Callable> ? unknown : CallableResultOf<Callable, Binary>;
|
|
28
|
-
type
|
|
29
|
-
type
|
|
30
|
-
type ExecutableInstanceMethod = ResolvedMethod<unknown, unknown, false, ExecutableMethodInheritance>;
|
|
28
|
+
type ExecutableStaticMethod = ResolvedMethod<unknown, unknown, true, false>;
|
|
29
|
+
type ExecutableInstanceMethod = ResolvedMethod<unknown, unknown, false, false>;
|
|
31
30
|
/** Project one exact resolved Function or static Method into a typed Client reference. */
|
|
32
31
|
export declare function reference<const Callable extends ResolvedFunction | ExecutableStaticMethod>(domain: Pick<Domain, 'origin' | 'revision'>, callable: Callable): CallableReference<ReferenceInput<Callable>, ReferenceOutput<Callable>>;
|
|
33
32
|
/** Project one exact resolved instance Method into a receiver-bound typed Client reference. */
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Path } from '@astrale-os/kernel-core/path';
|
|
2
2
|
import { callableAddress, Key, patterns, } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
3
3
|
export function reference(domain, callable) {
|
|
4
|
-
if (
|
|
4
|
+
if (Key.origin(callable.key) !== domain.origin)
|
|
5
|
+
invalid();
|
|
6
|
+
if ('owner' in callable && callable.abstract === true)
|
|
5
7
|
invalid();
|
|
6
8
|
const common = Object.freeze({
|
|
7
9
|
origin: domain.origin,
|
|
@@ -12,7 +14,7 @@ export function reference(domain, callable) {
|
|
|
12
14
|
if ('owner' in callable && !callable.static) {
|
|
13
15
|
const bind = (receiver) => admitReference({
|
|
14
16
|
...common,
|
|
15
|
-
target: Path.instanceMethod(Path.from(receiver), callable.
|
|
17
|
+
target: Path.instanceMethod(Path.from(receiver), callable.key),
|
|
16
18
|
});
|
|
17
19
|
return Object.assign(bind, common);
|
|
18
20
|
}
|
|
@@ -52,7 +54,7 @@ function matchesCallable(target, callable) {
|
|
|
52
54
|
if (last?.kind !== 'method' || last.name !== coordinate.name)
|
|
53
55
|
return false;
|
|
54
56
|
if (last.dispatch === 'instance')
|
|
55
|
-
return
|
|
57
|
+
return last.class === Key.of(coordinate.owner);
|
|
56
58
|
const owner = steps.at(-2);
|
|
57
59
|
return (anchor.kind === 'domain' &&
|
|
58
60
|
anchor.origin === Key.origin(callable) &&
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { invocation } from '@astrale-os/kernel-protocol';
|
|
2
2
|
import type { EffectiveAuth } from './auth.js';
|
|
3
|
-
import type { SchemaExpectation } from './expectation.js';
|
|
4
3
|
export interface LearnedRoute {
|
|
5
4
|
readonly route: invocation.Route;
|
|
6
5
|
readonly credential?: string;
|
|
@@ -27,7 +26,7 @@ export declare class RouteCache {
|
|
|
27
26
|
private readonly keyTokens;
|
|
28
27
|
private readonly store?;
|
|
29
28
|
constructor(maximumAgeMs: number, maximumSize?: number, store?: SessionRouteStore);
|
|
30
|
-
key(source: string, call: invocation.Call, auth: EffectiveAuth
|
|
29
|
+
key(source: string, call: invocation.Call, auth: EffectiveAuth): Promise<string>;
|
|
31
30
|
get(key: string, sourceCredential?: string, now?: number): Promise<LearnedRoute | undefined>;
|
|
32
31
|
learn(key: string, route: invocation.Route, credential: string | undefined, sourceCredential?: string, now?: number): Promise<LearnedRoute>;
|
|
33
32
|
delete(key: string): void;
|
|
@@ -14,16 +14,10 @@ export class RouteCache {
|
|
|
14
14
|
this.store = store === undefined ? undefined : captureSessionRouteStore(store);
|
|
15
15
|
this.restore();
|
|
16
16
|
}
|
|
17
|
-
async key(source, call, auth
|
|
17
|
+
async key(source, call, auth) {
|
|
18
18
|
const credential = auth.credential === undefined ? 'anonymous' : await digestText(auth.credential);
|
|
19
19
|
const delegate = auth.delegate === undefined ? 'anonymous' : await digestText(canonicalDelegate(auth.delegate));
|
|
20
|
-
return JSON.stringify([
|
|
21
|
-
source,
|
|
22
|
-
call.target,
|
|
23
|
-
credential,
|
|
24
|
-
delegate,
|
|
25
|
-
expected === undefined ? null : [expected.origin, expected.revision],
|
|
26
|
-
]);
|
|
20
|
+
return JSON.stringify([source, call.target, credential, delegate]);
|
|
27
21
|
}
|
|
28
22
|
async get(key, sourceCredential, now = Date.now()) {
|
|
29
23
|
const cached = this.entries.get(key);
|
|
@@ -4,7 +4,6 @@ import type { SessionOperation, SessionPolicy } from '../context/index.js';
|
|
|
4
4
|
import type { SessionAuth } from './auth.js';
|
|
5
5
|
import type { RouteCache } from './cache.js';
|
|
6
6
|
import type { ClientPoolCapability } from './envelope.js';
|
|
7
|
-
import type { SchemaExpectation } from './expectation.js';
|
|
8
7
|
import type { SessionEnvelopeTransport, SessionRequestOptions } from './request.js';
|
|
9
8
|
export interface SessionDispatcherOptions {
|
|
10
9
|
readonly kernel: IssuerId;
|
|
@@ -20,7 +19,7 @@ export interface SessionDispatcherOptions {
|
|
|
20
19
|
export declare class SessionDispatcher {
|
|
21
20
|
private readonly state;
|
|
22
21
|
constructor(state: SessionDispatcherOptions);
|
|
23
|
-
dispatch(input: Call, options: SessionRequestOptions, operation: SessionOperation
|
|
22
|
+
dispatch(input: Call, options: SessionRequestOptions, operation: SessionOperation): Promise<Result>;
|
|
24
23
|
private dispatchSource;
|
|
25
24
|
private followSource;
|
|
26
25
|
private dispatchDestinationWithRecovery;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Key } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
1
2
|
import * as invocationProtocol from '@astrale-os/kernel-protocol/invocation';
|
|
2
3
|
import { acceptCall, dispatchTrace, isAdmittedMissError, isAdmittedStaleRouteError, } from '../../client/index.js';
|
|
3
4
|
import { ClientError, ResponseError } from '../../errors/index.js';
|
|
@@ -9,25 +10,24 @@ export class SessionDispatcher {
|
|
|
9
10
|
constructor(state) {
|
|
10
11
|
this.state = state;
|
|
11
12
|
}
|
|
12
|
-
async dispatch(input, options, operation
|
|
13
|
+
async dispatch(input, options, operation) {
|
|
13
14
|
this.state.requireOpen();
|
|
14
15
|
const call = acceptCall(input);
|
|
15
16
|
// Authority is resolved before warm lookup so changed credentials or delegation cannot reuse a
|
|
16
17
|
// carrier minted for a different caller partition.
|
|
17
18
|
const auth = await resolveAuth(this.state.auth, call, operation);
|
|
18
19
|
const source = this.state.kernel;
|
|
19
|
-
const cacheKey = await this.state.cache.key(source, call, auth
|
|
20
|
+
const cacheKey = await this.state.cache.key(source, call, auth);
|
|
20
21
|
const dispatch = Object.freeze({
|
|
21
22
|
call,
|
|
22
23
|
auth,
|
|
23
24
|
source,
|
|
24
25
|
cacheKey,
|
|
25
|
-
...(expected === undefined ? {} : { expected }),
|
|
26
26
|
});
|
|
27
27
|
let learned = await this.state.cache.get(cacheKey, auth.credential);
|
|
28
28
|
if (learned !== undefined) {
|
|
29
29
|
try {
|
|
30
|
-
requireCachedRoute(learned, source,
|
|
30
|
+
requireCachedRoute(learned, source, call.target, this.state.envelopeTransport, this.state.websocketAvailable, this.state.policy);
|
|
31
31
|
}
|
|
32
32
|
catch {
|
|
33
33
|
this.state.cache.delete(cacheKey);
|
|
@@ -48,7 +48,6 @@ export class SessionDispatcher {
|
|
|
48
48
|
...sessionTransportOptions(operation, options.idempotencyKey),
|
|
49
49
|
...(state.auth.delegate === undefined ? {} : { delegate: state.auth.delegate }),
|
|
50
50
|
...(routing === undefined ? {} : { routing }),
|
|
51
|
-
...(state.expected === undefined ? {} : { schema: { revision: state.expected.revision } }),
|
|
52
51
|
}));
|
|
53
52
|
}
|
|
54
53
|
async followSource(result, state, options, operation) {
|
|
@@ -58,13 +57,13 @@ export class SessionDispatcher {
|
|
|
58
57
|
if (redirect.route.via.issuer !== state.source) {
|
|
59
58
|
throw new ClientError('Redirect issuer differs from the session-pinned source Kernel identity.');
|
|
60
59
|
}
|
|
61
|
-
|
|
60
|
+
requireTargetPublication(redirect.route, state.call.target);
|
|
62
61
|
const learned = await this.state.cache.learn(state.cacheKey, redirect.route, redirect.credential, state.auth.credential);
|
|
63
62
|
return this.dispatchDestinationWithRecovery(learned, state, options, operation, redirect.trace);
|
|
64
63
|
}
|
|
65
64
|
async dispatchDestinationWithRecovery(learned, state, options, operation, trace) {
|
|
66
65
|
try {
|
|
67
|
-
return await this.dispatchDestination(learned, state.call, options, operation, state.source,
|
|
66
|
+
return await this.dispatchDestination(learned, state.call, options, operation, state.source, trace);
|
|
68
67
|
}
|
|
69
68
|
catch (cause) {
|
|
70
69
|
const stale = isAdmittedStaleRouteError(cause);
|
|
@@ -88,11 +87,11 @@ export class SessionDispatcher {
|
|
|
88
87
|
return this.followSource(refreshed, state, options, operation);
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
|
-
async dispatchDestination(learned, call, options, operation, source,
|
|
90
|
+
async dispatchDestination(learned, call, options, operation, source, trace) {
|
|
92
91
|
if (learned.route.via.issuer !== source) {
|
|
93
92
|
throw new ClientError('Learned route issuer differs from the session-pinned source Kernel.');
|
|
94
93
|
}
|
|
95
|
-
|
|
94
|
+
requireTargetPublication(learned.route, call.target);
|
|
96
95
|
const envelope = selectEnvelope(learned.route.endpoint, this.state.envelopeTransport, this.state.websocketAvailable, this.state.pool, this.state.policy);
|
|
97
96
|
const requestOptions = {
|
|
98
97
|
...sessionTransportOptions(operation, options.idempotencyKey),
|
|
@@ -107,11 +106,11 @@ export class SessionDispatcher {
|
|
|
107
106
|
return result;
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
|
-
function requireCachedRoute(learned, source,
|
|
109
|
+
function requireCachedRoute(learned, source, target, envelopeTransport, websocketAvailable, policy) {
|
|
111
110
|
if (learned.route.via.issuer !== source) {
|
|
112
111
|
throw new ClientError('Learned route issuer differs from the session-pinned source Kernel.');
|
|
113
112
|
}
|
|
114
|
-
|
|
113
|
+
requireTargetPublication(learned.route, target);
|
|
115
114
|
selectEnvelopeTarget(learned.route.endpoint, envelopeTransport, websocketAvailable, policy);
|
|
116
115
|
}
|
|
117
116
|
function isRouteCompatibilityConflict(input) {
|
|
@@ -125,11 +124,12 @@ function isRouteCompatibilityConflict(input) {
|
|
|
125
124
|
return (failure?.data.code === invocationProtocol.SCHEMA_REVISION_MISMATCH ||
|
|
126
125
|
failure?.data.code === invocationProtocol.SERVICE_TRUST_REQUIRED);
|
|
127
126
|
}
|
|
128
|
-
function
|
|
129
|
-
if (
|
|
127
|
+
function requireTargetPublication(route, target) {
|
|
128
|
+
if (typeof target === 'string')
|
|
130
129
|
return;
|
|
131
130
|
const actual = route.via.publication;
|
|
132
|
-
if (actual.origin !==
|
|
131
|
+
if (actual.origin !== Key.origin(target.callable) ||
|
|
132
|
+
(target.revision !== undefined && actual.revision !== target.revision)) {
|
|
133
133
|
throw new ClientError('Resolved route does not match the expected Schema revision.');
|
|
134
134
|
}
|
|
135
135
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { admitSessionAuth, resolveAuth, type Auth, type EffectiveAuth, type SessionAuth, } from './auth.js';
|
|
2
|
-
export type { SchemaExpectation } from './expectation.js';
|
|
3
2
|
export { RouteCache, type LearnedRoute, type PersistedRoute, type SessionRouteArtifact, type SessionRouteStore, } from './cache.js';
|
|
4
3
|
export { requireResultKind, SessionDispatcher, type SessionDispatcherOptions } from './dispatch.js';
|
|
5
4
|
export { type ClientPoolCapability, type EnvelopeSelection } from './envelope.js';
|
package/dist/session/session.js
CHANGED
|
@@ -119,11 +119,19 @@ export class ClientSession {
|
|
|
119
119
|
async invoke(reference, input, options) {
|
|
120
120
|
const admittedReference = admitReference(reference);
|
|
121
121
|
const admittedOptions = admitRequestOptions(options);
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
const { anchor, steps } = admittedReference.target.ast;
|
|
123
|
+
const last = steps.at(-1);
|
|
124
|
+
const instance = last?.kind === 'method' && last.dispatch === 'instance'
|
|
125
|
+
? Path.fromAST({ anchor, steps: steps.slice(0, -1) }).raw
|
|
126
|
+
: undefined;
|
|
127
|
+
const result = await this.dispatcher.dispatch({
|
|
128
|
+
target: Object.freeze({
|
|
129
|
+
callable: admittedReference.callable,
|
|
130
|
+
revision: admittedReference.revision,
|
|
131
|
+
...(instance === undefined ? {} : { instance }),
|
|
132
|
+
}),
|
|
133
|
+
input,
|
|
134
|
+
}, admittedOptions, this.operation(admittedOptions));
|
|
127
135
|
const narrowed = requireResultKind(admittedReference.outputMode, result);
|
|
128
136
|
return (narrowed.kind === 'value'
|
|
129
137
|
? narrowed.value
|
|
@@ -163,7 +171,7 @@ export class ClientSession {
|
|
|
163
171
|
origin: owner.origin,
|
|
164
172
|
revision: owner.revision,
|
|
165
173
|
callable: method.key,
|
|
166
|
-
target: Path.instanceMethod(Path.id(node.id), method.
|
|
174
|
+
target: Path.instanceMethod(Path.id(node.id), method.key),
|
|
167
175
|
outputMode: method.output.mode,
|
|
168
176
|
}, input);
|
|
169
177
|
}
|
|
@@ -19,7 +19,7 @@ const abstractMethod = method({
|
|
|
19
19
|
auth: 'authenticated',
|
|
20
20
|
input: { type: 'null' },
|
|
21
21
|
output: { type: 'null' },
|
|
22
|
-
|
|
22
|
+
abstract: true,
|
|
23
23
|
});
|
|
24
24
|
const abstractDomain = schema.resolve(defineSchema('client.reference.typecheck', {
|
|
25
25
|
classes: {
|
|
@@ -28,3 +28,11 @@ const abstractDomain = schema.resolve(defineSchema('client.reference.typecheck',
|
|
|
28
28
|
}));
|
|
29
29
|
// @ts-expect-error Abstract Methods are declarations and cannot become Client references.
|
|
30
30
|
reference(abstractDomain, abstractDomain.classes.AbstractItem.methods.abstractMethod);
|
|
31
|
+
// @ts-expect-error Exact identity is derived internally, never supplied as a Session option.
|
|
32
|
+
void session.invoke(dynamicReference, dynamicInput, { expect: undefined });
|
|
33
|
+
// @ts-expect-error Raw Client options do not select a declaration.
|
|
34
|
+
const unsupportedClientOptions = { expect: undefined };
|
|
35
|
+
void unsupportedClientOptions;
|
|
36
|
+
// @ts-expect-error Internal metadata dispatch is absent from the public package facade.
|
|
37
|
+
import { dispatchTrace } from '../index.js';
|
|
38
|
+
void dispatchTrace;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { NodePath } from '@astrale-os/kernel-core/path';
|
|
1
2
|
import type { RequestOptions, TransportRequest } from '../index.js';
|
|
2
3
|
import { TransportError } from '../../errors/index.js';
|
|
3
4
|
/** One invocation-owned total timeout budget shared by selection and fallback. */
|
|
@@ -13,4 +14,4 @@ export declare class InvocationBudget {
|
|
|
13
14
|
private remaining;
|
|
14
15
|
}
|
|
15
16
|
export declare function mayFallback(error: unknown): error is TransportError;
|
|
16
|
-
export declare function warningTarget(input: TransportRequest):
|
|
17
|
+
export declare function warningTarget(input: TransportRequest): NodePath;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { targetPath } from '@astrale-os/kernel-core/callable';
|
|
1
2
|
import { TransportError } from '../../errors/index.js';
|
|
2
3
|
import { invocationFailure } from '../failure.js';
|
|
3
4
|
import { positiveInteger } from '../index.js';
|
|
@@ -66,7 +67,7 @@ export function mayFallback(error) {
|
|
|
66
67
|
error.phase !== 'timeout');
|
|
67
68
|
}
|
|
68
69
|
export function warningTarget(input) {
|
|
69
|
-
return input.call.target;
|
|
70
|
+
return targetPath(input.call.target);
|
|
70
71
|
}
|
|
71
72
|
function abortReason(signal) {
|
|
72
73
|
return signal.reason instanceof Error
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/kernel-client",
|
|
3
|
-
"version": "0.6.0-beta.
|
|
3
|
+
"version": "0.6.0-beta.57",
|
|
4
4
|
"description": "Universal Client — protocol-first, transport-agnostic",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astrale",
|
|
@@ -65,14 +65,14 @@
|
|
|
65
65
|
"access": "public"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@astrale-os/kernel-core": "0.9.0-beta.
|
|
69
|
-
"@astrale-os/kernel-dsl": "0.2.0-beta.
|
|
70
|
-
"@astrale-os/kernel-protocol": "0.5.0-beta.
|
|
68
|
+
"@astrale-os/kernel-core": "0.9.0-beta.44",
|
|
69
|
+
"@astrale-os/kernel-dsl": "0.2.0-beta.32",
|
|
70
|
+
"@astrale-os/kernel-protocol": "0.5.0-beta.48",
|
|
71
71
|
"@tanstack/pacer": "0.20.1",
|
|
72
72
|
"msgpackr": "^2.0.5"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@astrale-os/kernel-server": "0.5.0-beta.
|
|
75
|
+
"@astrale-os/kernel-server": "0.5.0-beta.50",
|
|
76
76
|
"@astrale/typescript-config": "npm:@jsr/astrale__typescript-config@~1.1.0",
|
|
77
77
|
"@types/node": "^22.0.0",
|
|
78
78
|
"typescript": "7.0.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|