Skip to content

Properly type lastSubmission instead of using any #2210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions apps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { conform, list, requestIntent, useFieldList, useForm } from "@conform-to/react";
import { parse } from "@conform-to/zod";
import { EnvelopeIcon, LockOpenIcon, UserPlusIcon } from "@heroicons/react/20/solid";
import type { ActionFunction, LoaderFunctionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";
import { Form, useActionData } from "@remix-run/react";
import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
import { Form } from "@remix-run/react";
import { Fragment, useRef, useState } from "react";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { typedjson, useTypedActionData, useTypedLoaderData } from "remix-typedjson";
import simplur from "simplur";
import invariant from "tiny-invariant";
import { z } from "zod";
Expand All @@ -29,6 +28,7 @@ import { TeamPresenter } from "~/presenters/TeamPresenter.server";
import { scheduleEmail } from "~/services/email.server";
import { requireUserId } from "~/services/session.server";
import { acceptInvitePath, organizationTeamPath, v3BillingPath } from "~/utils/pathBuilder";
import { isSubmissionResult } from "~/utils/conformTo";

const Params = z.object({
organizationSlug: z.string(),
Expand Down Expand Up @@ -76,7 +76,7 @@ const schema = z.object({
}, z.string().email().array().nonempty("At least one email is required")),
});

export const action: ActionFunction = async ({ request, params }) => {
export const action = async ({ request, params }: ActionFunctionArgs) => {
const userId = await requireUserId(request);
const { organizationSlug } = params;
invariant(organizationSlug, "organizationSlug is required");
Expand All @@ -85,7 +85,7 @@ export const action: ActionFunction = async ({ request, params }) => {
const submission = parse(formData, { schema });

if (!submission.value || submission.intent !== "submit") {
return json(submission);
return typedjson(submission);
}

try {
Expand Down Expand Up @@ -117,20 +117,21 @@ export const action: ActionFunction = async ({ request, params }) => {
simplur`${submission.value.emails.length} member[|s] invited`
);
} catch (error: any) {
return json({ errors: { body: error.message } }, { status: 400 });
return typedjson({ errors: { body: error.message } }, { status: 400 });
}
};

export default function Page() {
const { limits } = useTypedLoaderData<typeof loader>();
const [total, setTotal] = useState(limits.used);
const organization = useOrganization();
const lastSubmission = useActionData();

const _lastSubmission = useTypedActionData<typeof action>();
const lastSubmission = isSubmissionResult(_lastSubmission) ? _lastSubmission : undefined;

const [form, { emails }] = useForm({
id: "invite-members",
// TODO: type this
lastSubmission: lastSubmission as any,
lastSubmission,
onValidate({ formData }) {
return parse(formData, { schema });
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { conform, useForm } from "@conform-to/react";
import { parse } from "@conform-to/zod";
import { HashtagIcon, LockClosedIcon } from "@heroicons/react/20/solid";
import { Form, useActionData, useNavigate, useNavigation } from "@remix-run/react";
import { Form, useNavigate, useNavigation } from "@remix-run/react";
import { type LoaderFunctionArgs } from "@remix-run/router";
import { type ActionFunctionArgs, json } from "@remix-run/server-runtime";
import { SlackIcon } from "@trigger.dev/companyicons";
import { useEffect, useState } from "react";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { typedjson, useTypedActionData, useTypedLoaderData } from "remix-typedjson";
import { z } from "zod";
import { InlineCode } from "~/components/code/InlineCode";
import { EnvironmentCombo } from "~/components/environments/EnvironmentLabel";
Expand Down Expand Up @@ -42,6 +42,7 @@ import {
type CreateAlertChannelOptions,
CreateAlertChannelService,
} from "~/v3/services/alerts/createAlertChannel.server";
import { isSubmissionResult } from "~/utils/conformTo";

const FormSchema = z
.object({
Expand Down Expand Up @@ -180,14 +181,14 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
const submission = parse(formData, { schema: FormSchema });

if (!submission.value) {
return json(submission);
return typedjson(submission);
}

const project = await findProjectBySlug(organizationSlug, projectParam, userId);

if (!project) {
submission.error.key = ["Project not found"];
return json(submission);
return typedjson(submission);
}

const service = new CreateAlertChannelService();
Expand All @@ -199,7 +200,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {

if (!alertChannel) {
submission.error.key = ["Failed to create alert channel"];
return json(submission);
return typedjson(submission);
}

return redirectWithSuccessMessage(
Expand All @@ -212,7 +213,8 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
export default function Page() {
const [isOpen, setIsOpen] = useState(false);
const { slack, option, emailAlertsEnabled } = useTypedLoaderData<typeof loader>();
const lastSubmission = useActionData();
const _lastSubmission = useTypedActionData<typeof action>();
const lastSubmission = isSubmissionResult(_lastSubmission) ? _lastSubmission : undefined;
const navigation = useNavigation();
const navigate = useNavigate();
const organization = useOrganization();
Expand All @@ -234,8 +236,7 @@ export default function Page() {
const [form, { channelValue: channelValue, alertTypes, environmentTypes, type, integrationId }] =
useForm({
id: "create-alert",
// TODO: type this
lastSubmission: lastSubmission as any,
lastSubmission,
onValidate({ formData }) {
return parse(formData, { schema: FormSchema });
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import {
PlusIcon,
TrashIcon,
} from "@heroicons/react/20/solid";
import { Form, type MetaFunction, Outlet, useActionData, useNavigation } from "@remix-run/react";
import { type ActionFunctionArgs, type LoaderFunctionArgs, json } from "@remix-run/server-runtime";
import { Form, type MetaFunction, Outlet, useNavigation } from "@remix-run/react";
import { type ActionFunctionArgs, type LoaderFunctionArgs } from "@remix-run/server-runtime";
import { SlackIcon } from "@trigger.dev/companyicons";
import { type ProjectAlertChannelType, type ProjectAlertType } from "@trigger.dev/database";
import assertNever from "assert-never";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { typedjson, useTypedActionData, useTypedLoaderData } from "remix-typedjson";
import { z } from "zod";
import { AlertsNoneDev, AlertsNoneDeployed } from "~/components/BlankStatePanels";
import { EnvironmentCombo } from "~/components/environments/EnvironmentLabel";
Expand Down Expand Up @@ -63,6 +63,7 @@ import {
v3NewProjectAlertPath,
v3ProjectAlertsPath,
} from "~/utils/pathBuilder";
import { isSubmissionResult } from "~/utils/conformTo";

export const meta: MetaFunction = () => {
return [
Expand Down Expand Up @@ -116,14 +117,14 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
const submission = parse(formData, { schema });

if (!submission.value) {
return json(submission);
return typedjson(submission);
}

const project = await findProjectBySlug(organizationSlug, projectParam, userId);

if (!project) {
submission.error.key = ["Project not found"];
return json(submission);
return typedjson(submission);
}

switch (submission.value.action) {
Expand Down Expand Up @@ -355,7 +356,9 @@ export default function Page() {
}

function DeleteAlertChannelButton(props: { id: string }) {
const lastSubmission = useActionData();
const _lastSubmission = useTypedActionData<typeof action>();
const lastSubmission = isSubmissionResult(_lastSubmission) ? _lastSubmission : undefined;

const navigation = useNavigation();

const isLoading =
Expand All @@ -365,8 +368,7 @@ function DeleteAlertChannelButton(props: { id: string }) {

const [form, { id }] = useForm({
id: "delete-alert-channel",
// TODO: type this
lastSubmission: lastSubmission as any,
lastSubmission,
onValidate({ formData }) {
return parse(formData, { schema });
},
Expand Down Expand Up @@ -394,7 +396,9 @@ function DeleteAlertChannelButton(props: { id: string }) {
}

function DisableAlertChannelButton(props: { id: string }) {
const lastSubmission = useActionData();
const _lastSubmission = useTypedActionData<typeof action>();
const lastSubmission = isSubmissionResult(_lastSubmission) ? _lastSubmission : undefined;

const navigation = useNavigation();

const isLoading =
Expand All @@ -404,8 +408,7 @@ function DisableAlertChannelButton(props: { id: string }) {

const [form, { id }] = useForm({
id: "disable-alert-channel",
// TODO: type this
lastSubmission: lastSubmission as any,
lastSubmission: lastSubmission,
onValidate({ formData }) {
return parse(formData, { schema });
},
Expand Down Expand Up @@ -434,7 +437,9 @@ function DisableAlertChannelButton(props: { id: string }) {
}

function EnableAlertChannelButton(props: { id: string }) {
const lastSubmission = useActionData();
const _lastSubmission = useTypedActionData<typeof action>();
const lastSubmission = isSubmissionResult(_lastSubmission) ? _lastSubmission : undefined;

const navigation = useNavigation();

const isLoading =
Expand All @@ -444,8 +449,7 @@ function EnableAlertChannelButton(props: { id: string }) {

const [form, { id }] = useForm({
id: "enable-alert-channel",
// TODO: type this
lastSubmission: lastSubmission as any,
lastSubmission,
onValidate({ formData }) {
return parse(formData, { schema });
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {
} from "@conform-to/react";
import { parse } from "@conform-to/zod";
import { LockClosedIcon, LockOpenIcon, PlusIcon, XMarkIcon } from "@heroicons/react/20/solid";
import { Form, useActionData, useNavigate, useNavigation } from "@remix-run/react";
import { type ActionFunctionArgs, type LoaderFunctionArgs, json } from "@remix-run/server-runtime";
import { Form, useNavigate, useNavigation } from "@remix-run/react";
import { type ActionFunctionArgs, type LoaderFunctionArgs } from "@remix-run/server-runtime";
import dotenv from "dotenv";
import { type RefObject, useCallback, useEffect, useRef, useState } from "react";
import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
import { redirect, typedjson, useTypedActionData, useTypedLoaderData } from "remix-typedjson";
import { z } from "zod";
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
import { Button, LinkButton } from "~/components/primitives/Buttons";
Expand Down Expand Up @@ -52,6 +52,7 @@ import {
import { EnvironmentVariablesRepository } from "~/v3/environmentVariables/environmentVariablesRepository.server";
import { EnvironmentVariableKey } from "~/v3/environmentVariables/repository";
import { Select, SelectItem } from "~/components/primitives/Select";
import { isSubmissionResult } from "~/utils/conformTo";

export const loader = async ({ request, params }: LoaderFunctionArgs) => {
const userId = await requireUserId(request);
Expand Down Expand Up @@ -127,7 +128,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
const submission = parse(formData, { schema });

if (!submission.value) {
return json(submission);
return typedjson(submission);
}

const project = await prisma.project.findUnique({
Expand All @@ -147,7 +148,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
});
if (!project) {
submission.error.key = ["Project not found"];
return json(submission);
return typedjson(submission);
}

const repository = new EnvironmentVariablesRepository(prisma);
Expand All @@ -166,7 +167,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
submission.error.variables = [result.error];
}

return json(submission);
return typedjson(submission);
}

return redirect(
Expand All @@ -181,7 +182,8 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
export default function Page() {
const [isOpen, setIsOpen] = useState(false);
const { environments, hasStaging } = useTypedLoaderData<typeof loader>();
const lastSubmission = useActionData();
const _lastSubmission = useTypedActionData<typeof action>();
const lastSubmission = isSubmissionResult(_lastSubmission) ? _lastSubmission : undefined;
const navigation = useNavigation();
const navigate = useNavigate();
const organization = useOrganization();
Expand All @@ -201,8 +203,7 @@ export default function Page() {

const [form, { environmentIds, variables }] = useForm({
id: "create-environment-variables",
// TODO: type this
lastSubmission: lastSubmission as any,
lastSubmission,
onValidate({ formData }) {
return parse(formData, { schema });
},
Expand Down
Loading