Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 67b5365d50 | |||
| ea25c37a10 | |||
| c1710ae72d | |||
| 9c5a7cf073 | |||
| 8eedf994af | |||
| 2c91c492df | |||
| b859abdb66 | |||
| 0876b87526 | |||
| 9c4be40adc | |||
| 2635f4bd10 | |||
| 401b7ee03d | |||
| 6881de84ab | |||
| 0ca8296b9a | |||
| 55946fcdb7 | |||
| c0f9f10b07 | |||
| e80aa2826d | |||
| 1be25d7639 | |||
| 3c3a5e1f28 | |||
| 8e741c7218 | |||
| 83455e3ad4 | |||
| f0f0420280 | |||
| c4533c36cb | |||
| f8e034c190 | |||
| 21f62e780c | |||
| c3564ca0d4 | |||
| 6e1b8a11d4 | |||
| 9900f19b70 | |||
| 237545754f | |||
| d7c1e98e5e | |||
| 71a0afeb8d | |||
| 36a390449a | |||
| 375e495423 | |||
| 866c20cd39 |
@@ -0,0 +1,43 @@
|
||||
# Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct that could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project email address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the Contributor Covenant, version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
|
||||
@@ -20,7 +20,7 @@ All of October we're participating in Hacktoberfest and invite you to join us! W
|
||||
|
||||
- Check out our [Hacktoberfest landing page](https://trigger.dev/hacktoberfest) for how to participate and win swag.
|
||||
- Contribute to either our [/trigger.dev](https://github.com/triggerdotdev/trigger.dev/labels/%F0%9F%8E%83%20hacktoberfest), [/api-reference](https://github.com/triggerdotdev/api-reference/issues?q=is%3Aopen+is%3Aissue+label%3A%F0%9F%8E%83hacktoberfest) or [/jobs-showcase](https://github.com/triggerdotdev/jobs-showcase/labels/%F0%9F%8E%83%20hacktoberfest) repositories and complete issues marked `🎃 Hacktoberfest` to be eligible for swag.
|
||||
- Join our [Discord](https://discord.gg/JtBAxBr2m3) and get involved in with the community.
|
||||
- Join our [Discord](https://discord.gg/JtBAxBr2m3) and get involved with the community.
|
||||
|
||||
_New to Hacktober? Check out the [Hacktoberfest website](https://hacktoberfest.digitalocean.com/) for more information._
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Preview } from "@storybook/react";
|
||||
import "../app/tailwind.css";
|
||||
import { unstable_createRemixStub } from "@remix-run/testing";
|
||||
import { createRemixStub } from "@remix-run/testing";
|
||||
import React from "react";
|
||||
import { LocaleContextProvider } from "../app/components/primitives/LocaleProvider";
|
||||
import { OperatingSystemContextProvider } from "../app/components/primitives/OperatingSystemProvider";
|
||||
@@ -26,10 +26,10 @@ const preview: Preview = {
|
||||
},
|
||||
decorators: [
|
||||
(Story) => {
|
||||
const RemixStub = unstable_createRemixStub([
|
||||
const RemixStub = createRemixStub([
|
||||
{
|
||||
path: "/*",
|
||||
element: <Story />,
|
||||
Component: Story,
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ export function Feedback({ button, defaultValue = "bug" }: FeedbackProps) {
|
||||
|
||||
const [form, { path, feedbackType, message }] = useForm({
|
||||
id: "accept-invite",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import { Button } from "../primitives/Buttons";
|
||||
import { Dialog, DialogContent, DialogTrigger } from "~/components/primitives/Dialog";
|
||||
import { Header1, Header2 } from "../primitives/Headers";
|
||||
import { Input } from "../primitives/Input";
|
||||
import { NamedIcon } from "../primitives/NamedIcon";
|
||||
import { Paragraph } from "../primitives/Paragraph";
|
||||
import { Spinner } from "../primitives/Spinner";
|
||||
import { useState } from "react";
|
||||
import { useFetcher } from "@remix-run/react";
|
||||
import { generateTwoRandomWords } from "~/utils/randomWords";
|
||||
|
||||
type ModalProps = {
|
||||
id: string;
|
||||
title: string;
|
||||
};
|
||||
|
||||
type ModalContentProps = ModalProps & {
|
||||
randomWord: string;
|
||||
closeModal: () => void;
|
||||
};
|
||||
|
||||
export function RegenerateApiKeyModal({ id, title }: ModalProps) {
|
||||
const randomWord = generateTwoRandomWords();
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="tertiary/small" leadingIconClassName="text-dimmed" LeadingIcon="key">
|
||||
Regenerate
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<RegenerateApiKeyModalContent
|
||||
id={id}
|
||||
title={title}
|
||||
randomWord={randomWord}
|
||||
closeModal={() => setOpen(false)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
const RegenerateApiKeyModalContent = ({ id, title, randomWord, closeModal }: ModalContentProps) => {
|
||||
const [confirmationText, setConfirmationText] = useState("");
|
||||
const fetcher = useFetcher();
|
||||
const isSubmitting = fetcher.state === "submitting";
|
||||
|
||||
// form submission completed
|
||||
if (fetcher.state === "loading") {
|
||||
closeModal();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-col items-center gap-y-6">
|
||||
<div className="flex justify-center">
|
||||
<Header1>{title} Environment</Header1>
|
||||
</div>
|
||||
<Header2 className="rounded border border-rose-500 bg-rose-500/10 px-3.5 py-2 text-center text-bright">
|
||||
Are you sure you want to regenerate the keys <br />
|
||||
for this environment?
|
||||
</Header2>
|
||||
<Paragraph variant="small" className="px-6 text-center">
|
||||
<>
|
||||
This will temporarily break any live jobs in the
|
||||
<span className="strong text-bright"> {title} Environment</span> until the new API keys
|
||||
are set in the relevant environment variables.
|
||||
</>
|
||||
</Paragraph>
|
||||
<fetcher.Form
|
||||
method="post"
|
||||
action={`/resources/environments/${id}/regenerate-api-key`}
|
||||
className="mt-2 flex w-full flex-col items-center gap-2"
|
||||
>
|
||||
<Paragraph variant="small" className="font-medium">
|
||||
To confirm, please enter the text:{" "}
|
||||
<span className="font-bold text-bright">{randomWord}</span>
|
||||
</Paragraph>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Confirmation Text"
|
||||
fullWidth={false}
|
||||
value={confirmationText}
|
||||
onChange={(e) => setConfirmationText(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
variant="primary/large"
|
||||
fullWidth
|
||||
className="mt-4"
|
||||
disabled={confirmationText !== randomWord}
|
||||
>
|
||||
{isSubmitting ? (
|
||||
<Spinner color="white" />
|
||||
) : (
|
||||
<>
|
||||
<NamedIcon
|
||||
name="key"
|
||||
className="mr-1.5 h-4 w-4 text-bright transition group-hover:text-bright"
|
||||
/>
|
||||
Regenerate API Keys
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</fetcher.Form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -46,7 +46,8 @@ export function ConnectToOAuthForm({
|
||||
|
||||
const [form, { title, slug, scopes, hasCustomClient, customClientId, customClientSecret }] =
|
||||
useForm({
|
||||
lastSubmission: fetcher.data,
|
||||
// TODO: type this
|
||||
lastSubmission: fetcher.data as any,
|
||||
shouldRevalidate: "onSubmit",
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, {
|
||||
|
||||
@@ -45,7 +45,8 @@ export function UpdateOAuthForm({
|
||||
const { isManagedCloud } = useFeatures();
|
||||
|
||||
const [form, { title, scopes, hasCustomClient, customClientId, customClientSecret }] = useForm({
|
||||
lastSubmission: fetcher.data,
|
||||
// TODO: type this
|
||||
lastSubmission: fetcher.data as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, {
|
||||
schema,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { RouteMatch, useMatches } from "@remix-run/react";
|
||||
import { UIMatch, useMatches } from "@remix-run/react";
|
||||
import { Fragment, ReactNode } from "react";
|
||||
import { BreadcrumbIcon } from "../primitives/BreadcrumbIcon";
|
||||
import { Handle } from "~/utils/handle";
|
||||
|
||||
export type BreadcrumbItem = (match: RouteMatch, allMatches: RouteMatch[]) => ReactNode;
|
||||
export type BreadcrumbItem = (match: UIMatch, allMatches: UIMatch[]) => ReactNode;
|
||||
|
||||
export function Breadcrumb() {
|
||||
const matches = useMatches();
|
||||
const matches = useMatches() as UIMatch<unknown, Handle>[];
|
||||
|
||||
return (
|
||||
<div className="hidden items-center md:flex">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Link, RouteMatch } from "@remix-run/react";
|
||||
import { Link, UIMatch } from "@remix-run/react";
|
||||
import { useState } from "react";
|
||||
import { useJob } from "~/hooks/useJob";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
PopoverSectionHeader,
|
||||
} from "../primitives/Popover";
|
||||
|
||||
export function JobsMenu({ matches }: { matches: RouteMatch[] }) {
|
||||
export function JobsMenu({ matches }: { matches: UIMatch[] }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const organization = useOrganization(matches);
|
||||
const project = useProject(matches);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { Fragment, useState } from "react";
|
||||
import simplur from "simplur";
|
||||
import { Badge } from "~/components/primitives/Badge";
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
PopoverSectionHeader,
|
||||
} from "../primitives/Popover";
|
||||
|
||||
export function ProjectsMenu({ matches }: { matches: RouteMatch[] }) {
|
||||
export function ProjectsMenu({ matches }: { matches: UIMatch[] }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const organizations = useOrganizations(matches);
|
||||
const isNewOrgPage = useIsNewOrganizationPage(matches);
|
||||
|
||||
@@ -36,7 +36,7 @@ export function RunPanel({
|
||||
? "border-slate-850"
|
||||
: "border-slate-900",
|
||||
onClick && "cursor-pointer",
|
||||
onClick && !selected && "hover:border-green-500/30",
|
||||
onClick && !selected && "hover:border-slate-500/30",
|
||||
className
|
||||
)}
|
||||
onClick={() => onClick && onClick()}
|
||||
|
||||
@@ -159,6 +159,16 @@ export function RunOverview({ run, trigger, showRerun, paths }: RunOverviewProps
|
||||
<div className="grid h-full grid-cols-2 gap-2">
|
||||
<div className="flex flex-col gap-6 overflow-y-auto py-4 pl-4 pr-2 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700">
|
||||
<div>
|
||||
{(run.tasks.length === 0 || run.tasks.every((t) => t.noop)) && (
|
||||
<Callout
|
||||
variant={"warning"}
|
||||
to="https://trigger.dev/docs/documentation/concepts/tasks"
|
||||
className="mb-4"
|
||||
>
|
||||
This Run completed but it did not use any Tasks – this can cause unpredictable
|
||||
results. Read the docs to view the solution.
|
||||
</Callout>
|
||||
)}
|
||||
<Header2 className="mb-2">Trigger</Header2>
|
||||
<RunPanel
|
||||
selected={selectedId === "trigger"}
|
||||
@@ -313,7 +323,8 @@ function RerunPopover({
|
||||
|
||||
const [form, { successRedirect }] = useForm({
|
||||
id: "rerun",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
@@ -386,7 +397,8 @@ export function CancelRun({ runId }: { runId: string }) {
|
||||
|
||||
const [form, { redirectUrl }] = useForm({
|
||||
id: "cancel-run",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema: cancelSchema });
|
||||
},
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
} from "../primitives/Table";
|
||||
import { TaskAttemptStatusLabel } from "./TaskAttemptStatus";
|
||||
import { TaskStatusIcon } from "./TaskStatus";
|
||||
import { ClientOnly } from "remix-utils";
|
||||
import { ClientOnly } from "remix-utils/client-only";
|
||||
import { Spinner } from "../primitives/Spinner";
|
||||
import type { DetailedTask } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/route";
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { H } from "@highlight-run/node";
|
||||
import type { DataFunctionArgs, EntryContext, Headers } from "@remix-run/node"; // or cloudflare/deno
|
||||
import { Response } from "@remix-run/node"; // or cloudflare/deno
|
||||
import {
|
||||
createReadableStreamFromReadable,
|
||||
type DataFunctionArgs,
|
||||
type EntryContext,
|
||||
} from "@remix-run/node"; // or cloudflare/deno
|
||||
import { RemixServer } from "@remix-run/react";
|
||||
import { parseAcceptLanguage } from "intl-parse-accept-language";
|
||||
import isbot from "isbot";
|
||||
@@ -36,7 +39,7 @@ export default function handleRequest(
|
||||
// response to render before sending it to the client. This
|
||||
// ensures that bots can see the full page content.
|
||||
if (isbot(request.headers.get("user-agent"))) {
|
||||
return serveTheBots(
|
||||
return handleBotRequest(
|
||||
request,
|
||||
responseStatusCode,
|
||||
responseHeaders,
|
||||
@@ -46,7 +49,7 @@ export default function handleRequest(
|
||||
);
|
||||
}
|
||||
|
||||
return serveBrowsers(
|
||||
return handleBrowserRequest(
|
||||
request,
|
||||
responseStatusCode,
|
||||
responseHeaders,
|
||||
@@ -56,7 +59,7 @@ export default function handleRequest(
|
||||
);
|
||||
}
|
||||
|
||||
function serveTheBots(
|
||||
function handleBotRequest(
|
||||
request: Request,
|
||||
responseStatusCode: number,
|
||||
responseHeaders: Headers,
|
||||
@@ -65,76 +68,97 @@ function serveTheBots(
|
||||
platform: OperatingSystemPlatform
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let shellRendered = false;
|
||||
const { pipe, abort } = renderToPipeableStream(
|
||||
<OperatingSystemContextProvider platform={platform}>
|
||||
<LocaleContextProvider locales={locales}>
|
||||
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />
|
||||
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />,
|
||||
</LocaleContextProvider>
|
||||
</OperatingSystemContextProvider>,
|
||||
{
|
||||
// Use onAllReady to wait for the entire document to be ready
|
||||
onAllReady() {
|
||||
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
|
||||
let body = new PassThrough();
|
||||
pipe(body);
|
||||
resolve(
|
||||
new Response(body, {
|
||||
status: responseStatusCode,
|
||||
headers: responseHeaders,
|
||||
})
|
||||
);
|
||||
},
|
||||
onShellError(err: unknown) {
|
||||
reject(err);
|
||||
},
|
||||
}
|
||||
);
|
||||
setTimeout(abort, ABORT_DELAY);
|
||||
});
|
||||
}
|
||||
shellRendered = true;
|
||||
const body = new PassThrough();
|
||||
const stream = createReadableStreamFromReadable(body);
|
||||
|
||||
responseHeaders.set("Content-Type", "text/html");
|
||||
|
||||
function serveBrowsers(
|
||||
request: Request,
|
||||
responseStatusCode: number,
|
||||
responseHeaders: Headers,
|
||||
remixContext: EntryContext,
|
||||
locales: string[],
|
||||
platform: OperatingSystemPlatform
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let didError = false;
|
||||
let shellReady = false;
|
||||
const { pipe, abort } = renderToPipeableStream(
|
||||
<OperatingSystemContextProvider platform={platform}>
|
||||
<LocaleContextProvider locales={locales}>
|
||||
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />
|
||||
</LocaleContextProvider>
|
||||
</OperatingSystemContextProvider>,
|
||||
{
|
||||
// use onShellReady to wait until a suspense boundary is triggered
|
||||
onShellReady() {
|
||||
shellReady = true;
|
||||
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
|
||||
let body = new PassThrough();
|
||||
pipe(body);
|
||||
resolve(
|
||||
new Response(body, {
|
||||
status: didError ? 500 : responseStatusCode,
|
||||
new Response(stream, {
|
||||
headers: responseHeaders,
|
||||
status: responseStatusCode,
|
||||
})
|
||||
);
|
||||
|
||||
pipe(body);
|
||||
},
|
||||
onShellError(err: unknown) {
|
||||
reject(err);
|
||||
onShellError(error: unknown) {
|
||||
reject(error);
|
||||
},
|
||||
onError(error: unknown) {
|
||||
didError = true;
|
||||
if (shellReady) {
|
||||
logError(error, request);
|
||||
responseStatusCode = 500;
|
||||
// Log streaming rendering errors from inside the shell. Don't log
|
||||
// errors encountered during initial shell rendering since they'll
|
||||
// reject and get logged in handleDocumentRequest.
|
||||
if (shellRendered) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
setTimeout(abort, ABORT_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
function handleBrowserRequest(
|
||||
request: Request,
|
||||
responseStatusCode: number,
|
||||
responseHeaders: Headers,
|
||||
remixContext: EntryContext,
|
||||
locales: string[],
|
||||
platform: OperatingSystemPlatform
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let shellRendered = false;
|
||||
const { pipe, abort } = renderToPipeableStream(
|
||||
<OperatingSystemContextProvider platform={platform}>
|
||||
<LocaleContextProvider locales={locales}>
|
||||
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />
|
||||
</LocaleContextProvider>
|
||||
</OperatingSystemContextProvider>,
|
||||
{
|
||||
onShellReady() {
|
||||
shellRendered = true;
|
||||
const body = new PassThrough();
|
||||
const stream = createReadableStreamFromReadable(body);
|
||||
|
||||
responseHeaders.set("Content-Type", "text/html");
|
||||
|
||||
resolve(
|
||||
new Response(stream, {
|
||||
headers: responseHeaders,
|
||||
status: responseStatusCode,
|
||||
})
|
||||
);
|
||||
|
||||
pipe(body);
|
||||
},
|
||||
onShellError(error: unknown) {
|
||||
reject(error);
|
||||
},
|
||||
onError(error: unknown) {
|
||||
responseStatusCode = 500;
|
||||
// Log streaming rendering errors from inside the shell. Don't log
|
||||
// errors encountered during initial shell rendering since they'll
|
||||
// reject and get logged in handleDocumentRequest.
|
||||
if (shellRendered) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
setTimeout(abort, ABORT_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { MatchedProject, useOptionalProject } from "./useProject";
|
||||
import { useUser } from "./useUser";
|
||||
|
||||
export type ProjectJobEnvironment = MatchedProject["environments"][number];
|
||||
|
||||
export function useEnvironments(matches?: RouteMatch[]) {
|
||||
export function useEnvironments(matches?: UIMatch[]) {
|
||||
const project = useOptionalProject(matches);
|
||||
if (!project) return;
|
||||
|
||||
return project.environments;
|
||||
}
|
||||
|
||||
export function useDevEnvironment(matches?: RouteMatch[]) {
|
||||
export function useDevEnvironment(matches?: UIMatch[]) {
|
||||
const user = useUser();
|
||||
const environments = useEnvironments(matches);
|
||||
if (!environments) return;
|
||||
@@ -21,7 +21,7 @@ export function useDevEnvironment(matches?: RouteMatch[]) {
|
||||
);
|
||||
}
|
||||
|
||||
export function useProdEnvironment(matches?: RouteMatch[]) {
|
||||
export function useProdEnvironment(matches?: UIMatch[]) {
|
||||
const environments = useEnvironments(matches);
|
||||
if (!environments) return;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { UseDataFunctionReturn } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.integrations_.$clientParam/route";
|
||||
@@ -6,7 +6,7 @@ import { useTypedMatchesData } from "./useTypedMatchData";
|
||||
|
||||
export type MatchedClient = UseDataFunctionReturn<typeof loader>["client"];
|
||||
|
||||
export function useOptionalIntegrationClient(matches?: RouteMatch[]) {
|
||||
export function useOptionalIntegrationClient(matches?: UIMatch[]) {
|
||||
const routeMatch = useTypedMatchesData<typeof loader>({
|
||||
id: "routes/_app.orgs.$organizationSlug.projects.$projectParam.integrations_.$clientParam",
|
||||
matches,
|
||||
@@ -15,7 +15,7 @@ export function useOptionalIntegrationClient(matches?: RouteMatch[]) {
|
||||
return routeMatch?.client;
|
||||
}
|
||||
|
||||
export function useIntegrationClient(matches?: RouteMatch[]) {
|
||||
export function useIntegrationClient(matches?: UIMatch[]) {
|
||||
const integration = useOptionalIntegrationClient(matches);
|
||||
invariant(integration, "Integration must be defined");
|
||||
return integration;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RouteMatch, useMatches } from "@remix-run/react";
|
||||
import { UIMatch, useMatches } from "@remix-run/react";
|
||||
|
||||
export function useIsProjectChildPage(matches?: RouteMatch[]) {
|
||||
export function useIsProjectChildPage(matches?: UIMatch[]) {
|
||||
if (!matches) {
|
||||
matches = useMatches();
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@ import { UseDataFunctionReturn } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam/route";
|
||||
import { useChanged } from "./useChanged";
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { useTypedMatchesData } from "./useTypedMatchData";
|
||||
|
||||
export type MatchedJob = UseDataFunctionReturn<typeof loader>["job"];
|
||||
|
||||
export const jobMatchId =
|
||||
"routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam";
|
||||
export function useOptionalJob(matches?: RouteMatch[]) {
|
||||
export function useOptionalJob(matches?: UIMatch[]) {
|
||||
const routeMatch = useTypedMatchesData<typeof loader>({
|
||||
id: jobMatchId,
|
||||
matches,
|
||||
@@ -22,7 +22,7 @@ export function useOptionalJob(matches?: RouteMatch[]) {
|
||||
return routeMatch.projectJobs.find((j) => j.id === routeMatch.job.id);
|
||||
}
|
||||
|
||||
export function useJob(matches?: RouteMatch[]) {
|
||||
export function useJob(matches?: UIMatch[]) {
|
||||
const job = useOptionalJob(matches);
|
||||
invariant(job, "Job must be defined");
|
||||
return job;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { UseDataFunctionReturn } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam/route";
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { useTypedMatchesData } from "./useTypedMatchData";
|
||||
|
||||
export type ProjectJob = UseDataFunctionReturn<typeof loader>["projectJobs"][number];
|
||||
@@ -12,7 +12,7 @@ export const jobsMatchId =
|
||||
// This is only used in the JobsMenu component, which is the breadcrumb job list dropdown.
|
||||
// This dropdown is only shown once you have selected a job, so we can assume that
|
||||
// the route above has loaded and we can use the data from it.
|
||||
export function useOptionalJobs(matches?: RouteMatch[]) {
|
||||
export function useOptionalJobs(matches?: UIMatch[]) {
|
||||
const routeMatch = useTypedMatchesData<typeof loader>({
|
||||
id: jobsMatchId,
|
||||
matches,
|
||||
@@ -21,7 +21,7 @@ export function useOptionalJobs(matches?: RouteMatch[]) {
|
||||
return routeMatch?.projectJobs;
|
||||
}
|
||||
|
||||
export function useJobs(matches?: RouteMatch[]) {
|
||||
export function useJobs(matches?: UIMatch[]) {
|
||||
const jobs = useOptionalJobs(matches);
|
||||
invariant(jobs, "Jobs must be defined");
|
||||
return jobs;
|
||||
|
||||
@@ -4,12 +4,12 @@ import type { loader as orgLoader } from "~/routes/_app.orgs.$organizationSlug/r
|
||||
import type { loader as appLoader } from "~/routes/_app/route";
|
||||
import { hydrateObject, useMatchesData } from "~/utils";
|
||||
import { useChanged } from "./useChanged";
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { useTypedMatchesData } from "./useTypedMatchData";
|
||||
|
||||
export type MatchedOrganization = UseDataFunctionReturn<typeof appLoader>["organizations"][number];
|
||||
|
||||
export function useOptionalOrganizations(matches?: RouteMatch[]) {
|
||||
export function useOptionalOrganizations(matches?: UIMatch[]) {
|
||||
const data = useTypedMatchesData<typeof appLoader>({
|
||||
id: "routes/_app",
|
||||
matches,
|
||||
@@ -17,13 +17,13 @@ export function useOptionalOrganizations(matches?: RouteMatch[]) {
|
||||
return data?.organizations;
|
||||
}
|
||||
|
||||
export function useOrganizations(matches?: RouteMatch[]) {
|
||||
export function useOrganizations(matches?: UIMatch[]) {
|
||||
const orgs = useOptionalOrganizations(matches);
|
||||
invariant(orgs, "No organizations found in loader.");
|
||||
return orgs;
|
||||
}
|
||||
|
||||
export function useOptionalOrganization(matches?: RouteMatch[]) {
|
||||
export function useOptionalOrganization(matches?: UIMatch[]) {
|
||||
const orgs = useOptionalOrganizations(matches);
|
||||
const org = useTypedMatchesData<typeof orgLoader>({
|
||||
id: "routes/_app.orgs.$organizationSlug",
|
||||
@@ -37,13 +37,13 @@ export function useOptionalOrganization(matches?: RouteMatch[]) {
|
||||
return orgs.find((o) => o.id === org.organization.id);
|
||||
}
|
||||
|
||||
export function useOrganization(matches?: RouteMatch[]) {
|
||||
export function useOrganization(matches?: UIMatch[]) {
|
||||
const org = useOptionalOrganization(matches);
|
||||
invariant(org, "No organization found in loader.");
|
||||
return org;
|
||||
}
|
||||
|
||||
export function useIsNewOrganizationPage(matches?: RouteMatch[]): boolean {
|
||||
export function useIsNewOrganizationPage(matches?: UIMatch[]): boolean {
|
||||
const data = useTypedMatchesData<any>({
|
||||
id: "routes/_app.orgs.new",
|
||||
matches,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { UseDataFunctionReturn } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam/route";
|
||||
@@ -9,7 +9,7 @@ export type MatchedProject = UseDataFunctionReturn<typeof loader>["project"];
|
||||
|
||||
export const projectMatchId = "routes/_app.orgs.$organizationSlug.projects.$projectParam";
|
||||
|
||||
export function useOptionalProject(matches?: RouteMatch[]) {
|
||||
export function useOptionalProject(matches?: UIMatch[]) {
|
||||
const routeMatch = useTypedMatchesData<typeof loader>({
|
||||
id: projectMatchId,
|
||||
matches,
|
||||
@@ -18,7 +18,7 @@ export function useOptionalProject(matches?: RouteMatch[]) {
|
||||
return routeMatch?.project;
|
||||
}
|
||||
|
||||
export function useProject(matches?: RouteMatch[]) {
|
||||
export function useProject(matches?: UIMatch[]) {
|
||||
const project = useOptionalProject(matches);
|
||||
invariant(project, "Project must be defined");
|
||||
return project;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { useEventSource } from "remix-utils";
|
||||
import { useEventSource } from "remix-utils/sse/react";
|
||||
import { projectPath, projectStreamingPath } from "~/utils/pathBuilder";
|
||||
import { useProject } from "./useProject";
|
||||
import { useOrganization } from "./useOrganizations";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { UseDataFunctionReturn } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import type { loader as runLoader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam/route";
|
||||
@@ -7,7 +7,7 @@ import { useTypedMatchesData } from "./useTypedMatchData";
|
||||
|
||||
export type MatchedRun = UseDataFunctionReturn<typeof runLoader>["run"];
|
||||
|
||||
export function useOptionalRun(matches?: RouteMatch[]) {
|
||||
export function useOptionalRun(matches?: UIMatch[]) {
|
||||
const project = useOptionalProject(matches);
|
||||
const routeMatch = useTypedMatchesData<typeof runLoader>({
|
||||
id: "routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam",
|
||||
@@ -21,7 +21,7 @@ export function useOptionalRun(matches?: RouteMatch[]) {
|
||||
return routeMatch.run;
|
||||
}
|
||||
|
||||
export function useRun(matches?: RouteMatch[]) {
|
||||
export function useRun(matches?: UIMatch[]) {
|
||||
const run = useOptionalRun(matches);
|
||||
invariant(run, "Run must be present");
|
||||
return run;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RouteMatch, useMatches } from "@remix-run/react";
|
||||
import { UIMatch, useMatches } from "@remix-run/react";
|
||||
import { RemixSerializedType, UseDataFunctionReturn, deserializeRemix } from "remix-typedjson";
|
||||
|
||||
type AppData = any;
|
||||
@@ -8,7 +8,7 @@ function useTypedDataFromMatches<T = AppData>({
|
||||
matches,
|
||||
}: {
|
||||
id: string;
|
||||
matches: RouteMatch[];
|
||||
matches: UIMatch[];
|
||||
}): UseDataFunctionReturn<T> | undefined {
|
||||
const match = matches.find((m) => m.id === id);
|
||||
return useTypedMatchData<T>(match);
|
||||
@@ -19,7 +19,7 @@ export function useTypedMatchesData<T = AppData>({
|
||||
matches,
|
||||
}: {
|
||||
id: string;
|
||||
matches?: RouteMatch[];
|
||||
matches?: UIMatch[];
|
||||
}): UseDataFunctionReturn<T> | undefined {
|
||||
if (!matches) {
|
||||
matches = useMatches();
|
||||
@@ -29,7 +29,7 @@ export function useTypedMatchesData<T = AppData>({
|
||||
}
|
||||
|
||||
export function useTypedMatchData<T = AppData>(
|
||||
match: RouteMatch | undefined
|
||||
match: UIMatch | undefined
|
||||
): UseDataFunctionReturn<T> | undefined {
|
||||
if (!match) {
|
||||
return undefined;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { User } from "~/models/user.server";
|
||||
import { useMatchesData } from "~/utils";
|
||||
import { useChanged } from "./useChanged";
|
||||
import { RouteMatch } from "@remix-run/react";
|
||||
import { UIMatch } from "@remix-run/react";
|
||||
import { useTypedMatchesData } from "./useTypedMatchData";
|
||||
import { loader } from "~/root";
|
||||
|
||||
export function useOptionalUser(matches?: RouteMatch[]): User | undefined {
|
||||
export function useOptionalUser(matches?: UIMatch[]): User | undefined {
|
||||
const routeMatch = useTypedMatchesData<typeof loader>({
|
||||
id: "root",
|
||||
matches,
|
||||
@@ -14,7 +14,7 @@ export function useOptionalUser(matches?: RouteMatch[]): User | undefined {
|
||||
return routeMatch?.user ?? undefined;
|
||||
}
|
||||
|
||||
export function useUser(matches?: RouteMatch[]): User {
|
||||
export function useUser(matches?: UIMatch[]): User {
|
||||
const maybeUser = useOptionalUser(matches);
|
||||
if (!maybeUser) {
|
||||
throw new Error(
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import { RuntimeEnvironmentType, type RuntimeEnvironment } from "@trigger.dev/database";
|
||||
import { prisma } from "~/db.server";
|
||||
import { customAlphabet } from "nanoid";
|
||||
|
||||
const apiKeyId = customAlphabet(
|
||||
"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
12
|
||||
);
|
||||
|
||||
type RegenerateAPIKeyInput = {
|
||||
userId: string;
|
||||
environmentId: string;
|
||||
};
|
||||
|
||||
export async function regenerateApiKey({ userId, environmentId }: RegenerateAPIKeyInput) {
|
||||
const environment = await prisma.runtimeEnvironment.findUnique({
|
||||
where: {
|
||||
id: environmentId,
|
||||
},
|
||||
include: {
|
||||
organization: true,
|
||||
project: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!environment) {
|
||||
throw new Error("Environment does not exist");
|
||||
}
|
||||
|
||||
// check if the user is part of the org
|
||||
const organization = await prisma.organization.findFirst({
|
||||
where: {
|
||||
id: environment.organization.id,
|
||||
members: { some: { userId } },
|
||||
},
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
throw new Error("User does not have permission to regenerate API key");
|
||||
}
|
||||
|
||||
// check if it is the user's dev environment
|
||||
if (environment.type === RuntimeEnvironmentType.DEVELOPMENT) {
|
||||
if (!environment.orgMemberId) {
|
||||
throw new Error("User does not have permission to regenerate API key");
|
||||
}
|
||||
|
||||
const orgMember = await prisma.orgMember.findFirst({
|
||||
where: {
|
||||
organizationId: organization.id,
|
||||
userId: userId,
|
||||
id: environment.orgMemberId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!orgMember) {
|
||||
throw new Error("User does not have permission to regenerate API key");
|
||||
}
|
||||
}
|
||||
|
||||
// generate and store new keys
|
||||
const newApiKey = createApiKeyForEnv(environment.type);
|
||||
const newPkApiKey = createPkApiKeyForEnv(environment.type);
|
||||
|
||||
const updatedEnviroment = await prisma.runtimeEnvironment.update({
|
||||
data: {
|
||||
apiKey: newApiKey,
|
||||
pkApiKey: newPkApiKey,
|
||||
},
|
||||
where: {
|
||||
id: environmentId,
|
||||
},
|
||||
});
|
||||
|
||||
return updatedEnviroment;
|
||||
}
|
||||
|
||||
export function createApiKeyForEnv(envType: RuntimeEnvironment["type"]) {
|
||||
return `tr_${envSlug(envType)}_${apiKeyId(20)}`;
|
||||
}
|
||||
|
||||
export function createPkApiKeyForEnv(envType: RuntimeEnvironment["type"]) {
|
||||
return `pk_${envSlug(envType)}_${apiKeyId(20)}`;
|
||||
}
|
||||
|
||||
export function envSlug(environmentType: RuntimeEnvironment["type"]) {
|
||||
switch (environmentType) {
|
||||
case "DEVELOPMENT": {
|
||||
return "dev";
|
||||
}
|
||||
case "PRODUCTION": {
|
||||
return "prod";
|
||||
}
|
||||
case "STAGING": {
|
||||
return "stg";
|
||||
}
|
||||
case "PREVIEW": {
|
||||
return "prev";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { customAlphabet } from "nanoid";
|
||||
import slug from "slug";
|
||||
import { prisma, PrismaClientOrTransaction } from "~/db.server";
|
||||
import { createProject } from "./project.server";
|
||||
import { createApiKeyForEnv, createPkApiKeyForEnv, envSlug } from "./api-key.server";
|
||||
|
||||
export type { Organization };
|
||||
|
||||
@@ -157,28 +158,3 @@ export async function createEnvironment(
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function createApiKeyForEnv(envType: RuntimeEnvironment["type"]) {
|
||||
return `tr_${envSlug(envType)}_${apiKeyId(20)}`;
|
||||
}
|
||||
|
||||
function createPkApiKeyForEnv(envType: RuntimeEnvironment["type"]) {
|
||||
return `pk_${envSlug(envType)}_${apiKeyId(20)}`;
|
||||
}
|
||||
|
||||
function envSlug(environmentType: RuntimeEnvironment["type"]) {
|
||||
switch (environmentType) {
|
||||
case "DEVELOPMENT": {
|
||||
return "dev";
|
||||
}
|
||||
case "PRODUCTION": {
|
||||
return "prod";
|
||||
}
|
||||
case "STAGING": {
|
||||
return "stg";
|
||||
}
|
||||
case "PREVIEW": {
|
||||
return "prev";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import omit from "lodash.omit";
|
||||
import { z } from "zod";
|
||||
import { PrismaClient, PrismaClientOrTransaction } from "~/db.server";
|
||||
import { workerLogger as logger } from "~/services/logger.server";
|
||||
import { PgListenService } from "~/services/db/pgListen.server";
|
||||
import { safeJsonParse } from "~/utils/json";
|
||||
|
||||
export interface MessageCatalogSchema {
|
||||
[key: string]: z.ZodFirstPartySchemaTypes | z.ZodDiscriminatedUnion<any, any>;
|
||||
@@ -164,8 +166,23 @@ export class ZodWorker<TMessageCatalog extends MessageCatalogSchema> {
|
||||
this.#logDebug("pool:create", { attempts });
|
||||
});
|
||||
|
||||
this.#runner?.events.on("pool:listen:success", ({ workerPool, client }) => {
|
||||
this.#runner?.events.on("pool:listen:success", async ({ workerPool, client }) => {
|
||||
this.#logDebug("pool:listen:success");
|
||||
|
||||
// hijack client instance to listen and react to incoming NOTIFY events
|
||||
const pgListen = new PgListenService(client, this.#name, logger);
|
||||
|
||||
await pgListen.on("trigger:graphile:migrate", async ({ latestMigration }) => {
|
||||
this.#logDebug("Detected incoming migration", { latestMigration });
|
||||
|
||||
if (latestMigration > 10) {
|
||||
// already migrated past v0.14 - nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
// simulate SIGTERM to trigger graceful shutdown
|
||||
this._handleSignal("SIGTERM");
|
||||
});
|
||||
});
|
||||
|
||||
this.#runner?.events.on("pool:listen:error", ({ error }) => {
|
||||
|
||||
@@ -156,6 +156,7 @@ export class RunPresenter {
|
||||
completedAt: true,
|
||||
style: true,
|
||||
parentId: true,
|
||||
noop: true,
|
||||
runConnection: {
|
||||
select: {
|
||||
integration: {
|
||||
|
||||
+13
-10
@@ -1,7 +1,10 @@
|
||||
import type { LinksFunction, LoaderArgs } from "@remix-run/node";
|
||||
import { ErrorBoundary as HighlightErrorBoundary } from "@highlight-run/react";
|
||||
import type { LinksFunction, LoaderFunctionArgs } from "@remix-run/node";
|
||||
import type { ShouldRevalidateFunction } from "@remix-run/react";
|
||||
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react";
|
||||
import { metaV1 } from "@remix-run/v1-meta";
|
||||
import { TypedMetaFunction, typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { ExternalScripts } from "remix-utils/external-scripts";
|
||||
import type { ToastMessage } from "~/models/message.server";
|
||||
import { commitSession, getSession } from "~/models/message.server";
|
||||
import tailwindStylesheetUrl from "~/tailwind.css";
|
||||
@@ -11,24 +14,24 @@ import { AppContainer, MainCenteredContainer } from "./components/layout/AppLayo
|
||||
import { Toast } from "./components/primitives/Toast";
|
||||
import { env } from "./env.server";
|
||||
import { featuresForRequest } from "./features.server";
|
||||
import { useHighlight } from "./hooks/useHighlight";
|
||||
import { usePostHog } from "./hooks/usePostHog";
|
||||
import { getUser } from "./services/session.server";
|
||||
import { appEnvTitleTag } from "./utils";
|
||||
import { ErrorBoundary as HighlightErrorBoundary } from "@highlight-run/react";
|
||||
import { useHighlight } from "./hooks/useHighlight";
|
||||
import { ExternalScripts } from "remix-utils";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: tailwindStylesheetUrl }];
|
||||
};
|
||||
|
||||
export const meta: TypedMetaFunction<typeof loader> = ({ data }) => ({
|
||||
title: `Trigger.dev${appEnvTitleTag(data?.appEnv)}`,
|
||||
charset: "utf-8",
|
||||
viewport: "width=1024, initial-scale=1",
|
||||
});
|
||||
export const meta: TypedMetaFunction<typeof loader> = (args) => {
|
||||
return metaV1(args, {
|
||||
title: `Trigger.dev${appEnvTitleTag(args.data.appEnv)}`,
|
||||
charset: "utf-8",
|
||||
viewport: "width=1024, initial-scale=1",
|
||||
});
|
||||
};
|
||||
|
||||
export const loader = async ({ request }: LoaderArgs) => {
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const session = await getSession(request.headers.get("cookie"));
|
||||
const toastMessage = session.get("toastMessage") as ToastMessage;
|
||||
const posthogProjectKey = env.POSTHOG_PROJECT_KEY;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LoaderArgs, json } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { redirect } from "remix-typedjson";
|
||||
import { LinkButton } from "~/components/primitives/Buttons";
|
||||
import { useOptionalOrganizations } from "~/hooks/useOrganizations";
|
||||
@@ -11,7 +11,7 @@ import { Link } from "@remix-run/react";
|
||||
import { NamedIcon } from "~/components/primitives/NamedIcon";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
|
||||
export const loader = async ({ request }: LoaderArgs) => {
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
|
||||
//if there are invites then we should redirect to the invites page
|
||||
|
||||
@@ -113,7 +113,8 @@ export default function Page() {
|
||||
|
||||
const [form, { name, email, marketingEmails }] = useForm({
|
||||
id: "account",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema: createSchema() });
|
||||
},
|
||||
|
||||
@@ -14,12 +14,12 @@ import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { OrganizationParamsSchema, jobPath, organizationTeamPath } from "~/utils/pathBuilder";
|
||||
import { OrgAdminHeader } from "../_app.orgs.$organizationSlug._index/OrgAdminHeader";
|
||||
import { Link } from "@remix-run/react/dist/components";
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { OrgUsagePresenter } from "~/presenters/OrgUsagePresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
|
||||
export async function loader({ params, request }: LoaderArgs) {
|
||||
export async function loader({ params, request }: LoaderFunctionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug } = OrganizationParamsSchema.parse(params);
|
||||
|
||||
|
||||
@@ -91,7 +91,8 @@ export default function Page() {
|
||||
|
||||
const [form, { emails }] = useForm({
|
||||
id: "invite-members",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { ArrowUpIcon } from "@heroicons/react/24/solid";
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { FrameworkSelector } from "~/components/frameworks/FrameworkSelector";
|
||||
import { JobsTable } from "~/components/jobs/JobsTable";
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
trimTrailingSlash,
|
||||
} from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { EnvironmentsStreamPresenter } from "~/presenters/EnvironmentsStreamPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { ProjectParamSchema } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
|
||||
+6
-8
@@ -2,8 +2,12 @@ import { conform, useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { useFetcher, useRevalidator } from "@remix-run/react";
|
||||
import { useEffect } from "react";
|
||||
import { useEventSource } from "remix-utils";
|
||||
import { useEventSource } from "remix-utils/sse/react";
|
||||
import { InlineCode } from "~/components/code/InlineCode";
|
||||
import {
|
||||
EndpointIndexStatusIcon,
|
||||
EndpointIndexStatusLabel,
|
||||
} from "~/components/environments/EndpointIndexStatus";
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
import { Button } from "~/components/primitives/Buttons";
|
||||
import { Callout, CalloutVariant } from "~/components/primitives/Callout";
|
||||
@@ -20,12 +24,6 @@ import { ClientEndpoint } from "~/presenters/EnvironmentsPresenter.server";
|
||||
import { endpointStreamingPath } from "~/utils/pathBuilder";
|
||||
import { EndpointIndexStatus, RuntimeEnvironmentType } from "../../../../../packages/database/src";
|
||||
import { bodySchema } from "../resources.environments.$environmentParam.endpoint";
|
||||
import {
|
||||
EndpointIndexStatusIcon,
|
||||
EndpointIndexStatusLabel,
|
||||
endpointIndexStatusTitle,
|
||||
} from "~/components/environments/EndpointIndexStatus";
|
||||
import { CodeBlock } from "~/components/code/CodeBlock";
|
||||
|
||||
type ConfigureEndpointSheetProps = {
|
||||
slug: string;
|
||||
@@ -39,7 +37,7 @@ export function ConfigureEndpointSheet({ slug, endpoint, onClose }: ConfigureEnd
|
||||
|
||||
const [form, { url, clientSlug }] = useForm({
|
||||
id: "endpoint-url",
|
||||
lastSubmission: setEndpointUrlFetcher.data,
|
||||
lastSubmission: setEndpointUrlFetcher.data as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema: bodySchema });
|
||||
},
|
||||
|
||||
+2
-1
@@ -40,7 +40,8 @@ export function FirstEndpointSheet({ projectId, environments }: FirstEndpointShe
|
||||
const setEndpointUrlFetcher = useFetcher();
|
||||
const [form, { url, environmentId }] = useForm({
|
||||
id: "new-endpoint-url",
|
||||
lastSubmission: setEndpointUrlFetcher.data,
|
||||
// TODO: type this
|
||||
lastSubmission: setEndpointUrlFetcher.data as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema: bodySchema });
|
||||
},
|
||||
|
||||
+15
-8
@@ -1,8 +1,8 @@
|
||||
import { useRevalidator } from "@remix-run/react";
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { useEventSource } from "remix-utils";
|
||||
import { useEventSource } from "remix-utils/sse/react";
|
||||
import {
|
||||
EndpointIndexStatusIcon,
|
||||
EndpointIndexStatusLabel,
|
||||
@@ -44,8 +44,9 @@ import { requestUrl } from "~/utils/requestUrl.server";
|
||||
import { RuntimeEnvironmentType } from "../../../../../packages/database/src";
|
||||
import { ConfigureEndpointSheet } from "./ConfigureEndpointSheet";
|
||||
import { FirstEndpointSheet } from "./FirstEndpointSheet";
|
||||
import { RegenerateApiKeyModal } from "~/components/environments/RegenerateApiKeyModal";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
@@ -148,11 +149,17 @@ export default function Page() {
|
||||
</Paragraph>
|
||||
<div className="mt-4 flex flex-col gap-6">
|
||||
{environments.map((environment) => (
|
||||
<div key={environment.id}>
|
||||
<Header3 className="flex items-center gap-1">
|
||||
<EnvironmentLabel environment={environment} /> Environment
|
||||
</Header3>
|
||||
<div className="mt-2 inline-flex flex-col gap-3">
|
||||
<div key={environment.id} className="w-[400px]">
|
||||
<div className="flex justify-between">
|
||||
<Header3 className="flex items-center gap-1">
|
||||
<EnvironmentLabel environment={environment} /> Environment
|
||||
</Header3>
|
||||
<RegenerateApiKeyModal
|
||||
id={environment.id}
|
||||
title={environmentTitle(environment)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-3 inline-flex w-full flex-col gap-3">
|
||||
<ClipboardField
|
||||
className="w-full max-w-none"
|
||||
secure
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { ChevronRightIcon } from "@heroicons/react/24/solid";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { useCallback, useState } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { Feedback } from "~/components/Feedback";
|
||||
@@ -56,7 +56,7 @@ import {
|
||||
integrationClientPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
const { organizationSlug, projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { HowToUseThisIntegration } from "~/components/helpContent/HelpContentText";
|
||||
import { JobSkeleton } from "~/components/jobs/JobSkeleton";
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
trimTrailingSlash,
|
||||
} from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug, projectParam, clientParam } =
|
||||
IntegrationClientParamSchema.parse(params);
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { connectionType } from "~/components/integrations/connectionType";
|
||||
import { BreadcrumbLink } from "~/components/navigation/NavBar";
|
||||
@@ -18,7 +18,7 @@ import { requireUserId } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import { IntegrationClientParamSchema, trimTrailingSlash } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug, projectParam, clientParam } =
|
||||
IntegrationClientParamSchema.parse(params);
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { BreadcrumbLink } from "~/components/navigation/NavBar";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
@@ -7,7 +7,7 @@ import { requireUserId } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import { IntegrationClientParamSchema, trimTrailingSlash } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug, projectParam, clientParam } =
|
||||
IntegrationClientParamSchema.parse(params);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { Outlet } from "@remix-run/react";
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { connectionType } from "~/components/integrations/connectionType";
|
||||
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
projectIntegrationsPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
const { organizationSlug, clientParam, projectParam } =
|
||||
IntegrationClientParamSchema.parse(params);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { useNavigation } from "@remix-run/react";
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { z } from "zod";
|
||||
import { HowToRunYourJob } from "~/components/helpContent/HelpContentText";
|
||||
@@ -30,7 +30,7 @@ export const RunListSearchSchema = z.object({
|
||||
direction: DirectionSchema.optional(),
|
||||
});
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { jobParam, projectParam, organizationSlug } = JobParamsSchema.parse(params);
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { RunStreamPresenter } from "~/presenters/RunStreamPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
await requireUserId(request);
|
||||
|
||||
const { runParam } = z.object({ runParam: z.string() }).parse(params);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { Await, useLoaderData } from "@remix-run/react";
|
||||
import { LoaderArgs, SerializeFrom, defer } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs, SerializeFrom, defer } from "@remix-run/server-runtime";
|
||||
import { Suspense } from "react";
|
||||
import { Spinner } from "~/components/primitives/Spinner";
|
||||
import { TaskDetail } from "~/components/run/TaskDetail";
|
||||
@@ -7,7 +7,7 @@ import { TaskDetailsPresenter } from "~/presenters/TaskDetailsPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { TaskParamsSchema } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { taskParam } = TaskParamsSchema.parse(params);
|
||||
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { TriggerDetail } from "~/components/run/TriggerDetail";
|
||||
import { useJob } from "~/hooks/useJob";
|
||||
@@ -6,7 +6,7 @@ import { useRun } from "~/hooks/useRun";
|
||||
import { TriggerDetailsPresenter } from "~/presenters/TriggerDetailsPresenter.server";
|
||||
import { RunParamsSchema } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const { runParam } = RunParamsSchema.parse(params);
|
||||
|
||||
const presenter = new TriggerDetailsPresenter();
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { useRevalidator } from "@remix-run/react";
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { Fragment, useEffect } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { useEventSource } from "remix-utils";
|
||||
import { useEventSource } from "remix-utils/sse/react";
|
||||
import { BreadcrumbLink } from "~/components/navigation/NavBar";
|
||||
import { BreadcrumbIcon } from "~/components/primitives/BreadcrumbIcon";
|
||||
import { RunOverview } from "~/components/run/RunOverview";
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
trimTrailingSlash,
|
||||
} from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { runParam } = RunParamsSchema.parse(params);
|
||||
|
||||
|
||||
+4
-3
@@ -3,7 +3,7 @@ import { parse } from "@conform-to/zod";
|
||||
import { ClipboardIcon } from "@heroicons/react/20/solid";
|
||||
import { ClockIcon, CodeBracketIcon } from "@heroicons/react/24/outline";
|
||||
import { Form, useActionData, useSubmit } from "@remix-run/react";
|
||||
import { ActionFunction, LoaderArgs, json } from "@remix-run/server-runtime";
|
||||
import { ActionFunction, LoaderFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { z } from "zod";
|
||||
@@ -38,7 +38,7 @@ import { Handle } from "~/utils/handle";
|
||||
import { isValidIcon } from "~/utils/icon";
|
||||
import { JobParamsSchema, jobRunDashboardPath, trimTrailingSlash } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug, projectParam, jobParam } = JobParamsSchema.parse(params);
|
||||
|
||||
@@ -166,7 +166,8 @@ export default function Page() {
|
||||
|
||||
const [form, { environmentId, payload, accountId }] = useForm({
|
||||
id: "test-job",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { Outlet, useLocation } from "@remix-run/react";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { Fragment } from "react";
|
||||
import { typedjson } from "remix-typedjson";
|
||||
import { JobStatusBadge } from "~/components/jobs/JobStatusBadge";
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
trimTrailingSlash,
|
||||
} from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { jobParam, projectParam, organizationSlug } = JobParamsSchema.parse(params);
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
import { BreadcrumbLink } from "~/components/navigation/NavBar";
|
||||
@@ -25,7 +25,7 @@ import { cn } from "~/utils/cn";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import { ProjectParamSchema, externalTriggerPath, trimTrailingSlash } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
const { organizationSlug, projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
@@ -138,7 +138,7 @@ export default function Integrations() {
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<TableBlankRow colSpan={5}>
|
||||
<TableBlankRow colSpan={100}>
|
||||
<Paragraph>No External triggers</Paragraph>
|
||||
</TableBlankRow>
|
||||
)}
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { NoSymbolIcon } from "@heroicons/react/20/solid";
|
||||
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
import { BreadcrumbLink } from "~/components/navigation/NavBar";
|
||||
@@ -25,7 +25,7 @@ import { requireUser } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import { ProjectParamSchema, docsPath, trimTrailingSlash } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
const { organizationSlug, projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
@@ -143,7 +143,7 @@ export default function Integrations() {
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<TableBlankRow colSpan={5}>
|
||||
<TableBlankRow colSpan={100}>
|
||||
<Paragraph>No Scheduled triggers</Paragraph>
|
||||
</TableBlankRow>
|
||||
)}
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
import { Response, json } from "@remix-run/node";
|
||||
import type { ActionFunction, LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/node";
|
||||
import type { ActionFunction, LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { Fragment } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
@@ -45,7 +45,7 @@ import { ActivateSourceService } from "~/services/sources/activateSource.server"
|
||||
import { redirectWithSuccessMessage } from "~/models/message.server";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
const { organizationSlug, projectParam, triggerParam } = TriggerSourceParamSchema.parse(params);
|
||||
|
||||
@@ -135,7 +135,8 @@ export default function Page() {
|
||||
|
||||
const [form, { jobId }] = useForm({
|
||||
id: "trigger-registration-retry",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { RunStreamPresenter } from "~/presenters/RunStreamPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
await requireUserId(request);
|
||||
|
||||
const { runParam } = z.object({ runParam: z.string() }).parse(params);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { Await, useLoaderData } from "@remix-run/react";
|
||||
import { LoaderArgs, defer } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs, defer } from "@remix-run/server-runtime";
|
||||
import { Suspense } from "react";
|
||||
import { Spinner } from "~/components/primitives/Spinner";
|
||||
import { TaskDetail } from "~/components/run/TaskDetail";
|
||||
@@ -7,7 +7,7 @@ import { TaskDetailsPresenter } from "~/presenters/TaskDetailsPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { TriggerSourceRunTaskParamsSchema } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { taskParam } = TriggerSourceRunTaskParamsSchema.parse(params);
|
||||
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { TriggerDetail } from "~/components/run/TriggerDetail";
|
||||
import { TriggerDetailsPresenter } from "~/presenters/TriggerDetailsPresenter.server";
|
||||
import { TriggerSourceRunParamsSchema } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const { runParam } = TriggerSourceRunParamsSchema.parse(params);
|
||||
|
||||
const presenter = new TriggerDetailsPresenter();
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { useRevalidator } from "@remix-run/react";
|
||||
import { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { Fragment, useEffect } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { useEventSource } from "remix-utils";
|
||||
import { useEventSource } from "remix-utils/sse/react";
|
||||
import { BreadcrumbLink } from "~/components/navigation/NavBar";
|
||||
import { BreadcrumbIcon } from "~/components/primitives/BreadcrumbIcon";
|
||||
import { RunOverview } from "~/components/run/RunOverview";
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
trimTrailingSlash,
|
||||
} from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { runParam, triggerParam } = TriggerSourceRunParamsSchema.parse(params);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Outlet } from "@remix-run/react";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import { RouteErrorDisplay } from "~/components/ErrorDisplay";
|
||||
@@ -13,7 +13,7 @@ import { requireUserId } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import { projectPath } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { projectParam } = params;
|
||||
invariant(projectParam, "projectParam not found");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { conform, useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import type { ActionFunction } from "@remix-run/node";
|
||||
import { json, redirect } from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import { Form, useActionData } from "@remix-run/react";
|
||||
import invariant from "tiny-invariant";
|
||||
import { z } from "zod";
|
||||
@@ -11,7 +11,6 @@ import { Fieldset } from "~/components/primitives/Fieldset";
|
||||
import { FormButtons } from "~/components/primitives/FormButtons";
|
||||
import { FormError } from "~/components/primitives/FormError";
|
||||
import { FormTitle } from "~/components/primitives/FormTitle";
|
||||
import { Hint } from "~/components/primitives/Hint";
|
||||
import { Input } from "~/components/primitives/Input";
|
||||
import { InputGroup } from "~/components/primitives/InputGroup";
|
||||
import { Label } from "~/components/primitives/Label";
|
||||
@@ -60,7 +59,8 @@ export default function NewOrganizationPage() {
|
||||
|
||||
const [form, { projectName }] = useForm({
|
||||
id: "create-project",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { UserPlusIcon } from "@heroicons/react/20/solid";
|
||||
import { Form, useActionData } from "@remix-run/react";
|
||||
import { ActionFunction, LoaderArgs, json } from "@remix-run/server-runtime";
|
||||
import { ActionFunction, LoaderFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { useState } from "react";
|
||||
import { UseDataFunctionReturn, typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
@@ -33,7 +33,7 @@ import { inviteTeamMemberPath, organizationTeamPath, resendInvitePath } from "~/
|
||||
import { OrgAdminHeader } from "../_app.orgs.$organizationSlug._index/OrgAdminHeader";
|
||||
import { DateTime } from "~/components/primitives/DateTime";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug } = params;
|
||||
invariant(organizationSlug, "organizationSlug not found");
|
||||
@@ -235,7 +235,8 @@ function LeaveTeamModal({
|
||||
|
||||
const [form, { memberId }] = useForm({
|
||||
id: "remove-member",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ShouldRevalidateFunction } from "@remix-run/react";
|
||||
import { Outlet } from "@remix-run/react";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import { RouteErrorDisplay } from "~/components/ErrorDisplay";
|
||||
@@ -11,7 +11,7 @@ import { commitCurrentOrgSession, setCurrentOrg } from "~/services/currentOrgani
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { organizationPath } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug } = params;
|
||||
invariant(organizationSlug, "organizationSlug not found");
|
||||
|
||||
@@ -56,7 +56,8 @@ export default function NewOrganizationPage() {
|
||||
|
||||
const [form, { orgName, projectName }] = useForm({
|
||||
id: "create-organization",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema });
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Outlet, ShouldRevalidateFunction } from "@remix-run/react";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { RouteErrorDisplay } from "~/components/ErrorDisplay";
|
||||
import { ImpersonationBanner } from "~/components/ImpersonationBanner";
|
||||
@@ -13,7 +13,7 @@ import { clearRedirectTo, commitSession } from "~/services/redirectTo.server";
|
||||
import { requireUser } from "~/services/session.server";
|
||||
import { confirmBasicDetailsPath } from "~/utils/pathBuilder";
|
||||
|
||||
export const loader = async ({ request }: LoaderArgs) => {
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
const organizations = await getOrganizations({ userId: user.id });
|
||||
const impersonationId = await getImpersonationId(request);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Form } from "@remix-run/react";
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { redirect } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { z } from "zod";
|
||||
@@ -15,7 +15,7 @@ export async function loader() {
|
||||
|
||||
const FormSchema = z.object({ id: z.string() });
|
||||
|
||||
export async function action({ request }: ActionArgs) {
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
if (request.method.toLowerCase() !== "post") {
|
||||
return new Response("Method not allowed", { status: 405 });
|
||||
}
|
||||
@@ -37,76 +37,73 @@ export default function AdminDashboardRoute() {
|
||||
const { users } = useTypedLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<main className="flex flex-1 overflow-hidden">
|
||||
{/* Primary column */}
|
||||
<section
|
||||
aria-labelledby="primary-heading"
|
||||
className="flex h-full min-w-0 flex-1 flex-col overflow-y-auto p-4 lg:order-last"
|
||||
>
|
||||
<h1 className="mb-2 text-2xl">Accounts ({users.length})</h1>
|
||||
<main
|
||||
aria-labelledby="primary-heading"
|
||||
className="flex h-full min-w-0 flex-1 flex-col overflow-y-auto p-4 lg:order-last"
|
||||
>
|
||||
<h1 className="mb-2 text-2xl">Accounts ({users.length})</h1>
|
||||
|
||||
<table className="w-full divide-y divide-border">
|
||||
<thead className="sticky top-0 text-left">
|
||||
<tr>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Email
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
GitHub username
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
id
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Created At
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Admin?
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-border">
|
||||
{users.map((user) => {
|
||||
return (
|
||||
<tr key={user.id} className="w-full px-4 py-2 text-left hover:bg-slate-900">
|
||||
<td className={cellClassName}>{user.email}</td>
|
||||
<td className={cellClassName}>
|
||||
<a
|
||||
href={`https://github.com/${user.displayName}`}
|
||||
target="_blank"
|
||||
className="text-indigo-500 underline"
|
||||
rel="noreferrer"
|
||||
<table className="w-full divide-y divide-border">
|
||||
<thead className="sticky -top-4 bg-midnight-800 text-left">
|
||||
<tr>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Email
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
GitHub username
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
id
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Created At
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Admin?
|
||||
</th>
|
||||
<th scope="col" className={headerClassName}>
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-border">
|
||||
{users.map((user) => {
|
||||
return (
|
||||
<tr key={user.id} className="w-full px-4 py-2 text-left hover:bg-slate-900">
|
||||
<td className={cellClassName}>{user.email}</td>
|
||||
<td className={cellClassName}>
|
||||
<a
|
||||
href={`https://github.com/${user.displayName}`}
|
||||
target="_blank"
|
||||
className="text-indigo-500 underline"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{user.displayName}
|
||||
</a>
|
||||
</td>
|
||||
<td className={cellClassName}>{user.id}</td>
|
||||
<td className={cellClassName}>{user.createdAt.toISOString()}</td>
|
||||
<td className={cellClassName}>{user.admin ? "✅" : ""}</td>
|
||||
<td className={cellClassName}>
|
||||
<Form method="post" reloadDocument>
|
||||
<input type="hidden" name="id" value={user.id} />
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
name="action"
|
||||
value="impersonate"
|
||||
className="mr-2"
|
||||
variant="primary/small"
|
||||
>
|
||||
{user.displayName}
|
||||
</a>
|
||||
</td>
|
||||
<td className={cellClassName}>{user.id}</td>
|
||||
<td className={cellClassName}>{user.createdAt.toISOString()}</td>
|
||||
<td className={cellClassName}>{user.admin ? "✅" : ""}</td>
|
||||
<td className={cellClassName}>
|
||||
<Form method="post" reloadDocument>
|
||||
<input type="hidden" name="id" value={user.id} />
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
name="action"
|
||||
value="impersonate"
|
||||
className="mr-2"
|
||||
variant="primary/small"
|
||||
>
|
||||
Impersonate
|
||||
</Button>
|
||||
</Form>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
Impersonate
|
||||
</Button>
|
||||
</Form>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ActionArgs, json, redirect } from "@remix-run/server-runtime";
|
||||
import { ActionFunctionArgs, json, redirect } from "@remix-run/server-runtime";
|
||||
import { prisma } from "~/db.server";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { workerQueue } from "~/services/worker.server";
|
||||
|
||||
export async function action({ request }: ActionArgs) {
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
// Next authenticate the request
|
||||
const authenticationResult = await authenticateApiRequest(request);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { HomeIcon } from "@heroicons/react/24/outline";
|
||||
import { Outlet } from "@remix-run/react";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { getUser, requireUserId } from "~/services/session.server";
|
||||
|
||||
export async function loader({ request }: LoaderArgs) {
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
await requireUserId(request);
|
||||
const user = await getUser(request);
|
||||
if (user == null) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActionArgs } from "@remix-run/server-runtime";
|
||||
import { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
|
||||
/*
|
||||
To use this route, use the stripe CLI to forward events to this route:
|
||||
@@ -9,7 +9,7 @@ import { ActionArgs } from "@remix-run/server-runtime";
|
||||
|
||||
stripe trigger price.created
|
||||
*/
|
||||
export async function action({ request }: ActionArgs) {
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
const body: any = await request.json();
|
||||
|
||||
const response = await fetch("https://jsonhero.io/api/create.json", {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "~/db.server";
|
||||
@@ -11,7 +11,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
logger.info("Fetching auth", { url: request.url });
|
||||
|
||||
const parsedParams = ParamsSchema.safeParse(params);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
@@ -11,7 +11,7 @@ const ParamsSchema = z.object({
|
||||
key: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Unregistering schedule", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { RegisterScheduleBodySchema, RegisterScheduleResponseBodySchema } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -11,7 +11,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Initializing schedule", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { UpdateTriggerSourceBodyV1Schema } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -11,7 +11,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Updating source", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { RegisterTriggerBodySchemaV1 } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -12,7 +12,7 @@ const ParamsSchema = z.object({
|
||||
key: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Registering trigger", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { InitializeTriggerBodySchema } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -11,7 +11,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Initializing trigger", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import {
|
||||
CreateExternalConnectionBody,
|
||||
@@ -16,7 +16,7 @@ const ParamsSchema = z.object({
|
||||
clientSlug: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActionArgs, json } from "@remix-run/server-runtime";
|
||||
import { ActionFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import {
|
||||
EndpointIndexErrorSchema,
|
||||
GetEndpointIndexResponse,
|
||||
@@ -14,7 +14,7 @@ const ParamsSchema = z.object({
|
||||
indexId: z.string(),
|
||||
});
|
||||
|
||||
export async function loader({ request, params }: ActionArgs) {
|
||||
export async function loader({ request, params }: ActionFunctionArgs) {
|
||||
if (request.method.toUpperCase() !== "GET") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActionArgs, json } from "@remix-run/server-runtime";
|
||||
import { ActionFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "~/db.server";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
@@ -14,7 +14,7 @@ const BodySchema = z.object({
|
||||
data: z.any().optional(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { ActionArgs, LoaderArgs, json } from "@remix-run/server-runtime";
|
||||
import { ActionFunctionArgs, LoaderFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { RuntimeEnvironmentType } from "@trigger.dev/database";
|
||||
import { z } from "zod";
|
||||
import { $transaction, PrismaClient, prisma } from "~/db.server";
|
||||
@@ -12,7 +12,7 @@ const ParamsSchema = z.object({
|
||||
indexHookIdentifier: z.string(),
|
||||
});
|
||||
|
||||
export async function loader({ params }: LoaderArgs) {
|
||||
export async function loader({ params }: LoaderFunctionArgs) {
|
||||
const parsedParams = ParamsSchema.safeParse(params);
|
||||
|
||||
if (!parsedParams.success) {
|
||||
@@ -39,7 +39,7 @@ export async function loader({ params }: LoaderArgs) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
const parsedParams = ParamsSchema.safeParse(params);
|
||||
|
||||
if (!parsedParams.success) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { generateErrorMessage } from "zod-error";
|
||||
@@ -11,7 +11,7 @@ const BodySchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request }: ActionArgs) {
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
logger.info("action", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { CancelEventService } from "~/services/events/cancelEvent.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { CancelRunsForEventService } from "~/services/events/cancelRunsForEvent.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
eventId: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
}
|
||||
|
||||
// Next authenticate the request
|
||||
const authenticationResult = await authenticateApiRequest(request);
|
||||
|
||||
if (!authenticationResult) {
|
||||
return json({ error: "Invalid or Missing API key" }, { status: 401 });
|
||||
}
|
||||
|
||||
const authenticatedEnv = authenticationResult.environment;
|
||||
|
||||
const parsed = ParamsSchema.safeParse(params);
|
||||
|
||||
if (!parsed.success) {
|
||||
return json({ error: "Invalid or Missing eventId" }, { status: 400 });
|
||||
}
|
||||
|
||||
const { eventId } = parsed.data;
|
||||
|
||||
const service = new CancelRunsForEventService();
|
||||
try {
|
||||
const res = await service.call(authenticatedEnv, eventId);
|
||||
|
||||
if (!res) {
|
||||
return json({ error: "Event not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
return json(res);
|
||||
} catch (err) {
|
||||
logger.error("CancelRunsForEventService.call() error", { error: err });
|
||||
return json({ error: "Internal Server Error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { eventRecordToApiJson } from "~/api.server";
|
||||
@@ -10,7 +10,7 @@ const ParamsSchema = z.object({
|
||||
eventId: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { GetEvent } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -10,7 +10,7 @@ const ParamsSchema = z.object({
|
||||
eventId: z.string(),
|
||||
});
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
if (request.method.toUpperCase() === "OPTIONS") {
|
||||
return apiCors(request, json({}));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { SendEventBodySchema } from "@trigger.dev/core";
|
||||
import { generateErrorMessage } from "zod-error";
|
||||
@@ -6,7 +6,7 @@ import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { IngestSendEvent } from "~/services/events/ingestSendEvent.server";
|
||||
import { eventRecordToApiJson } from "~/api.server";
|
||||
|
||||
export async function action({ request }: ActionArgs) {
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { LoaderArgs, json } from "@remix-run/server-runtime";
|
||||
import { LoaderFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "~/db.server";
|
||||
import { resolveApiConnection } from "~/models/runConnection.server";
|
||||
@@ -10,7 +10,7 @@ const ParamsSchema = z.object({
|
||||
connectionId: z.string(),
|
||||
});
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
const authenticationResult = await authenticateApiRequest(request);
|
||||
if (!authenticationResult) {
|
||||
return json({ error: "Invalid or Missing API key" }, { status: 401 });
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "~/db.server";
|
||||
@@ -14,7 +14,7 @@ const SearchQuerySchema = z.object({
|
||||
take: z.coerce.number().default(20),
|
||||
});
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
if (request.method.toUpperCase() === "OPTIONS") {
|
||||
return apiCors(request, json({}));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { PrismaErrorSchema } from "~/db.server";
|
||||
import { z } from "zod";
|
||||
@@ -10,7 +10,7 @@ const ParamsSchema = z.object({
|
||||
runId: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Organization, RuntimeEnvironment } from "@trigger.dev/database";
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import type { LogMessage } from "@trigger.dev/core";
|
||||
import { LogMessageSchema } from "@trigger.dev/core";
|
||||
@@ -13,7 +13,7 @@ const ParamsSchema = z.object({
|
||||
runId: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import {
|
||||
JobRunStatusRecordSchema,
|
||||
@@ -19,7 +19,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "PUT") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { JobRunStatusRecordSchema } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -13,7 +13,7 @@ const ParamsSchema = z.object({
|
||||
|
||||
const RecordsSchema = z.array(JobRunStatusRecordSchema);
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
if (request.method.toUpperCase() === "OPTIONS") {
|
||||
return apiCors(request, json({}));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { RuntimeEnvironmentType } from "@trigger.dev/database";
|
||||
import { z } from "zod";
|
||||
@@ -12,7 +12,7 @@ const ParamsSchema = z.object({
|
||||
secret: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import type { CompleteTaskBodyOutput, ServerTask } from "@trigger.dev/core";
|
||||
import { CompleteTaskBodyInputSchema } from "@trigger.dev/core";
|
||||
@@ -14,7 +14,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { FailTaskBodyInput, FailTaskBodyInputSchema, ServerTask } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -14,7 +14,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { TaskStatus } from "@trigger.dev/database";
|
||||
import {
|
||||
@@ -28,7 +28,7 @@ const HeadersSchema = z.object({
|
||||
"x-cached-tasks-cursor": z.string().optional().nullable(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { ApiRunPresenter } from "~/presenters/ApiRunPresenter.server";
|
||||
@@ -17,7 +17,7 @@ const SearchQuerySchema = z.object({
|
||||
taskdetails: z.coerce.boolean().default(false),
|
||||
});
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
if (request.method.toUpperCase() === "OPTIONS") {
|
||||
return apiCors(request, json({}));
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { ActionArgs, LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { HandleHttpSourceService } from "~/services/sources/handleHttpSource.server";
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Handling http source", { url: request.url });
|
||||
|
||||
try {
|
||||
@@ -26,7 +26,7 @@ export async function action({ request, params }: ActionArgs) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function loader({ request, params }: LoaderArgs) {
|
||||
export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
logger.info("Handling http source", { url: request.url });
|
||||
|
||||
const { id } = z.object({ id: z.string() }).parse(params);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { prisma } from "~/db.server";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
|
||||
export async function loader({ request }: LoaderArgs) {
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
// Next authenticate the request
|
||||
const authenticationResult = await authenticateApiRequest(request);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { UpdateTriggerSourceBodyV2Schema } from "@trigger.dev/core";
|
||||
import { z } from "zod";
|
||||
@@ -11,7 +11,7 @@ const ParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Updating source", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import {
|
||||
REGISTER_SOURCE_EVENT_V2,
|
||||
@@ -10,6 +10,7 @@ import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { IngestSendEvent } from "~/services/events/ingestSendEvent.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { RegisterTriggerSourceServiceV2 } from "~/services/triggers/registerTriggerSourceV2.server";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
endpointSlug: z.string(),
|
||||
@@ -17,7 +18,11 @@ const ParamsSchema = z.object({
|
||||
key: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionArgs) {
|
||||
const HeadersSchema = z.object({
|
||||
"idempotency-key": z.string().optional(),
|
||||
});
|
||||
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.info("Registering trigger", { url: request.url });
|
||||
|
||||
// Ensure this is a POST request
|
||||
@@ -77,11 +82,18 @@ export async function action({ request, params }: ActionArgs) {
|
||||
dynamicTriggerId: parsedParams.data.id,
|
||||
};
|
||||
|
||||
const headers = HeadersSchema.safeParse(Object.fromEntries(request.headers));
|
||||
|
||||
const eventId =
|
||||
headers.success && headers.data["idempotency-key"]
|
||||
? headers.data["idempotency-key"]
|
||||
: `${registration.id}:${nanoid()}`;
|
||||
|
||||
const ingestEventService = new IngestSendEvent();
|
||||
await ingestEventService.call(
|
||||
authenticatedEnv,
|
||||
{
|
||||
id: registration.id,
|
||||
id: eventId,
|
||||
name: REGISTER_SOURCE_EVENT_V2,
|
||||
source: "trigger.dev",
|
||||
payload,
|
||||
|
||||
@@ -127,7 +127,8 @@ export default function Page() {
|
||||
|
||||
const [form, { name, email, confirmEmail }] = useForm({
|
||||
id: "confirm-basic-details",
|
||||
lastSubmission,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parse(formData, { schema: createSchema() });
|
||||
},
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { getInviteFromToken } from "~/models/member.server";
|
||||
import { redirectWithErrorMessage, redirectWithSuccessMessage } from "~/models/message.server";
|
||||
import { getUser } from "~/services/session.server";
|
||||
|
||||
export async function loader({ request }: LoaderArgs) {
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const user = await getUser(request);
|
||||
|
||||
const url = new URL(request.url);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user