Skip to content

Commit 9be0675

Browse files
spalladinomralj
authored andcommitted
fix: Parse boolean env var with zod
See the note on boolean coercion [here](https://v3.zod.dev/?id=coercion-for-primitives)
1 parent 4b9f6e1 commit 9be0675

File tree

3 files changed

+67
-2
lines changed

3 files changed

+67
-2
lines changed

yarn-project/end-to-end/src/spartan/utils.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createLogger, sleep } from '@aztec/aztec.js';
22
import type { RollupCheatCodes } from '@aztec/aztec/testing';
33
import type { Logger } from '@aztec/foundation/log';
44
import { makeBackoff, retry } from '@aztec/foundation/retry';
5+
import { schemas } from '@aztec/foundation/schemas';
56
import { type AztecNodeAdminConfig, createAztecNodeAdminClient } from '@aztec/stdlib/interfaces/client';
67

78
import { ChildProcess, exec, execSync, spawn } from 'child_process';
@@ -15,13 +16,15 @@ const logger = createLogger('e2e:k8s-utils');
1516

1617
const testConfigSchema = z.object({
1718
NAMESPACE: z.string().default('scenario'),
18-
REAL_VERIFIER: z.coerce.boolean().default(true),
19+
REAL_VERIFIER: schemas.Boolean.optional().default(true),
1920
});
2021

2122
export type TestConfig = z.infer<typeof testConfigSchema>;
2223

2324
export function setupEnvironment(env: unknown): TestConfig {
24-
return testConfigSchema.parse(env);
25+
const config = testConfigSchema.parse(env);
26+
logger.warn(`Loaded env config`, config);
27+
return config;
2528
}
2629

2730
/**
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { schemas } from './schemas.js';
2+
3+
describe('schemas', () => {
4+
describe('Boolean', () => {
5+
it('accepts a boolean value', () => {
6+
expect(schemas.Boolean.parse(true)).toEqual(true);
7+
expect(schemas.Boolean.parse(false)).toEqual(false);
8+
});
9+
10+
it('accepts a numeric value', () => {
11+
expect(schemas.Boolean.parse(1)).toEqual(true);
12+
expect(schemas.Boolean.parse(0)).toEqual(false);
13+
});
14+
15+
it('rejects a non binary numeric value', () => {
16+
expect(schemas.Boolean.safeParse(2).success).toEqual(false);
17+
});
18+
19+
it('accepts string values', () => {
20+
expect(schemas.Boolean.parse('true')).toEqual(true);
21+
expect(schemas.Boolean.parse('false')).toEqual(false);
22+
expect(schemas.Boolean.parse('TRUE')).toEqual(true);
23+
expect(schemas.Boolean.parse('FALSE')).toEqual(false);
24+
expect(schemas.Boolean.parse('True')).toEqual(true);
25+
expect(schemas.Boolean.parse('False')).toEqual(false);
26+
expect(schemas.Boolean.parse(' true ')).toEqual(true);
27+
expect(schemas.Boolean.parse(' false ')).toEqual(false);
28+
});
29+
30+
it('accepts numeric values as string', () => {
31+
expect(schemas.Boolean.parse('1')).toEqual(true);
32+
expect(schemas.Boolean.parse('0')).toEqual(false);
33+
});
34+
35+
it('rejects other string values', () => {
36+
expect(schemas.Boolean.safeParse('falso').success).toEqual(false);
37+
});
38+
39+
it('rejects empty strings', () => {
40+
expect(schemas.Boolean.safeParse('').success).toEqual(false);
41+
});
42+
43+
it('handles defaults', () => {
44+
expect(schemas.Boolean.optional().default(true).parse(undefined)).toEqual(true);
45+
expect(schemas.Boolean.optional().default(false).parse(undefined)).toEqual(false);
46+
});
47+
});
48+
});

yarn-project/foundation/src/schemas/schemas.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ export const schemas = {
2121
/** Point. Serialized as a hex string. */
2222
Point: Point.schema,
2323

24+
/** Coerces truthy-like string values to boolean. */
25+
Boolean: z.union([
26+
z.boolean(),
27+
z
28+
.number()
29+
.refine(arg => arg === 0 || arg === 1, { message: `Numeric value for a boolean variable must be 0 or 1` })
30+
.transform(arg => arg === 1),
31+
z
32+
.string()
33+
.transform(arg => arg.trim().toLowerCase())
34+
.refine(arg => ['true', 'false', '1', '0'].includes(arg))
35+
.transform(arg => arg === '1' || arg === 'true'),
36+
]),
37+
2438
/** Coerces any input to bigint. */
2539
BigInt: z.union([z.bigint(), z.number(), z.string()]).pipe(z.coerce.bigint()),
2640

0 commit comments

Comments
 (0)