refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
@@ -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/generator/README.md
|
||||
README.md: ee71c26141dc56360f4e9e1ae3c7e2add6e3a19b
|
||||
README.zh.md: a1fa777493578533c93db6cd3354b89c8757d837
|
||||
README.md: 06fcc69ce860a7cd0e893289ba59835ef3e160a7
|
||||
README.zh.md: 66b90c946157154741248d50fe95a194e5d39ad3
|
||||
|
||||
@@ -4,7 +4,7 @@ English | [中文](README.zh.md)
|
||||
|
||||
TypeScript project analyzer and model-driven Typert generator. It converts the developer-authored source type tree into compiler-independent `FaceModel` and `TypeGraph` data before any artifact is rendered. Static analysis can consume that model without Cordis; emitters never receive TypeScript AST or checker objects.
|
||||
|
||||
The analyzer can use independent `ts.Program` instances seeded from `tsconfig.host.json` or `tsconfig.client.json`. Direct project references establish compiler-face membership, while package subpaths establish TypeRT runtime-face contributions: an ordinary single-project package declaring `dsh.client` may contribute both Host and Client runtime models, and only a split project explicitly referenced through `tsconfig.host.json` or `tsconfig.client.json` is restricted to that corresponding face. `package.json#exports` establishes every cross-package public boundary, and source imports or re-exports are the only allowed cross-face edges. Types owned by NPM dependencies, including global declarations from `@types` packages, remain `external` references instead of being expanded.
|
||||
The analyzer can use independent `ts.Program` instances seeded from `tsconfig.host.json` or `tsconfig.client.json`. Direct project references establish compiler-face membership, while package subpaths establish Typert runtime-face contributions: an ordinary single-project package declaring `dsh.client` may contribute both Host and Client runtime models, and only a split project explicitly referenced through `tsconfig.host.json` or `tsconfig.client.json` is restricted to that corresponding face. `package.json#exports` establishes every cross-package public boundary, and source imports or re-exports are the only allowed cross-face edges. Types owned by NPM dependencies, including global declarations from `@types` packages, remain `external` references instead of being expanded.
|
||||
|
||||
## Analysis Model
|
||||
|
||||
@@ -18,7 +18,7 @@ Each face contains package exports, Cordis services and events, explicitly tagge
|
||||
|
||||
`WorkspaceTypertGenerator` discovers contributors by walking package public exports reachable from Cordis `Context` or `Events` augmentations and explicit `@typert` declarations. When invoked for artifact publication, it requires host artifacts at `lib/typert.host.{js,d.ts}` exposed as `package/typert`, and client artifacts at `lib/typert.client.{js,d.ts}` exposed as `package/client/typert`. Generated declarations expose `TYPERT` as `unknown`, so contributing business packages do not depend on the runtime registry.
|
||||
|
||||
Publication is package opt-in, and business packages without the corresponding public entry do not need Typert artifacts. The repository's Host tsdown runs workspace TypeRT generation with `tsconfig.host.json` as its only program seed; it produces both Host reflection artifacts and the `typert.remote-client.*` projection of Host Remote contracts for the Client. The subsequent Client tsdown neither starts TypeRT nor analyzes `tsconfig.client.json`. Static consumers can still call `WorkspaceAnalyzer` directly, explicitly select a face and package subset, and process packages in batches without publishing or loading runtime artifacts.
|
||||
Publication is package opt-in, and business packages without the corresponding public entry do not need Typert artifacts. The repository's Host tsdown runs workspace Typert generation with `tsconfig.host.json` as its only program seed; it produces both Host reflection artifacts and the `typert.remote-client.*` projection of Host Remote contracts for the Client. The subsequent Client tsdown neither starts Typert nor analyzes `tsconfig.client.json`. Static consumers can still call `WorkspaceAnalyzer` directly, explicitly select a face and package subset, and process packages in batches without publishing or loading runtime artifacts.
|
||||
|
||||
## Repository-specific Cordis projection
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
TypeScript 项目分析器和模型驱动的 Typert 生成器。在生成任何产物之前,它会先将开发者编写的源类型树转换为独立于编译器的 `FaceModel` 和 `TypeGraph` 数据。静态分析无需 Cordis 即可消费该模型;各产物生成组件均不会接收 TypeScript 抽象语法树(AST)或类型检查器对象。
|
||||
|
||||
分析器可以分别使用由 `tsconfig.host.json` 或 `tsconfig.client.json` 初始化的独立 `ts.Program`。直接项目引用确定编译器 face 的成员归属,而包子路径确定 TypeRT 运行时 face 的贡献:声明 `dsh.client` 的普通单项目包可以同时贡献 Host 与 Client 运行时模型;只有通过 `tsconfig.host.json` 或 `tsconfig.client.json` 显式引用的拆分项目,才会被限制在相应 face。`package.json#exports` 确定所有跨包公开边界,跨 face 的边只能来自源码导入或重新导出。NPM 依赖拥有的类型(包括 `@types` 包中的全局声明)继续以 `external` 引用表示,不会被展开。
|
||||
分析器可以分别使用由 `tsconfig.host.json` 或 `tsconfig.client.json` 初始化的独立 `ts.Program`。直接项目引用确定编译器 face 的成员归属,而包子路径确定 Typert 运行时 face 的贡献:声明 `dsh.client` 的普通单项目包可以同时贡献 Host 与 Client 运行时模型;只有通过 `tsconfig.host.json` 或 `tsconfig.client.json` 显式引用的拆分项目,才会被限制在相应 face。`package.json#exports` 确定所有跨包公开边界,跨 face 的边只能来自源码导入或重新导出。NPM 依赖拥有的类型(包括 `@types` 包中的全局声明)继续以 `external` 引用表示,不会被展开。
|
||||
|
||||
## 分析模型
|
||||
|
||||
@@ -18,7 +18,7 @@ TypeScript 项目分析器和模型驱动的 Typert 生成器。在生成任何
|
||||
|
||||
`WorkspaceTypertGenerator` 会遍历从 Cordis `Context` 或 `Events` 扩充声明及显式 `@typert` 声明可达的包公开导出,以发现贡献方。发布产物时,它要求宿主侧产物位于 `lib/typert.host.{js,d.ts}` 并以 `package/typert` 暴露,客户端侧产物位于 `lib/typert.client.{js,d.ts}` 并以 `package/client/typert` 暴露。生成的声明将 `TYPERT` 暴露为 `unknown`,因此参与贡献的业务包无需依赖运行时注册表。
|
||||
|
||||
各包可自行选择是否发布,未提供对应公开入口的业务包无需生成 Typert 产物。仓库的 Host tsdown 会以 `tsconfig.host.json` 为唯一 program 种子运行 workspace TypeRT 生成;它既生成 Host 反射产物,也把 Host Remote 约定投影为 Client 使用的 `typert.remote-client.*`。后续 Client tsdown 不启动 TypeRT,也不分析 `tsconfig.client.json`。静态消费方仍可直接调用 `WorkspaceAnalyzer`,显式选择 face 与包子集,并在不发布或加载运行时产物的情况下分批处理包。
|
||||
各包可自行选择是否发布,未提供对应公开入口的业务包无需生成 Typert 产物。仓库的 Host tsdown 会以 `tsconfig.host.json` 为唯一 program 种子运行 workspace Typert 生成;它既生成 Host 反射产物,也把 Host Remote 约定投影为 Client 使用的 `typert.remote-client.*`。后续 Client tsdown 不启动 Typert,也不分析 `tsconfig.client.json`。静态消费方仍可直接调用 `WorkspaceAnalyzer`,显式选择 face 与包子集,并在不发布或加载运行时产物的情况下分批处理包。
|
||||
|
||||
## 本仓库的 Cordis 投影
|
||||
|
||||
|
||||
@@ -938,7 +938,7 @@ class FaceAnalyzer {
|
||||
if (binding === undefined) {
|
||||
this.fail(
|
||||
first.method,
|
||||
'Remote methods require GatewayService or readonly typertGateway = bindTypeRTGateway(this, serviceKey)',
|
||||
'Remote methods require TypertRemoteService or readonly typertGateway = bindTypertRemote(this, serviceKey)',
|
||||
)
|
||||
}
|
||||
for (const { method, invocation } of marked) {
|
||||
@@ -1020,7 +1020,7 @@ class FaceAnalyzer {
|
||||
}
|
||||
} else {
|
||||
if (hostSymbol !== undefined && this.isWorkspaceClass(hostSymbol)) {
|
||||
this.fail(parameter, `non-JSON class parameter ${hostSymbol.name} requires a TypeRTLookupMap entry`)
|
||||
this.fail(parameter, `non-JSON class parameter ${hostSymbol.name} requires a TypertLookupMap entry`)
|
||||
}
|
||||
modeled = {
|
||||
name: parameter.name.text,
|
||||
@@ -1045,7 +1045,7 @@ class FaceAnalyzer {
|
||||
if (invocation.kind === 'context') {
|
||||
const context = this.contextDeclarations().get(invocation.context)
|
||||
if (context === undefined) {
|
||||
this.fail(method, `Remote Scope ${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 Scope wire field ${wire} conflicts with a method parameter`)
|
||||
@@ -1109,14 +1109,14 @@ class FaceAnalyzer {
|
||||
const field = this.gatewayFieldBinding(declaration)
|
||||
const base = this.gatewayServiceBinding(declaration)
|
||||
if (field !== undefined && base !== undefined) {
|
||||
this.fail(field.site, 'GatewayService subclasses must not declare a second typertGateway binding')
|
||||
this.fail(field.site, 'TypertRemoteService subclasses must not declare a second typertRemote binding')
|
||||
}
|
||||
return field ?? base
|
||||
}
|
||||
|
||||
private gatewayFieldBinding(declaration: ts.ClassDeclaration): GatewayBinding | undefined {
|
||||
const candidates = declaration.members.filter((member): member is ts.PropertyDeclaration =>
|
||||
ts.isPropertyDeclaration(member) && memberName(member.name) === 'typertGateway')
|
||||
ts.isPropertyDeclaration(member) && memberName(member.name) === 'typertRemote')
|
||||
const [property, duplicate] = candidates
|
||||
if (property === undefined) return undefined
|
||||
if (duplicate !== undefined) this.fail(duplicate, 'Service has more than one typertGateway field')
|
||||
@@ -1127,15 +1127,15 @@ class FaceAnalyzer {
|
||||
}
|
||||
if (property.initializer === undefined
|
||||
|| !ts.isCallExpression(property.initializer)
|
||||
|| !this.isTypeMetaSymbol(property.initializer.expression, 'bindTypeRTGateway')) {
|
||||
this.fail(property, 'typertGateway must call bindTypeRTGateway()')
|
||||
|| !this.isTypeMetaSymbol(property.initializer.expression, 'bindTypertRemote')) {
|
||||
this.fail(property, 'typertGateway must call bindTypertRemote()')
|
||||
}
|
||||
const call = property.initializer
|
||||
if (call.arguments.length < 2 || call.arguments.length > 3) {
|
||||
this.fail(call, 'bindTypeRTGateway() requires this, service key, and an optional options object')
|
||||
this.fail(call, 'bindTypertRemote() requires this, service key, and an optional options object')
|
||||
}
|
||||
if (call.arguments[0]?.kind !== ts.SyntaxKind.ThisKeyword) {
|
||||
this.fail(call.arguments[0] ?? call, 'bindTypeRTGateway() first argument must be this')
|
||||
this.fail(call.arguments[0] ?? call, 'bindTypertRemote() first argument must be this')
|
||||
}
|
||||
return this.gatewayBindingArguments(call, property)
|
||||
}
|
||||
@@ -1144,22 +1144,22 @@ class FaceAnalyzer {
|
||||
const heritage = (declaration.heritageClauses ?? [])
|
||||
.filter(clause => clause.token === ts.SyntaxKind.ExtendsKeyword)
|
||||
.flatMap(clause => [...clause.types])
|
||||
.find(type => this.isTypeMetaSymbol(type.expression, 'GatewayService'))
|
||||
.find(type => this.isTypeMetaSymbol(type.expression, 'TypertRemoteService'))
|
||||
if (heritage === undefined) return undefined
|
||||
|
||||
const constructor = declaration.members.find(ts.isConstructorDeclaration)
|
||||
if (constructor?.body === undefined) {
|
||||
this.fail(heritage, 'GatewayService subclasses must declare a constructor with super(ctx, serviceKey)')
|
||||
this.fail(heritage, 'TypertRemoteService subclasses must declare a constructor with super(ctx, serviceKey)')
|
||||
}
|
||||
const call = constructor.body.statements.flatMap((statement) => {
|
||||
if (!ts.isExpressionStatement(statement) || !ts.isCallExpression(statement.expression)) return []
|
||||
return statement.expression.expression.kind === ts.SyntaxKind.SuperKeyword ? [statement.expression] : []
|
||||
})[0]
|
||||
if (call === undefined) {
|
||||
this.fail(constructor, 'GatewayService constructor must call super(ctx, serviceKey) directly')
|
||||
this.fail(constructor, 'TypertRemoteService constructor must call super(ctx, serviceKey) directly')
|
||||
}
|
||||
if (call.arguments.length < 2 || call.arguments.length > 3) {
|
||||
this.fail(call, 'GatewayService super() requires context, service key, and an optional options object')
|
||||
this.fail(call, 'TypertRemoteService super() requires context, service key, and an optional options object')
|
||||
}
|
||||
return this.gatewayBindingArguments(call, heritage)
|
||||
}
|
||||
@@ -1173,12 +1173,12 @@ class FaceAnalyzer {
|
||||
const options = call.arguments[2]
|
||||
if (options !== undefined) {
|
||||
if (!ts.isObjectLiteralExpression(options)) {
|
||||
this.fail(options, 'bindTypeRTGateway() options must be an object literal')
|
||||
this.fail(options, 'bindTypertRemote() options must be an object literal')
|
||||
}
|
||||
for (const propertyOption of options.properties) {
|
||||
if (!ts.isPropertyAssignment(propertyOption)
|
||||
|| memberName(propertyOption.name) !== 'namespace') {
|
||||
this.fail(propertyOption, 'bindTypeRTGateway() only supports a namespace option')
|
||||
this.fail(propertyOption, 'bindTypertRemote() only supports a namespace option')
|
||||
}
|
||||
const value = stringLiteralValue(propertyOption.initializer)
|
||||
if (value === undefined) this.fail(propertyOption.initializer, 'Gateway namespace must be a string literal')
|
||||
@@ -1260,32 +1260,32 @@ class FaceAnalyzer {
|
||||
if (this.staticLookups !== undefined) return this.staticLookups
|
||||
const byKey = new Map<string, StaticLookupDeclaration>()
|
||||
const byHost = new Map<SymbolId, StaticLookupDeclaration>()
|
||||
for (const declaration of this.typeMetaMapMembers('TypeRTLookupMap')) {
|
||||
for (const declaration of this.typeMetaMapMembers('TypertLookupMap')) {
|
||||
if (!ts.isPropertySignature(declaration) || declaration.type === undefined) {
|
||||
this.fail(declaration, 'TypeRTLookupMap entries must be required properties')
|
||||
this.fail(declaration, 'TypertLookupMap entries must be required properties')
|
||||
}
|
||||
const key = memberName(declaration.name)
|
||||
if (!isRemoteSegment(key)) this.fail(declaration.name, 'TypeRTLookupMap key must contain only RPC endpoint segment characters')
|
||||
if (!isRemoteSegment(key)) this.fail(declaration.name, 'TypertLookupMap key must contain only RPC endpoint segment characters')
|
||||
if (!ts.isTypeReferenceNode(declaration.type)
|
||||
|| !this.isTypeMetaSymbol(declaration.type.typeName, 'TypeRTLookup')
|
||||
|| !this.isTypeMetaSymbol(declaration.type.typeName, 'TypertLookup')
|
||||
|| declaration.type.typeArguments?.length !== 2) {
|
||||
this.fail(declaration.type, 'TypeRTLookupMap values must be TypeRTLookup<Host, Wire>')
|
||||
this.fail(declaration.type, 'TypertLookupMap values must be TypertLookup<Host, Wire>')
|
||||
}
|
||||
const hostType = declaration.type.typeArguments[0]
|
||||
const wireType = declaration.type.typeArguments[1]
|
||||
if (hostType === undefined || wireType === undefined) {
|
||||
this.fail(declaration.type, 'TypeRTLookupMap values must be TypeRTLookup<Host, Wire>')
|
||||
this.fail(declaration.type, 'TypertLookupMap values must be TypertLookup<Host, Wire>')
|
||||
}
|
||||
const host = this.symbolAtType(hostType)
|
||||
if (host === undefined) this.fail(hostType, 'TypeRTLookup Host must be a named type')
|
||||
if (host === undefined) this.fail(hostType, 'TypertLookup Host must be a named type')
|
||||
const entry: StaticLookupDeclaration = {
|
||||
key,
|
||||
hostSymbol: this.symbolId(host),
|
||||
wireType,
|
||||
site: declaration,
|
||||
}
|
||||
if (byKey.has(key)) this.fail(declaration, `duplicate TypeRTLookupMap key ${key}`)
|
||||
if (byHost.has(entry.hostSymbol)) this.fail(declaration, `Host type ${host.name} has more than one TypeRT lookup`)
|
||||
if (byKey.has(key)) this.fail(declaration, `duplicate TypertLookupMap key ${key}`)
|
||||
if (byHost.has(entry.hostSymbol)) this.fail(declaration, `Host type ${host.name} has more than one Typert lookup`)
|
||||
byKey.set(key, entry)
|
||||
byHost.set(entry.hostSymbol, entry)
|
||||
}
|
||||
@@ -1296,20 +1296,20 @@ class FaceAnalyzer {
|
||||
private contextDeclarations(): ReadonlyMap<string, StaticContextDeclaration> {
|
||||
if (this.staticContexts !== undefined) return this.staticContexts
|
||||
const result = new Map<string, StaticContextDeclaration>()
|
||||
for (const declaration of this.typeMetaMapMembers('TypeRTContextMap')) {
|
||||
for (const declaration of this.typeMetaMapMembers('TypertContextMap')) {
|
||||
if (!ts.isPropertySignature(declaration) || declaration.type === undefined) {
|
||||
this.fail(declaration, 'TypeRTContextMap entries must be required properties')
|
||||
this.fail(declaration, 'TypertContextMap entries must be required properties')
|
||||
}
|
||||
const key = memberName(declaration.name)
|
||||
if (!isRemoteSegment(key)) this.fail(declaration.name, 'TypeRTContextMap key must contain only RPC endpoint segment characters')
|
||||
if (!isRemoteSegment(key)) this.fail(declaration.name, 'TypertContextMap key must contain only RPC endpoint segment characters')
|
||||
if (!ts.isTypeReferenceNode(declaration.type)
|
||||
|| !this.isTypeMetaSymbol(declaration.type.typeName, 'TypeRTContext')
|
||||
|| !this.isTypeMetaSymbol(declaration.type.typeName, 'TypertContext')
|
||||
|| declaration.type.typeArguments?.length !== 1) {
|
||||
this.fail(declaration.type, 'TypeRTContextMap values must be TypeRTContext<Wire>')
|
||||
this.fail(declaration.type, 'TypertContextMap values must be TypertContext<Wire>')
|
||||
}
|
||||
if (result.has(key)) this.fail(declaration, `duplicate TypeRTContextMap key ${key}`)
|
||||
if (result.has(key)) this.fail(declaration, `duplicate TypertContextMap key ${key}`)
|
||||
const wireType = declaration.type.typeArguments[0]
|
||||
if (wireType === undefined) this.fail(declaration.type, 'TypeRTContextMap values must be TypeRTContext<Wire>')
|
||||
if (wireType === undefined) this.fail(declaration.type, 'TypertContextMap values must be TypertContext<Wire>')
|
||||
result.set(key, {
|
||||
key,
|
||||
wireType,
|
||||
@@ -1320,13 +1320,13 @@ class FaceAnalyzer {
|
||||
return result
|
||||
}
|
||||
|
||||
private typeMetaMapMembers(name: 'TypeRTLookupMap' | 'TypeRTContextMap'): ts.TypeElement[] {
|
||||
private typeMetaMapMembers(name: 'TypertLookupMap' | 'TypertContextMap'): ts.TypeElement[] {
|
||||
const result: ts.TypeElement[] = []
|
||||
for (const sourceFile of this.program.getSourceFiles()) {
|
||||
for (const statement of sourceFile.statements) {
|
||||
if (!ts.isModuleDeclaration(statement)
|
||||
|| !ts.isStringLiteral(statement.name)
|
||||
|| statement.name.text !== '@deepseek-ai/dsh-type-meta'
|
||||
|| statement.name.text !== '@deepseek-ai/dsh-typert-protocol'
|
||||
|| statement.body === undefined
|
||||
|| !ts.isModuleBlock(statement.body)) continue
|
||||
for (const nested of statement.body.statements) {
|
||||
@@ -1788,11 +1788,11 @@ class FaceAnalyzer {
|
||||
const declaration = preferredDeclaration(resolved)
|
||||
if (declaration === undefined) return false
|
||||
const registration = this.registrationForFile(declaration.getSourceFile().fileName)
|
||||
if (registration?.name === '@deepseek-ai/dsh-type-meta') return true
|
||||
if (registration?.name === '@deepseek-ai/dsh-typert-protocol') return true
|
||||
for (let current: ts.Node | undefined = declaration; current !== undefined; current = optionalParent(current)) {
|
||||
if (ts.isModuleDeclaration(current)
|
||||
&& ts.isStringLiteral(current.name)
|
||||
&& current.name.text === '@deepseek-ai/dsh-type-meta') return true
|
||||
&& current.name.text === '@deepseek-ai/dsh-typert-protocol') return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1986,10 +1986,10 @@ class FaceAnalyzer {
|
||||
const result: MemberModel[] = []
|
||||
for (const member of members) {
|
||||
if (ts.isPropertyDeclaration(member)
|
||||
&& memberName(member.name) === 'typertGateway'
|
||||
&& memberName(member.name) === 'typertRemote'
|
||||
&& member.initializer !== undefined
|
||||
&& ts.isCallExpression(member.initializer)
|
||||
&& this.isTypeMetaSymbol(member.initializer.expression, 'bindTypeRTGateway')) continue
|
||||
&& this.isTypeMetaSymbol(member.initializer.expression, 'bindTypertRemote')) continue
|
||||
const visibility = visibilityOf(member)
|
||||
const isStatic = hasModifier(member, ts.SyntaxKind.StaticKeyword)
|
||||
if (visibility !== 'public' || isStatic || ts.isConstructorDeclaration(member)) continue
|
||||
@@ -2566,10 +2566,10 @@ function sourceFileHasSurface(sourceFile: ts.SourceFile): boolean {
|
||||
if (ts.isClassDeclaration(statement)) {
|
||||
for (const member of statement.members) {
|
||||
if (ts.isPropertyDeclaration(member)
|
||||
&& memberName(member.name) === 'typertGateway'
|
||||
&& memberName(member.name) === 'typertRemote'
|
||||
&& member.initializer !== undefined
|
||||
&& ts.isCallExpression(member.initializer)
|
||||
&& expressionName(member.initializer.expression) === 'bindTypeRTGateway') return true
|
||||
&& expressionName(member.initializer.expression) === 'bindTypertRemote') return true
|
||||
for (const decorator of ts.canHaveDecorators(member) ? ts.getDecorators(member) ?? [] : []) {
|
||||
const expression = ts.isCallExpression(decorator.expression)
|
||||
? decorator.expression.expression
|
||||
@@ -2860,8 +2860,8 @@ function stringLiteralValue(node: ts.Node | undefined): string | undefined {
|
||||
}
|
||||
|
||||
function isRemoteSegment(value: string): boolean {
|
||||
// Generation bootstraps workspace artifacts before dsh-type-meta is built,
|
||||
// so this extraction-only copy must mirror isTypeRTRemoteSegment().
|
||||
// Generation bootstraps workspace artifacts before dsh-typert-protocol is built,
|
||||
// so this extraction-only copy must mirror isTypertRemoteSegment().
|
||||
return value !== '.' && value !== '..' && /^[A-Za-z0-9_$.-]+$/.test(value)
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ export interface ServiceMethodEntry {
|
||||
export interface ServiceEntry {
|
||||
/** The `ctx.<key>` name, e.g. `llm`. */
|
||||
key: string
|
||||
/** The service class/interface name, e.g. `LlmService`. */
|
||||
/** The service class/interface name, e.g. `LlmRuntime`. */
|
||||
type: string
|
||||
/** Whether the service class is abstract (a seam interface). */
|
||||
abstract: boolean
|
||||
@@ -628,7 +628,7 @@ function renderRuntimeApi(
|
||||
'',
|
||||
'/** One named type shape the service signatures reference. */',
|
||||
'export interface TypeApiEntry {',
|
||||
' /** The exported type/interface name, e.g. `BashRunResult`. */',
|
||||
' /** The exported type/interface name, e.g. `ShellRunResult`. */',
|
||||
' name: string',
|
||||
' /** The full declaration text, comments stripped. */',
|
||||
' declaration: string',
|
||||
|
||||
@@ -344,8 +344,8 @@ export class FaceModelEmitter {
|
||||
'/* Generated by @deepseek-ai/dsh-typert-generator from the Host FaceModel — do not edit. */',
|
||||
'import type {',
|
||||
' RemoteResult,',
|
||||
' TypeRTRemoteContribution,',
|
||||
'} from \'@deepseek-ai/dsh-type-meta\'',
|
||||
' TypertRemoteContribution,',
|
||||
'} from \'@deepseek-ai/dsh-typert-protocol\'',
|
||||
]
|
||||
const sourceMap = new GenMapping({ file: 'typert.remote-client.d.ts' })
|
||||
for (const [specifier, values] of [...grouped].sort(([left], [right]) => left.localeCompare(right))) {
|
||||
@@ -354,7 +354,7 @@ export class FaceModelEmitter {
|
||||
lines.push(`import type { ${names.join(', ')} } from ${quote(specifier)}`)
|
||||
}
|
||||
lines.push('')
|
||||
lines.push('declare module \'@deepseek-ai/dsh-type-meta\' {')
|
||||
lines.push('declare module \'@deepseek-ai/dsh-typert-protocol\' {')
|
||||
const direct = packageModel.invocations.filter(invocation => invocation.invocation.kind === 'direct')
|
||||
const scoped = packageModel.invocations.filter(invocation =>
|
||||
invocation.invocation.kind === 'context' || invocation.scope !== undefined)
|
||||
@@ -366,19 +366,19 @@ export class FaceModelEmitter {
|
||||
}
|
||||
lines.push(' }')
|
||||
}
|
||||
lines.push(' interface TypeRTRemoteMap {')
|
||||
lines.push(' interface TypertRemoteMap {')
|
||||
for (const invocation of direct) {
|
||||
this.pushRemoteSignature(lines, sourceMap, packageModel, invocation, referenceNames, false)
|
||||
}
|
||||
lines.push(' }')
|
||||
lines.push(' interface TypeRTRemoteNamespaceMap {')
|
||||
lines.push(' interface TypertRemoteNamespaceMap {')
|
||||
for (const namespace of uniqueNamespaces(direct)) {
|
||||
lines.push(` ${quote(namespace)}: ${remoteNamespaceInterface(namespace)}`)
|
||||
}
|
||||
lines.push(' }')
|
||||
}
|
||||
if (scoped.length > 0) {
|
||||
lines.push(' interface TypeRTRemoteScopeMap {')
|
||||
lines.push(' interface TypertRemoteScopeMap {')
|
||||
for (const invocation of scoped) {
|
||||
this.pushRemoteSignature(lines, sourceMap, packageModel, invocation, referenceNames, true)
|
||||
}
|
||||
@@ -386,7 +386,7 @@ export class FaceModelEmitter {
|
||||
}
|
||||
lines.push('}')
|
||||
lines.push('')
|
||||
lines.push('export declare const TYPERT_REMOTE: TypeRTRemoteContribution')
|
||||
lines.push('export declare const TYPERT_REMOTE: TypertRemoteContribution')
|
||||
lines.push('export default TYPERT_REMOTE')
|
||||
lines.push('//# sourceMappingURL=typert.remote-client.d.ts.map')
|
||||
return {
|
||||
@@ -489,7 +489,7 @@ function uniqueNamespaces(invocations: readonly InvocationModel[]): string[] {
|
||||
}
|
||||
|
||||
function remoteNamespaceInterface(namespace: string): string {
|
||||
return `TypeRTRemoteNamespace$${Buffer.from(namespace, 'utf8').toString('hex')}`
|
||||
return `TypertRemoteNamespace$${Buffer.from(namespace, 'utf8').toString('hex')}`
|
||||
}
|
||||
|
||||
interface SchemaExport {
|
||||
@@ -897,7 +897,7 @@ function remoteImports(invocations: readonly InvocationModel[]): RemoteTypeImpor
|
||||
}
|
||||
|
||||
function allocateRemoteImportNames(imports: readonly RemoteTypeImportModel[]): ReadonlyMap<SymbolId, string> {
|
||||
const used = new Set(['TypeRTRemoteContribution', 'TYPERT_REMOTE'])
|
||||
const used = new Set(['TypertRemoteContribution', 'TYPERT_REMOTE'])
|
||||
const names = new Map<SymbolId, string>()
|
||||
for (const imported of imports) {
|
||||
const base = safeIdentifier(imported.name)
|
||||
|
||||
@@ -124,7 +124,7 @@ export interface InvocationParameterModel {
|
||||
readonly boundary: RemoteBoundaryModel
|
||||
}
|
||||
|
||||
/** One strictly analyzed Host method exported through TypeRT Gateway. */
|
||||
/** One strictly analyzed Host method exported through Typert Gateway. */
|
||||
export interface InvocationModel {
|
||||
readonly id: string
|
||||
readonly service: string
|
||||
|
||||
@@ -34,11 +34,11 @@ function collectServices(root: string): ServiceEntry[] {
|
||||
return collectServicesWithPolicy(root, TEST_POLICY)
|
||||
}
|
||||
|
||||
function renderEvents(events: EventEntry[], onPage = 'bash.md'): string {
|
||||
function renderEvents(events: EventEntry[], onPage = 'shell.md'): string {
|
||||
return renderPageRegion(onPage, [], events, TEST_POLICY)
|
||||
}
|
||||
|
||||
function renderServices(services: ServiceEntry[], onPage = 'bash.md'): string {
|
||||
function renderServices(services: ServiceEntry[], onPage = 'shell.md'): string {
|
||||
return renderPageRegion(onPage, services, [], TEST_POLICY)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('Typert-backed Cordis catalog', () => {
|
||||
}
|
||||
}
|
||||
expect(projector.renderRuntimeApi(model)).toBe(
|
||||
expected('packages/self-modification/tool-cordis/src/api-catalog.ts'),
|
||||
expected('packages/extensions/tool-cordis/src/api-catalog.ts'),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TypeRTContext, TypeRTLookup } from '@deepseek-ai/dsh-type-meta'
|
||||
import type { TypertContext, TypertLookup } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import type { AgentId } from './types.ts'
|
||||
|
||||
/** Host-only live Agent object. */
|
||||
@@ -6,13 +6,13 @@ export class Agent {
|
||||
constructor(readonly id: AgentId) {}
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-type-meta' {
|
||||
interface TypeRTLookupMap {
|
||||
agent: TypeRTLookup<Agent, AgentId>
|
||||
declare module '@deepseek-ai/dsh-typert-protocol' {
|
||||
interface TypertLookupMap {
|
||||
agent: TypertLookup<Agent, AgentId>
|
||||
}
|
||||
|
||||
interface TypeRTContextMap {
|
||||
agent: TypeRTContext<AgentId>
|
||||
interface TypertContextMap {
|
||||
agent: TypertContext<AgentId>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GatewayService, Remote, RemoteScope } from '@deepseek-ai/dsh-type-meta'
|
||||
import { TypertRemoteService, Remote, RemoteScope } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import type { Agent } from '@fixture/domain'
|
||||
import type {
|
||||
CreateGoalRequest,
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
} from './types.ts'
|
||||
|
||||
/** Remote-only business Service with no Cordis declaration merge. */
|
||||
export class GoalService extends GatewayService {
|
||||
export class GoalService extends TypertRemoteService {
|
||||
constructor() {
|
||||
super(undefined, 'goals')
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"allowImportingTsExtensions": true,
|
||||
"ignoreDeprecations": "6.0",
|
||||
"paths": {
|
||||
"@deepseek-ai/dsh-type-meta": ["./type-meta.d.ts"],
|
||||
"@deepseek-ai/dsh-typert-protocol": ["./typert-protocol.d.ts"],
|
||||
"@fixture/domain": ["./packages/domain/src/index.ts"],
|
||||
"@fixture/domain/*": ["./packages/domain/src/*"],
|
||||
"@fixture/remote": ["./packages/remote/src/index.ts"],
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
declare module '@deepseek-ai/dsh-type-meta' {
|
||||
export interface TypeRTLookup<Host, Wire> {
|
||||
declare module '@deepseek-ai/dsh-typert-protocol' {
|
||||
export interface TypertLookup<Host, Wire> {
|
||||
readonly host: Host
|
||||
readonly wire: Wire
|
||||
}
|
||||
|
||||
export interface TypeRTContext<Wire> {
|
||||
export interface TypertContext<Wire> {
|
||||
readonly wire: Wire
|
||||
}
|
||||
|
||||
export interface TypeRTLookupMap {}
|
||||
export interface TypeRTContextMap {}
|
||||
export interface TypeRTRemoteMap {}
|
||||
export interface TypeRTRemoteScopeMap {}
|
||||
export interface TypertLookupMap {}
|
||||
export interface TypertContextMap {}
|
||||
export interface TypertRemoteMap {}
|
||||
export interface TypertRemoteScopeMap {}
|
||||
|
||||
export interface RemoteFailure {
|
||||
readonly code: string
|
||||
@@ -23,22 +23,22 @@ declare module '@deepseek-ai/dsh-type-meta' {
|
||||
| { readonly ok: true; readonly value: T }
|
||||
| { readonly ok: false; readonly error: RemoteFailure }
|
||||
|
||||
export type TypeRTRemoteNamespace<Namespace extends string> = {
|
||||
[Endpoint in keyof TypeRTRemoteMap as Endpoint extends `${Namespace}/${infer Method}`
|
||||
export type TypertRemoteNamespace<Namespace extends string> = {
|
||||
[Endpoint in keyof TypertRemoteMap as Endpoint extends `${Namespace}/${infer Method}`
|
||||
? Method
|
||||
: never]: TypeRTRemoteMap[Endpoint]
|
||||
: never]: TypertRemoteMap[Endpoint]
|
||||
}
|
||||
|
||||
export interface TypeRTRemoteNamespaceMap {}
|
||||
export interface TypertRemoteNamespaceMap {}
|
||||
|
||||
export interface TypeRTRemoteContribution {
|
||||
export interface TypertRemoteContribution {
|
||||
readonly package: string
|
||||
readonly descriptors: readonly unknown[]
|
||||
}
|
||||
|
||||
export abstract class GatewayService {
|
||||
readonly typertGateway: {
|
||||
readonly service: GatewayService
|
||||
export abstract class TypertRemoteService {
|
||||
readonly typertRemote: {
|
||||
readonly service: TypertRemoteService
|
||||
readonly serviceKey: string
|
||||
readonly namespace: string
|
||||
}
|
||||
@@ -49,7 +49,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
|
||||
)
|
||||
}
|
||||
|
||||
export function bindTypeRTGateway<Service extends object>(
|
||||
export function bindTypertRemote<Service extends object>(
|
||||
service: Service,
|
||||
serviceKey: string,
|
||||
options?: { readonly namespace?: string },
|
||||
@@ -66,7 +66,7 @@ declare module '@deepseek-ai/dsh-type-meta' {
|
||||
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Result>,
|
||||
) => void
|
||||
|
||||
export function RemoteScope(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>,
|
||||
@@ -116,8 +116,8 @@ describe('Remote model generation', { timeout: 60_000 }, () => {
|
||||
expect(artifact?.remote?.dts).toContain(
|
||||
"'goals/create': (agentId: AgentId, request: CreateGoalRequest, signal?: AbortSignal) => Promise<RemoteResult<CreateGoalResult>>",
|
||||
)
|
||||
expect(artifact?.remote?.dts).toContain('interface TypeRTRemoteNamespace$676f616c73 {\n create:')
|
||||
expect(artifact?.remote?.dts).toContain("'goals': TypeRTRemoteNamespace$676f616c73")
|
||||
expect(artifact?.remote?.dts).toContain('interface TypertRemoteNamespace$676f616c73 {\n create:')
|
||||
expect(artifact?.remote?.dts).toContain("'goals': TypertRemoteNamespace$676f616c73")
|
||||
expect(artifact?.remote?.dts).toContain(
|
||||
"'agent:goals/create': (request: CreateGoalRequest, signal?: AbortSignal) => Promise<RemoteResult<CreateGoalResult>>",
|
||||
)
|
||||
@@ -394,13 +394,13 @@ export interface ClientMarker {
|
||||
{
|
||||
name: 'missing binding',
|
||||
edit: (source: string) => source.replace(
|
||||
"export class GoalService extends GatewayService {\n constructor() {\n super(undefined, 'goals')\n }",
|
||||
"export class GoalService extends TypertRemoteService {\n constructor() {\n super(undefined, 'goals')\n }",
|
||||
'export class GoalService {',
|
||||
),
|
||||
message: 'Remote methods require GatewayService',
|
||||
message: 'Remote methods require TypertRemoteService',
|
||||
},
|
||||
{
|
||||
name: 'dynamic GatewayService key',
|
||||
name: 'dynamic TypertRemoteService key',
|
||||
edit: (source: string) => source.replace(
|
||||
" constructor() {\n super(undefined, 'goals')\n }",
|
||||
' constructor(serviceKey: string) {\n super(undefined, serviceKey)\n }',
|
||||
@@ -408,41 +408,41 @@ export interface ClientMarker {
|
||||
message: 'Gateway service key must be a string literal',
|
||||
},
|
||||
{
|
||||
name: 'GatewayService without a constructor',
|
||||
name: 'TypertRemoteService without a constructor',
|
||||
edit: (source: string) => source.replace(
|
||||
" constructor() {\n super(undefined, 'goals')\n }\n\n",
|
||||
'',
|
||||
),
|
||||
message: 'GatewayService subclasses must declare a constructor',
|
||||
message: 'TypertRemoteService subclasses must declare a constructor',
|
||||
},
|
||||
{
|
||||
name: 'GatewayService without a direct super call',
|
||||
name: 'TypertRemoteService without a direct super call',
|
||||
edit: (source: string) => source.replace(
|
||||
" super(undefined, 'goals')",
|
||||
' void undefined',
|
||||
),
|
||||
message: 'GatewayService constructor must call super',
|
||||
message: 'TypertRemoteService constructor must call super',
|
||||
},
|
||||
{
|
||||
name: 'GatewayService super call without a service key',
|
||||
name: 'TypertRemoteService super call without a service key',
|
||||
edit: (source: string) => source.replace(
|
||||
" super(undefined, 'goals')",
|
||||
' super(undefined)',
|
||||
),
|
||||
message: 'GatewayService super\\(\\) requires context, service key',
|
||||
message: 'TypertRemoteService super\\(\\) requires context, service key',
|
||||
},
|
||||
{
|
||||
name: 'duplicate GatewayService field binding',
|
||||
name: 'duplicate TypertRemoteService field binding',
|
||||
edit: (source: string) => source
|
||||
.replace(
|
||||
'import { GatewayService, Remote, RemoteScope }',
|
||||
'import { GatewayService, Remote, RemoteScope, bindTypeRTGateway }',
|
||||
'import { TypertRemoteService, Remote, RemoteScope }',
|
||||
'import { TypertRemoteService, Remote, RemoteScope, bindTypertRemote }',
|
||||
)
|
||||
.replace(
|
||||
'export class GoalService extends GatewayService {',
|
||||
"export class GoalService extends GatewayService {\n readonly typertGateway = bindTypeRTGateway(this, 'goals')",
|
||||
'export class GoalService extends TypertRemoteService {',
|
||||
"export class GoalService extends TypertRemoteService {\n readonly typertRemote = bindTypertRemote(this, 'goals')",
|
||||
),
|
||||
message: 'GatewayService subclasses must not declare a second typertGateway binding',
|
||||
message: 'TypertRemoteService subclasses must not declare a second typertRemote binding',
|
||||
},
|
||||
{
|
||||
name: 'private method',
|
||||
@@ -520,11 +520,11 @@ export interface ClientMarker {
|
||||
it('rejects a workspace class parameter without a lookup declaration', () => {
|
||||
const root = copyFixture()
|
||||
editFile(root, 'packages/domain/src/index.ts', source => source.replace(
|
||||
' interface TypeRTLookupMap {\n agent: TypeRTLookup<Agent, AgentId>\n }\n\n',
|
||||
' interface TypertLookupMap {\n agent: TypertLookup<Agent, AgentId>\n }\n\n',
|
||||
'',
|
||||
))
|
||||
|
||||
expect(() => analyzeRemote(root, false)).toThrow(/non-JSON class parameter Agent requires a TypeRTLookupMap entry/)
|
||||
expect(() => analyzeRemote(root, false)).toThrow(/non-JSON class parameter Agent requires a TypertLookupMap entry/)
|
||||
})
|
||||
|
||||
it.each([
|
||||
@@ -557,7 +557,7 @@ export interface ClientMarker {
|
||||
const root = copyFixture()
|
||||
editFile(root, 'packages/remote/src/index.ts', source => source.replace("@RemoteScope('agent')", "@RemoteScope('missing')"))
|
||||
|
||||
expect(() => analyzeRemote(root, false)).toThrow(/Remote Scope 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', () => {
|
||||
@@ -565,7 +565,7 @@ export interface ClientMarker {
|
||||
editFile(root, 'packages/domain/src/types.ts', source => `${source}\n/** Deliberately distinct Context identity for the failure fixture. */\nexport type OtherAgentId = string\n`)
|
||||
editFile(root, 'packages/domain/src/index.ts', source => source
|
||||
.replace("import type { AgentId } from './types.ts'", "import type { AgentId, OtherAgentId } from './types.ts'")
|
||||
.replace('agent: TypeRTContext<AgentId>', 'agent: TypeRTContext<OtherAgentId>'))
|
||||
.replace('agent: TypertContext<AgentId>', 'agent: TypertContext<OtherAgentId>'))
|
||||
|
||||
expect(() => analyzeRemote(root, false)).toThrow(/Remote scope agent wire type .* does not match lookup wire type/)
|
||||
})
|
||||
@@ -573,7 +573,7 @@ export interface ClientMarker {
|
||||
it('rejects duplicate endpoints across Remote services', () => {
|
||||
const root = copyFixture()
|
||||
editFile(root, 'packages/remote/src/index.ts', source => `${source}
|
||||
export class DuplicateGoalService extends GatewayService {
|
||||
export class DuplicateGoalService extends TypertRemoteService {
|
||||
constructor() {
|
||||
super(undefined, 'duplicate', { namespace: 'goals' })
|
||||
}
|
||||
@@ -637,22 +637,22 @@ function assertRemoteConsumerTypechecks(
|
||||
import remote from '@fixture/remote/remote'
|
||||
import type {
|
||||
RemoteResult,
|
||||
TypeRTRemoteContribution,
|
||||
TypeRTRemoteScopeMap,
|
||||
TypeRTRemoteMap,
|
||||
TypeRTRemoteNamespaceMap,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
TypertRemoteContribution,
|
||||
TypertRemoteScopeMap,
|
||||
TypertRemoteMap,
|
||||
TypertRemoteNamespaceMap,
|
||||
} from '@deepseek-ai/dsh-typert-protocol'
|
||||
import type { CreateGoalResult, RenameGoalResult } from '@fixture/remote/types'
|
||||
|
||||
const contribution: TypeRTRemoteContribution = remote
|
||||
declare const create: TypeRTRemoteMap['goals/create']
|
||||
declare const createScoped: TypeRTRemoteScopeMap['agent:goals/create']
|
||||
declare const rename: TypeRTRemoteScopeMap['agent:goals/rename']
|
||||
const contribution: TypertRemoteContribution = remote
|
||||
declare const create: TypertRemoteMap['goals/create']
|
||||
declare const createScoped: TypertRemoteScopeMap['agent:goals/create']
|
||||
declare const rename: TypertRemoteScopeMap['agent:goals/rename']
|
||||
const created: Promise<RemoteResult<CreateGoalResult>> = create('agent-1', { title: 'ship' })
|
||||
const cancellable: Promise<RemoteResult<CreateGoalResult>> = create('agent-1', { title: 'ship' }, new AbortController().signal)
|
||||
const createdScoped: Promise<RemoteResult<CreateGoalResult>> = createScoped({ title: 'ship' })
|
||||
const renamed: Promise<RemoteResult<RenameGoalResult>> = rename({ ref: 'goal-1', title: 'land' })
|
||||
declare const ctx: { remote: TypeRTRemoteNamespaceMap }
|
||||
declare const ctx: { remote: TypertRemoteNamespaceMap }
|
||||
const navigated: Promise<RemoteResult<CreateGoalResult>> = ctx.remote.goals.create('agent-1', { title: 'navigate' })
|
||||
void contribution
|
||||
void created
|
||||
@@ -669,7 +669,7 @@ void navigated
|
||||
composite: false,
|
||||
skipLibCheck: false,
|
||||
paths: {
|
||||
'@deepseek-ai/dsh-type-meta': ['./type-meta.d.ts'],
|
||||
'@deepseek-ai/dsh-typert-protocol': ['./typert-protocol.d.ts'],
|
||||
'@fixture/domain/types': ['./packages/domain/src/types.ts'],
|
||||
'@fixture/remote/types': ['./packages/remote/src/types.ts'],
|
||||
'@fixture/remote/remote': ['./packages/remote/lib/typert.remote-client.d.ts'],
|
||||
@@ -731,8 +731,8 @@ void navigated
|
||||
function assertRemoteConsumerWithoutImportHasNoNamespace(consumerRoot: string): void {
|
||||
const consumerPath = join(consumerRoot, 'consumer-without-remote.ts')
|
||||
writeFileSync(consumerPath, `
|
||||
import type { TypeRTRemoteNamespaceMap } from '@deepseek-ai/dsh-type-meta'
|
||||
declare const ctx: { remote: TypeRTRemoteNamespaceMap }
|
||||
import type { TypertRemoteNamespaceMap } from '@deepseek-ai/dsh-typert-protocol'
|
||||
declare const ctx: { remote: TypertRemoteNamespaceMap }
|
||||
ctx.remote.goals.create('agent-1', { title: 'must not compile' })
|
||||
`)
|
||||
const configPath = join(consumerRoot, 'tsconfig.consumer-without-remote.json')
|
||||
@@ -742,7 +742,7 @@ ctx.remote.goals.create('agent-1', { title: 'must not compile' })
|
||||
composite: false,
|
||||
skipLibCheck: false,
|
||||
paths: {
|
||||
'@deepseek-ai/dsh-type-meta': ['./type-meta.d.ts'],
|
||||
'@deepseek-ai/dsh-typert-protocol': ['./typert-protocol.d.ts'],
|
||||
},
|
||||
},
|
||||
files: ['./consumer-without-remote.ts'],
|
||||
|
||||
@@ -880,7 +880,7 @@ describe('WorkspaceAnalyzer', { timeout: 60_000 }, () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('confines explicit face projects to their selected TypeRT face', () => {
|
||||
it('confines explicit face projects to their selected Typert face', () => {
|
||||
const root = copyFixture('typert-split-project-')
|
||||
configureDualRuntimeClient(root, true)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"path": "../../../vendor/cordis"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -430,7 +430,7 @@ describe('validateTypertManifest', () => {
|
||||
package: 'pkg',
|
||||
face: 'host',
|
||||
schemas: [],
|
||||
model: { services: [{ key: 'tools', exportName: 'ToolRegistry', tags: [], members: 'x', types: [] }], events: [], objects: [] },
|
||||
model: { services: [{ key: 'tools', exportName: 'ToolRuntime', tags: [], members: 'x', types: [] }], events: [], objects: [] },
|
||||
})).toThrow('service "tools".members must be an array')
|
||||
})
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"path": "../registry"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# 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: 658baa8bae68c33acf3fe22dba5bf463356a551b
|
||||
README.zh.md: eac0c19e6192279d89136b6c459a0741aa6c04c3
|
||||
# pnpm run verify-translation-pairing --write packages/typert/protocol/README.md
|
||||
README.md: 84f9f1b31cca35cffce5dc5fc84db1017adaad08
|
||||
README.zh.md: 97e4734a7292f0a305ff8ed00ff1d72d1a53b5e9
|
||||
@@ -1,28 +1,28 @@
|
||||
# @deepseek-ai/dsh-type-meta
|
||||
# @deepseek-ai/dsh-typert-protocol
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Compiler-independent declarations shared by business packages, generated TypeRT artifacts, the Host Gateway, and Client API. This package owns the Remote Service base, decorators, explicit binding fallback, merge-extensible protocol maps, invocation descriptors, codecs, and provider contracts; it does not run TypeScript analysis or register a concrete Cordis service.
|
||||
Compiler-independent declarations shared by business packages, generated Typert artifacts, the Host Gateway, and Client API. This package owns the Remote Service base, decorators, explicit binding fallback, merge-extensible protocol maps, invocation descriptors, codecs, and provider contracts; it does not run TypeScript analysis or register a concrete Cordis service.
|
||||
|
||||
## Remote declarations
|
||||
|
||||
- `@Remote` marks a public instance method for direct invocation on its registered Cordis Service.
|
||||
- `@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`.
|
||||
- `TypertRemoteService` binds the Cordis key passed to `super(ctx, serviceKey, options?)` to the same default wire namespace.
|
||||
- `bindTypertRemote(this, serviceKey, options?)` provides the same visible, frozen binding for a Service that cannot inherit from `TypertRemoteService`.
|
||||
- `remoteMethods(service)` returns a detached declaration-order snapshot used by the Gateway's SRC fallback.
|
||||
|
||||
A Host method opts into cooperative cancellation by declaring `signal: AbortSignal` as its final parameter. `InvocationDescriptor.cancellation` records that reserved injection point; the signal never becomes a JSON parameter or lookup field. SRC recognizes the final parameter name, while strict generation also verifies the global `AbortSignal` type.
|
||||
|
||||
Decorator initializers retain markers in a module-private `WeakMap` keyed by the Service prototype. They do not add constructor symbols, prototype properties, parameter metadata, or runtime reflection fields. A `GatewayService` exposes the same public readonly `typertGateway` binding that the explicit helper returns.
|
||||
Decorator initializers retain markers in a module-private `WeakMap` keyed by the Service prototype. They do not add constructor symbols, prototype properties, parameter metadata, or runtime reflection fields. A `TypertRemoteService` exposes the same public readonly `typertRemote` binding that the explicit helper returns.
|
||||
|
||||
## TypeRT protocol
|
||||
## Typert protocol
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
The Host assembly extends `TypeRTRemoteEventSelection` with the Host events it forwards to consumers, which narrows the `ctx.remote.$on` key face; `TypeRTForwardableEvent` states the shapes a one-way delivery can carry at all, excluding Scope-bound and answered events. `TypeRTClientRemote` carries both roles of that surface: consumers subscribe through `$on`, and the Client half owning the host frame sink hands frames over through `$dispatch`.
|
||||
The Host assembly extends `TypertRemoteEventSelection` with the Host events it forwards to consumers, which narrows the `ctx.remote.$on` key face; `TypertForwardableEvent` states the shapes a one-way delivery can carry at all, excluding Scope-bound and answered events. `TypertClientRemote` carries both roles of that surface: consumers subscribe through `$on`, and the Client half owning the host frame sink hands frames over through `$dispatch`.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Model Experience
|
||||
|
||||
@@ -34,5 +34,5 @@ No direct effect.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- Decorator markers contain only the method name and direct or Context invocation mode. Parameter, result, lookup, and schema reflection require the TypeRT build pipeline.
|
||||
- Decorator markers contain only the method name and direct or Context invocation mode. Parameter, result, lookup, and schema reflection require the Typert build pipeline.
|
||||
- Remote decorators accept only public, non-static instance methods with string names. SRC execution cannot represent overloaded, destructured, defaulted, or rest-parameter signatures.
|
||||
@@ -1,28 +1,28 @@
|
||||
# @deepseek-ai/dsh-type-meta
|
||||
# @deepseek-ai/dsh-typert-protocol
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
该包提供不依赖编译器的声明,由业务包、生成的 TypeRT 产物、宿主网关和客户端 API 共享。它负责 Remote 服务基类、装饰器、显式绑定回退、可通过声明合并扩展的协议映射、调用描述符、编解码器和提供方约定;它不执行 TypeScript 分析,也不注册具体 Cordis 服务。
|
||||
该包提供不依赖编译器的声明,由业务包、生成的 Typert 产物、宿主网关和客户端 API 共享。它负责 Remote 服务基类、装饰器、显式绑定回退、可通过声明合并扩展的协议映射、调用描述符、编解码器和提供方约定;它不执行 TypeScript 分析,也不注册具体 Cordis 服务。
|
||||
|
||||
## Remote 声明
|
||||
|
||||
- `@Remote` 将公开实例方法标记为可在其注册的 Cordis 服务上直接调用。
|
||||
- `@RemoteScope(key)` 标记接收者选自合并声明的作用域 Context 类型的方法。
|
||||
- `GatewayService` 将传给 `super(ctx, serviceKey, options?)` 的 Cordis 键绑定到同一默认协议命名空间。
|
||||
- `bindTypeRTGateway(this, serviceKey, options?)` 为无法继承 `GatewayService` 的服务提供同样可见且冻结的绑定。
|
||||
- `TypertRemoteService` 将传给 `super(ctx, serviceKey, options?)` 的 Cordis 键绑定到同一默认协议命名空间。
|
||||
- `bindTypertRemote(this, serviceKey, options?)` 为无法继承 `TypertRemoteService` 的服务提供同样可见且冻结的绑定。
|
||||
- `remoteMethods(service)` 返回按声明顺序排列、与内部状态分离的快照,供 Gateway 的 SRC 回退路径使用。
|
||||
|
||||
宿主方法通过将 `signal: AbortSignal` 声明为最后一个参数来启用协作式取消。`InvocationDescriptor.cancellation` 记录这个保留的注入点;该信号绝不会成为 JSON 参数或查找字段。SRC 识别末位参数名,严格生成还会校验它是否具有全局 `AbortSignal` 类型。
|
||||
|
||||
装饰器初始化器将标记保存在以服务原型为键的模块私有 `WeakMap` 中。它们不会在构造函数上添加符号,也不会添加原型属性、参数元数据或运行时反射字段。`GatewayService` 会暴露与显式辅助函数相同的公开只读 `typertGateway` 绑定。
|
||||
装饰器初始化器将标记保存在以服务原型为键的模块私有 `WeakMap` 中。它们不会在构造函数上添加符号,也不会添加原型属性、参数元数据或运行时反射字段。`TypertRemoteService` 会暴露与显式辅助函数相同的公开只读 `typertRemote` 绑定。
|
||||
|
||||
## TypeRT 协议
|
||||
## Typert 协议
|
||||
|
||||
业务包扩展 `TypeRTLookupMap` 和 `TypeRTContextMap`,以关联宿主对象或作用域 Context 与其协议身份。生成的产物扩展 `TypeRTRemoteMap`、`TypeRTRemoteScopeMap` 和 `TypeRTRemoteNamespaceMap`,使客户端导入后仅暴露选定的 Remote 方法。`InvocationDescriptor` 是供注册表、网关和客户端 Remote 使用的共享运行时形式。
|
||||
业务包扩展 `TypertLookupMap` 和 `TypertContextMap`,以关联宿主对象或作用域 Context 与其协议身份。生成的产物扩展 `TypertRemoteMap`、`TypertRemoteScopeMap` 和 `TypertRemoteNamespaceMap`,使客户端导入后仅暴露选定的 Remote 方法。`InvocationDescriptor` 是供注册表、网关和客户端 Remote 使用的共享运行时形式。
|
||||
|
||||
Host 装配以转发给消费端的 Host 事件扩展 `TypeRTRemoteEventSelection`,从而收窄 `ctx.remote.$on` 的键面;`TypeRTForwardableEvent` 陈述单向投递根本能承载哪些形状,把 Scope 化事件与有返回值的事件排除在外。`TypeRTClientRemote` 承载该面的两种角色:消费方经 `$on` 订阅,持有 Host 帧 sink 的 Client 半经 `$dispatch` 交出帧。
|
||||
Host 装配以转发给消费端的 Host 事件扩展 `TypertRemoteEventSelection`,从而收窄 `ctx.remote.$on` 的键面;`TypertForwardableEvent` 陈述单向投递根本能承载哪些形状,把 Scope 化事件与有返回值的事件排除在外。`TypertClientRemote` 承载该面的两种角色:消费方经 `$on` 订阅,持有 Host 帧 sink 的 Client 半经 `$dispatch` 交出帧。
|
||||
|
||||
查找包与 Context 包同时负责该约定的两侧:声明合并提供静态关联,运行时提供方则向 `ctx.typert` 注册身份解析。查找提供方或宿主 Context 提供方提供稳定声明与默认解析器,宿主组合可以另行配置同步或异步解析器;策略拒绝可用 `TypeRTLookupFailure` 携带由边界适配器拥有的失败值。严格编解码器携带生成的 schema;`src-json` 编解码器标识约束更弱的源码启动路径。
|
||||
查找包与 Context 包同时负责该约定的两侧:声明合并提供静态关联,运行时提供方则向 `ctx.typert` 注册身份解析。查找提供方或宿主 Context 提供方提供稳定声明与默认解析器,宿主组合可以另行配置同步或异步解析器;策略拒绝可用 `TypertLookupFailure` 携带由边界适配器拥有的失败值。严格编解码器携带生成的 schema;`src-json` 编解码器标识约束更弱的源码启动路径。
|
||||
|
||||
## 模型体验
|
||||
|
||||
@@ -34,5 +34,5 @@ Host 装配以转发给消费端的 Host 事件扩展 `TypeRTRemoteEventSelectio
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- 装饰器标记仅包含方法名,以及直接调用或 Context 调用模式。参数、结果、查找和 schema 反射需要 TypeRT 构建流水线。
|
||||
- 装饰器标记仅包含方法名,以及直接调用或 Context 调用模式。参数、结果、查找和 schema 反射需要 Typert 构建流水线。
|
||||
- Remote 装饰器只接受具有字符串名称的公开、非静态实例方法。SRC 执行无法表示重载签名,以及包含解构参数、默认参数或剩余参数的方法签名。
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-type-meta",
|
||||
"description": "Compiler-independent Remote metadata and TypeRT provider protocols",
|
||||
"name": "@deepseek-ai/dsh-typert-protocol",
|
||||
"description": "Compiler-independent Remote metadata and Typert provider protocols",
|
||||
"version": "0.0.1-rc.2",
|
||||
"publishConfig": {
|
||||
"access": "restricted"
|
||||
@@ -8,7 +8,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
||||
"directory": "packages/typert/type-meta"
|
||||
"directory": "packages/typert/protocol"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Remote decorators and explicit Gateway bindings backed only by private
|
||||
* module state. Strict reflection remains a TypeRT compiler responsibility.
|
||||
* @module @deepseek-ai/dsh-type-meta
|
||||
* module state. Strict reflection remains a Typert compiler responsibility.
|
||||
* @module @deepseek-ai/dsh-typert-protocol
|
||||
*/
|
||||
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
import type { TypeRTContextMap } from './types.ts'
|
||||
import type { TypertContextMap } from './types.ts'
|
||||
|
||||
const TYPERT_REMOTE_SEGMENT_PATTERN = /^[A-Za-z0-9_$.-]+$/
|
||||
|
||||
@@ -14,7 +14,7 @@ const TYPERT_REMOTE_SEGMENT_PATTERN = /^[A-Za-z0-9_$.-]+$/
|
||||
* @param value - namespace, method, lookup, or Context segment.
|
||||
* @returns whether the value can cross the shared RPC carrier unchanged.
|
||||
*/
|
||||
export function isTypeRTRemoteSegment(value: string): boolean {
|
||||
export function isTypertRemoteSegment(value: string): boolean {
|
||||
return value !== '.' && value !== '..' && TYPERT_REMOTE_SEGMENT_PATTERN.test(value)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export function isTypeRTRemoteSegment(value: string): boolean {
|
||||
* A lookup policy rejection whose typed payload belongs to the active boundary adapter.
|
||||
* Gateway adapters preserve this payload instead of collapsing it into an infrastructure failure.
|
||||
*/
|
||||
export class TypeRTLookupFailure<Failure = unknown> extends Error {
|
||||
export class TypertLookupFailure<Failure = unknown> extends Error {
|
||||
/** Adapter-owned failure returned to the caller. */
|
||||
readonly failure: Failure
|
||||
|
||||
@@ -31,8 +31,8 @@ export class TypeRTLookupFailure<Failure = unknown> extends Error {
|
||||
* @param failure - typed failure owned by the active boundary adapter.
|
||||
*/
|
||||
constructor(failure: Failure) {
|
||||
super('TypeRT lookup policy rejected the requested identity')
|
||||
this.name = 'TypeRTLookupFailure'
|
||||
super('Typert lookup policy rejected the requested identity')
|
||||
this.name = 'TypertLookupFailure'
|
||||
this.failure = failure
|
||||
}
|
||||
}
|
||||
@@ -43,50 +43,50 @@ export type {
|
||||
InvocationSourceLocation,
|
||||
RemoteFailure,
|
||||
RemoteResult,
|
||||
TypeRTClientRemote,
|
||||
TypeRTClientContextBinder,
|
||||
TypeRTCodec,
|
||||
TypeRTContext,
|
||||
TypeRTContextMap,
|
||||
TypeRTContextRegistry,
|
||||
TypeRTContextWire,
|
||||
TypeRTDisposer,
|
||||
TypeRTForwardableEvent,
|
||||
TypeRTHostContextProvider,
|
||||
TypeRTHostContextResolver,
|
||||
TypeRTLocalRegistry,
|
||||
TypeRTLookup,
|
||||
TypeRTLookupDefinition,
|
||||
TypeRTLookupHost,
|
||||
TypeRTLookupMap,
|
||||
TypeRTLookupProvider,
|
||||
TypeRTLookupResolver,
|
||||
TypeRTLookupRegistry,
|
||||
TypeRTLookupWire,
|
||||
TypeRTRemoteScopeApi,
|
||||
TypeRTRemoteScopeMap,
|
||||
TypeRTRemoteScopeNamespace,
|
||||
TypeRTRemoteContribution,
|
||||
TypeRTRemoteEvent,
|
||||
TypeRTRemoteEventSelection,
|
||||
TypeRTRemoteMap,
|
||||
TypeRTRemoteNamespace,
|
||||
TypeRTRemoteNamespaceMap,
|
||||
TypeRTRemoteRegistry,
|
||||
TypeRTRegistryChange,
|
||||
TypeRTRegistryListener,
|
||||
TypeRTSchema,
|
||||
TypeRTService,
|
||||
TypertClientRemote,
|
||||
TypertClientContextBinder,
|
||||
TypertCodec,
|
||||
TypertContext,
|
||||
TypertContextMap,
|
||||
TypertContextRegistry,
|
||||
TypertContextWire,
|
||||
TypertDisposer,
|
||||
TypertForwardableEvent,
|
||||
TypertHostContextProvider,
|
||||
TypertHostContextResolver,
|
||||
TypertLocalRegistry,
|
||||
TypertLookup,
|
||||
TypertLookupDefinition,
|
||||
TypertLookupHost,
|
||||
TypertLookupMap,
|
||||
TypertLookupProvider,
|
||||
TypertLookupResolver,
|
||||
TypertLookupRegistry,
|
||||
TypertLookupWire,
|
||||
TypertRemoteScopeApi,
|
||||
TypertRemoteScopeMap,
|
||||
TypertRemoteScopeNamespace,
|
||||
TypertRemoteContribution,
|
||||
TypertRemoteEvent,
|
||||
TypertRemoteEventSelection,
|
||||
TypertRemoteMap,
|
||||
TypertRemoteNamespace,
|
||||
TypertRemoteNamespaceMap,
|
||||
TypertRemoteRegistry,
|
||||
TypertRegistryChange,
|
||||
TypertRegistryListener,
|
||||
TypertSchema,
|
||||
TypertRegistryContract,
|
||||
} from './types.ts'
|
||||
|
||||
/** Options for an explicit Service-to-Gateway binding. */
|
||||
export interface TypeRTGatewayBindingOptions {
|
||||
export interface TypertGatewayBindingOptions {
|
||||
/** Wire namespace; defaults to the Cordis service key. */
|
||||
readonly namespace?: string
|
||||
}
|
||||
|
||||
/** Visible declaration that one Service participates in TypeRT Gateway export. */
|
||||
export interface TypeRTGatewayBinding<Service extends object = object> {
|
||||
/** Visible declaration that one Service participates in Typert Gateway export. */
|
||||
export interface TypertGatewayBinding<Service extends object = object> {
|
||||
readonly service: Service
|
||||
readonly serviceKey: string
|
||||
readonly namespace: string
|
||||
@@ -132,31 +132,31 @@ const markers = new WeakMap<object, Map<string, StoredRemoteMethodMarker>>()
|
||||
* @param options - optional distinct wire namespace.
|
||||
* @returns a frozen, inspectable binding with no compiler-injected metadata.
|
||||
*/
|
||||
export function bindTypeRTGateway<Service extends object>(
|
||||
export function bindTypertRemote<Service extends object>(
|
||||
service: Service,
|
||||
serviceKey: string,
|
||||
options: TypeRTGatewayBindingOptions = {},
|
||||
): TypeRTGatewayBinding<Service> {
|
||||
options: TypertGatewayBindingOptions = {},
|
||||
): TypertGatewayBinding<Service> {
|
||||
validateName('service key', serviceKey)
|
||||
const namespace = options.namespace ?? serviceKey
|
||||
validateName('namespace', namespace)
|
||||
return Object.freeze({ service, serviceKey, namespace })
|
||||
}
|
||||
|
||||
/** Cordis Service base that exposes its registered name through TypeRT Gateway. */
|
||||
export abstract class GatewayService<out T = never> extends Service<T> {
|
||||
/** Cordis Service base that exposes its registered name through Typert Gateway. */
|
||||
export abstract class TypertRemoteService<out T = never> extends Service<T> {
|
||||
/** Visible binding consumed by the Gateway's source-mode discovery. */
|
||||
readonly typertGateway: TypeRTGatewayBinding<this>
|
||||
readonly typertRemote: TypertGatewayBinding<this>
|
||||
|
||||
/**
|
||||
* Register the Service and bind the same key to TypeRT Gateway.
|
||||
* Register the Service and bind the same key to Typert Gateway.
|
||||
* @param ctx - owning Cordis Context.
|
||||
* @param serviceKey - exact Cordis service key and default wire namespace.
|
||||
* @param options - optional distinct wire namespace.
|
||||
*/
|
||||
protected constructor(ctx: Context, serviceKey: string, options: TypeRTGatewayBindingOptions = {}) {
|
||||
protected constructor(ctx: Context, serviceKey: string, options: TypertGatewayBindingOptions = {}) {
|
||||
super(ctx, serviceKey)
|
||||
this.typertGateway = bindTypeRTGateway(this, this.name, options)
|
||||
this.typertRemote = bindTypertRemote(this, this.name, options)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ export function Remote<This extends object, Args extends unknown[], Result>(
|
||||
addMarkerInitializer(decoratorContext, { kind: 'direct' }, methodOrExportName)
|
||||
}
|
||||
}
|
||||
if (context === undefined) throw new TypeError('type-meta: Remote decorator context is missing')
|
||||
if (context === undefined) throw new TypeError('typert-protocol: Remote decorator context is missing')
|
||||
addMarkerInitializer(context, { kind: 'direct' })
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ export function Remote<This extends object, Args extends unknown[], Result>(
|
||||
* @returns a standard method decorator that records only private module state.
|
||||
*/
|
||||
export function RemoteScope(
|
||||
key: Extract<keyof TypeRTContextMap, string>,
|
||||
key: Extract<keyof TypertContextMap, string>,
|
||||
exportName?: string,
|
||||
): RemoteMethodDecorator {
|
||||
validateName('Scope key', key)
|
||||
@@ -233,13 +233,13 @@ function addMarkerInitializer<This extends object>(
|
||||
exportName?: string,
|
||||
): void {
|
||||
if (context.private || context.static || typeof context.name !== 'string') {
|
||||
throw new TypeError('type-meta: Remote decorators require a public instance method with a string name')
|
||||
throw new TypeError('typert-protocol: Remote decorators require a public instance method with a string name')
|
||||
}
|
||||
const method = context.name
|
||||
context.addInitializer(function (this: This) {
|
||||
const prototype = Object.getPrototypeOf(this) as object | null
|
||||
if (prototype === null) {
|
||||
throw new TypeError(`type-meta: cannot mark Remote method "${method}" on an object without a prototype`)
|
||||
throw new TypeError(`typert-protocol: cannot mark Remote method "${method}" on an object without a prototype`)
|
||||
}
|
||||
mark(prototype, method, invocation, exportName)
|
||||
})
|
||||
@@ -263,7 +263,7 @@ function mark(
|
||||
const current = table.get(method)
|
||||
if (current !== undefined) {
|
||||
if (current.exportName === marker.exportName && sameInvocation(current.invocation, invocation)) return
|
||||
throw new Error(`type-meta: Remote method "${method}" has conflicting invocation markers`)
|
||||
throw new Error(`typert-protocol: Remote method "${method}" has conflicting invocation markers`)
|
||||
}
|
||||
table.set(method, Object.freeze(marker))
|
||||
}
|
||||
@@ -274,7 +274,7 @@ function sameInvocation(left: RemoteInvocationMarker, right: RemoteInvocationMar
|
||||
}
|
||||
|
||||
function validateName(subject: string, value: string): void {
|
||||
if (!isTypeRTRemoteSegment(value)) {
|
||||
throw new TypeError(`type-meta: ${subject} must contain only RPC endpoint segment characters`)
|
||||
if (!isTypertRemoteSegment(value)) {
|
||||
throw new TypeError(`typert-protocol: ${subject} must contain only RPC endpoint segment characters`)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
/**
|
||||
* Package-owned invariant companion for `@deepseek-ai/dsh-type-meta`.
|
||||
* @module @deepseek-ai/dsh-type-meta/invariant
|
||||
* Package-owned invariant companion for `@deepseek-ai/dsh-typert-protocol`.
|
||||
* @module @deepseek-ai/dsh-typert-protocol/invariant
|
||||
*/
|
||||
|
||||
/* jscpd:ignore-start */
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
|
||||
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-type-meta'
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-typert-protocol'
|
||||
|
||||
/** Cordis companion plugin name. */
|
||||
export const name = 'type-meta-invariant'
|
||||
export const name = 'typert-protocol-invariant'
|
||||
/** Service required before the companion can reserve package ownership. */
|
||||
export const inject = ['invariants']
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Compiler-independent TypeRT protocol shared by business packages, generated
|
||||
* Compiler-independent Typert protocol shared by business packages, generated
|
||||
* Remote artifacts, the Host Gateway, and Client API implementations.
|
||||
* @module @deepseek-ai/dsh-type-meta/types
|
||||
* @module @deepseek-ai/dsh-typert-protocol/types
|
||||
*/
|
||||
|
||||
import type { Context, Events } from '@deepseek-ai/cordis'
|
||||
@@ -11,33 +11,33 @@ declare const LOOKUP_WIRE: unique symbol
|
||||
declare const CONTEXT_WIRE: unique symbol
|
||||
|
||||
/** Type-level association between a Host object and its wire identity. */
|
||||
export interface TypeRTLookup<Host, Wire> {
|
||||
export interface TypertLookup<Host, Wire> {
|
||||
readonly [LOOKUP_HOST]: Host
|
||||
readonly [LOOKUP_WIRE]: Wire
|
||||
}
|
||||
|
||||
/** Extract the Host object associated with one lookup declaration. */
|
||||
export type TypeRTLookupHost<Lookup> = Lookup extends TypeRTLookup<infer Host, infer _Wire> ? Host : never
|
||||
export type TypertLookupHost<Lookup> = Lookup extends TypertLookup<infer Host, infer _Wire> ? Host : never
|
||||
|
||||
/** Extract the wire identity associated with one lookup declaration. */
|
||||
export type TypeRTLookupWire<Lookup> = Lookup extends TypeRTLookup<infer _Host, infer Wire> ? Wire : never
|
||||
export type TypertLookupWire<Lookup> = Lookup extends TypertLookup<infer _Host, infer Wire> ? Wire : never
|
||||
|
||||
/** Type-level association between a scoped Context kind and its wire identity. */
|
||||
export interface TypeRTContext<Wire> {
|
||||
export interface TypertContext<Wire> {
|
||||
readonly [CONTEXT_WIRE]: Wire
|
||||
}
|
||||
|
||||
/** Extract the wire identity associated with one scoped Context declaration. */
|
||||
export type TypeRTContextWire<ContextType> = ContextType extends TypeRTContext<infer Wire> ? Wire : never
|
||||
export type TypertContextWire<ContextType> = ContextType extends TypertContext<infer Wire> ? Wire : never
|
||||
|
||||
/** Merge-extensible Host object lookup declarations. */
|
||||
export interface TypeRTLookupMap {}
|
||||
export interface TypertLookupMap {}
|
||||
|
||||
/** Merge-extensible scoped Context declarations. */
|
||||
export interface TypeRTContextMap {}
|
||||
export interface TypertContextMap {}
|
||||
|
||||
/** Merge-extensible direct Remote method signatures generated for consumers. */
|
||||
export interface TypeRTRemoteMap {}
|
||||
export interface TypertRemoteMap {}
|
||||
|
||||
/**
|
||||
* One Remote call's failure as the carrier reported it. `code` stays open here:
|
||||
@@ -62,7 +62,7 @@ export type RemoteResult<T> =
|
||||
| { readonly ok: false; readonly error: RemoteFailure }
|
||||
|
||||
/** Merge-extensible scoped Remote method signatures generated for consumers. */
|
||||
export interface TypeRTRemoteScopeMap {}
|
||||
export interface TypertRemoteScopeMap {}
|
||||
|
||||
/**
|
||||
* Cordis event names whose shape a one-way Remote delivery can carry: unbound
|
||||
@@ -70,26 +70,26 @@ export interface TypeRTRemoteScopeMap {}
|
||||
* Host assembly's selection; this predicate only excludes shapes the carrier
|
||||
* cannot represent.
|
||||
*/
|
||||
export type TypeRTForwardableEvent = {
|
||||
export type TypertForwardableEvent = {
|
||||
[Event in keyof Events]: unknown extends ThisParameterType<Events[Event]>
|
||||
? ReturnType<Events[Event]> extends void ? Event : never
|
||||
: never
|
||||
}[keyof Events]
|
||||
|
||||
/** Merge-extensible forwarding selection declared once by the Host assembly. */
|
||||
export interface TypeRTRemoteEventSelection {}
|
||||
export interface TypertRemoteEventSelection {}
|
||||
|
||||
/** Legal `$on` keys: selected events that exist in the current compilation face. */
|
||||
export type TypeRTRemoteEvent = Extract<keyof Events, keyof TypeRTRemoteEventSelection>
|
||||
export type TypertRemoteEvent = Extract<keyof Events, keyof TypertRemoteEventSelection>
|
||||
|
||||
/**
|
||||
* Resolve one direct Remote namespace from the generated flat endpoint map.
|
||||
* @template Namespace - wire namespace before the endpoint slash.
|
||||
*/
|
||||
export type TypeRTRemoteNamespace<Namespace extends string> = {
|
||||
[Endpoint in keyof TypeRTRemoteMap as Endpoint extends `${Namespace}/${infer Method}`
|
||||
export type TypertRemoteNamespace<Namespace extends string> = {
|
||||
[Endpoint in keyof TypertRemoteMap as Endpoint extends `${Namespace}/${infer Method}`
|
||||
? Method
|
||||
: never]: TypeRTRemoteMap[Endpoint]
|
||||
: never]: TypertRemoteMap[Endpoint]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,36 +97,36 @@ 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 TypeRTRemoteScopeNamespace<
|
||||
export type TypertRemoteScopeNamespace<
|
||||
Namespace extends string,
|
||||
ContextKey extends string = string,
|
||||
> = {
|
||||
[Endpoint in keyof TypeRTRemoteScopeMap as Endpoint extends `${ContextKey}:${Namespace}/${infer Method}`
|
||||
[Endpoint in keyof TypertRemoteScopeMap as Endpoint extends `${ContextKey}:${Namespace}/${infer Method}`
|
||||
? Method
|
||||
: never]: TypeRTRemoteScopeMap[Endpoint]
|
||||
: never]: TypertRemoteScopeMap[Endpoint]
|
||||
}
|
||||
|
||||
type TypeRTRemoteScopeNamespaceKey<
|
||||
type TypertRemoteScopeNamespaceKey<
|
||||
ContextKey extends string,
|
||||
Endpoint = keyof TypeRTRemoteScopeMap,
|
||||
Endpoint = keyof TypertRemoteScopeMap,
|
||||
> = Endpoint extends `${ContextKey}:${infer Namespace}/${string}` ? Namespace : never
|
||||
|
||||
/** Generated scoped Remote namespaces available to one Context kind. */
|
||||
export type TypeRTRemoteScopeApi<ContextKey extends string> = {
|
||||
[Namespace in TypeRTRemoteScopeNamespaceKey<ContextKey>]:
|
||||
TypeRTRemoteScopeNamespace<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. */
|
||||
export interface TypeRTRemoteNamespaceMap {}
|
||||
export interface TypertRemoteNamespaceMap {}
|
||||
|
||||
/** Awaitable disposer returned by Cordis-owned TypeRT registrations. */
|
||||
export type TypeRTDisposer = () => Promise<void>
|
||||
/** Awaitable disposer returned by Cordis-owned Typert registrations. */
|
||||
export type TypertDisposer = () => Promise<void>
|
||||
|
||||
type StringKeyOf<Value> = Extract<keyof Value, string>
|
||||
|
||||
/** Minimal runtime-schema capability carried by strict generated codecs. */
|
||||
export interface TypeRTSchema<Output = unknown> {
|
||||
export interface TypertSchema<Output = unknown> {
|
||||
/**
|
||||
* Parse and validate one boundary value.
|
||||
* @param value - untrusted boundary value.
|
||||
@@ -136,11 +136,11 @@ export interface TypeRTSchema<Output = unknown> {
|
||||
}
|
||||
|
||||
/** Codec attached to one invocation parameter or result. */
|
||||
export type TypeRTCodec =
|
||||
export type TypertCodec =
|
||||
| {
|
||||
readonly mode: 'strict'
|
||||
readonly typeSymbol: string
|
||||
readonly schema: TypeRTSchema
|
||||
readonly schema: TypertSchema
|
||||
}
|
||||
| {
|
||||
readonly mode: 'src-json'
|
||||
@@ -157,7 +157,7 @@ export interface InvocationParameterDescriptor {
|
||||
/** Lookup key when `source` is `lookup`. */
|
||||
readonly lookup?: string
|
||||
/** Boundary codec for the wire representation. */
|
||||
readonly codec: TypeRTCodec
|
||||
readonly codec: TypertCodec
|
||||
/** Missing wire fields decode to `undefined` only for an explicitly declared `T | undefined`. */
|
||||
readonly acceptsUndefined?: true
|
||||
}
|
||||
@@ -188,7 +188,7 @@ export interface InvocationDescriptor {
|
||||
readonly kind: 'context'
|
||||
readonly context: string
|
||||
readonly wire: string
|
||||
readonly codec: TypeRTCodec
|
||||
readonly codec: TypertCodec
|
||||
}
|
||||
/** Optional consuming-Context projection for one direct lookup parameter. */
|
||||
readonly scope?: {
|
||||
@@ -205,13 +205,13 @@ export interface InvocationDescriptor {
|
||||
readonly parameter: 'signal'
|
||||
}
|
||||
/** Codec for the resolved method result. */
|
||||
readonly result: TypeRTCodec
|
||||
readonly result: TypertCodec
|
||||
/** Source declaration used only for diagnostics. */
|
||||
readonly sourceLocation?: InvocationSourceLocation
|
||||
}
|
||||
|
||||
/** Generated Host contract selected explicitly by a Client assembly. */
|
||||
export interface TypeRTRemoteContribution {
|
||||
export interface TypertRemoteContribution {
|
||||
/** npm package that owns the Remote methods. */
|
||||
readonly package: string
|
||||
/** Consumer-side invocation descriptors generated from that package. */
|
||||
@@ -219,13 +219,13 @@ export interface TypeRTRemoteContribution {
|
||||
}
|
||||
|
||||
/** Client Remote capability implemented by the Gateway and consumed by Remote assemblies. */
|
||||
export interface TypeRTClientRemote extends TypeRTRemoteNamespaceMap {
|
||||
export interface TypertClientRemote extends TypertRemoteNamespaceMap {
|
||||
/**
|
||||
* Mount one generated Host-for-Client contribution in the caller's fiber.
|
||||
* @param contribution - explicitly selected Remote package artifact.
|
||||
* @returns disposer after namespace services and concrete methods are ready.
|
||||
*/
|
||||
$mount(contribution: TypeRTRemoteContribution): Promise<TypeRTDisposer>
|
||||
$mount(contribution: TypertRemoteContribution): Promise<TypertDisposer>
|
||||
/**
|
||||
* Subscribe to one forwarded Host event; delivery is one-way, in registration
|
||||
* order, and isolates a throwing listener from the rest.
|
||||
@@ -234,11 +234,11 @@ export interface TypeRTClientRemote extends TypeRTRemoteNamespaceMap {
|
||||
* @param listener - receives the Host's argument list as declared by Cordis `Events`.
|
||||
* @returns disposer owned by the calling fiber.
|
||||
*/
|
||||
$on<Event extends TypeRTRemoteEvent>(event: Event, listener: Events[Event]): () => void
|
||||
$on<Event extends TypertRemoteEvent>(event: Event, listener: Events[Event]): () => void
|
||||
/**
|
||||
* Hand one decoded forwarded frame to the subscription table. The carrier
|
||||
* owning the Host frame sink calls this; a consumer subscribes with
|
||||
* {@link TypeRTClientRemote.$on} and never calls it.
|
||||
* {@link TypertClientRemote.$on} and never calls it.
|
||||
*
|
||||
* `event` is a plain string because this is the wire boundary: the name is
|
||||
* whatever the Host assembly's allowlist selected, and one nobody subscribed
|
||||
@@ -254,12 +254,12 @@ export interface TypeRTClientRemote extends TypeRTRemoteNamespaceMap {
|
||||
* @param id - validated wire identity.
|
||||
* @returns the Host object, or `undefined` when unavailable.
|
||||
*/
|
||||
export type TypeRTLookupResolver<Host = unknown, Wire = unknown> = (
|
||||
export type TypertLookupResolver<Host = unknown, Wire = unknown> = (
|
||||
id: Wire,
|
||||
) => Host | undefined | Promise<Host | undefined>
|
||||
|
||||
/** Runtime provider for one declared Host object lookup. */
|
||||
export interface TypeRTLookupProvider<Host = unknown, Wire = unknown> {
|
||||
export interface TypertLookupProvider<Host = unknown, Wire = unknown> {
|
||||
/** Source parameter name recognized by the SRC weak parser. */
|
||||
readonly parameter: string
|
||||
/** Wire field replacing the Host object parameter. */
|
||||
@@ -277,7 +277,7 @@ export interface TypeRTLookupProvider<Host = unknown, Wire = unknown> {
|
||||
}
|
||||
|
||||
/** Stable wire declaration retained after a lookup provider unloads. */
|
||||
export interface TypeRTLookupDefinition {
|
||||
export interface TypertLookupDefinition {
|
||||
/** Merge-declared lookup key. */
|
||||
readonly key: string
|
||||
/** Source parameter name recognized by the SRC weak parser. */
|
||||
@@ -291,7 +291,7 @@ export interface TypeRTLookupDefinition {
|
||||
}
|
||||
|
||||
/** Host resolver for one scoped Remote kind. */
|
||||
export interface TypeRTHostContextProvider<Wire = unknown> {
|
||||
export interface TypertHostContextProvider<Wire = unknown> {
|
||||
/** Wire field carrying the Context identity. */
|
||||
readonly wire: string
|
||||
/** Canonical wire type symbol used by strict generation. */
|
||||
@@ -305,12 +305,12 @@ export interface TypeRTHostContextProvider<Wire = unknown> {
|
||||
}
|
||||
|
||||
/** Composition-owned resolver replacing one Host Context provider's default lookup policy. */
|
||||
export type TypeRTHostContextResolver<Wire = unknown> = (
|
||||
export type TypertHostContextResolver<Wire = unknown> = (
|
||||
id: Wire,
|
||||
) => Context | undefined | Promise<Context | undefined>
|
||||
|
||||
/** Client resolver for the identity carried by the calling scoped Context. */
|
||||
export interface TypeRTClientContextBinder<Wire = unknown> {
|
||||
export interface TypertClientContextBinder<Wire = unknown> {
|
||||
/**
|
||||
* Read the Remote identity represented by a calling Context.
|
||||
* @param ctx - Context rebound by the Cordis service tracker.
|
||||
@@ -319,17 +319,17 @@ export interface TypeRTClientContextBinder<Wire = unknown> {
|
||||
identity(ctx: Context): Wire | undefined
|
||||
}
|
||||
|
||||
/** Notification emitted after a TypeRT runtime registry changes. */
|
||||
export interface TypeRTRegistryChange {
|
||||
/** Notification emitted after a Typert runtime registry changes. */
|
||||
export interface TypertRegistryChange {
|
||||
readonly kind: 'local' | 'remote' | 'lookup' | 'host-context' | 'client-context'
|
||||
readonly key: string
|
||||
}
|
||||
|
||||
/** Listener for one TypeRT runtime registry. */
|
||||
export type TypeRTRegistryListener = (change: TypeRTRegistryChange) => void
|
||||
/** Listener for one Typert runtime registry. */
|
||||
export type TypertRegistryListener = (change: TypertRegistryChange) => void
|
||||
|
||||
/** Current-environment invocation definitions. */
|
||||
export interface TypeRTLocalRegistry {
|
||||
export interface TypertLocalRegistry {
|
||||
/**
|
||||
* Look up one invocation by `<namespace>/<method>`.
|
||||
* @param endpoint - canonical endpoint.
|
||||
@@ -337,7 +337,7 @@ export interface TypeRTLocalRegistry {
|
||||
*/
|
||||
get(endpoint: string): InvocationDescriptor | undefined
|
||||
/**
|
||||
* Report whether a strict definition has existed during this TypeRT Service lifetime.
|
||||
* Report whether a strict definition has existed during this Typert Service lifetime.
|
||||
* @param endpoint - canonical endpoint.
|
||||
* @returns `true` after the endpoint has been registered at least once, even if withdrawn.
|
||||
*/
|
||||
@@ -349,17 +349,17 @@ export interface TypeRTLocalRegistry {
|
||||
* @param listener - synchronous contained observer.
|
||||
* @returns disposer for this subscription.
|
||||
*/
|
||||
subscribe(listener: TypeRTRegistryListener): TypeRTDisposer
|
||||
subscribe(listener: TypertRegistryListener): TypertDisposer
|
||||
}
|
||||
|
||||
/** Consumer-selected Remote contribution registry. */
|
||||
export interface TypeRTRemoteRegistry {
|
||||
export interface TypertRemoteRegistry {
|
||||
/**
|
||||
* Register one generated contribution for the calling Cordis fiber.
|
||||
* @param contribution - generated Remote descriptors.
|
||||
* @returns disposer withdrawing the exact contribution.
|
||||
*/
|
||||
register(contribution: TypeRTRemoteContribution): TypeRTDisposer
|
||||
register(contribution: TypertRemoteContribution): TypertDisposer
|
||||
/**
|
||||
* Look up one Remote descriptor by endpoint.
|
||||
* @param endpoint - canonical endpoint.
|
||||
@@ -373,24 +373,24 @@ export interface TypeRTRemoteRegistry {
|
||||
* @param listener - synchronous contained observer.
|
||||
* @returns disposer for this subscription.
|
||||
*/
|
||||
subscribe(listener: TypeRTRegistryListener): TypeRTDisposer
|
||||
subscribe(listener: TypertRegistryListener): TypertDisposer
|
||||
}
|
||||
|
||||
/** Runtime registry for Host object lookup providers. */
|
||||
export interface TypeRTLookupRegistry {
|
||||
export interface TypertLookupRegistry {
|
||||
/**
|
||||
* Register one provider under its merge-declared key.
|
||||
* @param key - lookup key.
|
||||
* @param provider - owning package's live resolver.
|
||||
* @returns disposer withdrawing the exact provider.
|
||||
*/
|
||||
register<K extends StringKeyOf<TypeRTLookupMap>>(
|
||||
register<K extends StringKeyOf<TypertLookupMap>>(
|
||||
key: K,
|
||||
provider: TypeRTLookupProvider<
|
||||
TypeRTLookupHost<TypeRTLookupMap[K]>,
|
||||
TypeRTLookupWire<TypeRTLookupMap[K]>
|
||||
provider: TypertLookupProvider<
|
||||
TypertLookupHost<TypertLookupMap[K]>,
|
||||
TypertLookupWire<TypertLookupMap[K]>
|
||||
>,
|
||||
): TypeRTDisposer
|
||||
): TypertDisposer
|
||||
/**
|
||||
* Replace one provider's default resolution policy while this contribution is active.
|
||||
* Configuration may precede provider registration; without a live provider, `get()` remains unavailable.
|
||||
@@ -398,21 +398,21 @@ export interface TypeRTLookupRegistry {
|
||||
* @param resolver - composition-owned resolver used by every lookup of this key.
|
||||
* @returns disposer restoring the provider's default resolver.
|
||||
*/
|
||||
configure<K extends StringKeyOf<TypeRTLookupMap>>(
|
||||
configure<K extends StringKeyOf<TypertLookupMap>>(
|
||||
key: K,
|
||||
resolver: TypeRTLookupResolver<
|
||||
TypeRTLookupHost<TypeRTLookupMap[K]>,
|
||||
TypeRTLookupWire<TypeRTLookupMap[K]>
|
||||
resolver: TypertLookupResolver<
|
||||
TypertLookupHost<TypertLookupMap[K]>,
|
||||
TypertLookupWire<TypertLookupMap[K]>
|
||||
>,
|
||||
): TypeRTDisposer
|
||||
): TypertDisposer
|
||||
/**
|
||||
* Look up one provider by runtime key.
|
||||
* @param key - descriptor lookup key.
|
||||
* @returns the live provider, or `undefined` when absent.
|
||||
*/
|
||||
get(key: string): TypeRTLookupProvider | undefined
|
||||
/** @returns lookup declarations observed during this TypeRT Service lifetime. */
|
||||
definitions(): readonly TypeRTLookupDefinition[]
|
||||
get(key: string): TypertLookupProvider | undefined
|
||||
/** @returns lookup declarations observed during this Typert Service lifetime. */
|
||||
definitions(): readonly TypertLookupDefinition[]
|
||||
/** @returns a snapshot of registered provider keys. */
|
||||
keys(): readonly string[]
|
||||
/**
|
||||
@@ -420,21 +420,21 @@ export interface TypeRTLookupRegistry {
|
||||
* @param listener - synchronous contained observer.
|
||||
* @returns disposer for this subscription.
|
||||
*/
|
||||
subscribe(listener: TypeRTRegistryListener): TypeRTDisposer
|
||||
subscribe(listener: TypertRegistryListener): TypertDisposer
|
||||
}
|
||||
|
||||
/** Runtime registry for Host Context resolvers and Client Context binders. */
|
||||
export interface TypeRTContextRegistry {
|
||||
export interface TypertContextRegistry {
|
||||
/**
|
||||
* Register a Host Context resolver.
|
||||
* @param key - merge-declared Context key.
|
||||
* @param provider - owning package's Host resolver.
|
||||
* @returns disposer withdrawing the exact provider.
|
||||
*/
|
||||
registerHost<K extends StringKeyOf<TypeRTContextMap>>(
|
||||
registerHost<K extends StringKeyOf<TypertContextMap>>(
|
||||
key: K,
|
||||
provider: TypeRTHostContextProvider<TypeRTContextWire<TypeRTContextMap[K]>>,
|
||||
): TypeRTDisposer
|
||||
provider: TypertHostContextProvider<TypertContextWire<TypertContextMap[K]>>,
|
||||
): TypertDisposer
|
||||
/**
|
||||
* Override one Host Context key's identity policy for the calling fiber.
|
||||
* Configuration may precede provider registration and restores the provider's default resolver on disposal.
|
||||
@@ -442,50 +442,50 @@ export interface TypeRTContextRegistry {
|
||||
* @param resolver - composition-owned resolver used by every Host Context lookup of this key.
|
||||
* @returns disposer restoring the provider's default resolver.
|
||||
*/
|
||||
configureHost<K extends StringKeyOf<TypeRTContextMap>>(
|
||||
configureHost<K extends StringKeyOf<TypertContextMap>>(
|
||||
key: K,
|
||||
resolver: TypeRTHostContextResolver<TypeRTContextWire<TypeRTContextMap[K]>>,
|
||||
): TypeRTDisposer
|
||||
resolver: TypertHostContextResolver<TypertContextWire<TypertContextMap[K]>>,
|
||||
): TypertDisposer
|
||||
/**
|
||||
* Register a Client Context identity binder.
|
||||
* @param key - merge-declared Context key.
|
||||
* @param binder - Client scope identity resolver.
|
||||
* @returns disposer withdrawing the exact binder.
|
||||
*/
|
||||
registerClient<K extends StringKeyOf<TypeRTContextMap>>(
|
||||
registerClient<K extends StringKeyOf<TypertContextMap>>(
|
||||
key: K,
|
||||
binder: TypeRTClientContextBinder<TypeRTContextWire<TypeRTContextMap[K]>>,
|
||||
): TypeRTDisposer
|
||||
binder: TypertClientContextBinder<TypertContextWire<TypertContextMap[K]>>,
|
||||
): TypertDisposer
|
||||
/**
|
||||
* Look up a Host Context resolver.
|
||||
* @param key - descriptor Context key.
|
||||
* @returns the provider, or `undefined` when absent.
|
||||
*/
|
||||
getHost(key: string): TypeRTHostContextProvider | undefined
|
||||
getHost(key: string): TypertHostContextProvider | undefined
|
||||
/**
|
||||
* Look up a Client Context binder.
|
||||
* @param key - descriptor Context key.
|
||||
* @returns the binder, or `undefined` when absent.
|
||||
*/
|
||||
getClient(key: string): TypeRTClientContextBinder | undefined
|
||||
getClient(key: string): TypertClientContextBinder | undefined
|
||||
/**
|
||||
* Observe later Context provider changes.
|
||||
* @param listener - synchronous contained observer.
|
||||
* @returns disposer for this subscription.
|
||||
*/
|
||||
subscribe(listener: TypeRTRegistryListener): TypeRTDisposer
|
||||
subscribe(listener: TypertRegistryListener): TypertDisposer
|
||||
}
|
||||
|
||||
/** Minimal TypeRT runtime consumed through dependency inversion. */
|
||||
export interface TypeRTService {
|
||||
readonly local: TypeRTLocalRegistry
|
||||
readonly remotes: TypeRTRemoteRegistry
|
||||
readonly lookups: TypeRTLookupRegistry
|
||||
readonly contexts: TypeRTContextRegistry
|
||||
/** Minimal Typert runtime consumed through dependency inversion. */
|
||||
export interface TypertRegistryContract {
|
||||
readonly local: TypertLocalRegistry
|
||||
readonly remotes: TypertRemoteRegistry
|
||||
readonly lookups: TypertLookupRegistry
|
||||
readonly contexts: TypertContextRegistry
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
typert: TypeRTService
|
||||
typert: TypertRegistryContract
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import {
|
||||
GatewayService,
|
||||
TypertRemoteService,
|
||||
Remote,
|
||||
RemoteScope,
|
||||
remoteMethods,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
} from '@deepseek-ai/dsh-typert-protocol'
|
||||
|
||||
class Goals extends GatewayService {
|
||||
class Goals extends TypertRemoteService {
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'goals')
|
||||
}
|
||||
@@ -3,15 +3,15 @@ import { fileURLToPath } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { describe, expect, expectTypeOf, it } from 'vitest'
|
||||
import {
|
||||
bindTypeRTGateway,
|
||||
GatewayService,
|
||||
bindTypertRemote,
|
||||
TypertRemoteService,
|
||||
Remote,
|
||||
RemoteScope,
|
||||
remoteMethods,
|
||||
type TypeRTContext,
|
||||
type TypeRTForwardableEvent,
|
||||
type TypeRTRemoteEvent,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
type TypertContext,
|
||||
type TypertForwardableEvent,
|
||||
type TypertRemoteEvent,
|
||||
} from '@deepseek-ai/dsh-typert-protocol'
|
||||
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Events {
|
||||
@@ -34,18 +34,18 @@ declare module '@deepseek-ai/cordis' {
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-type-meta' {
|
||||
interface TypeRTContextMap {
|
||||
metaFixture: TypeRTContext<string>
|
||||
declare module '@deepseek-ai/dsh-typert-protocol' {
|
||||
interface TypertContextMap {
|
||||
metaFixture: TypertContext<string>
|
||||
}
|
||||
|
||||
interface TypeRTRemoteEventSelection extends
|
||||
interface TypertRemoteEventSelection extends
|
||||
Record<'meta-fixture/forwardable' | 'meta-fixture/absent', true> {}
|
||||
}
|
||||
|
||||
describe('type-meta Remote declarations', () => {
|
||||
it('binds a GatewayService name and executes decorators through the Vitest source transform', async () => {
|
||||
class Goals extends GatewayService {
|
||||
describe('typert-protocol Remote declarations', () => {
|
||||
it('binds a TypertRemoteService name and executes decorators through the Vitest source transform', async () => {
|
||||
class Goals extends TypertRemoteService {
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'goals')
|
||||
}
|
||||
@@ -61,7 +61,7 @@ describe('type-meta Remote declarations', () => {
|
||||
}
|
||||
}
|
||||
|
||||
class NamespacedGoals extends GatewayService {
|
||||
class NamespacedGoals extends TypertRemoteService {
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'internalGoals', { namespace: 'goals' })
|
||||
}
|
||||
@@ -70,8 +70,8 @@ describe('type-meta Remote declarations', () => {
|
||||
const ctx = new Context()
|
||||
const goals = new Goals(ctx)
|
||||
const namespaced = new NamespacedGoals(ctx)
|
||||
expect(goals.typertGateway).toEqual({ service: goals, serviceKey: 'goals', namespace: 'goals' })
|
||||
expect(namespaced.typertGateway).toEqual({
|
||||
expect(goals.typertRemote).toEqual({ service: goals, serviceKey: 'goals', namespace: 'goals' })
|
||||
expect(namespaced.typertRemote).toEqual({
|
||||
service: namespaced,
|
||||
serviceKey: 'internalGoals',
|
||||
namespace: 'goals',
|
||||
@@ -94,7 +94,7 @@ describe('type-meta Remote declarations', () => {
|
||||
|
||||
it('keeps decorator markers in private module state', () => {
|
||||
class Goals {
|
||||
readonly typertGateway = bindTypeRTGateway(this, 'goals')
|
||||
readonly typertRemote = bindTypertRemote(this, 'goals')
|
||||
|
||||
create(agent: object, request: object): object {
|
||||
return { agent, request }
|
||||
@@ -117,8 +117,8 @@ describe('type-meta Remote declarations', () => {
|
||||
|
||||
const goals = new Goals()
|
||||
for (const initialize of initializers) initialize.call(goals)
|
||||
expect(goals.typertGateway).toEqual({ service: goals, serviceKey: 'goals', namespace: 'goals' })
|
||||
expect(Object.isFrozen(goals.typertGateway)).toBe(true)
|
||||
expect(goals.typertRemote).toEqual({ service: goals, serviceKey: 'goals', namespace: 'goals' })
|
||||
expect(Object.isFrozen(goals.typertRemote)).toBe(true)
|
||||
expect(remoteMethods(goals)).toEqual([
|
||||
{ method: 'create', invocation: { kind: 'direct' } },
|
||||
{ method: 'scoped', invocation: { kind: 'context', context: 'metaFixture' } },
|
||||
@@ -231,19 +231,19 @@ describe('type-meta Remote declarations', () => {
|
||||
})
|
||||
|
||||
it('rejects ambiguous binding names', () => {
|
||||
expect(() => bindTypeRTGateway({}, '')).toThrow('service key')
|
||||
expect(() => bindTypeRTGateway({}, 'goals', { namespace: 'api/goals' })).toThrow('namespace')
|
||||
expect(() => bindTypeRTGateway({}, 'goals', { namespace: 'api goals' })).toThrow('namespace')
|
||||
expect(() => bindTypertRemote({}, '')).toThrow('service key')
|
||||
expect(() => bindTypertRemote({}, 'goals', { namespace: 'api/goals' })).toThrow('namespace')
|
||||
expect(() => bindTypertRemote({}, 'goals', { namespace: 'api goals' })).toThrow('namespace')
|
||||
})
|
||||
|
||||
it('admits only one-way event shapes and only selected events that exist', () => {
|
||||
expectTypeOf<'meta-fixture/forwardable'>().toExtend<TypeRTForwardableEvent>()
|
||||
expectTypeOf<'meta-fixture/scoped'>().not.toExtend<TypeRTForwardableEvent>()
|
||||
expectTypeOf<'meta-fixture/answered'>().not.toExtend<TypeRTForwardableEvent>()
|
||||
expectTypeOf<'meta-fixture/forwardable'>().toExtend<TypertForwardableEvent>()
|
||||
expectTypeOf<'meta-fixture/scoped'>().not.toExtend<TypertForwardableEvent>()
|
||||
expectTypeOf<'meta-fixture/answered'>().not.toExtend<TypertForwardableEvent>()
|
||||
|
||||
expectTypeOf<'meta-fixture/forwardable'>().toExtend<TypeRTRemoteEvent>()
|
||||
expectTypeOf<'meta-fixture/scoped'>().not.toExtend<TypeRTRemoteEvent>()
|
||||
expectTypeOf<'meta-fixture/absent'>().not.toExtend<TypeRTRemoteEvent>()
|
||||
expectTypeOf<'meta-fixture/forwardable'>().toExtend<TypertRemoteEvent>()
|
||||
expectTypeOf<'meta-fixture/scoped'>().not.toExtend<TypertRemoteEvent>()
|
||||
expectTypeOf<'meta-fixture/absent'>().not.toExtend<TypertRemoteEvent>()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"path": "../../../vendor/cordis"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -53,7 +53,7 @@
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@deepseek-ai/dsh-type-meta": "workspace:^",
|
||||
"@deepseek-ai/dsh-typert-protocol": "workspace:^",
|
||||
"zod": "^4.4.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Browser face of the shared TypeRT runtime registry. */
|
||||
/** Browser face of the shared Typert runtime registry. */
|
||||
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { TypertRegistry } from '../service.ts'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** Host entry for the shared TypeRT runtime registry. */
|
||||
/** Host entry for the shared Typert runtime registry. */
|
||||
|
||||
import type { z } from 'zod'
|
||||
import type { TypeRTDisposer } from '@deepseek-ai/dsh-type-meta'
|
||||
import type { TypertDisposer } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import type {
|
||||
TypertContribution,
|
||||
TypertFace,
|
||||
@@ -14,9 +14,9 @@ import type {
|
||||
export { default, TypertRegistry, typertEndpoint, typertKey, typertPackageKey } from './service.ts'
|
||||
export type * from './types.ts'
|
||||
|
||||
declare module '@deepseek-ai/dsh-type-meta' {
|
||||
interface TypeRTService {
|
||||
register(contribution: TypertContribution): TypeRTDisposer
|
||||
declare module '@deepseek-ai/dsh-typert-protocol' {
|
||||
interface TypertRegistryContract {
|
||||
register(contribution: TypertContribution): TypertDisposer
|
||||
get(key: string): TypertSchemaRecord | undefined
|
||||
resolve(key: string): TypertSchemaRecord
|
||||
list(filter?: TypertSchemaFilter): TypertSchemaRecord[]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Runtime registry for generated TypeRT reflection, Remote invocations, and
|
||||
* Runtime registry for generated Typert reflection, Remote invocations, and
|
||||
* dependency-inverted lookup/Context providers. It performs no TypeScript
|
||||
* analysis or schema generation.
|
||||
* @module @deepseek-ai/dsh-typert-registry
|
||||
@@ -9,27 +9,27 @@ import { Context, Service } from '@deepseek-ai/cordis'
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
InvocationDescriptor,
|
||||
TypeRTClientContextBinder,
|
||||
TypeRTContextMap,
|
||||
TypeRTContextRegistry,
|
||||
TypeRTContextWire,
|
||||
TypeRTDisposer,
|
||||
TypeRTHostContextProvider,
|
||||
TypeRTHostContextResolver,
|
||||
TypeRTLocalRegistry,
|
||||
TypeRTLookupHost,
|
||||
TypeRTLookupDefinition,
|
||||
TypeRTLookupMap,
|
||||
TypeRTLookupProvider,
|
||||
TypeRTLookupResolver,
|
||||
TypeRTLookupRegistry,
|
||||
TypeRTLookupWire,
|
||||
TypeRTRemoteContribution,
|
||||
TypeRTRemoteRegistry,
|
||||
TypeRTRegistryChange,
|
||||
TypeRTRegistryListener,
|
||||
TypeRTService,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
TypertClientContextBinder,
|
||||
TypertContextMap,
|
||||
TypertContextRegistry,
|
||||
TypertContextWire,
|
||||
TypertDisposer,
|
||||
TypertHostContextProvider,
|
||||
TypertHostContextResolver,
|
||||
TypertLocalRegistry,
|
||||
TypertLookupHost,
|
||||
TypertLookupDefinition,
|
||||
TypertLookupMap,
|
||||
TypertLookupProvider,
|
||||
TypertLookupResolver,
|
||||
TypertLookupRegistry,
|
||||
TypertLookupWire,
|
||||
TypertRemoteContribution,
|
||||
TypertRemoteRegistry,
|
||||
TypertRegistryChange,
|
||||
TypertRegistryListener,
|
||||
TypertRegistryContract,
|
||||
} from '@deepseek-ai/dsh-typert-protocol'
|
||||
import type {
|
||||
TypertContribution,
|
||||
TypertFace,
|
||||
@@ -78,14 +78,14 @@ interface ProviderEntry<Provider> {
|
||||
readonly owner: object
|
||||
}
|
||||
|
||||
type ReportObserverError = (change: TypeRTRegistryChange, error: unknown) => void
|
||||
type ReportObserverError = (change: TypertRegistryChange, error: unknown) => void
|
||||
|
||||
class ChangeSource {
|
||||
private readonly listeners = new Set<TypeRTRegistryListener>()
|
||||
private readonly listeners = new Set<TypertRegistryListener>()
|
||||
|
||||
constructor(private readonly report: ReportObserverError) {}
|
||||
|
||||
subscribe(ctx: Context, listener: TypeRTRegistryListener): TypeRTDisposer {
|
||||
subscribe(ctx: Context, listener: TypertRegistryListener): TypertDisposer {
|
||||
const { listeners } = this
|
||||
return ctx.effect(function* () {
|
||||
listeners.add(listener)
|
||||
@@ -93,7 +93,7 @@ class ChangeSource {
|
||||
}, 'typert registry subscription')
|
||||
}
|
||||
|
||||
emit(change: TypeRTRegistryChange): void {
|
||||
emit(change: TypertRegistryChange): void {
|
||||
for (const listener of [...this.listeners]) {
|
||||
try {
|
||||
listener(change)
|
||||
@@ -174,7 +174,7 @@ class DescriptorStore {
|
||||
return [...this.entries.values()].map(entry => entry.descriptor)
|
||||
}
|
||||
|
||||
subscribe(ctx: Context, listener: TypeRTRegistryListener): TypeRTDisposer {
|
||||
subscribe(ctx: Context, listener: TypertRegistryListener): TypertDisposer {
|
||||
return this.changes.subscribe(ctx, listener)
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ class RemoteStore {
|
||||
|
||||
constructor(private readonly descriptors: DescriptorStore) {}
|
||||
|
||||
view(ctx: Context): TypeRTRemoteRegistry {
|
||||
view(ctx: Context): TypertRemoteRegistry {
|
||||
return {
|
||||
register: contribution => this.register(ctx, contribution),
|
||||
get: endpoint => this.descriptors.get(endpoint),
|
||||
@@ -193,7 +193,7 @@ class RemoteStore {
|
||||
}
|
||||
}
|
||||
|
||||
private register(ctx: Context, contribution: TypeRTRemoteContribution): TypeRTDisposer {
|
||||
private register(ctx: Context, contribution: TypertRemoteContribution): TypertDisposer {
|
||||
validateSegment('Remote package name', contribution.package)
|
||||
if (this.packages.has(contribution.package)) {
|
||||
throw new Error(`typert: Remote package "${contribution.package}" is already registered`)
|
||||
@@ -214,29 +214,29 @@ class RemoteStore {
|
||||
}
|
||||
|
||||
class LookupStore {
|
||||
private readonly providers = new Map<string, ProviderEntry<TypeRTLookupProvider>>()
|
||||
private readonly providers = new Map<string, ProviderEntry<TypertLookupProvider>>()
|
||||
private readonly resolvers = new Map<string, ProviderEntry<LookupResolverEntry>>()
|
||||
private readonly definitions = new Map<string, TypeRTLookupDefinition>()
|
||||
private readonly definitions = new Map<string, TypertLookupDefinition>()
|
||||
private readonly changes: ChangeSource
|
||||
|
||||
constructor(report: ReportObserverError) {
|
||||
this.changes = new ChangeSource(report)
|
||||
}
|
||||
|
||||
view(ctx: Context): TypeRTLookupRegistry {
|
||||
view(ctx: Context): TypertLookupRegistry {
|
||||
return {
|
||||
register: <K extends Extract<keyof TypeRTLookupMap, string>>(
|
||||
register: <K extends Extract<keyof TypertLookupMap, string>>(
|
||||
key: K,
|
||||
provider: TypeRTLookupProvider<
|
||||
TypeRTLookupHost<TypeRTLookupMap[K]>,
|
||||
TypeRTLookupWire<TypeRTLookupMap[K]>
|
||||
provider: TypertLookupProvider<
|
||||
TypertLookupHost<TypertLookupMap[K]>,
|
||||
TypertLookupWire<TypertLookupMap[K]>
|
||||
>,
|
||||
) => this.register(ctx, key, provider),
|
||||
configure: <K extends Extract<keyof TypeRTLookupMap, string>>(
|
||||
configure: <K extends Extract<keyof TypertLookupMap, string>>(
|
||||
key: K,
|
||||
resolver: TypeRTLookupResolver<
|
||||
TypeRTLookupHost<TypeRTLookupMap[K]>,
|
||||
TypeRTLookupWire<TypeRTLookupMap[K]>
|
||||
resolver: TypertLookupResolver<
|
||||
TypertLookupHost<TypertLookupMap[K]>,
|
||||
TypertLookupWire<TypertLookupMap[K]>
|
||||
>,
|
||||
) => this.configure(ctx, key, resolver),
|
||||
get: key => this.get(key),
|
||||
@@ -246,7 +246,7 @@ class LookupStore {
|
||||
}
|
||||
}
|
||||
|
||||
private get(key: string): TypeRTLookupProvider | undefined {
|
||||
private get(key: string): TypertLookupProvider | undefined {
|
||||
const provider = this.providers.get(key)?.provider
|
||||
if (provider === undefined) return undefined
|
||||
const resolver = this.resolvers.get(key)?.provider
|
||||
@@ -263,8 +263,8 @@ class LookupStore {
|
||||
private configure<Host, Wire>(
|
||||
ctx: Context,
|
||||
key: string,
|
||||
resolver: TypeRTLookupResolver<Host, Wire>,
|
||||
): TypeRTDisposer {
|
||||
resolver: TypertLookupResolver<Host, Wire>,
|
||||
): TypertDisposer {
|
||||
validateSegment('lookup key', key)
|
||||
if (this.resolvers.has(key)) throw new Error(`typert: lookup "${key}" resolver is already configured`)
|
||||
const owner = {}
|
||||
@@ -287,14 +287,14 @@ class LookupStore {
|
||||
}, `typert.lookups.configure(${JSON.stringify(key)})`)
|
||||
}
|
||||
|
||||
private register<Host, Wire>(ctx: Context, key: string, provider: TypeRTLookupProvider<Host, Wire>): TypeRTDisposer {
|
||||
private register<Host, Wire>(ctx: Context, key: string, provider: TypertLookupProvider<Host, Wire>): TypertDisposer {
|
||||
validateSegment('lookup key', key)
|
||||
validateSegment('lookup parameter', provider.parameter)
|
||||
validateWireName('lookup wire field', provider.wire)
|
||||
validateNonempty('lookup Host type symbol', provider.hostTypeSymbol)
|
||||
validateNonempty('lookup wire type symbol', provider.wireTypeSymbol)
|
||||
if (this.providers.has(key)) throw new Error(`typert: lookup "${key}" is already registered`)
|
||||
const definition: TypeRTLookupDefinition = {
|
||||
const definition: TypertLookupDefinition = {
|
||||
key,
|
||||
parameter: provider.parameter,
|
||||
wire: provider.wire,
|
||||
@@ -306,7 +306,7 @@ class LookupStore {
|
||||
throw new Error(`typert: lookup "${key}" changed its wire declaration during this registry lifetime`)
|
||||
}
|
||||
const owner = {}
|
||||
const entry: ProviderEntry<TypeRTLookupProvider> = { provider, owner }
|
||||
const entry: ProviderEntry<TypertLookupProvider> = { provider, owner }
|
||||
const { definitions, providers, changes } = this
|
||||
return ctx.effect(function* () {
|
||||
definitions.set(key, definition)
|
||||
@@ -326,7 +326,7 @@ interface LookupResolverEntry {
|
||||
resolve(id: unknown): Promise<unknown>
|
||||
}
|
||||
|
||||
function lookupDefinitionEquals(left: TypeRTLookupDefinition, right: TypeRTLookupDefinition): boolean {
|
||||
function lookupDefinitionEquals(left: TypertLookupDefinition, right: TypertLookupDefinition): boolean {
|
||||
return left.parameter === right.parameter
|
||||
&& left.wire === right.wire
|
||||
&& left.hostTypeSymbol === right.hostTypeSymbol
|
||||
@@ -334,28 +334,28 @@ function lookupDefinitionEquals(left: TypeRTLookupDefinition, right: TypeRTLooku
|
||||
}
|
||||
|
||||
class ContextStore {
|
||||
private readonly hosts = new Map<string, ProviderEntry<TypeRTHostContextProvider>>()
|
||||
private readonly hosts = new Map<string, ProviderEntry<TypertHostContextProvider>>()
|
||||
private readonly hostResolvers = new Map<string, ProviderEntry<HostContextResolverEntry>>()
|
||||
private readonly clients = new Map<string, ProviderEntry<TypeRTClientContextBinder>>()
|
||||
private readonly clients = new Map<string, ProviderEntry<TypertClientContextBinder>>()
|
||||
private readonly changes: ChangeSource
|
||||
|
||||
constructor(report: ReportObserverError) {
|
||||
this.changes = new ChangeSource(report)
|
||||
}
|
||||
|
||||
view(ctx: Context): TypeRTContextRegistry {
|
||||
view(ctx: Context): TypertContextRegistry {
|
||||
return {
|
||||
registerHost: <K extends Extract<keyof TypeRTContextMap, string>>(
|
||||
registerHost: <K extends Extract<keyof TypertContextMap, string>>(
|
||||
key: K,
|
||||
provider: TypeRTHostContextProvider<TypeRTContextWire<TypeRTContextMap[K]>>,
|
||||
provider: TypertHostContextProvider<TypertContextWire<TypertContextMap[K]>>,
|
||||
) => this.registerHost(ctx, key, provider),
|
||||
configureHost: <K extends Extract<keyof TypeRTContextMap, string>>(
|
||||
configureHost: <K extends Extract<keyof TypertContextMap, string>>(
|
||||
key: K,
|
||||
resolver: TypeRTHostContextResolver<TypeRTContextWire<TypeRTContextMap[K]>>,
|
||||
resolver: TypertHostContextResolver<TypertContextWire<TypertContextMap[K]>>,
|
||||
) => this.configureHost(ctx, key, resolver),
|
||||
registerClient: <K extends Extract<keyof TypeRTContextMap, string>>(
|
||||
registerClient: <K extends Extract<keyof TypertContextMap, string>>(
|
||||
key: K,
|
||||
binder: TypeRTClientContextBinder<TypeRTContextWire<TypeRTContextMap[K]>>,
|
||||
binder: TypertClientContextBinder<TypertContextWire<TypertContextMap[K]>>,
|
||||
) => this.registerClient(ctx, key, binder),
|
||||
getHost: key => this.getHost(key),
|
||||
getClient: key => this.clients.get(key)?.provider,
|
||||
@@ -363,7 +363,7 @@ class ContextStore {
|
||||
}
|
||||
}
|
||||
|
||||
private getHost(key: string): TypeRTHostContextProvider | undefined {
|
||||
private getHost(key: string): TypertHostContextProvider | undefined {
|
||||
const provider = this.hosts.get(key)?.provider
|
||||
if (provider === undefined) return undefined
|
||||
const resolver = this.hostResolvers.get(key)?.provider
|
||||
@@ -378,8 +378,8 @@ class ContextStore {
|
||||
private configureHost<Wire>(
|
||||
ctx: Context,
|
||||
key: string,
|
||||
resolver: TypeRTHostContextResolver<Wire>,
|
||||
): TypeRTDisposer {
|
||||
resolver: TypertHostContextResolver<Wire>,
|
||||
): TypertDisposer {
|
||||
validateSegment('Context key', key)
|
||||
if (this.hostResolvers.has(key)) throw new Error(`typert: host-context "${key}" resolver is already configured`)
|
||||
const entry: ProviderEntry<HostContextResolverEntry> = {
|
||||
@@ -399,14 +399,14 @@ class ContextStore {
|
||||
}, `typert.contexts.configureHost(${JSON.stringify(key)})`)
|
||||
}
|
||||
|
||||
private registerHost<Wire>(ctx: Context, key: string, provider: TypeRTHostContextProvider<Wire>): TypeRTDisposer {
|
||||
private registerHost<Wire>(ctx: Context, key: string, provider: TypertHostContextProvider<Wire>): TypertDisposer {
|
||||
validateSegment('Context key', key)
|
||||
validateWireName('Context wire field', provider.wire)
|
||||
validateNonempty('Context wire type symbol', provider.wireTypeSymbol)
|
||||
return this.registerProvider(ctx, this.hosts, 'host-context', key, provider)
|
||||
}
|
||||
|
||||
private registerClient<Wire>(ctx: Context, key: string, binder: TypeRTClientContextBinder<Wire>): TypeRTDisposer {
|
||||
private registerClient<Wire>(ctx: Context, key: string, binder: TypertClientContextBinder<Wire>): TypertDisposer {
|
||||
validateSegment('Context key', key)
|
||||
return this.registerProvider(ctx, this.clients, 'client-context', key, binder)
|
||||
}
|
||||
@@ -417,7 +417,7 @@ class ContextStore {
|
||||
kind: 'host-context' | 'client-context',
|
||||
key: string,
|
||||
provider: Provider,
|
||||
): TypeRTDisposer {
|
||||
): TypertDisposer {
|
||||
if (table.has(key)) throw new Error(`typert: ${kind} provider "${key}" is already registered`)
|
||||
const entry: ProviderEntry<Provider> = { provider, owner: {} }
|
||||
const { changes } = this
|
||||
@@ -443,7 +443,7 @@ interface HostContextResolverEntry {
|
||||
* dependency providers.
|
||||
* @typert service typert
|
||||
*/
|
||||
export class TypertRegistry extends Service implements TypeRTService {
|
||||
export class TypertRegistry extends Service implements TypertRegistryContract {
|
||||
private readonly schemas = new Map<string, TypertSchemaRecord>()
|
||||
private readonly packages = new Map<string, TypertPackageRecord>()
|
||||
private readonly localStore: DescriptorStore
|
||||
@@ -464,7 +464,7 @@ export class TypertRegistry extends Service implements TypeRTService {
|
||||
}
|
||||
|
||||
/** Current-environment invocation definitions. */
|
||||
get local(): TypeRTLocalRegistry {
|
||||
get local(): TypertLocalRegistry {
|
||||
const ctx = this.ctx
|
||||
return {
|
||||
get: endpoint => this.localStore.get(endpoint),
|
||||
@@ -475,17 +475,17 @@ export class TypertRegistry extends Service implements TypeRTService {
|
||||
}
|
||||
|
||||
/** Consumer-selected Remote definitions. */
|
||||
get remotes(): TypeRTRemoteRegistry {
|
||||
get remotes(): TypertRemoteRegistry {
|
||||
return this.remoteStore.view(this.ctx)
|
||||
}
|
||||
|
||||
/** Host object lookup providers. */
|
||||
get lookups(): TypeRTLookupRegistry {
|
||||
get lookups(): TypertLookupRegistry {
|
||||
return this.lookupStore.view(this.ctx)
|
||||
}
|
||||
|
||||
/** Host Context providers and Client Context binders. */
|
||||
get contexts(): TypeRTContextRegistry {
|
||||
get contexts(): TypertContextRegistry {
|
||||
return this.contextStore.view(this.ctx)
|
||||
}
|
||||
|
||||
@@ -496,7 +496,7 @@ export class TypertRegistry extends Service implements TypeRTService {
|
||||
* @param contribution - generated schemas, reflection, and Host invocations.
|
||||
* @returns the exact effect disposer that removes this contribution.
|
||||
*/
|
||||
register(contribution: TypertContribution): TypeRTDisposer {
|
||||
register(contribution: TypertContribution): TypertDisposer {
|
||||
const packageRecord = this.validatePackage(contribution)
|
||||
const schemaRecords = this.validateSchemas(contribution)
|
||||
const invocations = contribution.invocations
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { z } from 'zod'
|
||||
import type { InvocationDescriptor } from '@deepseek-ai/dsh-type-meta'
|
||||
import type { InvocationDescriptor } from '@deepseek-ai/dsh-typert-protocol'
|
||||
|
||||
/** Independently compiled side that produced a contribution. */
|
||||
export type TypertFace = 'host' | 'client'
|
||||
|
||||
@@ -9,19 +9,19 @@ import TypertRegistry, {
|
||||
} from '@deepseek-ai/dsh-typert-registry'
|
||||
import type {
|
||||
InvocationDescriptor,
|
||||
TypeRTContext,
|
||||
TypeRTLookup,
|
||||
TypeRTRemoteContribution,
|
||||
} from '@deepseek-ai/dsh-type-meta'
|
||||
TypertContext,
|
||||
TypertLookup,
|
||||
TypertRemoteContribution,
|
||||
} from '@deepseek-ai/dsh-typert-protocol'
|
||||
import { apply as applyClientRegistry, inject as clientRegistryInject } from '../src/client/index.ts'
|
||||
|
||||
declare module '@deepseek-ai/dsh-type-meta' {
|
||||
interface TypeRTLookupMap {
|
||||
fixture: TypeRTLookup<{ readonly id: string }, string>
|
||||
declare module '@deepseek-ai/dsh-typert-protocol' {
|
||||
interface TypertLookupMap {
|
||||
fixture: TypertLookup<{ readonly id: string }, string>
|
||||
}
|
||||
|
||||
interface TypeRTContextMap {
|
||||
registryFixture: TypeRTContext<string>
|
||||
interface TypertContextMap {
|
||||
registryFixture: TypertContext<string>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ function toolsContribution(schema: z.ZodType = z.object({ name: z.string() })):
|
||||
model: {
|
||||
services: [{
|
||||
key: 'tools',
|
||||
exportName: 'ToolRegistry',
|
||||
exportName: 'ToolRuntime',
|
||||
summary: 'Tool registry and execution pipeline.',
|
||||
tags: [],
|
||||
members: [{
|
||||
@@ -258,7 +258,7 @@ describe('TypertRegistry', () => {
|
||||
it('mounts Remote contributions in the calling fiber and withdraws them exactly', async () => {
|
||||
const ctx = await makeCtx()
|
||||
const descriptor = invocation()
|
||||
const contribution: TypeRTRemoteContribution = {
|
||||
const contribution: TypertRemoteContribution = {
|
||||
package: '@fixture/remote',
|
||||
descriptors: [descriptor],
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
"path": "../../../vendor/cordis"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
},
|
||||
{
|
||||
"path": "../type-meta"
|
||||
"path": "../protocol"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user