Skip to content

Commit

Permalink
Fix bug where missing key was not recongized if value was union
Browse files Browse the repository at this point in the history
  • Loading branch information
BenLorantfy committed Jun 3, 2024
1 parent 2312c2b commit 9e5e1c9
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 25 deletions.
1 change: 0 additions & 1 deletion .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { StorybookConfig } from "@storybook/react-vite";
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
"@storybook/addon-onboarding",
"@storybook/addon-links",
"@storybook/addon-essentials",
"@chromatic-com/storybook",
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zod-error-viewer",
"version": "1.1.5",
"version": "1.1.6",
"license": "MIT",
"author": {
"name": "Ben Lorantfy",
Expand Down Expand Up @@ -59,7 +59,6 @@
"@storybook/addon-essentials": "^8.1.5",
"@storybook/addon-interactions": "^8.1.5",
"@storybook/addon-links": "^8.1.5",
"@storybook/addon-onboarding": "^8.1.5",
"@storybook/blocks": "^8.1.5",
"@storybook/react": "^8.1.5",
"@storybook/react-vite": "^8.1.5",
Expand Down
11 changes: 0 additions & 11 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/ZodErrorViewer.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const missingKeysData = {
/**
* An example showing how missing keys are displayed
*/
// TODO: add test for missing key that is a union
export const MissingKeys: Story = {
args: {
data: missingKeysData,
Expand All @@ -140,6 +141,7 @@ export const MissingKeys: Story = {
height: z.number(),
age: z.number(),
sideKick: z.literal("Chewbacca"),
hairColor: z.union([z.literal("brown"), z.literal("black")]),
}),
})
.safeParse(missingKeysData).error!,
Expand Down
2 changes: 1 addition & 1 deletion src/ZodErrorViewer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ test("renders correctly for missing keys", () => {
expect(`\n${document.body.innerText}\n`).toMatchInlineSnapshot(`
"
1{
2 "person": { // Error: Object missing required keys: 'height', 'age', 'sideKick'
2 "person": { // Error: Object missing required keys: 'height', 'age', 'sideKick', 'hairColor'
3 "name": "Han Solo"
4 }
5}
Expand Down
36 changes: 26 additions & 10 deletions src/ZodErrorViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { type CSSProperties, useState, useMemo } from "react";
import { z, ZodError, ZodIssueCode } from "zod";
import { z, ZodError, ZodIssue, ZodIssueCode } from "zod";

const defaultTheme = {
lineNumber: "black",
Expand Down Expand Up @@ -258,17 +258,13 @@ function getRelevantIssues(error: ZodError, path: Array<string | number>) {

const missingKeys = [];
for (const issue of error.issues) {
if (
issue.code === ZodIssueCode.invalid_type &&
issue.received === "undefined" &&
issue.message === "Required" &&
issue.path.slice(0, issue.path.length - 1).join(".") === path.join(".")
) {
if (isMissing(issue, path)) {
missingKeys.push(issue.path[issue.path.length - 1]);
} else if (
issue.code === ZodIssueCode.invalid_literal &&
typeof issue.received === "undefined" &&
issue.path.slice(0, issue.path.length - 1).join(".") === path.join(".")
issue.code === ZodIssueCode.invalid_union &&
issue.unionErrors.every((err) =>
err.issues.some((iss) => isMissing(iss, path)),
)
) {
missingKeys.push(issue.path[issue.path.length - 1]);
}
Expand All @@ -288,6 +284,26 @@ function getRelevantIssues(error: ZodError, path: Array<string | number>) {
return relevantIssues;
}

function isMissing(issue: ZodIssue, path: Array<string | number>) {
if (
issue.code === ZodIssueCode.invalid_type &&
issue.received === "undefined" &&
issue.path.slice(0, issue.path.length - 1).join(".") === path.join(".")
) {
return true;
}

if (
issue.code === ZodIssueCode.invalid_literal &&
typeof issue.received === "undefined" &&
issue.path.slice(0, issue.path.length - 1).join(".") === path.join(".")
) {
return true;
}

return false;
}

function Line({
num,
value,
Expand Down

0 comments on commit 9e5e1c9

Please sign in to comment.