Răsfoiți Sursa

fix(core): handle Zod 4 record, default, and literal types in formatZodType (#239)

Add ZodRecord and ZodDefault cases to formatZodType() in both core and
yaml packages. Fix ZodLiteral to support Zod 4's def.values array
in addition to Zod 3's def.value.

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Matt Van Horn 2 luni în urmă
părinte
comite
a7689129db
2 a modificat fișierele cu 40 adăugiri și 4 ștergeri
  1. 20 2
      packages/core/src/schema.ts
  2. 20 2
      packages/yaml/src/prompt.ts

+ 20 - 2
packages/core/src/schema.ts

@@ -1283,8 +1283,12 @@ function formatZodType(schema: z.ZodType): string {
     case "boolean":
       return "boolean";
     case "ZodLiteral":
-    case "literal":
-      return JSON.stringify(def.value);
+    case "literal": {
+      // Zod 4 uses def.values (array), Zod 3 uses def.value
+      const litValues = def.values as unknown[] | undefined;
+      const litValue = litValues?.[0] ?? def.value;
+      return JSON.stringify(litValue);
+    }
     case "ZodEnum":
     case "enum": {
       // Zod 3 uses values array, Zod 4 uses entries object
@@ -1345,6 +1349,20 @@ function formatZodType(schema: z.ZodType): string {
         ? options.map((opt) => formatZodType(opt)).join(" | ")
         : "unknown";
     }
+    case "ZodRecord":
+    case "record": {
+      const keyType = (def.keyType as z.ZodType) ?? undefined;
+      const valueType =
+        (def.valueType as z.ZodType) ?? (def.element as z.ZodType) ?? undefined;
+      const keyStr = keyType ? formatZodType(keyType) : "string";
+      const valueStr = valueType ? formatZodType(valueType) : "unknown";
+      return `Record<${keyStr}, ${valueStr}>`;
+    }
+    case "ZodDefault":
+    case "default": {
+      const inner = (def.innerType as z.ZodType) ?? (def.wrapped as z.ZodType);
+      return inner ? formatZodType(inner) : "unknown";
+    }
     default:
       return "unknown";
   }

+ 20 - 2
packages/yaml/src/prompt.ts

@@ -56,8 +56,12 @@ function formatZodType(schema: ZodLike): string {
     case "boolean":
       return "boolean";
     case "ZodLiteral":
-    case "literal":
-      return JSON.stringify(def.value);
+    case "literal": {
+      // Zod 4 uses def.values (array), Zod 3 uses def.value
+      const litValues = def.values as unknown[] | undefined;
+      const litValue = litValues?.[0] ?? def.value;
+      return JSON.stringify(litValue);
+    }
     case "ZodEnum":
     case "enum": {
       let values: string[];
@@ -115,6 +119,20 @@ function formatZodType(schema: ZodLike): string {
         ? options.map((opt) => formatZodType(opt)).join(" | ")
         : "unknown";
     }
+    case "ZodRecord":
+    case "record": {
+      const keyType = (def.keyType as ZodLike) ?? undefined;
+      const valueType =
+        (def.valueType as ZodLike) ?? (def.element as ZodLike) ?? undefined;
+      const keyStr = keyType ? formatZodType(keyType) : "string";
+      const valueStr = valueType ? formatZodType(valueType) : "unknown";
+      return `Record<${keyStr}, ${valueStr}>`;
+    }
+    case "ZodDefault":
+    case "default": {
+      const inner = (def.innerType as ZodLike) ?? (def.wrapped as ZodLike);
+      return inner ? formatZodType(inner) : "unknown";
+    }
     default:
       return "unknown";
   }