From 301bcb75dd8c15b8ea1a9d0ca8c75c15d7cd92bd Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 19 Sep 2023 11:35:22 +0100 Subject: [PATCH] fix(faucet,store-indexer): fix invalid env message (#1546) --- .changeset/mean-islands-brake.md | 6 +++++ packages/faucet/bin/faucet-server.ts | 21 +++-------------- packages/faucet/bin/parseEnv.ts | 29 ++++++++++++++++++++++++ packages/store-indexer/bin/parseEnv.ts | 31 ++++++++++++++++---------- 4 files changed, 57 insertions(+), 30 deletions(-) create mode 100644 .changeset/mean-islands-brake.md create mode 100644 packages/faucet/bin/parseEnv.ts diff --git a/.changeset/mean-islands-brake.md b/.changeset/mean-islands-brake.md new file mode 100644 index 0000000000..10d43a1386 --- /dev/null +++ b/.changeset/mean-islands-brake.md @@ -0,0 +1,6 @@ +--- +"@latticexyz/faucet": patch +"@latticexyz/store-indexer": patch +--- + +Improves error message when parsing env variables diff --git a/packages/faucet/bin/faucet-server.ts b/packages/faucet/bin/faucet-server.ts index f3edcabe0a..625eb72232 100644 --- a/packages/faucet/bin/faucet-server.ts +++ b/packages/faucet/bin/faucet-server.ts @@ -1,28 +1,13 @@ #!/usr/bin/env node import "dotenv/config"; -import { z } from "zod"; import fastify from "fastify"; import { fastifyTRPCPlugin } from "@trpc/server/adapters/fastify"; -import { http, parseEther, isHex, createClient } from "viem"; +import { http, createClient } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { AppRouter, createAppRouter } from "../src/createAppRouter"; +import { parseEnv } from "./parseEnv"; -const env = z - .object({ - HOST: z.string().default("0.0.0.0"), - PORT: z.coerce.number().positive().default(3002), - RPC_HTTP_URL: z.string(), - FAUCET_PRIVATE_KEY: z.string().refine(isHex), - DRIP_AMOUNT_ETHER: z - .string() - .default("1") - .transform((ether) => parseEther(ether)), - }) - .parse(process.env, { - errorMap: (issue) => ({ - message: `Missing or invalid environment variable: ${issue.path.join(".")}`, - }), - }); +const env = parseEnv(); const client = createClient({ transport: http(env.RPC_HTTP_URL), diff --git a/packages/faucet/bin/parseEnv.ts b/packages/faucet/bin/parseEnv.ts new file mode 100644 index 0000000000..dd739618c9 --- /dev/null +++ b/packages/faucet/bin/parseEnv.ts @@ -0,0 +1,29 @@ +import { isHex, parseEther } from "viem"; +import { z, ZodError, ZodIntersection, ZodTypeAny } from "zod"; + +const commonSchema = z.object({ + HOST: z.string().default("0.0.0.0"), + PORT: z.coerce.number().positive().default(3002), + RPC_HTTP_URL: z.string(), + FAUCET_PRIVATE_KEY: z.string().refine(isHex), + DRIP_AMOUNT_ETHER: z + .string() + .default("1") + .transform((ether) => parseEther(ether)), +}); + +export function parseEnv( + schema?: TSchema +): z.infer : typeof commonSchema> { + const envSchema = schema !== undefined ? z.intersection(commonSchema, schema) : commonSchema; + try { + return envSchema.parse(process.env); + } catch (error) { + if (error instanceof ZodError) { + const { _errors, ...invalidEnvVars } = error.format(); + console.error(`\nMissing or invalid environment variables:\n\n ${Object.keys(invalidEnvVars).join("\n ")}\n`); + process.exit(1); + } + throw error; + } +} diff --git a/packages/store-indexer/bin/parseEnv.ts b/packages/store-indexer/bin/parseEnv.ts index b4c3803b23..7e223c1a03 100644 --- a/packages/store-indexer/bin/parseEnv.ts +++ b/packages/store-indexer/bin/parseEnv.ts @@ -1,5 +1,4 @@ -import { isDefined } from "@latticexyz/common/utils"; -import { z, ZodIntersection, ZodTypeAny } from "zod"; +import { z, ZodError, ZodIntersection, ZodTypeAny } from "zod"; const commonSchema = z.intersection( z.object({ @@ -9,22 +8,30 @@ const commonSchema = z.intersection( MAX_BLOCK_RANGE: z.coerce.bigint().positive().default(1000n), POLLING_INTERVAL: z.coerce.number().positive().default(1000), }), - z - .object({ + z.union([ + z.object({ RPC_HTTP_URL: z.string(), + RPC_WS_URL: z.string().optional(), + }), + z.object({ + RPC_HTTP_URL: z.string().optional(), RPC_WS_URL: z.string(), - }) - .partial() - .refine((values) => Object.values(values).some(isDefined)) + }), + ]) ); export function parseEnv( schema?: TSchema ): z.infer : typeof commonSchema> { const envSchema = schema !== undefined ? z.intersection(commonSchema, schema) : commonSchema; - return envSchema.parse(process.env, { - errorMap: (issue) => ({ - message: `Missing or invalid environment variable: ${issue.path.join(".")}`, - }), - }); + try { + return envSchema.parse(process.env); + } catch (error) { + if (error instanceof ZodError) { + const { _errors, ...invalidEnvVars } = error.format(); + console.error(`\nMissing or invalid environment variables:\n\n ${Object.keys(invalidEnvVars).join("\n ")}\n`); + process.exit(1); + } + throw error; + } }