@deepseek-ai/dsh-typert-protocol 0.1.5-rc.2 → 0.1.6-alpha.2
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.i18n.yaml +2 -2
- package/README.md +4 -2
- package/README.zh.md +7 -5
- package/lib/index.js +32 -1
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +1 -0
- package/lib/types/owned-value.d.ts +22 -0
- package/lib/types/owned-value.js +32 -0
- package/lib/types/types.d.ts +6 -4
- package/package.json +1 -1
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/typert/protocol/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: e41fa9fa305d8f55ce55d3eace647ad5afcea0e3
|
|
6
|
+
README.zh.md: e784e771016ebec0913e0ea847258fe653ae3bd0
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
With `dsh-typert-protocol`, business packages can expose Host methods to Remote clients: mark a method with `@Remote` (or `@RemoteScope` for scoped receivers), bind the service to a wire namespace, and associate Host objects and scoped Contexts with wire identities through the merge-extensible protocol maps. Generated artifacts, the Host Gateway, and the Client API consume the same invocation descriptors, codecs, and provider contracts
|
|
12
|
+
With `dsh-typert-protocol`, business packages can expose Host methods to Remote clients: mark a method with `@Remote` (or `@RemoteScope` for scoped receivers), bind the service to a wire namespace, and associate Host objects and scoped Contexts with wire identities through the merge-extensible protocol maps. Generated artifacts, the Host Gateway, and the Client API consume the same invocation descriptors, codecs, and provider contracts. Invocation-owned values transfer cleanup to Gateway without adding a reference count. The package registers no Cordis service and runs no TypeScript analysis.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -48,6 +48,8 @@ Generation turns the method into a wire endpoint under the service's namespace;
|
|
|
48
48
|
|
|
49
49
|
Complex Host objects cannot cross the wire directly. A business package declares the association through the merge-extensible `TypertLookupMap` and `TypertContextMap`. A Host Context adapter owns the stable wire declaration and resolves wire identities to live Contexts. A Client Context adapter maps in both directions because scoped calls originate from a Client Context and forwarded Host events resolve their explicit wire identity there. Host composition may override its synchronous or asynchronous resolver. A resolver that refuses on policy grounds throws `RemoteError` with its own code, which reaches the caller unchanged.
|
|
50
50
|
|
|
51
|
+
Client Context resolution is synchronous. `typertOwnedValue(value, release)` transfers a non-throwing, idempotent cleanup to the invocation owner; Gateway calls it after handler and reply settlement. A borrowed Context requires no cleanup wrapper. The shared `TYPERT_OWNED_VALUE` symbol and `isTypertOwnedValue` recognizer work across independently bundled providers and Gateway; the wrapper itself does not retain a resource.
|
|
52
|
+
|
|
51
53
|
### Reporting and reading a Remote failure
|
|
52
54
|
|
|
53
55
|
One class carries every Remote failure: `RemoteError`, holding a stable `<domain>/<reason>` code and the details typed for that code. This package declares the universal carrier codes (`gateway/bad-request`, `gateway/cancelled`, `gateway/internal`) and owns `RemoteErrorDetailsMap`, the merge-extensible table every other package extends beside its own throwing code:
|
|
@@ -91,7 +93,7 @@ The merge-extensible protocol maps keep static associations in the type system,
|
|
|
91
93
|
|
|
92
94
|
### Wire identity grammar
|
|
93
95
|
|
|
94
|
-
Every namespace, method, lookup, and Context segment must satisfy `isTypertRemoteSegment()`, so generated names cross the shared RPC carrier unchanged. Strict codecs carry generated
|
|
96
|
+
Every namespace, method, lookup, and Context segment must satisfy `isTypertRemoteSegment()`, so generated names cross the shared RPC carrier unchanged. Strict codecs carry generated schema factories; `src-json` codecs identify the weaker source-launch path.
|
|
95
97
|
|
|
96
98
|
### Source map
|
|
97
99
|
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@ kind: "package-library"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
借助 `dsh-typert-protocol`,业务包可以向 Remote 客户端暴露 Host 方法:用 `@Remote`(作用域接收者用 `@RemoteScope`)标记方法,把服务绑定到 wire 命名空间,并通过可合并扩展的协议映射把 Host 对象与作用域 Context 关联到 wire identity。生成产物、Host Gateway 与 Client API
|
|
12
|
+
借助 `dsh-typert-protocol`,业务包可以向 Remote 客户端暴露 Host 方法:用 `@Remote`(作用域接收者用 `@RemoteScope`)标记方法,把服务绑定到 wire 命名空间,并通过可合并扩展的协议映射把 Host 对象与作用域 Context 关联到 wire identity。生成产物、Host Gateway 与 Client API 消费同一套调用描述符、编解码器与提供方约定。调用持有的值把清理责任交给 Gateway,不另增引用计数。本包不注册任何 Cordis 服务,也不运行 TypeScript 分析。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -46,7 +46,9 @@ export class GoalService extends TypertRemoteService {
|
|
|
46
46
|
|
|
47
47
|
### 把 Host 对象与 Context 关联到 wire identity
|
|
48
48
|
|
|
49
|
-
复杂的 Host 对象不能直接跨 wire 传输。业务包通过可合并扩展的 `TypertLookupMap` 与 `TypertContextMap` 声明关联。Host Context
|
|
49
|
+
复杂的 Host 对象不能直接跨 wire 传输。业务包通过可合并扩展的 `TypertLookupMap` 与 `TypertContextMap` 声明关联。Host Context 适配器拥有稳定 wire 声明,并把 wire identity 解析为活跃 Context。Client Context 适配器需要双向映射,因为作用域调用从 Client Context 发起,而转发的 Host 事件要在 Client 侧解析其显式 wire identity。Host 组合可以覆盖其同步或异步解析器。因策略原因拒绝解析的解析器会抛出带有自身错误码的 `RemoteError`,该码原样到达调用方。
|
|
50
|
+
|
|
51
|
+
Client Context 解析保持同步。`typertOwnedValue(value, release)` 把不抛异常、幂等的清理交给调用 owner;Gateway 在处理器和回复均结束后调用它。借用的 Context 不需要清理包装层。共享的 `TYPERT_OWNED_VALUE` symbol 与 `isTypertOwnedValue` 识别函数可跨独立打包的提供方与 Gateway 使用;包装层自身不会 retain 资源。
|
|
50
52
|
|
|
51
53
|
### 报告与读取 Remote 失败
|
|
52
54
|
|
|
@@ -65,7 +67,7 @@ throw new RemoteError('goal/not-found', `goal "${id}" does not exist`, { goalId:
|
|
|
65
67
|
|
|
66
68
|
### 在 Client 侧接收转发的 Host 事件
|
|
67
69
|
|
|
68
|
-
Host
|
|
70
|
+
Host 装配以转发给消费方的 Cordis 事件扩展 `TypertRemoteEventSelection`,从而收窄 `ctx.remote.$on` 的键集。`TypertForwardableEvent` 接受无作用域且返回 `void` 的通知,以及最后一个 `next()` 回调返回事件结果类型的异步作用域 waterfall(瀑布式事件)。`TypertClientEventListener` 从同一条 `Events` 成员派生 Client listener,并保留 signal、可选和只读字段、数组、回调与结果类型。`TypertClientRemote` 只公开 `$mount()` 与 `$on()`;事件传输仍由 Gateway 私有持有。
|
|
69
71
|
|
|
70
72
|
-----
|
|
71
73
|
|
|
@@ -83,7 +85,7 @@ Host 装配以转发给消费端的 Cordis 事件扩展 `TypertRemoteEventSelect
|
|
|
83
85
|
|
|
84
86
|
### Remote 标记
|
|
85
87
|
|
|
86
|
-
`@Remote` 与 `@RemoteScope` 调度一个初始化器,把方法名、可选导出名与调用模式追加到原型描述符;`remoteMethods(service)` 校验其版本,并返回与已存描述符分离、按声明顺序排列的快照,供 Gateway
|
|
88
|
+
`@Remote` 与 `@RemoteScope` 调度一个初始化器,把方法名、可选导出名与调用模式追加到原型描述符;`remoteMethods(service)` 校验其版本,并返回与已存描述符分离、按声明顺序排列的快照,供 Gateway 的源码模式回退读取。标记要求名称为字符串的公开、非静态实例方法,同一方法上的冲突标记会被拒绝。
|
|
87
89
|
|
|
88
90
|
### 协议映射与描述符
|
|
89
91
|
|
|
@@ -91,7 +93,7 @@ Host 装配以转发给消费端的 Cordis 事件扩展 `TypertRemoteEventSelect
|
|
|
91
93
|
|
|
92
94
|
### Wire 标识文法
|
|
93
95
|
|
|
94
|
-
每个命名空间、方法、查找与 Context 段都必须满足 `isTypertRemoteSegment()`,生成的名字才能原样跨共享 RPC 载体传输。严格编解码器携带生成的 schema;`src-json` 编解码器标识约束更弱的源码启动路径。
|
|
96
|
+
每个命名空间、方法、查找与 Context 段都必须满足 `isTypertRemoteSegment()`,生成的名字才能原样跨共享 RPC 载体传输。严格编解码器携带生成的 schema factory;`src-json` 编解码器标识约束更弱的源码启动路径。
|
|
95
97
|
|
|
96
98
|
### 源码地图
|
|
97
99
|
|
package/lib/index.js
CHANGED
|
@@ -37,6 +37,37 @@ function remoteErrorOf(value) {
|
|
|
37
37
|
if (typeof value === "object" && value !== null && value.isDSHRemoteError === true && typeof value.code === "string") return value;
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
|
+
//#region lib/types/owned-value.js
|
|
41
|
+
/** Generic invocation-owned values returned by synchronous Client Context resolvers. */
|
|
42
|
+
/** Shared identity across independently bundled Context providers and Gateway. */
|
|
43
|
+
const TYPERT_OWNED_VALUE = Symbol.for("dsh.typert.owned-value");
|
|
44
|
+
/**
|
|
45
|
+
* Transfer cleanup ownership without adding another resource reference count.
|
|
46
|
+
* @param value - resolved payload passed to the invocation.
|
|
47
|
+
* @param release - non-throwing synchronous release, called at most once.
|
|
48
|
+
* @returns an owned payload disposed after invocation and reply settlement.
|
|
49
|
+
*/
|
|
50
|
+
function typertOwnedValue(value, release) {
|
|
51
|
+
let active = true;
|
|
52
|
+
return {
|
|
53
|
+
[TYPERT_OWNED_VALUE]: true,
|
|
54
|
+
value,
|
|
55
|
+
[Symbol.dispose]() {
|
|
56
|
+
if (!active) return;
|
|
57
|
+
active = false;
|
|
58
|
+
release();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Identify invocation-owned values using the shared marker.
|
|
64
|
+
* @param value - borrowed or owned resolver result.
|
|
65
|
+
* @returns whether the result carries invocation cleanup.
|
|
66
|
+
*/
|
|
67
|
+
function isTypertOwnedValue(value) {
|
|
68
|
+
return typeof value === "object" && value !== null && TYPERT_OWNED_VALUE in value && value[TYPERT_OWNED_VALUE] === true;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
40
71
|
//#region lib/types/index.js
|
|
41
72
|
/**
|
|
42
73
|
* Remote decorators and explicit Gateway bindings backed by versioned
|
|
@@ -181,4 +212,4 @@ function validateName(subject, value) {
|
|
|
181
212
|
if (!isTypertRemoteSegment(value)) throw new TypeError(`typert-protocol: ${subject} must contain only RPC endpoint segment characters`);
|
|
182
213
|
}
|
|
183
214
|
//#endregion
|
|
184
|
-
export { Remote, RemoteError, RemoteScope, TypertRemoteService, bindTypertRemote, isTypertRemoteSegment, remoteErrorOf, remoteMethods };
|
|
215
|
+
export { Remote, RemoteError, RemoteScope, TYPERT_OWNED_VALUE, TypertRemoteService, bindTypertRemote, isTypertOwnedValue, isTypertRemoteSegment, remoteErrorOf, remoteMethods, typertOwnedValue };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import { Service, type Context } from '@deepseek-ai/cordis';
|
|
8
8
|
import type { TypertContextMap } from './types.ts';
|
|
9
9
|
export { RemoteError, remoteErrorOf } from './remote-error.ts';
|
|
10
|
+
export { TYPERT_OWNED_VALUE, isTypertOwnedValue, typertOwnedValue } from './owned-value.ts';
|
|
11
|
+
export type { TypertOwnedValue } from './owned-value.ts';
|
|
10
12
|
/**
|
|
11
13
|
* Test one generated Remote name against the Connection endpoint grammar.
|
|
12
14
|
* @param value - namespace, method, lookup, or Context segment.
|
package/lib/types/index.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { Service } from '@deepseek-ai/cordis';
|
|
8
8
|
export { RemoteError, remoteErrorOf } from "./remote-error.js";
|
|
9
|
+
export { TYPERT_OWNED_VALUE, isTypertOwnedValue, typertOwnedValue } from "./owned-value.js";
|
|
9
10
|
const TYPERT_REMOTE_SEGMENT_PATTERN = /^[A-Za-z0-9_$.-]+$/;
|
|
10
11
|
/**
|
|
11
12
|
* Test one generated Remote name against the Connection endpoint grammar.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Generic invocation-owned values returned by synchronous Client Context resolvers. */
|
|
2
|
+
/** Shared identity across independently bundled Context providers and Gateway. */
|
|
3
|
+
export declare const TYPERT_OWNED_VALUE: unique symbol;
|
|
4
|
+
/** A borrowed payload paired with the invocation owner's idempotent cleanup. */
|
|
5
|
+
export interface TypertOwnedValue<Value> extends Disposable {
|
|
6
|
+
readonly [TYPERT_OWNED_VALUE]: true;
|
|
7
|
+
readonly value: Value;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Transfer cleanup ownership without adding another resource reference count.
|
|
11
|
+
* @param value - resolved payload passed to the invocation.
|
|
12
|
+
* @param release - non-throwing synchronous release, called at most once.
|
|
13
|
+
* @returns an owned payload disposed after invocation and reply settlement.
|
|
14
|
+
*/
|
|
15
|
+
export declare function typertOwnedValue<Value>(value: Value, release: () => void): TypertOwnedValue<Value>;
|
|
16
|
+
/**
|
|
17
|
+
* Identify invocation-owned values using the shared marker.
|
|
18
|
+
* @param value - borrowed or owned resolver result.
|
|
19
|
+
* @returns whether the result carries invocation cleanup.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isTypertOwnedValue(value: unknown): value is TypertOwnedValue<unknown>;
|
|
22
|
+
//# sourceMappingURL=owned-value.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Generic invocation-owned values returned by synchronous Client Context resolvers. */
|
|
2
|
+
/** Shared identity across independently bundled Context providers and Gateway. */
|
|
3
|
+
export const TYPERT_OWNED_VALUE = Symbol.for('dsh.typert.owned-value');
|
|
4
|
+
/**
|
|
5
|
+
* Transfer cleanup ownership without adding another resource reference count.
|
|
6
|
+
* @param value - resolved payload passed to the invocation.
|
|
7
|
+
* @param release - non-throwing synchronous release, called at most once.
|
|
8
|
+
* @returns an owned payload disposed after invocation and reply settlement.
|
|
9
|
+
*/
|
|
10
|
+
export function typertOwnedValue(value, release) {
|
|
11
|
+
let active = true;
|
|
12
|
+
return {
|
|
13
|
+
[TYPERT_OWNED_VALUE]: true,
|
|
14
|
+
value,
|
|
15
|
+
[Symbol.dispose]() {
|
|
16
|
+
if (!active)
|
|
17
|
+
return;
|
|
18
|
+
active = false;
|
|
19
|
+
release();
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Identify invocation-owned values using the shared marker.
|
|
25
|
+
* @param value - borrowed or owned resolver result.
|
|
26
|
+
* @returns whether the result carries invocation cleanup.
|
|
27
|
+
*/
|
|
28
|
+
export function isTypertOwnedValue(value) {
|
|
29
|
+
return typeof value === 'object' && value !== null
|
|
30
|
+
&& TYPERT_OWNED_VALUE in value && value[TYPERT_OWNED_VALUE] === true;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=owned-value.js.map
|
package/lib/types/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @module @deepseek-ai/dsh-typert-protocol/types
|
|
5
5
|
*/
|
|
6
6
|
import type { Context, Events } from '@deepseek-ai/cordis';
|
|
7
|
+
import type { TypertOwnedValue } from './owned-value.ts';
|
|
7
8
|
declare const LOOKUP_HOST: unique symbol;
|
|
8
9
|
declare const LOOKUP_WIRE: unique symbol;
|
|
9
10
|
declare const CONTEXT_WIRE: unique symbol;
|
|
@@ -152,7 +153,8 @@ export interface TypertSchema<Output = unknown> {
|
|
|
152
153
|
export type TypertCodec = {
|
|
153
154
|
readonly mode: 'strict';
|
|
154
155
|
readonly typeSymbol: string;
|
|
155
|
-
|
|
156
|
+
/** Materialize and return the process-realm schema on first boundary use. */
|
|
157
|
+
readonly create: () => TypertSchema;
|
|
156
158
|
} | {
|
|
157
159
|
readonly mode: 'src-json';
|
|
158
160
|
};
|
|
@@ -305,11 +307,11 @@ export interface TypertClientContextAdapter<Wire = unknown> {
|
|
|
305
307
|
*/
|
|
306
308
|
identity(ctx: Context): Wire | undefined;
|
|
307
309
|
/**
|
|
308
|
-
* Resolve a
|
|
310
|
+
* Resolve a validated identity synchronously for one Client invocation.
|
|
309
311
|
* @param id - validated wire identity.
|
|
310
|
-
* @returns
|
|
312
|
+
* @returns a borrowed or invocation-owned Client Context, or undefined when unavailable.
|
|
311
313
|
*/
|
|
312
|
-
resolve(id: Wire): Context | undefined;
|
|
314
|
+
resolve(id: Wire): Context | TypertOwnedValue<Context> | undefined;
|
|
313
315
|
}
|
|
314
316
|
/** Notification emitted after a Typert runtime registry changes. */
|
|
315
317
|
export interface TypertRegistryChange {
|
package/package.json
CHANGED