agent-relay 6.0.2 → 6.0.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.
- package/README.md +10 -3
- package/dist/index.cjs +2024 -962
- package/dist/src/cli/commands/cloud.d.ts.map +1 -1
- package/dist/src/cli/commands/cloud.js +17 -144
- package/dist/src/cli/commands/cloud.js.map +1 -1
- package/dist/src/cli/commands/setup.d.ts +2 -39
- package/dist/src/cli/commands/setup.d.ts.map +1 -1
- package/dist/src/cli/commands/setup.js +4 -333
- package/dist/src/cli/commands/setup.js.map +1 -1
- package/dist/src/cli/lib/auth-ssh.d.ts +2 -33
- package/dist/src/cli/lib/auth-ssh.d.ts.map +1 -1
- package/dist/src/cli/lib/auth-ssh.js +3 -39
- package/dist/src/cli/lib/auth-ssh.js.map +1 -1
- package/dist/src/cli/lib/ssh-interactive.d.ts +4 -66
- package/dist/src/cli/lib/ssh-interactive.d.ts.map +1 -1
- package/dist/src/cli/lib/ssh-interactive.js +4 -436
- package/dist/src/cli/lib/ssh-interactive.js.map +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/README.md +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/locales/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/mini/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/package.json +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v3/tests/all-errors.test.ts +3 -3
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v3/tests/object.test.ts +5 -5
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v3/tests/partials.test.ts +3 -3
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/errors.ts +2 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/external.ts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/from-json-schema.ts +39 -23
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/parse.ts +6 -6
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/schemas.ts +389 -148
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/catch.test.ts +4 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/codec.test.ts +142 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/continuability.test.ts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/datetime.test.ts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/default.test.ts +44 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/detached-methods.test.ts +197 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +31 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +214 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +161 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/function.test.ts +6 -6
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/global-config.test.ts +39 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/index.test.ts +2 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/jitless-allows-eval.test.ts +46 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/locales_ka.test.ts +29 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/locales_ro.test.ts +24 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/number.test.ts +55 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/object.test.ts +83 -6
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/optional.test.ts +114 -4
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/partial.test.ts +28 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/prefault.test.ts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/record.test.ts +85 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +49 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/refine.test.ts +63 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/string.test.ts +50 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +4 -4
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +128 -14
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/transform.test.ts +17 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/tuple.test.ts +315 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/union.test.ts +54 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/api.ts +25 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/checks.ts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/core.ts +17 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/errors.ts +31 -24
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/json-schema-processors.ts +15 -17
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/parse.ts +7 -7
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/regexes.ts +8 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/schemas.ts +218 -66
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/tests/locales/el.test.ts +215 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/tests/locales/fr.test.ts +72 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/tests/locales/hr.test.ts +163 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/tests/locales/uz.test.ts +22 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/tests/record-constructor.test.ts +58 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/to-json-schema.ts +9 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/util.ts +52 -35
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/core/versions.ts +2 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/el.ts +121 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/en.ts +4 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/fr.ts +24 -8
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/hr.ts +131 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/index.ts +3 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/it.ts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/ka.ts +8 -8
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/ro.ts +129 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/locales/uz.ts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/mini/external.ts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/mini/schemas.ts +55 -24
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/mini/tests/codec.test.ts +19 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/mini/tests/index.test.ts +27 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/mini/tests/object.test.ts +9 -9
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +51 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/mini/tests/string.test.ts +5 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v3/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/errors.js +2 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/external.d.cts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/external.d.ts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/from-json-schema.cjs +31 -16
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/from-json-schema.js +31 -16
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/schemas.cjs +346 -117
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/schemas.d.cts +34 -12
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/schemas.d.ts +34 -12
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/classic/schemas.js +345 -117
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/api.cjs +7 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/api.d.cts +20 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/api.d.ts +20 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/api.js +7 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/checks.d.cts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/checks.d.ts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/core.cjs +3 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/core.js +4 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/errors.cjs +26 -23
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/errors.d.cts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/errors.d.ts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/errors.js +26 -23
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/json-schema-processors.cjs +14 -19
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/json-schema-processors.js +14 -19
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/parse.cjs +7 -7
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/parse.js +7 -7
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/regexes.cjs +9 -3
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/regexes.d.cts +6 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/regexes.d.ts +6 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/regexes.js +7 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/schemas.cjs +196 -59
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/schemas.d.cts +21 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/schemas.d.ts +21 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/schemas.js +196 -59
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/to-json-schema.cjs +10 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/to-json-schema.js +10 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/util.cjs +54 -30
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/util.d.cts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/util.d.ts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/util.js +55 -32
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/versions.cjs +2 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/versions.d.cts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/versions.d.ts +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/core/versions.js +2 -2
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/el.cjs +136 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/el.d.cts +5 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/el.d.ts +4 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/el.js +109 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/en.cjs +4 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/en.js +4 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/fr.cjs +24 -7
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/fr.js +24 -7
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/hr.cjs +149 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/hr.d.cts +5 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/hr.d.ts +4 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/hr.js +122 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/index.cjs +8 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/index.d.cts +3 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/index.d.ts +3 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/index.js +3 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/it.cjs +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/it.js +1 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/ka.cjs +8 -8
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/ka.js +8 -8
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/ro.cjs +146 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/ro.d.cts +5 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/ro.d.ts +4 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/ro.js +119 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/uz.cjs +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/locales/uz.js +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/mini/external.d.cts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/mini/external.d.ts +1 -0
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/mini/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/mini/schemas.cjs +41 -4
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/mini/schemas.d.cts +27 -9
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/mini/schemas.d.ts +27 -9
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/mini/schemas.js +40 -4
- package/node_modules/@relaycast/sdk/node_modules/zod/v4/package.json +2 -1
- package/node_modules/@relaycast/sdk/node_modules/zod/v4-mini/package.json +2 -1
- package/package.json +10 -10
|
@@ -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<
|
|
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(
|
|
44
|
-
expect(f._zod.optout).toEqual(
|
|
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(
|
|
51
|
-
expect(g._zod.optout).toEqual(
|
|
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,7 +156,33 @@ test("catch/prefault/default", () => {
|
|
|
156
156
|
f: z.string().prefault("prefault value"),
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
expect(mySchema.
|
|
159
|
+
expect(mySchema.safeParse({}).error!.issues).toMatchInlineSnapshot(`
|
|
160
|
+
[
|
|
161
|
+
{
|
|
162
|
+
"code": "invalid_type",
|
|
163
|
+
"expected": "nonoptional",
|
|
164
|
+
"message": "Invalid input: expected nonoptional, received undefined",
|
|
165
|
+
"path": [
|
|
166
|
+
"d",
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
]
|
|
170
|
+
`);
|
|
171
|
+
|
|
172
|
+
expect(mySchema.safeParse({}, { jitless: true }).error!.issues).toMatchInlineSnapshot(`
|
|
173
|
+
[
|
|
174
|
+
{
|
|
175
|
+
"code": "invalid_type",
|
|
176
|
+
"expected": "nonoptional",
|
|
177
|
+
"message": "Invalid input: expected nonoptional, received undefined",
|
|
178
|
+
"path": [
|
|
179
|
+
"d",
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
]
|
|
183
|
+
`);
|
|
184
|
+
|
|
185
|
+
expect(mySchema.parse({ d: undefined })).toMatchInlineSnapshot(`
|
|
160
186
|
{
|
|
161
187
|
"b": "default value",
|
|
162
188
|
"c": "prefault value",
|
|
@@ -166,7 +192,7 @@ test("catch/prefault/default", () => {
|
|
|
166
192
|
}
|
|
167
193
|
`);
|
|
168
194
|
|
|
169
|
-
expect(mySchema.parse({}, { jitless: true })).toMatchInlineSnapshot(`
|
|
195
|
+
expect(mySchema.parse({ d: undefined }, { jitless: true })).toMatchInlineSnapshot(`
|
|
170
196
|
{
|
|
171
197
|
"b": "default value",
|
|
172
198
|
"c": "prefault value",
|
|
@@ -41,7 +41,7 @@ test("object schema with prefault should return shallow clone", () => {
|
|
|
41
41
|
.object({
|
|
42
42
|
a: z.string(),
|
|
43
43
|
})
|
|
44
|
-
.
|
|
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);
|
|
@@ -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
|
+
});
|
package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts
CHANGED
|
@@ -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", () => {
|
|
@@ -217,6 +217,16 @@ test("base64 validations", () => {
|
|
|
217
217
|
"?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?'
|
|
218
218
|
".MTIzND2Nzg5MC4=", // Invalid character '.'
|
|
219
219
|
"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // Missing padding
|
|
220
|
+
// Whitespace is not part of canonical base64 (RFC 4648 §3.3) — atob() strips
|
|
221
|
+
// whitespace internally before validating, so the length check alone would
|
|
222
|
+
// accept "123 " etc.
|
|
223
|
+
"123 ", // bypasses length-mod-4 via trailing whitespace
|
|
224
|
+
"SGVsbG8gV29ybGQ= ", // trailing space
|
|
225
|
+
" SGVsbG8gV29ybGQ=", // leading space
|
|
226
|
+
"SGVsbG8gV29ybGQ=\n", // trailing newline
|
|
227
|
+
"SGVs bG8gV29ybGQ=", // internal space
|
|
228
|
+
"SGVs\nbG8gV29ybGQ=", // internal newline
|
|
229
|
+
"SGVs\tbG8gV29ybGQ=", // internal tab
|
|
220
230
|
];
|
|
221
231
|
|
|
222
232
|
for (const str of invalidBase64Strings) {
|
|
@@ -454,6 +464,12 @@ test("httpurl", () => {
|
|
|
454
464
|
).toThrow();
|
|
455
465
|
expect(() => httpUrl.parse("http://asdf.c")).toThrow();
|
|
456
466
|
expect(() => httpUrl.parse("mailto:asdf@lckj.com")).toThrow();
|
|
467
|
+
// missing // after protocol
|
|
468
|
+
expect(() => httpUrl.parse("http:example.com")).toThrow();
|
|
469
|
+
expect(() => httpUrl.parse("https:example.com")).toThrow();
|
|
470
|
+
// missing one /
|
|
471
|
+
expect(() => httpUrl.parse("https:/www.google.com")).toThrow();
|
|
472
|
+
expect(() => httpUrl.parse("http:/example.com")).toThrow();
|
|
457
473
|
});
|
|
458
474
|
|
|
459
475
|
test("url error overrides", () => {
|
|
@@ -611,12 +627,26 @@ test("cuid", () => {
|
|
|
611
627
|
"origin": "string",
|
|
612
628
|
"code": "invalid_format",
|
|
613
629
|
"format": "cuid",
|
|
614
|
-
"pattern": "/^[cC][
|
|
630
|
+
"pattern": "/^[cC][0-9a-z]{6,}$/",
|
|
615
631
|
"path": [],
|
|
616
632
|
"message": "Invalid cuid"
|
|
617
633
|
}
|
|
618
634
|
]]
|
|
619
635
|
`);
|
|
636
|
+
|
|
637
|
+
// Strings containing non-base36 characters that the old denylist regex
|
|
638
|
+
// (/^[cC][^\s-]{8,}$/) accepted. The new regex restricts the body to
|
|
639
|
+
// [0-9a-z], matching the actual CUID v1 base36 format. See #3621.
|
|
640
|
+
const previouslyAcceptedNonCuids = [
|
|
641
|
+
"cly63t164000245zw008pggon';select1;", // SQLi-shaped (no whitespace, no hyphen)
|
|
642
|
+
"c<script>alert(1)</script>aaaaaa", // XSS-shaped
|
|
643
|
+
"c{};alert(1)//", // bracket / curly chars
|
|
644
|
+
"C0123_45678", // underscore is not base36
|
|
645
|
+
"cAAAAAAAAA", // uppercase letters in body are not base36 (CUIDs are lowercase)
|
|
646
|
+
];
|
|
647
|
+
for (const s of previouslyAcceptedNonCuids) {
|
|
648
|
+
expect(cuid.safeParse(s).success).toBe(false);
|
|
649
|
+
}
|
|
620
650
|
});
|
|
621
651
|
|
|
622
652
|
test("cuid2", () => {
|
|
@@ -811,6 +841,25 @@ test("min max getters", () => {
|
|
|
811
841
|
expect(z.string().maxLength).toEqual(null);
|
|
812
842
|
});
|
|
813
843
|
|
|
844
|
+
test("boundary cases with zero length", () => {
|
|
845
|
+
// Test length(0) - only empty string should pass
|
|
846
|
+
const lengthZero = z.string().length(0);
|
|
847
|
+
expect(lengthZero.parse("")).toEqual("");
|
|
848
|
+
expect(() => lengthZero.parse("a")).toThrow();
|
|
849
|
+
|
|
850
|
+
// Test min(0) - all strings including empty should pass
|
|
851
|
+
const minZero = z.string().min(0);
|
|
852
|
+
expect(minZero.parse("")).toEqual("");
|
|
853
|
+
expect(minZero.parse("a")).toEqual("a");
|
|
854
|
+
expect(minZero.parse("hello")).toEqual("hello");
|
|
855
|
+
|
|
856
|
+
// Test max(0) - only empty string should pass
|
|
857
|
+
const maxZero = z.string().max(0);
|
|
858
|
+
expect(maxZero.parse("")).toEqual("");
|
|
859
|
+
expect(() => maxZero.parse("a")).toThrow();
|
|
860
|
+
expect(() => maxZero.parse("hello")).toThrow();
|
|
861
|
+
});
|
|
862
|
+
|
|
814
863
|
test("trim", () => {
|
|
815
864
|
expect(z.string().trim().min(2).parse(" 12 ")).toEqual("12");
|
|
816
865
|
|
package/node_modules/@relaycast/sdk/node_modules/zod/src/v4/classic/tests/template-literal.test.ts
CHANGED
|
@@ -482,7 +482,7 @@ test("template literal parsing - failure - basic cases", () => {
|
|
|
482
482
|
expect(() => nullishBruh.parse("1null")).toThrow();
|
|
483
483
|
expect(() => nullishBruh.parse("undefined")).toThrow();
|
|
484
484
|
expect(() => cuid.parse("bjld2cyuq0000t3rmniod1foy")).toThrow();
|
|
485
|
-
expect(() => cuid.parse("
|
|
485
|
+
expect(() => cuid.parse("cjld2")).toThrow();
|
|
486
486
|
expect(() => cuid.parse("cjld2 cyu")).toThrow();
|
|
487
487
|
expect(() => cuid.parse("cjld2cyuq0000t3rmniod1foy ")).toThrow();
|
|
488
488
|
expect(() => cuid.parse("1cjld2cyuq0000t3rmniod1foy")).toThrow();
|
|
@@ -555,8 +555,8 @@ test("regexes", () => {
|
|
|
555
555
|
expect(optionalNumber._zod.pattern.source).toMatchInlineSnapshot(`"^(-?\\d+(?:\\.\\d+)?)?$"`);
|
|
556
556
|
expect(nullishBruh._zod.pattern.source).toMatchInlineSnapshot(`"^(((bruh)|null))?$"`);
|
|
557
557
|
expect(nullishString._zod.pattern.source).toMatchInlineSnapshot(`"^(([\\s\\S]{0,}|null))?$"`);
|
|
558
|
-
expect(cuid._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][
|
|
559
|
-
expect(cuidZZZ._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][
|
|
558
|
+
expect(cuid._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][0-9a-z]{6,}$"`);
|
|
559
|
+
expect(cuidZZZ._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][0-9a-z]{6,}ZZZ$"`);
|
|
560
560
|
expect(cuid2._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9a-z]+$"`);
|
|
561
561
|
expect(datetime._zod.pattern.source).toMatchInlineSnapshot(
|
|
562
562
|
`"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"`
|
|
@@ -717,7 +717,7 @@ test("template literal parsing - failure - issue format", () => {
|
|
|
717
717
|
{
|
|
718
718
|
"code": "invalid_format",
|
|
719
719
|
"format": "template_literal",
|
|
720
|
-
"pattern": "^[cC][
|
|
720
|
+
"pattern": "^[cC][0-9a-z]{6,}ZZZ$",
|
|
721
721
|
"path": [],
|
|
722
722
|
"message": "Invalid input"
|
|
723
723
|
}
|