Skip to content

Commit

Permalink
validate there are no duplicate column names in a def (#307)
Browse files Browse the repository at this point in the history
Signed-off-by: Aaron Sutula <asutula@users.noreply.github.com>
Co-authored-by: Aaron Sutula <asutula@users.noreply.github.com>
  • Loading branch information
asutula and asutula authored Aug 12, 2024
1 parent 81018c1 commit 54e2ab1
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 23 deletions.
20 changes: 10 additions & 10 deletions package-lock.json

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

12 changes: 10 additions & 2 deletions packages/validators/src/validators/defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ const columnNameSchema = z
"Column name can't start with a number and can contain any combination of letters, numbers, and underscores.",
);

function columnsNameUnique<T extends { name: string }>(columns: T[]) {
const columnNames = columns.map((column) => column.name);
const uniqueColumnNames = new Set(columnNames);
return columnNames.length === uniqueColumnNames.size;
}

const columnsSchema = z
.array(
z.object({
Expand All @@ -25,7 +31,8 @@ const columnsSchema = z
}),
)
.min(1, "At least one column is required.")
.max(24, "A definition can have at most 24 columns.");
.max(24, "A definition can have at most 24 columns.")
.refine(columnsNameUnique, { message: "Column names must be unique." });

const schemaSchema: z.ZodType<Schema> = z.object({
columns: z
Expand All @@ -37,7 +44,8 @@ const schemaSchema: z.ZodType<Schema> = z.object({
}),
)
.min(1, "At least one column is required.")
.max(24, "A definition can have at most 24 columns."),
.max(24, "A definition can have at most 24 columns.")
.refine(columnsNameUnique, { message: "Column names must be unique." }),
defConstraints: z.array(z.string().trim().min(1)).optional(),
});

Expand Down
2 changes: 1 addition & 1 deletion packages/web/app/_components/new-env-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { type z } from "zod";
import { skipToken } from "@tanstack/react-query";
import { type schema } from "@tableland/studio-store";
import { envNameSchema } from "@tableland/studio-validators";
import { FormRootMessage } from "@/components/form-root";
import { FormRootMessage } from "@/components/form";
import InputWithCheck from "@/components/input-with-check";
import { Button } from "@/components/ui/button";
import {
Expand Down
2 changes: 1 addition & 1 deletion packages/web/app/_components/new-team-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { type z } from "zod";
import { skipToken } from "@tanstack/react-query";
import { type schema } from "@tableland/studio-store";
import { newTeamSchema } from "@tableland/studio-validators";
import { FormRootMessage } from "@/components/form-root";
import { FormRootMessage } from "@/components/form";
import InputWithCheck from "@/components/input-with-check";
import TagInput from "@/components/tag-input";
import { Button } from "@/components/ui/button";
Expand Down
2 changes: 1 addition & 1 deletion packages/web/components/edit-def.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useForm } from "react-hook-form";
import { type z } from "zod";
import { skipToken } from "@tanstack/react-query";
import { updateDefFormSchema } from "@tableland/studio-validators";
import { FormRootMessage } from "@/components/form-root";
import { FormRootMessage } from "@/components/form";
import InputWithCheck from "@/components/input-with-check";
import { Button } from "@/components/ui/button";
import {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from "react";
import { useFormContext } from "react-hook-form";
import { useFormField } from "./ui/form";
import { cn } from "@/lib/utils";

const FormRootMessage = React.forwardRef<
Expand Down Expand Up @@ -27,4 +28,28 @@ const FormRootMessage = React.forwardRef<
});
FormRootMessage.displayName = "FormRootMessage";

export { FormRootMessage };
const FormMessage = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, children, ...props }, ref) => {
const { error, formMessageId } = useFormField();
const body = error?.root?.message ?? error?.message ?? children;

if (!body) {
return null;
}

return (
<p
ref={ref}
id={formMessageId}
className={cn("text-[0.8rem] font-medium text-destructive", className)}
{...props}
>
{body}
</p>
);
});
FormMessage.displayName = "FormMessage";

export { FormRootMessage, FormMessage };
2 changes: 1 addition & 1 deletion packages/web/components/import-table-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import TeamSwitcher from "./team-switcher";
import ProjectSwitcher from "./project-switcher";
import EnvSwitcher from "./env-switcher";
import ChainSelector from "@/components/chain-selector";
import { FormRootMessage } from "@/components/form-root";
import { FormRootMessage } from "@/components/form";
import InputWithCheck from "@/components/input-with-check";
import { Button } from "@/components/ui/button";
import {
Expand Down
3 changes: 1 addition & 2 deletions packages/web/components/new-def-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { type z } from "zod";
import { skipToken } from "@tanstack/react-query";
import { newDefFormSchema } from "@tableland/studio-validators";
import Columns from "./columns";
import { FormRootMessage } from "./form-root";
import { FormRootMessage, FormMessage } from "./form";
import InputWithCheck from "./input-with-check";
import { Button } from "./ui/button";
import DefConstraints from "./def-constraints";
Expand All @@ -30,7 +30,6 @@ import {
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/trpc/react";
Expand Down
2 changes: 1 addition & 1 deletion packages/web/components/new-project-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
} from "@/components/ui/form";
import { Button } from "@/components/ui/button";
import InputWithCheck from "@/components/input-with-check";
import { FormRootMessage } from "@/components/form-root";
import { FormRootMessage } from "@/components/form";
import { cn } from "@/lib/utils";

export interface NewProjectFormProps {
Expand Down
2 changes: 1 addition & 1 deletion packages/web/components/registration-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
DialogTitle,
} from "./ui/dialog";
import { Input } from "./ui/input";
import { FormRootMessage } from "./form-root";
import { FormRootMessage } from "./form";
import {
Form,
FormControl,
Expand Down
4 changes: 2 additions & 2 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"dependencies": {
"@codemirror/lang-sql": "^6.7.0",
"@hookform/resolvers": "^3.3.4",
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
Expand Down Expand Up @@ -63,7 +63,7 @@
"next": "^14.2.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.46.2",
"react-hook-form": "^7.52.2",
"react-share": "^5.1.0",
"siwe": "^2.3.2",
"superjson": "^2.2.1",
Expand Down

1 comment on commit 54e2ab1

@vercel
Copy link

@vercel vercel bot commented on 54e2ab1 Aug 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.