refactor(typert): rename RemoteContext to RemoteScope
This commit is contained in:
@@ -1032,10 +1032,10 @@ class FaceAnalyzer {
|
||||
if (invocation.kind === 'context') {
|
||||
const context = this.contextDeclarations().get(invocation.context)
|
||||
if (context === undefined) {
|
||||
this.fail(method, `Remote Context ${invocation.context} has no TypeRTContextMap entry`)
|
||||
this.fail(method, `Remote Scope ${invocation.context} has no TypeRTContextMap entry`)
|
||||
}
|
||||
const wire = `${invocation.context}Id`
|
||||
if (wires.has(wire)) this.fail(method, `Remote Context wire field ${wire} conflicts with a method parameter`)
|
||||
if (wires.has(wire)) this.fail(method, `Remote Scope wire field ${wire} conflicts with a method parameter`)
|
||||
receiver = {
|
||||
kind: 'context',
|
||||
context: invocation.context,
|
||||
@@ -1200,18 +1200,18 @@ class FaceAnalyzer {
|
||||
}
|
||||
marker = { kind: 'direct', exportName }
|
||||
} else if (ts.isCallExpression(expression)
|
||||
&& this.isTypeMetaSymbol(expression.expression, 'RemoteContext')) {
|
||||
&& this.isTypeMetaSymbol(expression.expression, 'RemoteScope')) {
|
||||
if (expression.arguments.length < 1 || expression.arguments.length > 2) {
|
||||
this.fail(expression, 'RemoteContext() requires a Context key and optional exported method name')
|
||||
this.fail(expression, 'RemoteScope() requires a Context key and optional exported method name')
|
||||
}
|
||||
const context = stringLiteralValue(expression.arguments[0])
|
||||
if (context === undefined || !isRemoteSegment(context)) {
|
||||
this.fail(expression.arguments[0] ?? expression, 'RemoteContext() key must be a string literal containing only RPC endpoint segment characters')
|
||||
this.fail(expression.arguments[0] ?? expression, 'RemoteScope() key must be a string literal containing only RPC endpoint segment characters')
|
||||
}
|
||||
const exportArgument = expression.arguments[1]
|
||||
const exportName = exportArgument === undefined ? undefined : stringLiteralValue(exportArgument)
|
||||
if (exportArgument !== undefined && (exportName === undefined || !isRemoteSegment(exportName))) {
|
||||
this.fail(exportArgument, 'RemoteContext() name must be a string literal containing only RPC endpoint segment characters')
|
||||
this.fail(exportArgument, 'RemoteScope() name must be a string literal containing only RPC endpoint segment characters')
|
||||
}
|
||||
marker = { kind: 'context', context, ...exportName === undefined ? {} : { exportName } }
|
||||
} else {
|
||||
@@ -2529,7 +2529,7 @@ function sourceFileHasSurface(sourceFile: ts.SourceFile): boolean {
|
||||
? decorator.expression.expression
|
||||
: decorator.expression
|
||||
const name = expressionName(expression)
|
||||
if (name === 'Remote' || name === 'RemoteContext') return true
|
||||
if (name === 'Remote' || name === 'RemoteScope') return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ export class FaceModelEmitter {
|
||||
lines.push(' }')
|
||||
}
|
||||
if (scoped.length > 0) {
|
||||
lines.push(' interface TypeRTRemoteContextMap {')
|
||||
lines.push(' interface TypeRTRemoteScopeMap {')
|
||||
for (const invocation of scoped) {
|
||||
this.pushRemoteSignature(lines, sourceMap, packageModel, invocation, referenceNames, true)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GatewayService, Remote, RemoteContext } from '@deepseek-ai/dsh-type-meta'
|
||||
import { GatewayService, Remote, RemoteScope } from '@deepseek-ai/dsh-type-meta'
|
||||
import type { Agent } from '@fixture/domain'
|
||||
import type {
|
||||
CreateGoalRequest,
|
||||
@@ -19,7 +19,7 @@ export class GoalService extends GatewayService {
|
||||
return { ref: `${agent.id}:${request.title}` }
|
||||
}
|
||||
|
||||
@RemoteContext('agent')
|
||||
@RemoteScope('agent')
|
||||
rename(request: RenameGoalRequest): RenameGoalResult {
|
||||
return { renamed: request.title.length > 0 }
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
|
||||
export interface TypeRTLookupMap {}
|
||||
export interface TypeRTContextMap {}
|
||||
export interface TypeRTRemoteMap {}
|
||||
export interface TypeRTRemoteContextMap {}
|
||||
export interface TypeRTRemoteScopeMap {}
|
||||
|
||||
export type TypeRTRemoteNamespace<Namespace extends string> = {
|
||||
[Endpoint in keyof TypeRTRemoteMap as Endpoint extends `${Namespace}/${infer Method}`
|
||||
@@ -56,7 +56,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
|
||||
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Result>,
|
||||
) => void
|
||||
|
||||
export function RemoteContext(key: Extract<keyof TypeRTContextMap, string>, exportName?: string):
|
||||
export function RemoteScope(key: Extract<keyof TypeRTContextMap, string>, exportName?: string):
|
||||
<This extends object, Args extends unknown[], Result>(
|
||||
method: (this: This, ...args: Args) => Result,
|
||||
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Result>,
|
||||
|
||||
@@ -288,7 +288,7 @@ export interface BoxPayload {
|
||||
const root = copyFixture()
|
||||
editFile(root, 'packages/remote/src/index.ts', source => source
|
||||
.replace(' @Remote\n', '')
|
||||
.replace(" @RemoteContext('agent')\n", ''))
|
||||
.replace(" @RemoteScope('agent')\n", ''))
|
||||
editFile(root, 'packages/remote/src/types.ts', source => `${source}
|
||||
|
||||
/** @typert schema */
|
||||
@@ -377,8 +377,8 @@ export interface ClientMarker {
|
||||
name: 'duplicate GatewayService field binding',
|
||||
edit: (source: string) => source
|
||||
.replace(
|
||||
'import { GatewayService, Remote, RemoteContext }',
|
||||
'import { GatewayService, Remote, RemoteContext, bindTypeRTGateway }',
|
||||
'import { GatewayService, Remote, RemoteScope }',
|
||||
'import { GatewayService, Remote, RemoteScope, bindTypeRTGateway }',
|
||||
)
|
||||
.replace(
|
||||
'export class GoalService extends GatewayService {',
|
||||
@@ -495,11 +495,11 @@ export interface ClientMarker {
|
||||
expect(() => analyzeRemote(root)).not.toThrow()
|
||||
})
|
||||
|
||||
it('rejects a Remote Context without a static Context declaration', () => {
|
||||
it('rejects a Remote Scope without a static Context declaration', () => {
|
||||
const root = copyFixture()
|
||||
editFile(root, 'packages/remote/src/index.ts', source => source.replace("@RemoteContext('agent')", "@RemoteContext('missing')"))
|
||||
editFile(root, 'packages/remote/src/index.ts', source => source.replace("@RemoteScope('agent')", "@RemoteScope('missing')"))
|
||||
|
||||
expect(() => analyzeRemote(root, false)).toThrow(/Remote Context missing has no TypeRTContextMap entry/)
|
||||
expect(() => analyzeRemote(root, false)).toThrow(/Remote Scope missing has no TypeRTContextMap entry/)
|
||||
})
|
||||
|
||||
it('rejects a direct scoped projection whose Context and lookup wire symbols differ', () => {
|
||||
@@ -579,7 +579,7 @@ function assertRemoteConsumerTypechecks(
|
||||
import remote from '@fixture/remote/remote'
|
||||
import type {
|
||||
TypeRTRemoteContribution,
|
||||
TypeRTRemoteContextMap,
|
||||
TypeRTRemoteScopeMap,
|
||||
TypeRTRemoteMap,
|
||||
TypeRTRemoteNamespaceMap,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
@@ -587,8 +587,8 @@ import type { CreateGoalResult, RenameGoalResult } from '@fixture/remote/types'
|
||||
|
||||
const contribution: TypeRTRemoteContribution = remote
|
||||
declare const create: TypeRTRemoteMap['goals/create']
|
||||
declare const createScoped: TypeRTRemoteContextMap['agent:goals/create']
|
||||
declare const rename: TypeRTRemoteContextMap['agent:goals/rename']
|
||||
declare const createScoped: TypeRTRemoteScopeMap['agent:goals/create']
|
||||
declare const rename: TypeRTRemoteScopeMap['agent:goals/rename']
|
||||
const created: Promise<CreateGoalResult> = create('agent-1', { title: 'ship' })
|
||||
const cancellable: Promise<CreateGoalResult> = create('agent-1', { title: 'ship' }, new AbortController().signal)
|
||||
const createdScoped: Promise<CreateGoalResult> = createScoped({ title: 'ship' })
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/typert/type-meta/README.md
|
||||
README.md: a76169742cb78d0d19814bcd0f978c71036a5a1c
|
||||
README.zh.md: 6f2d2fd6e241441fae8102c0639608e9b27b9bec
|
||||
README.md: 9bd475f8973ec54756fe0e63d5b7fa485381697d
|
||||
README.zh.md: 10a6309bc47001d572abb3dd3f794ebfcf6252e8
|
||||
|
||||
@@ -7,7 +7,7 @@ Compiler-independent declarations shared by business packages, generated TypeRT
|
||||
## Remote declarations
|
||||
|
||||
- `@Remote` marks a public instance method for direct invocation on its registered Cordis Service.
|
||||
- `@RemoteContext(key)` marks a method whose receiver is selected from a merge-declared scoped Context kind.
|
||||
- `@RemoteScope(key)` marks a method whose receiver is selected from a merge-declared scoped Context kind.
|
||||
- `GatewayService` binds the Cordis key passed to `super(ctx, serviceKey, options?)` to the same default wire namespace.
|
||||
- `bindTypeRTGateway(this, serviceKey, options?)` provides the same visible, frozen binding for a Service that cannot inherit from `GatewayService`.
|
||||
- `remoteMethods(service)` returns a detached declaration-order snapshot used by the Gateway's SRC fallback.
|
||||
@@ -18,7 +18,7 @@ Decorator initializers retain markers in a module-private `WeakMap` keyed by the
|
||||
|
||||
## TypeRT protocol
|
||||
|
||||
Business packages extend `TypeRTLookupMap` and `TypeRTContextMap` to associate Host objects or scoped Contexts with their wire identities. Generated artifacts extend `TypeRTRemoteMap`, `TypeRTRemoteContextMap`, and `TypeRTRemoteNamespaceMap` so Client imports expose only selected Remote methods. `InvocationDescriptor` is the shared runtime form consumed by the registry, Gateway, and Client API.
|
||||
Business packages extend `TypeRTLookupMap` and `TypeRTContextMap` to associate Host objects or scoped Contexts with their wire identities. Generated artifacts extend `TypeRTRemoteMap`, `TypeRTRemoteScopeMap`, and `TypeRTRemoteNamespaceMap` so Client imports expose only selected Remote methods. `InvocationDescriptor` is the shared runtime form consumed by the registry, Gateway, and Client Remote.
|
||||
|
||||
Lookup and Context packages own both sides of their contract: declaration merging supplies the static association, while runtime providers register identity resolution with `ctx.typert`. A lookup or Host Context provider supplies the stable declaration and default resolver, while Host composition may separately configure a synchronous or asynchronous resolver; policy rejections may use `TypeRTLookupFailure` to carry a failure value owned by the boundary adapter. Strict codecs carry generated schemas; `src-json` codecs identify the weaker source-launch path.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
## Remote 声明
|
||||
|
||||
- `@Remote` 将公开实例方法标记为可在其注册的 Cordis 服务上直接调用。
|
||||
- `@RemoteContext(key)` 标记接收者选自合并声明的作用域 Context 类型的方法。
|
||||
- `@RemoteScope(key)` 标记接收者选自合并声明的作用域 Context 类型的方法。
|
||||
- `GatewayService` 将 `super(ctx, serviceKey, options?)` 接收的 Cordis key 同时绑定为默认 wire namespace。
|
||||
- `bindTypeRTGateway(this, serviceKey, options?)` 为无法继承 `GatewayService` 的 Service 提供同样可见且冻结的绑定。
|
||||
- `remoteMethods(service)` 返回按声明顺序排列、与内部状态分离的快照,供 Gateway 的 SRC 回退路径使用。
|
||||
@@ -18,7 +18,7 @@ Host 方法通过将 `signal: AbortSignal` 声明为最后一个参数来启用
|
||||
|
||||
## TypeRT 协议
|
||||
|
||||
业务包扩展 `TypeRTLookupMap` 和 `TypeRTContextMap`,以关联 Host 对象或作用域 Context 与其协议身份。生成的产物扩展 `TypeRTRemoteMap`、`TypeRTRemoteContextMap` 和 `TypeRTRemoteNamespaceMap`,使 Client 导入后仅暴露选定的 Remote 方法。`InvocationDescriptor` 是供注册表、Gateway 和 Client API 使用的共享运行时形式。
|
||||
业务包扩展 `TypeRTLookupMap` 和 `TypeRTContextMap`,以关联 Host 对象或作用域 Context 与其协议身份。生成的产物扩展 `TypeRTRemoteMap`、`TypeRTRemoteScopeMap` 和 `TypeRTRemoteNamespaceMap`,使 Client 导入后仅暴露选定的 Remote 方法。`InvocationDescriptor` 是供注册表、Gateway 和 Client Remote 使用的共享运行时形式。
|
||||
|
||||
查找包与 Context 包同时负责其契约的两侧:声明合并提供静态关联,运行时提供方则向 `ctx.typert` 注册身份解析。lookup 或 Host Context provider 提供稳定声明与默认 resolver,Host 组合可以另行配置同步或异步 resolver;策略拒绝可用 `TypeRTLookupFailure` 携带由边界适配器拥有的失败值。严格编解码器携带生成的 schema;`src-json` 编解码器标识约束更弱的源码启动路径。
|
||||
|
||||
|
||||
@@ -60,9 +60,9 @@ export type {
|
||||
TypeRTLookupResolver,
|
||||
TypeRTLookupRegistry,
|
||||
TypeRTLookupWire,
|
||||
TypeRTRemoteContextApi,
|
||||
TypeRTRemoteContextMap,
|
||||
TypeRTRemoteContextNamespace,
|
||||
TypeRTRemoteScopeApi,
|
||||
TypeRTRemoteScopeMap,
|
||||
TypeRTRemoteScopeNamespace,
|
||||
TypeRTRemoteContribution,
|
||||
TypeRTRemoteMap,
|
||||
TypeRTRemoteNamespace,
|
||||
@@ -191,16 +191,16 @@ export function Remote<This extends object, Args extends unknown[], Result>(
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a decorator for a method resolved from one scoped Remote Context.
|
||||
* @param key - merge-declared Context key.
|
||||
* Create a decorator for a method resolved from one Remote Scope.
|
||||
* @param key - scope key declared through the Context map.
|
||||
* @param exportName - optional Remote export name; defaults to the method name.
|
||||
* @returns a standard method decorator that records only private module state.
|
||||
*/
|
||||
export function RemoteContext(
|
||||
export function RemoteScope(
|
||||
key: Extract<keyof TypeRTContextMap, string>,
|
||||
exportName?: string,
|
||||
): RemoteMethodDecorator {
|
||||
validateName('Context key', key)
|
||||
validateName('Scope key', key)
|
||||
if (exportName !== undefined) validateName('Remote export name', exportName)
|
||||
return function <This extends object, Args extends unknown[], Result>(
|
||||
_method: (this: This, ...args: Args) => Result,
|
||||
|
||||
@@ -40,7 +40,7 @@ export interface TypeRTContextMap {}
|
||||
export interface TypeRTRemoteMap {}
|
||||
|
||||
/** Merge-extensible scoped Remote method signatures generated for consumers. */
|
||||
export interface TypeRTRemoteContextMap {}
|
||||
export interface TypeRTRemoteScopeMap {}
|
||||
|
||||
/**
|
||||
* Resolve one direct Remote namespace from the generated flat endpoint map.
|
||||
@@ -57,24 +57,24 @@ export type TypeRTRemoteNamespace<Namespace extends string> = {
|
||||
* The calling Cordis Context supplies the concrete identity at runtime.
|
||||
* @template Namespace - wire namespace between the Context prefix and method.
|
||||
*/
|
||||
export type TypeRTRemoteContextNamespace<
|
||||
export type TypeRTRemoteScopeNamespace<
|
||||
Namespace extends string,
|
||||
ContextKey extends string = string,
|
||||
> = {
|
||||
[Endpoint in keyof TypeRTRemoteContextMap as Endpoint extends `${ContextKey}:${Namespace}/${infer Method}`
|
||||
[Endpoint in keyof TypeRTRemoteScopeMap as Endpoint extends `${ContextKey}:${Namespace}/${infer Method}`
|
||||
? Method
|
||||
: never]: TypeRTRemoteContextMap[Endpoint]
|
||||
: never]: TypeRTRemoteScopeMap[Endpoint]
|
||||
}
|
||||
|
||||
type TypeRTRemoteContextNamespaceKey<
|
||||
type TypeRTRemoteScopeNamespaceKey<
|
||||
ContextKey extends string,
|
||||
Endpoint = keyof TypeRTRemoteContextMap,
|
||||
Endpoint = keyof TypeRTRemoteScopeMap,
|
||||
> = Endpoint extends `${ContextKey}:${infer Namespace}/${string}` ? Namespace : never
|
||||
|
||||
/** Generated scoped Remote namespaces available to one Context kind. */
|
||||
export type TypeRTRemoteContextApi<ContextKey extends string> = {
|
||||
[Namespace in TypeRTRemoteContextNamespaceKey<ContextKey>]:
|
||||
TypeRTRemoteContextNamespace<Namespace, ContextKey>
|
||||
export type TypeRTRemoteScopeApi<ContextKey extends string> = {
|
||||
[Namespace in TypeRTRemoteScopeNamespaceKey<ContextKey>]:
|
||||
TypeRTRemoteScopeNamespace<Namespace, ContextKey>
|
||||
}
|
||||
|
||||
/** Merge-extensible direct namespace surface generated for Client Remote services. */
|
||||
@@ -227,7 +227,7 @@ export interface TypeRTLookupDefinition {
|
||||
readonly wireTypeSymbol: string
|
||||
}
|
||||
|
||||
/** Host resolver for one scoped Remote Context kind. */
|
||||
/** Host resolver for one scoped Remote kind. */
|
||||
export interface TypeRTHostContextProvider<Wire = unknown> {
|
||||
/** Wire field carrying the Context identity. */
|
||||
readonly wire: string
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Context } from 'cordis'
|
||||
import {
|
||||
GatewayService,
|
||||
Remote,
|
||||
RemoteContext,
|
||||
RemoteScope,
|
||||
remoteMethods,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
|
||||
@@ -16,7 +16,7 @@ class Goals extends GatewayService {
|
||||
return value
|
||||
}
|
||||
|
||||
@RemoteContext('agent')
|
||||
@RemoteScope('agent')
|
||||
scoped(value: string): string {
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
bindTypeRTGateway,
|
||||
GatewayService,
|
||||
Remote,
|
||||
RemoteContext,
|
||||
RemoteScope,
|
||||
remoteMethods,
|
||||
type TypeRTContext,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
@@ -29,7 +29,7 @@ describe('type-meta Remote declarations', () => {
|
||||
return value
|
||||
}
|
||||
|
||||
@RemoteContext('metaFixture')
|
||||
@RemoteScope('metaFixture')
|
||||
scoped(value: string): string {
|
||||
return value
|
||||
}
|
||||
@@ -84,7 +84,7 @@ describe('type-meta Remote declarations', () => {
|
||||
Reflect.get(Goals.prototype, 'create') as (this: Goals, ...args: unknown[]) => unknown,
|
||||
methodContext('create', initializers),
|
||||
)
|
||||
RemoteContext('metaFixture')(
|
||||
RemoteScope('metaFixture')(
|
||||
Reflect.get(Goals.prototype, 'scoped') as (this: Goals, ...args: unknown[]) => unknown,
|
||||
methodContext('scoped', initializers),
|
||||
)
|
||||
@@ -141,7 +141,7 @@ describe('type-meta Remote declarations', () => {
|
||||
Reflect.get(Service.prototype, 'run') as (this: Service, ...args: unknown[]) => unknown,
|
||||
methodContext('run', initializers),
|
||||
)
|
||||
RemoteContext('metaFixture', 'inspect')(
|
||||
RemoteScope('metaFixture', 'inspect')(
|
||||
Reflect.get(Service.prototype, 'scoped') as (this: Service, ...args: unknown[]) => unknown,
|
||||
methodContext('scoped', initializers),
|
||||
)
|
||||
@@ -166,8 +166,8 @@ describe('type-meta Remote declarations', () => {
|
||||
expect(() => Remote('bad name')).toThrow('export name')
|
||||
expect(() => Remote('.')).toThrow('export name')
|
||||
expect(() => Remote('..')).toThrow('export name')
|
||||
expect(() => RemoteContext('' as 'metaFixture')).toThrow('Context key')
|
||||
expect(() => RemoteContext('metaFixture', 'bad/name')).toThrow('export name')
|
||||
expect(() => RemoteScope('' as 'metaFixture')).toThrow('Scope key')
|
||||
expect(() => RemoteScope('metaFixture', 'bad/name')).toThrow('export name')
|
||||
|
||||
for (const context of [
|
||||
{ ...methodContext('run', []), private: true },
|
||||
@@ -195,7 +195,7 @@ describe('type-meta Remote declarations', () => {
|
||||
Reflect.get(Service.prototype, 'run'),
|
||||
methodContext('run', conflicting),
|
||||
)
|
||||
RemoteContext('metaFixture')(
|
||||
RemoteScope('metaFixture')(
|
||||
Reflect.get(Service.prototype, 'run'),
|
||||
methodContext('run', conflicting),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user