Skip to content

Commit 2cef25b

Browse files
committed
chore: bring in new tests from recent merge
1 parent 2e02c25 commit 2cef25b

File tree

4 files changed

+65
-70
lines changed

4 files changed

+65
-70
lines changed

src/client/v3/index.v3.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
/* eslint-disable @typescript-eslint/no-unused-expressions */
44
import { Client, getSupportedElicitationModes } from '../index.js';
55
import * as z from 'zod/v3';
6-
import { AnyObjectSchema } from '../../server/zod-compat.js';
76
import {
87
RequestSchema,
98
NotificationSchema,
@@ -912,22 +911,25 @@ test('should apply defaults for form-mode elicitation when applyDefaults is enab
912911
* Test that custom request/notification/result schemas can be used with the Client class.
913912
*/
914913
test('should typecheck', () => {
915-
const GetWeatherRequestSchema = RequestSchema.extend({
914+
const GetWeatherRequestSchema = z.object({
915+
...RequestSchema.shape,
916916
method: z.literal('weather/get'),
917917
params: z.object({
918918
city: z.string()
919919
})
920920
});
921921

922-
const GetForecastRequestSchema = RequestSchema.extend({
922+
const GetForecastRequestSchema = z.object({
923+
...RequestSchema.shape,
923924
method: z.literal('weather/forecast'),
924925
params: z.object({
925926
city: z.string(),
926927
days: z.number()
927928
})
928929
});
929930

930-
const WeatherForecastNotificationSchema = NotificationSchema.extend({
931+
const WeatherForecastNotificationSchema = z.object({
932+
...NotificationSchema.shape,
931933
method: z.literal('weather/alert'),
932934
params: z.object({
933935
severity: z.enum(['warning', 'watch']),
@@ -937,7 +939,9 @@ test('should typecheck', () => {
937939

938940
const WeatherRequestSchema = GetWeatherRequestSchema.or(GetForecastRequestSchema);
939941
const WeatherNotificationSchema = WeatherForecastNotificationSchema;
940-
const WeatherResultSchema = ResultSchema.extend({
942+
const WeatherResultSchema = z.object({
943+
...ResultSchema.shape,
944+
_meta: z.record(z.string(), z.unknown()).optional(),
941945
temperature: z.number(),
942946
conditions: z.string()
943947
});

src/server/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ export class Server<
354354
params: LegacyElicitRequestFormParams | ElicitRequestFormParams | ElicitRequestURLParams,
355355
options?: RequestOptions
356356
): Promise<ElicitResult> {
357-
const mode = 'mode' in params ? params.mode : 'form';
357+
const mode = ('mode' in params ? params.mode : 'form') as 'form' | 'url';
358358

359359
switch (mode) {
360360
case 'url': {
@@ -370,7 +370,9 @@ export class Server<
370370
throw new Error('Client does not support form elicitation.');
371371
}
372372
const formParams: ElicitRequestFormParams =
373-
'mode' in params ? (params as ElicitRequestFormParams) : { ...(params as LegacyElicitRequestFormParams), mode: 'form' };
373+
'mode' in params
374+
? (params as ElicitRequestFormParams)
375+
: ({ ...(params as LegacyElicitRequestFormParams), mode: 'form' } as ElicitRequestFormParams);
374376

375377
const result = await this.request({ method: 'elicitation/create', params: formParams }, ElicitResultSchema, options);
376378

src/server/zod-json-schema-compat.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type * as z4c from 'zod/v4/core';
99

1010
import * as z4mini from 'zod/v4-mini';
1111

12-
import { AnyObjectSchema, isZ4Schema } from './zod-compat.js';
12+
import { AnySchema, AnyObjectSchema, getObjectShape, safeParse, isZ4Schema, type ZodV3Internal, type ZodV4Internal } from './zod-compat.js';
1313
import { zodToJsonSchema } from 'zod-to-json-schema';
1414

1515
type JsonSchema = Record<string, unknown>;
@@ -43,3 +43,52 @@ export function toJsonSchemaCompat(schema: AnyObjectSchema, opts?: CommonOpts):
4343
pipeStrategy: opts?.pipeStrategy ?? 'input'
4444
}) as JsonSchema;
4545
}
46+
47+
export function getMethodLiteral(schema: AnyObjectSchema): string {
48+
const shape = getObjectShape(schema);
49+
const methodSchema = shape?.method as AnySchema | undefined;
50+
if (!methodSchema) {
51+
throw new Error('Schema is missing a method literal');
52+
}
53+
54+
const value = getLiteralValue(methodSchema);
55+
if (typeof value !== 'string') {
56+
throw new Error('Schema method literal must be a string');
57+
}
58+
59+
return value;
60+
}
61+
62+
export function getLiteralValue(schema: AnySchema): unknown {
63+
if (isZ4Schema(schema)) {
64+
const v4Schema = schema as unknown as ZodV4Internal;
65+
const v4Def = v4Schema._zod?.def;
66+
const candidates = [v4Def?.value, Array.isArray(v4Def?.values) ? v4Def.values[0] : undefined, v4Schema.value];
67+
68+
for (const candidate of candidates) {
69+
if (typeof candidate !== 'undefined') {
70+
return candidate;
71+
}
72+
}
73+
} else {
74+
const v3Schema = schema as unknown as ZodV3Internal;
75+
const legacyDef = v3Schema._def;
76+
const candidates = [legacyDef?.value, Array.isArray(legacyDef?.values) ? legacyDef.values[0] : undefined, v3Schema.value];
77+
78+
for (const candidate of candidates) {
79+
if (typeof candidate !== 'undefined') {
80+
return candidate;
81+
}
82+
}
83+
}
84+
85+
return undefined;
86+
}
87+
88+
export function parseWithCompat(schema: AnySchema, data: unknown): unknown {
89+
const result = safeParse(schema, data);
90+
if (!result.success) {
91+
throw result.error;
92+
}
93+
return result.data;
94+
}

src/shared/protocol.ts

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
import {
2-
AnySchema,
3-
AnyObjectSchema,
4-
SchemaOutput,
5-
getObjectShape,
6-
safeParse,
7-
isZ4Schema,
8-
type ZodV3Internal,
9-
type ZodV4Internal
10-
} from '../server/zod-compat.js';
1+
import { AnySchema, AnyObjectSchema, SchemaOutput, safeParse } from '../server/zod-compat.js';
112
import {
123
CancelledNotificationSchema,
134
ClientCapabilities,
@@ -36,6 +27,7 @@ import {
3627
} from '../types.js';
3728
import { Transport, TransportSendOptions } from './transport.js';
3829
import { AuthInfo } from '../server/auth/types.js';
30+
import { getMethodLiteral, parseWithCompat } from '../server/zod-json-schema-compat.js';
3931

4032
/**
4133
* Callback for progress notifications.
@@ -730,55 +722,3 @@ export function mergeCapabilities<T extends ServerCapabilities | ClientCapabilit
730722
}
731723
return result;
732724
}
733-
734-
// Helper functions for Zod v3/v4 compatibility
735-
736-
function getMethodLiteral(schema: AnyObjectSchema): string {
737-
const shape = getObjectShape(schema);
738-
const methodSchema = shape?.method as AnySchema | undefined;
739-
if (!methodSchema) {
740-
throw new Error('Schema is missing a method literal');
741-
}
742-
743-
const value = getLiteralValue(methodSchema);
744-
if (typeof value !== 'string') {
745-
throw new Error('Schema method literal must be a string');
746-
}
747-
748-
return value;
749-
}
750-
751-
function getLiteralValue(schema: AnySchema): unknown {
752-
if (isZ4Schema(schema)) {
753-
const v4Schema = schema as unknown as ZodV4Internal;
754-
const v4Def = v4Schema._zod?.def;
755-
const candidates = [v4Def?.value, Array.isArray(v4Def?.values) ? v4Def.values[0] : undefined, v4Schema.value];
756-
757-
for (const candidate of candidates) {
758-
if (typeof candidate !== 'undefined') {
759-
return candidate;
760-
}
761-
}
762-
} else {
763-
const v3Schema = schema as unknown as ZodV3Internal;
764-
const legacyDef = v3Schema._def;
765-
const candidates = [legacyDef?.value, Array.isArray(legacyDef?.values) ? legacyDef.values[0] : undefined, v3Schema.value];
766-
767-
for (const candidate of candidates) {
768-
if (typeof candidate !== 'undefined') {
769-
return candidate;
770-
}
771-
}
772-
}
773-
774-
return undefined;
775-
}
776-
777-
function parseWithCompat(schema: AnySchema, data: unknown): unknown {
778-
const result = safeParse(schema, data);
779-
if (!result.success) {
780-
// Type guard: if success is false, error is guaranteed to exist
781-
throw result.error;
782-
}
783-
return result.data;
784-
}

0 commit comments

Comments
 (0)