@wecode-ai/weibo-openclaw-plugin 2.2.3 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/node_modules/tar/dist/commonjs/index.min.js +3 -3
  2. package/node_modules/tar/dist/commonjs/index.min.js.map +3 -3
  3. package/node_modules/tar/dist/commonjs/pack.d.ts +3 -1
  4. package/node_modules/tar/dist/commonjs/pack.d.ts.map +1 -1
  5. package/node_modules/tar/dist/commonjs/pack.js +33 -7
  6. package/node_modules/tar/dist/commonjs/pack.js.map +1 -1
  7. package/node_modules/tar/dist/esm/index.min.js +3 -3
  8. package/node_modules/tar/dist/esm/index.min.js.map +3 -3
  9. package/node_modules/tar/dist/esm/pack.d.ts +3 -1
  10. package/node_modules/tar/dist/esm/pack.d.ts.map +1 -1
  11. package/node_modules/tar/dist/esm/pack.js +33 -7
  12. package/node_modules/tar/dist/esm/pack.js.map +1 -1
  13. package/node_modules/tar/package.json +4 -4
  14. package/node_modules/zod/README.md +1 -18
  15. package/node_modules/zod/locales/package.json +2 -1
  16. package/node_modules/zod/mini/package.json +2 -1
  17. package/node_modules/zod/package.json +1 -1
  18. package/node_modules/zod/src/v3/tests/all-errors.test.ts +3 -3
  19. package/node_modules/zod/src/v3/tests/object.test.ts +5 -5
  20. package/node_modules/zod/src/v3/tests/partials.test.ts +3 -3
  21. package/node_modules/zod/src/v4/classic/errors.ts +2 -2
  22. package/node_modules/zod/src/v4/classic/external.ts +1 -0
  23. package/node_modules/zod/src/v4/classic/from-json-schema.ts +39 -23
  24. package/node_modules/zod/src/v4/classic/parse.ts +6 -6
  25. package/node_modules/zod/src/v4/classic/schemas.ts +414 -151
  26. package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +6 -0
  27. package/node_modules/zod/src/v4/classic/tests/catch.test.ts +50 -0
  28. package/node_modules/zod/src/v4/classic/tests/codec.test.ts +142 -1
  29. package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +1 -1
  30. package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +1 -1
  31. package/node_modules/zod/src/v4/classic/tests/default.test.ts +44 -0
  32. package/node_modules/zod/src/v4/classic/tests/detached-methods.test.ts +197 -0
  33. package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +34 -1
  34. package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +214 -2
  35. package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +161 -0
  36. package/node_modules/zod/src/v4/classic/tests/function.test.ts +6 -6
  37. package/node_modules/zod/src/v4/classic/tests/global-config.test.ts +39 -0
  38. package/node_modules/zod/src/v4/classic/tests/index.test.ts +2 -2
  39. package/node_modules/zod/src/v4/classic/tests/jitless-allows-eval.test.ts +46 -0
  40. package/node_modules/zod/src/v4/classic/tests/locales_ka.test.ts +29 -0
  41. package/node_modules/zod/src/v4/classic/tests/locales_ro.test.ts +24 -0
  42. package/node_modules/zod/src/v4/classic/tests/number.test.ts +55 -0
  43. package/node_modules/zod/src/v4/classic/tests/object.test.ts +83 -6
  44. package/node_modules/zod/src/v4/classic/tests/optional.test.ts +114 -4
  45. package/node_modules/zod/src/v4/classic/tests/partial.test.ts +24 -1
  46. package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +1 -1
  47. package/node_modules/zod/src/v4/classic/tests/preprocess-types.test.ts +26 -0
  48. package/node_modules/zod/src/v4/classic/tests/preprocess.test.ts +69 -0
  49. package/node_modules/zod/src/v4/classic/tests/record.test.ts +85 -0
  50. package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +49 -0
  51. package/node_modules/zod/src/v4/classic/tests/refine.test.ts +63 -0
  52. package/node_modules/zod/src/v4/classic/tests/string.test.ts +50 -1
  53. package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +4 -4
  54. package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +150 -15
  55. package/node_modules/zod/src/v4/classic/tests/transform.test.ts +17 -0
  56. package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +315 -2
  57. package/node_modules/zod/src/v4/classic/tests/union.test.ts +54 -0
  58. package/node_modules/zod/src/v4/core/api.ts +31 -6
  59. package/node_modules/zod/src/v4/core/checks.ts +1 -1
  60. package/node_modules/zod/src/v4/core/core.ts +17 -2
  61. package/node_modules/zod/src/v4/core/errors.ts +31 -24
  62. package/node_modules/zod/src/v4/core/json-schema-processors.ts +17 -18
  63. package/node_modules/zod/src/v4/core/parse.ts +7 -7
  64. package/node_modules/zod/src/v4/core/regexes.ts +8 -1
  65. package/node_modules/zod/src/v4/core/schemas.ts +263 -71
  66. package/node_modules/zod/src/v4/core/tests/locales/el.test.ts +215 -0
  67. package/node_modules/zod/src/v4/core/tests/locales/fr.test.ts +72 -0
  68. package/node_modules/zod/src/v4/core/tests/locales/hr.test.ts +163 -0
  69. package/node_modules/zod/src/v4/core/tests/locales/uz.test.ts +22 -0
  70. package/node_modules/zod/src/v4/core/tests/record-constructor.test.ts +58 -0
  71. package/node_modules/zod/src/v4/core/to-json-schema.ts +10 -1
  72. package/node_modules/zod/src/v4/core/util.ts +52 -35
  73. package/node_modules/zod/src/v4/core/versions.ts +2 -2
  74. package/node_modules/zod/src/v4/locales/el.ts +121 -0
  75. package/node_modules/zod/src/v4/locales/en.ts +4 -0
  76. package/node_modules/zod/src/v4/locales/fr.ts +24 -8
  77. package/node_modules/zod/src/v4/locales/hr.ts +131 -0
  78. package/node_modules/zod/src/v4/locales/index.ts +3 -0
  79. package/node_modules/zod/src/v4/locales/it.ts +1 -1
  80. package/node_modules/zod/src/v4/locales/ka.ts +8 -8
  81. package/node_modules/zod/src/v4/locales/ro.ts +129 -0
  82. package/node_modules/zod/src/v4/locales/uz.ts +1 -0
  83. package/node_modules/zod/src/v4/mini/external.ts +1 -0
  84. package/node_modules/zod/src/v4/mini/schemas.ts +56 -25
  85. package/node_modules/zod/src/v4/mini/tests/codec.test.ts +19 -0
  86. package/node_modules/zod/src/v4/mini/tests/index.test.ts +32 -2
  87. package/node_modules/zod/src/v4/mini/tests/object.test.ts +9 -9
  88. package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +51 -1
  89. package/node_modules/zod/src/v4/mini/tests/string.test.ts +5 -0
  90. package/node_modules/zod/v3/package.json +2 -1
  91. package/node_modules/zod/v4/classic/errors.js +2 -2
  92. package/node_modules/zod/v4/classic/external.d.cts +1 -0
  93. package/node_modules/zod/v4/classic/external.d.ts +1 -0
  94. package/node_modules/zod/v4/classic/from-json-schema.cjs +31 -16
  95. package/node_modules/zod/v4/classic/from-json-schema.js +31 -16
  96. package/node_modules/zod/v4/classic/package.json +2 -1
  97. package/node_modules/zod/v4/classic/schemas.cjs +358 -119
  98. package/node_modules/zod/v4/classic/schemas.d.cts +42 -14
  99. package/node_modules/zod/v4/classic/schemas.d.ts +42 -14
  100. package/node_modules/zod/v4/classic/schemas.js +356 -118
  101. package/node_modules/zod/v4/core/api.cjs +7 -2
  102. package/node_modules/zod/v4/core/api.d.cts +26 -5
  103. package/node_modules/zod/v4/core/api.d.ts +26 -5
  104. package/node_modules/zod/v4/core/api.js +7 -2
  105. package/node_modules/zod/v4/core/checks.d.cts +1 -1
  106. package/node_modules/zod/v4/core/checks.d.ts +1 -1
  107. package/node_modules/zod/v4/core/core.cjs +3 -1
  108. package/node_modules/zod/v4/core/core.js +4 -2
  109. package/node_modules/zod/v4/core/errors.cjs +26 -23
  110. package/node_modules/zod/v4/core/errors.d.cts +1 -0
  111. package/node_modules/zod/v4/core/errors.d.ts +1 -0
  112. package/node_modules/zod/v4/core/errors.js +26 -23
  113. package/node_modules/zod/v4/core/json-schema-processors.cjs +16 -20
  114. package/node_modules/zod/v4/core/json-schema-processors.js +16 -20
  115. package/node_modules/zod/v4/core/package.json +2 -1
  116. package/node_modules/zod/v4/core/parse.cjs +7 -7
  117. package/node_modules/zod/v4/core/parse.js +7 -7
  118. package/node_modules/zod/v4/core/regexes.cjs +9 -3
  119. package/node_modules/zod/v4/core/regexes.d.cts +6 -0
  120. package/node_modules/zod/v4/core/regexes.d.ts +6 -0
  121. package/node_modules/zod/v4/core/regexes.js +7 -1
  122. package/node_modules/zod/v4/core/schemas.cjs +211 -65
  123. package/node_modules/zod/v4/core/schemas.d.cts +39 -1
  124. package/node_modules/zod/v4/core/schemas.d.ts +39 -1
  125. package/node_modules/zod/v4/core/schemas.js +210 -64
  126. package/node_modules/zod/v4/core/to-json-schema.cjs +12 -1
  127. package/node_modules/zod/v4/core/to-json-schema.js +12 -1
  128. package/node_modules/zod/v4/core/util.cjs +54 -30
  129. package/node_modules/zod/v4/core/util.d.cts +1 -0
  130. package/node_modules/zod/v4/core/util.d.ts +1 -0
  131. package/node_modules/zod/v4/core/util.js +55 -32
  132. package/node_modules/zod/v4/core/versions.cjs +2 -2
  133. package/node_modules/zod/v4/core/versions.d.cts +1 -1
  134. package/node_modules/zod/v4/core/versions.d.ts +1 -1
  135. package/node_modules/zod/v4/core/versions.js +2 -2
  136. package/node_modules/zod/v4/locales/el.cjs +136 -0
  137. package/node_modules/zod/v4/locales/el.d.cts +5 -0
  138. package/node_modules/zod/v4/locales/el.d.ts +4 -0
  139. package/node_modules/zod/v4/locales/el.js +109 -0
  140. package/node_modules/zod/v4/locales/en.cjs +4 -0
  141. package/node_modules/zod/v4/locales/en.js +4 -0
  142. package/node_modules/zod/v4/locales/fr.cjs +24 -7
  143. package/node_modules/zod/v4/locales/fr.js +24 -7
  144. package/node_modules/zod/v4/locales/hr.cjs +149 -0
  145. package/node_modules/zod/v4/locales/hr.d.cts +5 -0
  146. package/node_modules/zod/v4/locales/hr.d.ts +4 -0
  147. package/node_modules/zod/v4/locales/hr.js +122 -0
  148. package/node_modules/zod/v4/locales/index.cjs +8 -1
  149. package/node_modules/zod/v4/locales/index.d.cts +3 -0
  150. package/node_modules/zod/v4/locales/index.d.ts +3 -0
  151. package/node_modules/zod/v4/locales/index.js +3 -0
  152. package/node_modules/zod/v4/locales/it.cjs +1 -1
  153. package/node_modules/zod/v4/locales/it.js +1 -1
  154. package/node_modules/zod/v4/locales/ka.cjs +8 -8
  155. package/node_modules/zod/v4/locales/ka.js +8 -8
  156. package/node_modules/zod/v4/locales/package.json +2 -1
  157. package/node_modules/zod/v4/locales/ro.cjs +146 -0
  158. package/node_modules/zod/v4/locales/ro.d.cts +5 -0
  159. package/node_modules/zod/v4/locales/ro.d.ts +4 -0
  160. package/node_modules/zod/v4/locales/ro.js +119 -0
  161. package/node_modules/zod/v4/locales/uz.cjs +1 -0
  162. package/node_modules/zod/v4/locales/uz.js +1 -0
  163. package/node_modules/zod/v4/mini/external.d.cts +1 -0
  164. package/node_modules/zod/v4/mini/external.d.ts +1 -0
  165. package/node_modules/zod/v4/mini/package.json +2 -1
  166. package/node_modules/zod/v4/mini/schemas.cjs +41 -4
  167. package/node_modules/zod/v4/mini/schemas.d.cts +28 -10
  168. package/node_modules/zod/v4/mini/schemas.d.ts +28 -10
  169. package/node_modules/zod/v4/mini/schemas.js +40 -4
  170. package/node_modules/zod/v4/package.json +2 -1
  171. package/node_modules/zod/v4-mini/package.json +2 -1
  172. package/package.json +2 -1
  173. package/src/accounts.js +1 -1
  174. package/src/accounts.js.map +1 -1
  175. package/src/channel.js +1 -1
  176. package/src/channel.js.map +1 -1
  177. package/src/outbound.d.ts.map +1 -1
  178. package/src/outbound.js +82 -4
  179. package/src/outbound.js.map +1 -1
  180. package/src/send.d.ts +23 -0
  181. package/src/send.d.ts.map +1 -1
  182. package/src/send.js +54 -2
  183. package/src/send.js.map +1 -1
  184. package/src/token.d.ts +8 -0
  185. package/src/token.d.ts.map +1 -1
  186. package/src/token.js +16 -1
  187. package/src/token.js.map +1 -1
@@ -1,4 +1,4 @@
1
- import { expect, expectTypeOf, test } from "vitest";
1
+ import { describe, expect, expectTypeOf, test } from "vitest";
2
2
  import * as z from "zod/v4";
3
3
  import * as core from "zod/v4/core";
4
4
 
@@ -232,8 +232,7 @@ test("inferred merged object type with optional properties", async () => {
232
232
  .object({ a: z.string(), b: z.string().optional() })
233
233
  .merge(z.object({ a: z.string().optional(), b: z.string() }));
234
234
  type Merged = z.infer<typeof Merged>;
235
- expectTypeOf<Merged>().toEqualTypeOf<{ a?: string; b: string }>();
236
- expectTypeOf<Merged>().toEqualTypeOf<{ a?: string; b: string }>();
235
+ expectTypeOf<Merged>().toEqualTypeOf<{ a?: string | undefined; b: string }>();
237
236
  });
238
237
 
239
238
  test("inferred unioned object type with optional properties", async () => {
@@ -242,7 +241,9 @@ test("inferred unioned object type with optional properties", async () => {
242
241
  z.object({ a: z.string().optional(), b: z.string() }),
243
242
  ]);
244
243
  type Unioned = z.infer<typeof Unioned>;
245
- expectTypeOf<Unioned>().toEqualTypeOf<{ a: string; b?: string } | { a?: string; b: string }>();
244
+ expectTypeOf<Unioned>().toEqualTypeOf<
245
+ { a: string; b?: string | undefined } | { a?: string | undefined; b: string }
246
+ >();
246
247
  });
247
248
 
248
249
  test("inferred enum type", async () => {
@@ -279,13 +280,13 @@ test("z.keyof returns enum", () => {
279
280
  test("inferred partial object type with optional properties", async () => {
280
281
  const Partial = z.object({ a: z.string(), b: z.string().optional() }).partial();
281
282
  type Partial = z.infer<typeof Partial>;
282
- expectTypeOf<Partial>().toEqualTypeOf<{ a?: string; b?: string }>();
283
+ expectTypeOf<Partial>().toEqualTypeOf<{ a?: string | undefined; b?: string | undefined }>();
283
284
  });
284
285
 
285
286
  test("inferred picked object type with optional properties", async () => {
286
287
  const Picked = z.object({ a: z.string(), b: z.string().optional() }).pick({ b: true });
287
288
  type Picked = z.infer<typeof Picked>;
288
- expectTypeOf<Picked>().toEqualTypeOf<{ b?: string }>();
289
+ expectTypeOf<Picked>().toEqualTypeOf<{ b?: string | undefined }>();
289
290
  });
290
291
 
291
292
  test("inferred type for unknown/any keys", () => {
@@ -405,6 +406,36 @@ test("unknownkeys merging", () => {
405
406
  expect(c._zod.def.catchall).toBeInstanceOf(core.$ZodNever);
406
407
  });
407
408
 
409
+ test("merge() throws when receiver has refinements", () => {
410
+ const a = z
411
+ .object({
412
+ password: z.string(),
413
+ confirmPassword: z.string(),
414
+ })
415
+ .refine((data) => data.password === data.confirmPassword);
416
+
417
+ const b = z.object({ email: z.string() });
418
+
419
+ expect(() => a.merge(b)).toThrow(".merge() cannot be used on object schemas containing refinements");
420
+ });
421
+
422
+ test("merge() throws when receiver has superRefine", () => {
423
+ const a = z.object({ x: z.string() }).superRefine(() => {});
424
+ const b = z.object({ y: z.number() });
425
+
426
+ expect(() => a.merge(b)).toThrow(".merge() cannot be used on object schemas containing refinements");
427
+ });
428
+
429
+ test("merge() preserves refinements on the second schema", () => {
430
+ const a = z.object({ name: z.string() });
431
+ const b = z.object({ age: z.number() }).refine((data) => data.age >= 18, { message: "Must be 18+" });
432
+
433
+ const merged = a.merge(b);
434
+
435
+ expect(merged.parse({ name: "n", age: 21 })).toEqual({ name: "n", age: 21 });
436
+ expect(() => merged.parse({ name: "n", age: 12 })).toThrow("Must be 18+");
437
+ });
438
+
408
439
  const personToExtend = z.object({
409
440
  firstName: z.string(),
410
441
  lastName: z.string(),
@@ -638,3 +669,49 @@ test("safeExtend() on object with refinements should not throw", () => {
638
669
 
639
670
  expect(() => schema.safeExtend({ b: z.string() })).not.toThrow();
640
671
  });
672
+
673
+ // __proto__ in input must not replace the prototype of the parsed object via
674
+ // the assignment setter on the result {}.
675
+ // https://github.com/colinhacks/zod/security/advisories/GHSA-r34p-xfmx-58wv
676
+ // https://github.com/colinhacks/zod/security/advisories/GHSA-84jv-fqfx-wxhr
677
+ describe("__proto__ in object catchall paths", () => {
678
+ const protoInput = () => JSON.parse('{"__proto__":{"isAdmin":true},"name":"alice"}');
679
+
680
+ test("looseObject drops __proto__ and preserves Object.prototype", () => {
681
+ const schema = z.looseObject({ name: z.string() });
682
+ const parsed = schema.parse(protoInput());
683
+ expect(Object.keys(parsed)).toEqual(["name"]);
684
+ expect((parsed as any).isAdmin).toBeUndefined();
685
+ expect(Object.getPrototypeOf(parsed)).toBe(Object.prototype);
686
+ });
687
+
688
+ test("passthrough drops __proto__", () => {
689
+ const schema = z.object({ name: z.string() }).passthrough();
690
+ const parsed = schema.parse(protoInput());
691
+ expect((parsed as any).isAdmin).toBeUndefined();
692
+ expect(Object.getPrototypeOf(parsed)).toBe(Object.prototype);
693
+ });
694
+
695
+ test("catchall(unknown) drops __proto__", () => {
696
+ const schema = z.object({ name: z.string() }).catchall(z.unknown());
697
+ const parsed = schema.parse(protoInput());
698
+ expect((parsed as any).isAdmin).toBeUndefined();
699
+ expect(Object.getPrototypeOf(parsed)).toBe(Object.prototype);
700
+ });
701
+
702
+ test("safeParseAsync + jitless drops __proto__", async () => {
703
+ const schema = z.looseObject({ name: z.string() });
704
+ const result = await schema.safeParseAsync(protoInput(), { jitless: true } as any);
705
+ expect(result.success).toBe(true);
706
+ if (result.success) {
707
+ expect((result.data as any).isAdmin).toBeUndefined();
708
+ expect(Object.getPrototypeOf(result.data)).toBe(Object.prototype);
709
+ }
710
+ });
711
+
712
+ test("strict does not surface __proto__ as unrecognized", () => {
713
+ const schema = z.object({ name: z.string() }).strict();
714
+ const result = schema.safeParse(protoInput());
715
+ expect(result.success).toBe(true);
716
+ });
717
+ });
@@ -40,15 +40,15 @@ test("optionality", () => {
40
40
 
41
41
  // z.undefined should NOT be optional
42
42
  const f = z.undefined();
43
- expect(f._zod.optin).toEqual("optional");
44
- expect(f._zod.optout).toEqual("optional");
43
+ expect(f._zod.optin).toEqual(undefined);
44
+ expect(f._zod.optout).toEqual(undefined);
45
45
  expectTypeOf<typeof f._zod.optin>().toEqualTypeOf<"optional" | undefined>();
46
46
  expectTypeOf<typeof f._zod.optout>().toEqualTypeOf<"optional" | undefined>();
47
47
 
48
48
  // z.union should be optional if any of the types are optional
49
49
  const g = z.union([z.string(), z.undefined()]);
50
- expect(g._zod.optin).toEqual("optional");
51
- expect(g._zod.optout).toEqual("optional");
50
+ expect(g._zod.optin).toEqual(undefined);
51
+ expect(g._zod.optout).toEqual(undefined);
52
52
  expectTypeOf<typeof g._zod.optin>().toEqualTypeOf<"optional" | undefined>();
53
53
  expectTypeOf<typeof g._zod.optout>().toEqualTypeOf<"optional" | undefined>();
54
54
 
@@ -135,6 +135,52 @@ test("optional prop with pipe", () => {
135
135
  schema.parse({}, { jitless: true });
136
136
  });
137
137
 
138
+ test("object absent keys require optin optional", () => {
139
+ const valueUndefined = z.object({
140
+ value: z.undefined(),
141
+ union: z.union([z.string(), z.undefined()]),
142
+ });
143
+
144
+ expect(valueUndefined.safeParse({}).error!.issues).toMatchInlineSnapshot(`
145
+ [
146
+ {
147
+ "code": "invalid_type",
148
+ "expected": "nonoptional",
149
+ "message": "Invalid input: expected nonoptional, received undefined",
150
+ "path": [
151
+ "value",
152
+ ],
153
+ },
154
+ {
155
+ "code": "invalid_type",
156
+ "expected": "nonoptional",
157
+ "message": "Invalid input: expected nonoptional, received undefined",
158
+ "path": [
159
+ "union",
160
+ ],
161
+ },
162
+ ]
163
+ `);
164
+ expect(valueUndefined.safeParse({}, { jitless: true }).success).toEqual(false);
165
+ expect(valueUndefined.parse({ value: undefined, union: undefined })).toEqual({
166
+ value: undefined,
167
+ union: undefined,
168
+ });
169
+
170
+ const optionalOutOnly = z.object({
171
+ value: z
172
+ .string()
173
+ .transform((val) => (Math.random() ? val : undefined))
174
+ .pipe(z.string().optional()),
175
+ });
176
+ expect(optionalOutOnly.safeParse({}).success).toEqual(false);
177
+ expect(optionalOutOnly.safeParse({}, { jitless: true }).success).toEqual(false);
178
+
179
+ const defaulted = z.object({ value: z.string().default("fallback") });
180
+ expect(defaulted.parse({})).toEqual({ value: "fallback" });
181
+ expect(defaulted.parse({}, { jitless: true })).toEqual({ value: "fallback" });
182
+ });
183
+
138
184
  // exactOptional tests
139
185
  test(".exactOptional()", () => {
140
186
  const schema = z.string().exactOptional();
@@ -221,3 +267,67 @@ test("exactOptional vs optional comparison", () => {
221
267
  // exactOptional() rejects explicit undefined
222
268
  expect(exactOptionalSchema.safeParse({ a: undefined }).success).toEqual(false);
223
269
  });
270
+
271
+ // Defensive inference coverage: every schema that propagates `optout` participates
272
+ // in object-key optionality inference. If anyone ever changes the set of values that
273
+ // `optout` can take (or how OptionalOutSchema matches them), these assertions must
274
+ // continue to hold or downstream `z.infer<typeof obj>` types silently flip required keys.
275
+ test("object key optionality through optout propagation", () => {
276
+ const direct = z.object({ k: z.string().optional() });
277
+ expectTypeOf<z.infer<typeof direct>>().toEqualTypeOf<{ k?: string | undefined }>();
278
+
279
+ const exact = z.object({ k: z.string().exactOptional() });
280
+ expectTypeOf<z.infer<typeof exact>>().toEqualTypeOf<{ k?: string }>();
281
+
282
+ // nullable() preserves the inner type's optout
283
+ const nullableOpt = z.object({ k: z.string().optional().nullable() });
284
+ expectTypeOf<z.infer<typeof nullableOpt>>().toEqualTypeOf<{ k?: string | null | undefined }>();
285
+
286
+ // optional() wrapping nullable() — still optional out
287
+ const optNullable = z.object({ k: z.string().nullable().optional() });
288
+ expectTypeOf<z.infer<typeof optNullable>>().toEqualTypeOf<{ k?: string | null | undefined }>();
289
+
290
+ // union containing an optional member must mark the key as optional
291
+ const unionWithOpt = z.object({ k: z.union([z.string(), z.string().optional()]) });
292
+ expectTypeOf<z.infer<typeof unionWithOpt>>().toEqualTypeOf<{ k?: string | undefined }>();
293
+
294
+ // pipe ending in optional()
295
+ const pipedToOpt = z.object({
296
+ k: z
297
+ .string()
298
+ .transform((v) => (Math.random() ? v : undefined))
299
+ .pipe(z.string().optional()),
300
+ });
301
+ expectTypeOf<z.output<typeof pipedToOpt>>().toEqualTypeOf<{ k?: string | undefined }>();
302
+
303
+ // mixed shape pinning required vs optional keys end-to-end
304
+ const mixed = z.object({
305
+ req: z.string(),
306
+ opt: z.string().optional(),
307
+ exact: z.string().exactOptional(),
308
+ def: z.string().default("x"),
309
+ nullableOpt: z.string().optional().nullable(),
310
+ });
311
+ expectTypeOf<z.output<typeof mixed>>().toEqualTypeOf<{
312
+ req: string;
313
+ opt?: string | undefined;
314
+ exact?: string;
315
+ def: string;
316
+ nullableOpt?: string | null | undefined;
317
+ }>();
318
+ });
319
+
320
+ // Defensive: tuple optional-tail inference also reads optout. The PR that introduced
321
+ // `"includeUndefined"` had to update TupleOutputTypeWithOptionals; pin the result so
322
+ // any future flag change has to keep this contract.
323
+ test("tuple tail optionality through optout propagation", () => {
324
+ const trailingOptional = z.tuple([z.string(), z.number().optional()]);
325
+ expectTypeOf<z.output<typeof trailingOptional>>().toEqualTypeOf<[string, (number | undefined)?]>();
326
+
327
+ const trailingExact = z.tuple([z.string(), z.number().exactOptional()]);
328
+ expectTypeOf<z.output<typeof trailingExact>>().toEqualTypeOf<[string, number?]>();
329
+
330
+ // Interior optional must NOT make the tail optional
331
+ const interiorOptional = z.tuple([z.string(), z.number().optional(), z.string()]);
332
+ expectTypeOf<z.output<typeof interiorOptional>>().toEqualTypeOf<[string, number | undefined, string]>();
333
+ });
@@ -156,6 +156,10 @@ test("catch/prefault/default", () => {
156
156
  f: z.string().prefault("prefault value"),
157
157
  });
158
158
 
159
+ // Catch (d) and default/prefault (b, c, e, f) handle absent keys gracefully.
160
+ // `a: catch().optional()` short-circuits to undefined when the original
161
+ // input was undefined, so the property is omitted from the output. All
162
+ // other catch/default/prefault keys produce their fallback values.
159
163
  expect(mySchema.parse({})).toMatchInlineSnapshot(`
160
164
  {
161
165
  "b": "default value",
@@ -165,7 +169,6 @@ test("catch/prefault/default", () => {
165
169
  "f": "prefault value",
166
170
  }
167
171
  `);
168
-
169
172
  expect(mySchema.parse({}, { jitless: true })).toMatchInlineSnapshot(`
170
173
  {
171
174
  "b": "default value",
@@ -175,6 +178,26 @@ test("catch/prefault/default", () => {
175
178
  "f": "prefault value",
176
179
  }
177
180
  `);
181
+
182
+ expect(mySchema.parse({ d: undefined })).toMatchInlineSnapshot(`
183
+ {
184
+ "b": "default value",
185
+ "c": "prefault value",
186
+ "d": "catch value",
187
+ "e": "default value",
188
+ "f": "prefault value",
189
+ }
190
+ `);
191
+
192
+ expect(mySchema.parse({ d: undefined }, { jitless: true })).toMatchInlineSnapshot(`
193
+ {
194
+ "b": "default value",
195
+ "c": "prefault value",
196
+ "d": "catch value",
197
+ "e": "default value",
198
+ "f": "prefault value",
199
+ }
200
+ `);
178
201
  });
179
202
 
180
203
  test("handleOptionalObjectResult branches", () => {
@@ -41,7 +41,7 @@ test("object schema with prefault should return shallow clone", () => {
41
41
  .object({
42
42
  a: z.string(),
43
43
  })
44
- .default({ a: "x" });
44
+ .prefault({ a: "x" });
45
45
  const result1 = schema.parse(undefined);
46
46
  const result2 = schema.parse(undefined);
47
47
  expect(result1).not.toBe(result2);
@@ -0,0 +1,26 @@
1
+ import { expectTypeOf, test } from "vitest";
2
+ import * as z from "zod/v4";
3
+
4
+ test("ZodPreprocess<B> assignable to ZodPipe<$ZodTransform, B>", () => {
5
+ const pre = z.preprocess((v) => v, z.string().optional());
6
+ const _asPipe: z.ZodPipe<z.core.$ZodTransform, z.ZodOptional<z.ZodString>> = pre;
7
+ const _asCorePipe: z.core.$ZodPipe<z.core.$ZodTransform, z.ZodOptional<z.ZodString>> = pre;
8
+ expectTypeOf(_asPipe).toMatchTypeOf<z.ZodPipe>();
9
+ expectTypeOf(_asCorePipe).toMatchTypeOf<z.core.$ZodPipe>();
10
+ });
11
+
12
+ test("ZodPreprocess optin/optout defer to B", () => {
13
+ const optionalInside = z.preprocess((v) => v, z.string().optional());
14
+ expectTypeOf<(typeof optionalInside)["_zod"]["optin"]>().toEqualTypeOf<"optional">();
15
+ expectTypeOf<(typeof optionalInside)["_zod"]["optout"]>().toEqualTypeOf<"optional">();
16
+
17
+ const required = z.preprocess((v) => v, z.string());
18
+ expectTypeOf<(typeof required)["_zod"]["optin"]>().toEqualTypeOf<"optional" | undefined>();
19
+ expectTypeOf<(typeof required)["_zod"]["optout"]>().toEqualTypeOf<"optional" | undefined>();
20
+ });
21
+
22
+ test("ZodPreprocess input/output inference", () => {
23
+ const pre = z.preprocess((v) => v, z.number().optional());
24
+ expectTypeOf<z.output<typeof pre>>().toEqualTypeOf<number | undefined>();
25
+ expectTypeOf<z.input<typeof pre>>().toEqualTypeOf<unknown>();
26
+ });
@@ -280,3 +280,72 @@ test("perform transform with non-fatal issues", () => {
280
280
  ]]
281
281
  `);
282
282
  });
283
+
284
+ test("preprocess accepts absent object keys (4.3 parity)", () => {
285
+ const schema = z.object({ a: z.preprocess((v) => v ?? "X", z.string()) });
286
+ expect(schema.parse({})).toEqual({ a: "X" });
287
+ expect(schema.parse({ a: "hi" })).toEqual({ a: "hi" });
288
+ expect(schema.parse({ a: undefined })).toEqual({ a: "X" });
289
+
290
+ // Outer optional clobbers preprocess output on undefined input
291
+ expect(
292
+ z
293
+ .preprocess((v) => v ?? "X", z.string())
294
+ .optional()
295
+ .parse(undefined)
296
+ ).toBeUndefined();
297
+ expect(
298
+ z
299
+ .preprocess((v) => v ?? "X", z.string())
300
+ .optional()
301
+ .parse("hi")
302
+ ).toBe("hi");
303
+ expect(z.object({ a: z.preprocess((v) => v ?? "X", z.string()).optional() }).parse({})).toEqual({});
304
+
305
+ // Top-level direct call unchanged
306
+ expect(z.preprocess((v) => v ?? "X", z.string()).parse(undefined)).toBe("X");
307
+ });
308
+
309
+ // https://github.com/colinhacks/zod/issues/5917
310
+ test("optional propagates through preprocess inside object", () => {
311
+ const outer = z.object({ x: z.preprocess((v) => v, z.number()).optional() });
312
+ const inner = z.object({ x: z.preprocess((v) => v, z.number().optional()) });
313
+
314
+ expect(outer.safeParse({}).success).toBe(true);
315
+ expect(inner.safeParse({}).success).toBe(true);
316
+
317
+ expect(outer.safeParse({ x: 1 })).toEqual({ success: true, data: { x: 1 } });
318
+ expect(inner.safeParse({ x: 1 })).toEqual({ success: true, data: { x: 1 } });
319
+
320
+ expect(inner._zod.def.shape.x._zod.optin).toBe("optional");
321
+ expect(inner._zod.def.shape.x._zod.optout).toBe("optional");
322
+ });
323
+
324
+ test("preprocess is a structural subtype of ZodPipe", () => {
325
+ const schema = z.preprocess((v) => v, z.string());
326
+ expect(schema).toBeInstanceOf(z.ZodPipe);
327
+ expect(schema).toBeInstanceOf(z.ZodPreprocess);
328
+ expect(schema._zod.def.type).toBe("pipe");
329
+ });
330
+
331
+ test("preprocess does not propagate values/propValues from inner schema", () => {
332
+ const inner = z.preprocess((v) => v, z.literal("test"));
333
+ expect(inner._zod.values).toBeUndefined();
334
+ expect(inner._zod.propValues).toBeUndefined();
335
+ });
336
+
337
+ test("preprocess as discriminator throws at construction (no propValues to inherit)", () => {
338
+ const schema = z.discriminatedUnion("kind", [
339
+ z.object({ kind: z.preprocess((v: any) => String(v).toUpperCase(), z.literal("A")), a: z.string() }),
340
+ z.object({ kind: z.preprocess((v: any) => String(v).toUpperCase(), z.literal("B")), b: z.number() }),
341
+ ]);
342
+ expect(() => schema.parse({ kind: "a", a: "x" })).toThrow(/Invalid discriminated union option/);
343
+ });
344
+
345
+ test("preprocess as record key does not restrict accepted keys", () => {
346
+ const schema = z.record(
347
+ z.preprocess((v: any) => String(v).toLowerCase(), z.enum(["a", "b"])),
348
+ z.string()
349
+ );
350
+ expect(schema.safeParse({ A: "x", B: "y" })).toEqual({ success: true, data: { a: "x", b: "y" } });
351
+ });
@@ -272,6 +272,67 @@ test("union exhaustiveness", () => {
272
272
  `);
273
273
  });
274
274
 
275
+ test("applies transforms on the key schema (#5296)", () => {
276
+ const single = z.record(
277
+ z.literal("a").transform(() => "b" as const),
278
+ z.string()
279
+ );
280
+ expect(single.parse({ a: "John" })).toEqual({ b: "John" });
281
+
282
+ const multi = z.record(
283
+ z.literal(["a", "b"]).transform((k) => k.toUpperCase()),
284
+ z.number()
285
+ );
286
+ expect(multi.parse({ a: 1, b: 2 })).toEqual({ A: 1, B: 2 });
287
+
288
+ // required-key semantics still hold when the keyType has a known value set
289
+ expect(multi.safeParse({ a: 1 }).success).toBe(false);
290
+
291
+ const en = z.record(
292
+ z.enum(["a", "b"]).transform((k) => k.toUpperCase()),
293
+ z.number()
294
+ );
295
+ expect(en.parse({ a: 1, b: 2 })).toEqual({ A: 1, B: 2 });
296
+
297
+ // matches partialRecord, which already applied transforms
298
+ const part = z.partialRecord(
299
+ z.literal("a").transform(() => "b" as const),
300
+ z.string()
301
+ );
302
+ expect(part.parse({ a: "John" })).toEqual({ b: "John" });
303
+ });
304
+
305
+ test("surfaces key schema refinement failures as invalid_key", () => {
306
+ // refine rejects "b" but it's still in the literal's value set
307
+ const schema = z.record(
308
+ z.literal(["a", "b"]).refine((k) => k === "a", { message: "only 'a' is allowed" }),
309
+ z.string()
310
+ );
311
+
312
+ expect(schema.safeParse({ a: "ok", b: "nope" })).toMatchInlineSnapshot(`
313
+ {
314
+ "error": [ZodError: [
315
+ {
316
+ "code": "invalid_key",
317
+ "origin": "record",
318
+ "issues": [
319
+ {
320
+ "code": "custom",
321
+ "path": [],
322
+ "message": "only 'a' is allowed"
323
+ }
324
+ ],
325
+ "path": [
326
+ "b"
327
+ ],
328
+ "message": "Invalid key in record"
329
+ }
330
+ ]],
331
+ "success": false,
332
+ }
333
+ `);
334
+ });
335
+
275
336
  test("string record parse - pass", () => {
276
337
  const schema = z.record(z.string(), z.boolean());
277
338
  schema.parse({
@@ -630,3 +691,27 @@ test("numeric string keys", () => {
630
691
  );
631
692
  expect(transformedSchema.parse({ 5: "five", 10: "ten" })).toEqual({ 10: "five", 20: "ten" });
632
693
  });
694
+
695
+ test("v3-compat single-arg form: z.record(valueType)", () => {
696
+ // single arg should default keyType to z.string() and use the arg as valueType
697
+ const schema = (z.record as any)(z.number());
698
+ expect(schema.keyType._zod.def.type).toEqual("string");
699
+ expect(schema.valueType._zod.def.type).toEqual("number");
700
+
701
+ expect(schema.parse({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 });
702
+ expect(schema.safeParse({ a: "x" }).success).toBe(false);
703
+
704
+ // params still flow through in the single-arg form
705
+ const withMessage = (z.record as any)(z.number(), "must be a number record");
706
+ expect(withMessage.keyType._zod.def.type).toEqual("string");
707
+ expect(withMessage.valueType._zod.def.type).toEqual("number");
708
+
709
+ // toJSONSchema should produce a well-formed schema (regression: previously produced
710
+ // additionalProperties from undefined valueType, crashing process())
711
+ const json = z.toJSONSchema(schema);
712
+ expect(json).toMatchObject({
713
+ type: "object",
714
+ propertyNames: { type: "string" },
715
+ additionalProperties: { type: "number" },
716
+ });
717
+ });
@@ -135,6 +135,11 @@ test("pick and omit with getter", () => {
135
135
  }
136
136
  expectTypeOf<Category>().toEqualTypeOf<_Category>();
137
137
 
138
+ // Shape should not surface `readonly` modifiers from getter-defined keys.
139
+ // object/strictObject/looseObject all pass shape through util.Writeable<T>.
140
+ type Shape = (typeof Category)["shape"];
141
+ expectTypeOf<Shape>().toEqualTypeOf<{ name: z.ZodString; subcategories: z.ZodArray<typeof Category> }>();
142
+
138
143
  const PickedCategory = Category.pick({ name: true });
139
144
  const OmittedCategory = Category.omit({ subcategories: true });
140
145
 
@@ -148,6 +153,50 @@ test("pick and omit with getter", () => {
148
153
  expect(() => OmittedCategory.parse({ name: "test", subcategories: [] })).toThrow();
149
154
  });
150
155
 
156
+ test("shape stays writeable through extend/safeExtend/partial/required", () => {
157
+ const Base = z.object({ name: z.string() });
158
+
159
+ const Extended = Base.extend({
160
+ get sub() {
161
+ return z.array(Extended);
162
+ },
163
+ });
164
+ type ExtendedShape = (typeof Extended)["shape"];
165
+ expectTypeOf<ExtendedShape>().toEqualTypeOf<{
166
+ name: z.ZodString;
167
+ sub: z.ZodArray<typeof Extended>;
168
+ }>();
169
+
170
+ const SafeExt = Base.safeExtend({ extra: z.string() } as const);
171
+ type SafeExtShape = (typeof SafeExt)["shape"];
172
+ expectTypeOf<SafeExtShape>().toEqualTypeOf<{
173
+ name: z.ZodString;
174
+ extra: z.ZodString;
175
+ }>();
176
+
177
+ const FromConst = Base.extend({ a: z.string(), b: z.number() } as const);
178
+ type FromConstShape = (typeof FromConst)["shape"];
179
+ expectTypeOf<FromConstShape>().toEqualTypeOf<{
180
+ name: z.ZodString;
181
+ a: z.ZodString;
182
+ b: z.ZodNumber;
183
+ }>();
184
+
185
+ const PartialExtended = Extended.partial();
186
+ type PartialShape = (typeof PartialExtended)["shape"];
187
+ expectTypeOf<PartialShape>().toEqualTypeOf<{
188
+ name: z.ZodOptional<z.ZodString>;
189
+ sub: z.ZodOptional<z.ZodArray<typeof Extended>>;
190
+ }>();
191
+
192
+ const RequiredExtended = Extended.required();
193
+ type RequiredShape = (typeof RequiredExtended)["shape"];
194
+ expectTypeOf<RequiredShape>().toEqualTypeOf<{
195
+ name: z.ZodNonOptional<z.ZodString>;
196
+ sub: z.ZodNonOptional<z.ZodArray<typeof Extended>>;
197
+ }>();
198
+ });
199
+
151
200
  test("deferred self-recursion", () => {
152
201
  const Feature = z.object({
153
202
  title: z.string(),
@@ -414,6 +414,69 @@ describe("chained refinements", () => {
414
414
  };
415
415
  expect(objectSchema.parse(validData)).toEqual(validData);
416
416
  });
417
+
418
+ test("should run superRefine validation even when base schema validation fails when 'when' is defined and returns true", () => {
419
+ const baseSchema = z.object({
420
+ foo: z.number(),
421
+ bar: z.number(),
422
+ });
423
+
424
+ const schema = baseSchema.superRefine(
425
+ (data, ctx) => {
426
+ if (data.foo > 10) {
427
+ ctx.addIssue({
428
+ code: "custom",
429
+ message: "foo must be less than 10",
430
+ });
431
+ }
432
+ },
433
+ {
434
+ when: ({ value }) => baseSchema.pick({ foo: true }).safeParse(value).success,
435
+ }
436
+ );
437
+
438
+ const result = schema.safeParse({
439
+ foo: 11,
440
+ });
441
+ expect(result.success).toEqual(false);
442
+
443
+ if (!result.success) {
444
+ expect(result.error.issues.length).toEqual(2);
445
+ expect(result.error.issues[0].message).toEqual("Invalid input: expected number, received undefined");
446
+ expect(result.error.issues[1].message).toEqual("foo must be less than 10");
447
+ }
448
+ });
449
+
450
+ test("should not run superRefine validation when 'when' is defined and returns false", () => {
451
+ const baseSchema = z.object({
452
+ foo: z.number(),
453
+ bar: z.number(),
454
+ });
455
+
456
+ const schema = baseSchema.superRefine(
457
+ (data, ctx) => {
458
+ if (data.foo > 10) {
459
+ ctx.addIssue({
460
+ code: "custom",
461
+ message: "foo must be less than 10",
462
+ });
463
+ }
464
+ },
465
+ {
466
+ when: ({ value }) => baseSchema.safeParse(value).success,
467
+ }
468
+ );
469
+
470
+ const result = schema.safeParse({
471
+ foo: 11,
472
+ });
473
+ expect(result.success).toEqual(false);
474
+
475
+ if (!result.success) {
476
+ expect(result.error.issues.length).toEqual(1);
477
+ expect(result.error.issues[0].message).toEqual("Invalid input: expected number, received undefined");
478
+ }
479
+ });
417
480
  });
418
481
 
419
482
  describe("type refinement with type guards", () => {