Skip to content

Commit 003dbac

Browse files
committed
chore: add back diagnostic
1 parent c2f2bf5 commit 003dbac

5 files changed

Lines changed: 53 additions & 3 deletions

File tree

docs/content/6.errors/DF0077.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: 'DF0077: In-Page Channel Function Not Registered'
3+
description: 'An in-page channel call names a function that is not registered on its endpoint.'
4+
---
5+
6+
## Message
7+
8+
> In-page channel function "{name}" is not registered on this endpoint.
9+
10+
## Cause
11+
12+
An in-page channel call named a function absent from the receiving endpoint's required `functions` option.
13+
14+
## Example
15+
16+
```ts
17+
await channel.call('missing' as any) // ✗ throws DF0077
18+
```
19+
20+
## Fix
21+
22+
Declare the function in the receiving endpoint's protocol side and `functions` option.
23+
24+
## Source
25+
26+
- [`packages/devframe/src/in-page-channel/internal.ts`](https://github.com/devframes/devframe/blob/main/packages/devframe/src/in-page-channel/internal.ts): `createLocalFunctionRegistry().resolve()` throws this when no local function definition matches the call name.

docs/content/6.errors/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Emitted by `devframe`: the framework-neutral host, RPC, streaming, assets, servi
8383
| [DF0074](/errors/DF0074) | error | JSON-Render Schema Is Asynchronous |
8484
| [DF0075](/errors/DF0075) | warn | No RPC Transport On This Runtime |
8585
| [DF0076](/errors/DF0076) | error | WebSocket Upgrade Unsupported On This Runtime |
86+
| [DF0077](/errors/DF0077) | error | In-Page Channel Function Not Registered |
8687

8788
## Hub: context & lifecycle (DF80xx)
8889

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { defineDiagnostics } from 'devframe/utils/nostics'
2+
3+
export const diagnostics = /* #__PURE__ */ defineDiagnostics({
4+
docsBase: 'https://devfra.me/errors',
5+
codes: {
6+
DF0077: {
7+
why: (p: { name: string }) => `In-page channel function "${p.name}" is not registered on this endpoint.`,
8+
fix: 'Declare the function in this endpoint\'s `functions` option.',
9+
},
10+
},
11+
})

packages/devframe/src/in-page-channel/in-page-channel.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,16 @@ describe('in-page channel over bring-your-own ports', () => {
229229
}
230230
})
231231

232-
it('rejects calls to unknown functions', async () => {
232+
it('rejects calls to unknown functions with a coded diagnostic', async () => {
233+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
233234
const { panel, dispose } = createLinkedPair()
234235
try {
235-
await expect(panel.call('missing' as any)).rejects.toThrow(/not found/)
236+
await expect(panel.call('missing' as any)).rejects.toThrow('In-page channel function "missing" is not registered')
237+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('[DF0077]'))
236238
}
237239
finally {
238240
dispose()
241+
warn.mockRestore()
239242
}
240243
})
241244

packages/devframe/src/in-page-channel/internal.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { RpcArgsSchema } from '../rpc/types'
44
import type { InPageChannelControlFrame } from './protocol'
55
import type { InPageFunctionDefinitionAny } from './types'
66
import { createBirpc } from 'birpc'
7+
import { diagnostics } from './diagnostics'
78
import { isControlFrame } from './protocol'
89

910
/**
@@ -162,6 +163,8 @@ export function channelMethod(kind: 'function' | 'event', name: string): string
162163
return `devframe:in-page:${kind}:${name}`
163164
}
164165

166+
const FUNCTION_METHOD_PREFIX = channelMethod('function', '')
167+
165168
/**
166169
* An endpoint's local function table, resolved by name when the remote side
167170
* calls in. Each handler is wrapped with the receive pipeline: deserialize
@@ -196,8 +199,14 @@ export function createLocalFunctionRegistry(codec: InPageChannelSerialization):
196199
resolve(name) {
197200
const definition = definitions.get(name)
198201
const registered = listeners.get(name)
199-
if (!definition && !registered?.size)
202+
if (!definition && !registered?.size) {
203+
if (name.startsWith(FUNCTION_METHOD_PREFIX)) {
204+
return () => {
205+
throw diagnostics.DF0077({ name: name.slice(FUNCTION_METHOD_PREFIX.length) })
206+
}
207+
}
200208
return undefined
209+
}
201210
return async (...rawArgs: unknown[]) => {
202211
const args = codec.deserialize ? rawArgs.map(codec.deserialize) : rawArgs
203212
if (definition?.jsonSerializable)

0 commit comments

Comments
 (0)