Skip to content

Commit 355b449

Browse files
committed
fix: infer JSON serialization in static RPC dumps
1 parent 6606ba5 commit 355b449

5 files changed

Lines changed: 40 additions & 17 deletions

File tree

docs/content/6.errors/DF0019.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ defineRpcFunction({
3737

3838
## Source
3939

40-
- [`packages/devframe/src/rpc/collector.ts`](https://github.com/devframes/devframe/blob/main/packages/devframe/src/rpc/collector.ts): `RpcFunctionsCollectorBase.register()` throws `DF0019` when a definition combines `agent` with `jsonSerializable: false`.
40+
- [`packages/devframe/src/rpc/agent-json-serialization.ts`](https://github.com/devframes/devframe/blob/main/packages/devframe/src/rpc/agent-json-serialization.ts): `ensureAgentJsonSerializable()` throws `DF0019` when a definition combines `agent` with `jsonSerializable: false` during registration or static dump collection.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { RpcFunctionDefinitionAny } from './types'
2+
import { diagnostics } from './diagnostics'
3+
4+
/**
5+
* Prevents using a coding-agent-exposed RPC function that is explicitly
6+
* marked as non-serializable, and marks these functions as serializable by
7+
* default.
8+
*
9+
* @internal
10+
*/
11+
export function ensureAgentJsonSerializable(fnDef: RpcFunctionDefinitionAny): void {
12+
if (fnDef.agent && fnDef.jsonSerializable === false)
13+
throw diagnostics.DF0019({ name: fnDef.name })
14+
if (fnDef.agent && !fnDef.jsonSerializable)
15+
fnDef.jsonSerializable = true
16+
}

packages/devframe/src/rpc/collector.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { RpcArgsSchema, RpcFunctionDefinition, RpcFunctionsCollector, RpcReturnSchema } from './types'
2+
import { ensureAgentJsonSerializable } from './agent-json-serialization'
23
import { diagnostics } from './diagnostics'
34
import { getRpcHandler } from './handler'
45

@@ -93,19 +94,3 @@ export class RpcFunctionsCollectorBase<
9394
return Array.from(this.definitions.keys())
9495
}
9596
}
96-
97-
/**
98-
* Prevents registering an agent function that is explicitly marked as
99-
* non-serializable, and ensures that agent functions are marked as
100-
* serializable by default.
101-
*
102-
* @internal
103-
*/
104-
function ensureAgentJsonSerializable(
105-
fnDef: RpcFunctionDefinition<string, any, any, any, any, any, any>,
106-
): void {
107-
if (fnDef.agent && fnDef.jsonSerializable === false)
108-
throw diagnostics.DF0019({ name: fnDef.name })
109-
if (fnDef.agent && !fnDef.jsonSerializable)
110-
fnDef.jsonSerializable = true
111-
}

packages/devframe/src/rpc/dump/__tests__/static.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@ describe('collectStaticRpcDump', () => {
2525
expect(result.files[expectedPath]?.serialization).toBe('json')
2626
})
2727

28+
it('infers JSON serialization for directly collected coding-agent-exposed functions', async () => {
29+
const getVersion = defineRpcFunction({
30+
name: 'test:agent-version',
31+
type: 'static',
32+
agent: { description: 'Return the current version.' },
33+
handler: () => '1.0.0',
34+
})
35+
36+
const result = await collectStaticRpcDump([getVersion], {})
37+
const expectedPath = `${DEVFRAME_RPC_DUMP_DIRNAME}/test~agent-version.static.json`
38+
39+
expect(getVersion.jsonSerializable).toBe(true)
40+
expect(result.manifest['test:agent-version']).toEqual({
41+
type: 'static',
42+
path: expectedPath,
43+
serialization: 'json',
44+
})
45+
expect(result.files[expectedPath]?.serialization).toBe('json')
46+
})
47+
2848
it('collects static rpc output into sharded file entries', async () => {
2949
const getVersion = defineRpcFunction({
3050
name: 'test:get-version',

packages/devframe/src/rpc/dump/static.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { RpcDumpRecord, RpcFunctionDefinitionAny } from '../types'
22
import {
33
DEVFRAME_RPC_DUMP_DIRNAME,
44
} from 'devframe/constants'
5+
import { ensureAgentJsonSerializable } from '../agent-json-serialization'
56
import { getRpcHandler } from '../handler'
67
import { dumpFunctions } from './collect'
78

@@ -131,6 +132,7 @@ export async function collectStaticRpcDump(
131132
const files: Record<string, StaticRpcDumpFile> = {}
132133

133134
for (const definition of definitions) {
135+
ensureAgentJsonSerializable(definition)
134136
const type = definition.type ?? 'query'
135137
const serialization: StaticRpcDumpSerialization
136138
= definition.jsonSerializable === true ? 'json' : 'structured-clone'

0 commit comments

Comments
 (0)