v2: add guard methods (#1842)
This commit is contained in:
parent
7ba58dac51
commit
1eb80c4d08
3 changed files with 172 additions and 3 deletions
|
|
@ -104,11 +104,13 @@ export { ProtocolError, UrlElicitationRequiredError } from '../../types/errors.j
|
|||
export {
|
||||
assertCompleteRequestPrompt,
|
||||
assertCompleteRequestResourceTemplate,
|
||||
isCallToolResult,
|
||||
isInitializedNotification,
|
||||
isInitializeRequest,
|
||||
isJSONRPCErrorResponse,
|
||||
isJSONRPCNotification,
|
||||
isJSONRPCRequest,
|
||||
isJSONRPCResponse,
|
||||
isJSONRPCResultResponse,
|
||||
isTaskAugmentedRequestParams,
|
||||
parseJSONRPCMessage
|
||||
|
|
|
|||
123
packages/core/src/types/guards.test.ts
Normal file
123
packages/core/src/types/guards.test.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { JSONRPC_VERSION } from './constants.js';
|
||||
import { isCallToolResult, isJSONRPCErrorResponse, isJSONRPCResponse, isJSONRPCResultResponse } from './guards.js';
|
||||
|
||||
describe('isJSONRPCResponse', () => {
|
||||
it('returns true for a valid result response', () => {
|
||||
expect(
|
||||
isJSONRPCResponse({
|
||||
jsonrpc: JSONRPC_VERSION,
|
||||
id: 1,
|
||||
result: {}
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for a valid error response', () => {
|
||||
expect(
|
||||
isJSONRPCResponse({
|
||||
jsonrpc: JSONRPC_VERSION,
|
||||
id: 1,
|
||||
error: { code: -32_600, message: 'Invalid Request' }
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for a request', () => {
|
||||
expect(
|
||||
isJSONRPCResponse({
|
||||
jsonrpc: JSONRPC_VERSION,
|
||||
id: 1,
|
||||
method: 'test'
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for a notification', () => {
|
||||
expect(
|
||||
isJSONRPCResponse({
|
||||
jsonrpc: JSONRPC_VERSION,
|
||||
method: 'test'
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for arbitrary objects', () => {
|
||||
expect(isJSONRPCResponse({ foo: 'bar' })).toBe(false);
|
||||
});
|
||||
|
||||
it('narrows the type correctly', () => {
|
||||
const value: unknown = {
|
||||
jsonrpc: JSONRPC_VERSION,
|
||||
id: 1,
|
||||
result: { content: [] }
|
||||
};
|
||||
if (isJSONRPCResponse(value)) {
|
||||
// Type should be narrowed to JSONRPCResponse
|
||||
expect(value.jsonrpc).toBe(JSONRPC_VERSION);
|
||||
expect(value.id).toBe(1);
|
||||
}
|
||||
});
|
||||
|
||||
it('agrees with isJSONRPCResultResponse || isJSONRPCErrorResponse', () => {
|
||||
const values = [
|
||||
{ jsonrpc: JSONRPC_VERSION, id: 1, result: {} },
|
||||
{ jsonrpc: JSONRPC_VERSION, id: 2, error: { code: -1, message: 'err' } },
|
||||
{ jsonrpc: JSONRPC_VERSION, id: 3, method: 'test' },
|
||||
{ jsonrpc: JSONRPC_VERSION, method: 'notify' },
|
||||
{ foo: 'bar' },
|
||||
null,
|
||||
42
|
||||
];
|
||||
for (const v of values) {
|
||||
expect(isJSONRPCResponse(v)).toBe(isJSONRPCResultResponse(v) || isJSONRPCErrorResponse(v));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCallToolResult', () => {
|
||||
it('returns false for an empty object (content is required)', () => {
|
||||
expect(isCallToolResult({})).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true for a result with content', () => {
|
||||
expect(
|
||||
isCallToolResult({
|
||||
content: [{ type: 'text', text: 'hello' }]
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for a result with isError', () => {
|
||||
expect(
|
||||
isCallToolResult({
|
||||
content: [{ type: 'text', text: 'fail' }],
|
||||
isError: true
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for a result with structuredContent', () => {
|
||||
expect(
|
||||
isCallToolResult({
|
||||
content: [],
|
||||
structuredContent: { key: 'value' }
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for non-objects', () => {
|
||||
expect(isCallToolResult(null)).toBe(false);
|
||||
expect(isCallToolResult(42)).toBe(false);
|
||||
expect(isCallToolResult('string')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for invalid content items', () => {
|
||||
expect(
|
||||
isCallToolResult({
|
||||
content: [{ type: 'invalid' }]
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
import {
|
||||
CallToolResultSchema,
|
||||
InitializedNotificationSchema,
|
||||
InitializeRequestSchema,
|
||||
JSONRPCErrorResponseSchema,
|
||||
JSONRPCMessageSchema,
|
||||
JSONRPCNotificationSchema,
|
||||
JSONRPCRequestSchema,
|
||||
JSONRPCResponseSchema,
|
||||
JSONRPCResultResponseSchema,
|
||||
TaskAugmentedRequestParamsSchema
|
||||
} from './schemas.js';
|
||||
import type {
|
||||
CallToolResult,
|
||||
CompleteRequest,
|
||||
CompleteRequestPrompt,
|
||||
CompleteRequestResourceTemplate,
|
||||
|
|
@ -18,6 +21,7 @@ import type {
|
|||
JSONRPCMessage,
|
||||
JSONRPCNotification,
|
||||
JSONRPCRequest,
|
||||
JSONRPCResponse,
|
||||
JSONRPCResultResponse,
|
||||
TaskAugmentedRequestParams
|
||||
} from './types.js';
|
||||
|
|
@ -58,6 +62,25 @@ export const isJSONRPCResultResponse = (value: unknown): value is JSONRPCResultR
|
|||
export const isJSONRPCErrorResponse = (value: unknown): value is JSONRPCErrorResponse =>
|
||||
JSONRPCErrorResponseSchema.safeParse(value).success;
|
||||
|
||||
/**
|
||||
* Checks if a value is a valid {@linkcode JSONRPCResponse} (either a result or error response).
|
||||
* @param value - The value to check.
|
||||
*
|
||||
* @returns True if the value is a valid {@linkcode JSONRPCResponse}, false otherwise.
|
||||
*/
|
||||
export const isJSONRPCResponse = (value: unknown): value is JSONRPCResponse => JSONRPCResponseSchema.safeParse(value).success;
|
||||
|
||||
/**
|
||||
* Checks if a value is a valid {@linkcode CallToolResult}.
|
||||
* @param value - The value to check.
|
||||
*
|
||||
* @returns True if the value is a valid {@linkcode CallToolResult}, false otherwise.
|
||||
*/
|
||||
export const isCallToolResult = (value: unknown): value is CallToolResult => {
|
||||
if (typeof value !== 'object' || value === null || !('content' in value)) return false;
|
||||
return CallToolResultSchema.safeParse(value).success;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a value is a valid {@linkcode TaskAugmentedRequestParams}.
|
||||
* @param value - The value to check.
|
||||
|
|
|
|||
Loading…
Reference in a new issue