Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| babe1c0e54 | |||
| 1224fceb18 | |||
| 8277f4d249 | |||
| 73cb8839a5 | |||
| 5d0a731cf6 | |||
| 25a152517e | |||
| d1092fcd2c | |||
| 61d33ed1b8 | |||
| 7a51612fc8 | |||
| 4d380173c8 | |||
| 8880d8afe2 | |||
| ef037af457 | |||
| 390ac6101e | |||
| aa97bf4a52 | |||
| 86d6e102a4 | |||
| adf497bc3e | |||
| f7bf25f03f | |||
| f8cab96fa2 | |||
| 225614fea3 | |||
| 740b7b2385 |
@@ -3,7 +3,12 @@ on:
|
||||
workflow_call:
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||
strategy:
|
||||
fail-fast: true # when a job fails, all remaining ones will be cancelled
|
||||
matrix:
|
||||
runs-on: [buildjet-4vcpu-ubuntu-2204, buildjet-4vcpu-ubuntu-2204-arm]
|
||||
name: ${{matrix.runs-on}}
|
||||
runs-on: ${{matrix.runs-on}}
|
||||
outputs:
|
||||
version: ${{ steps.get_version.outputs.version }}
|
||||
short_sha: ${{ steps.get_commit.outputs.sha_short }}
|
||||
@@ -36,6 +41,9 @@ jobs:
|
||||
echo "Invalid reference: ${GITHUB_REF}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ${{matrix.runs-on}} == *-arm ]]; then
|
||||
IMAGE_TAG="${IMAGE_TAG}-arm"
|
||||
fi
|
||||
echo "::set-output name=version::${IMAGE_TAG}"
|
||||
- name: 🔢 Get the commit hash
|
||||
id: get_commit
|
||||
@@ -65,8 +73,12 @@ jobs:
|
||||
- name: 🐙 Push 'latest' to GitHub Container Registry
|
||||
if: startsWith(github.ref, 'refs/tags/v.docker')
|
||||
run: |
|
||||
docker tag release_build_image $REGISTRY/$REPOSITORY:latest
|
||||
docker push $REGISTRY/$REPOSITORY:latest
|
||||
LATEST=latest
|
||||
if [[ ${{matrix.runs-on}} == *-arm ]]; then
|
||||
LATEST="${LATEST}-arm"
|
||||
fi
|
||||
docker tag release_build_image $REGISTRY/$REPOSITORY:$LATEST
|
||||
docker push $REGISTRY/$REPOSITORY:$LATEST
|
||||
env:
|
||||
REGISTRY: ghcr.io/triggerdotdev
|
||||
REPOSITORY: trigger.dev
|
||||
|
||||
@@ -5,9 +5,11 @@ type Environment = Pick<RuntimeEnvironment, "type">;
|
||||
|
||||
export function EnvironmentLabel({
|
||||
environment,
|
||||
userName,
|
||||
className,
|
||||
}: {
|
||||
environment: Environment;
|
||||
userName?: string;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
@@ -18,19 +20,19 @@ export function EnvironmentLabel({
|
||||
className
|
||||
)}
|
||||
>
|
||||
{environmentTitle(environment)}
|
||||
{environmentTitle(environment, userName)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function environmentTitle(environment: Environment) {
|
||||
export function environmentTitle(environment: Environment, username?: string) {
|
||||
switch (environment.type) {
|
||||
case "PRODUCTION":
|
||||
return "Prod";
|
||||
case "STAGING":
|
||||
return "Staging";
|
||||
case "DEVELOPMENT":
|
||||
return "Dev";
|
||||
return username ? `Dev: ${username}` : "Dev";
|
||||
case "PREVIEW":
|
||||
return "Preview";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { CodeBlock } from "../code/CodeBlock";
|
||||
import { DateTime } from "../primitives/DateTime";
|
||||
import { Header3 } from "../primitives/Headers";
|
||||
import {
|
||||
RunPanel,
|
||||
RunPanelBody,
|
||||
RunPanelDivider,
|
||||
RunPanelIconProperty,
|
||||
RunPanelIconSection,
|
||||
} from "~/components/run/RunCard";
|
||||
import { Event } from "~/presenters/EventPresenter.server";
|
||||
|
||||
export function EventDetail({ event }: { event: Event }) {
|
||||
const { id, name, payload, context, timestamp, deliveredAt } = event;
|
||||
|
||||
return (
|
||||
<RunPanel selected={false}>
|
||||
<RunPanelBody>
|
||||
<RunPanelIconSection>
|
||||
<RunPanelIconProperty
|
||||
icon="calendar"
|
||||
label="Created"
|
||||
value={<DateTime date={timestamp} />}
|
||||
/>
|
||||
{deliveredAt && (
|
||||
<RunPanelIconProperty
|
||||
icon="flag"
|
||||
label="Delivered"
|
||||
value={<DateTime date={deliveredAt} />}
|
||||
/>
|
||||
)}
|
||||
<RunPanelIconProperty icon="id" label="Event name" value={name} />
|
||||
<RunPanelIconProperty icon="account" label="Event ID" value={id} />
|
||||
</RunPanelIconSection>
|
||||
<RunPanelDivider />
|
||||
<div className="mt-4 flex flex-col gap-2">
|
||||
<Header3>Payload</Header3>
|
||||
<CodeBlock code={payload} />
|
||||
<Header3>Context</Header3>
|
||||
<CodeBlock code={context} />
|
||||
</div>
|
||||
</RunPanelBody>
|
||||
</RunPanel>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { z } from "zod";
|
||||
import { DirectionSchema, FilterableEnvironment } from "~/components/runs/RunStatuses";
|
||||
|
||||
export const EventListSearchSchema = z.object({
|
||||
cursor: z.string().optional(),
|
||||
direction: DirectionSchema.optional(),
|
||||
environment: FilterableEnvironment.optional(),
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import { useNavigate } from "@remix-run/react";
|
||||
import { useOptimisticLocation } from "~/hooks/useOptimisticLocation";
|
||||
import { EnvironmentLabel } from "../environments/EnvironmentLabel";
|
||||
import { Paragraph } from "../primitives/Paragraph";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../primitives/Select";
|
||||
import { EventListSearchSchema } from "./EventStatuses";
|
||||
import { environmentKeys, FilterableEnvironment } from "~/components/runs/RunStatuses";
|
||||
|
||||
export function EventsFilters() {
|
||||
const navigate = useNavigate();
|
||||
const location = useOptimisticLocation();
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const { environment } = EventListSearchSchema.parse(Object.fromEntries(searchParams.entries()));
|
||||
|
||||
const handleFilterChange = (filterType: string, value: string | undefined) => {
|
||||
if (value) {
|
||||
searchParams.set(filterType, value);
|
||||
} else {
|
||||
searchParams.delete(filterType);
|
||||
}
|
||||
searchParams.delete("cursor");
|
||||
searchParams.delete("direction");
|
||||
navigate(`${location.pathname}?${searchParams.toString()}`);
|
||||
};
|
||||
|
||||
const handleEnvironmentChange = (value: FilterableEnvironment | "ALL") => {
|
||||
handleFilterChange("environment", value === "ALL" ? undefined : value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-row justify-between gap-x-2">
|
||||
<SelectGroup>
|
||||
<Select
|
||||
name="environment"
|
||||
value={environment ?? "ALL"}
|
||||
onValueChange={handleEnvironmentChange}
|
||||
>
|
||||
<SelectTrigger size="secondary/small" width="full">
|
||||
<SelectValue placeholder={"Select environment"} className="ml-2 p-0" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={"ALL"}>
|
||||
<Paragraph variant="extra-small" className="pl-0.5">
|
||||
All environments
|
||||
</Paragraph>
|
||||
</SelectItem>
|
||||
{environmentKeys.map((env) => (
|
||||
<SelectItem key={env} value={env}>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<EnvironmentLabel environment={{ type: env }} />
|
||||
<Paragraph variant="extra-small">environment</Paragraph>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</SelectGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import { StopIcon } from "@heroicons/react/24/outline";
|
||||
import { CheckIcon } from "@heroicons/react/24/solid";
|
||||
import { RuntimeEnvironmentType, User } from "@trigger.dev/database";
|
||||
import { EnvironmentLabel } from "../environments/EnvironmentLabel";
|
||||
import { DateTime } from "../primitives/DateTime";
|
||||
import { Paragraph } from "../primitives/Paragraph";
|
||||
import { Spinner } from "../primitives/Spinner";
|
||||
import {
|
||||
Table,
|
||||
TableBlankRow,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableCellChevron,
|
||||
TableHeader,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
} from "../primitives/Table";
|
||||
|
||||
type EventTableItem = {
|
||||
id: string;
|
||||
name: string | null;
|
||||
environment: {
|
||||
type: RuntimeEnvironmentType;
|
||||
userId?: string;
|
||||
userName?: string;
|
||||
};
|
||||
createdAt: Date | null;
|
||||
isTest: boolean;
|
||||
deliverAt: Date | null;
|
||||
deliveredAt: Date | null;
|
||||
cancelledAt: Date | null;
|
||||
runs: number;
|
||||
};
|
||||
|
||||
type EventsTableProps = {
|
||||
total: number;
|
||||
hasFilters: boolean;
|
||||
events: EventTableItem[];
|
||||
isLoading?: boolean;
|
||||
eventsParentPath: string;
|
||||
currentUser: User;
|
||||
};
|
||||
|
||||
export function EventsTable({
|
||||
total,
|
||||
hasFilters,
|
||||
events,
|
||||
isLoading = false,
|
||||
eventsParentPath,
|
||||
currentUser,
|
||||
}: EventsTableProps) {
|
||||
return (
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHeaderCell>Event</TableHeaderCell>
|
||||
<TableHeaderCell>Env</TableHeaderCell>
|
||||
<TableHeaderCell>Received Time</TableHeaderCell>
|
||||
<TableHeaderCell>Delivery Time</TableHeaderCell>
|
||||
<TableHeaderCell>Delivered</TableHeaderCell>
|
||||
<TableHeaderCell>Canceled Time</TableHeaderCell>
|
||||
<TableHeaderCell>Test</TableHeaderCell>
|
||||
<TableHeaderCell>Runs</TableHeaderCell>
|
||||
<TableHeaderCell>
|
||||
<span className="sr-only">Go to page</span>
|
||||
</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{total === 0 && !hasFilters ? (
|
||||
<TableBlankRow colSpan={9}>
|
||||
<NoEvents title="No events found" />
|
||||
</TableBlankRow>
|
||||
) : events.length === 0 ? (
|
||||
<TableBlankRow colSpan={9}>
|
||||
<NoEvents title="No events match your filters" />
|
||||
</TableBlankRow>
|
||||
) : (
|
||||
events.map((event) => {
|
||||
const path = `${eventsParentPath}/events/${event.id}`;
|
||||
const usernameForEnv =
|
||||
currentUser.id !== event.environment.userId ? event.environment.userName : undefined;
|
||||
|
||||
return (
|
||||
<TableRow key={event.id}>
|
||||
<TableCell to={path}>{typeof event.name === "string" ? event.name : "-"}</TableCell>
|
||||
<TableCell to={path}>
|
||||
<EnvironmentLabel environment={event.environment} userName={usernameForEnv} />
|
||||
</TableCell>
|
||||
<TableCell to={path}>
|
||||
{event.createdAt ? <DateTime date={event.createdAt} /> : "–"}
|
||||
</TableCell>
|
||||
<TableCell to={path}>
|
||||
{event.deliverAt ? <DateTime date={event.deliverAt} /> : "–"}
|
||||
</TableCell>
|
||||
<TableCell to={path}>
|
||||
{event.deliveredAt ? <DateTime date={event.deliveredAt} /> : "–"}
|
||||
</TableCell>
|
||||
<TableCell to={path}>
|
||||
{event.cancelledAt ? <DateTime date={event.cancelledAt} /> : "–"}
|
||||
</TableCell>
|
||||
<TableCell to={path}>
|
||||
{event.isTest ? (
|
||||
<CheckIcon className="h-4 w-4 text-slate-400" />
|
||||
) : (
|
||||
<StopIcon className="h-4 w-4 text-slate-850" />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell to={path}>{event.runs}</TableCell>
|
||||
<TableCellChevron to={path} isSticky />
|
||||
</TableRow>
|
||||
);
|
||||
})
|
||||
)}
|
||||
{isLoading && (
|
||||
<TableBlankRow
|
||||
colSpan={8}
|
||||
className="absolute left-0 top-0 flex h-full w-full items-center justify-center gap-2 bg-slate-900/90"
|
||||
>
|
||||
<Spinner /> <span className="text-dimmed">Loading…</span>
|
||||
</TableBlankRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
function NoEvents({ title }: { title: string }) {
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<Paragraph className="w-auto">{title}</Paragraph>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,37 +3,10 @@ import { CodeExample } from "~/routes/resources.codeexample";
|
||||
import { Api } from "~/services/externalApis/apis.server";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { Feedback } from "../Feedback";
|
||||
import { Header1, Header2 } from "../primitives/Headers";
|
||||
import { Header1, Header2, Header3 } from "../primitives/Headers";
|
||||
import { Paragraph } from "../primitives/Paragraph";
|
||||
import { TextLink } from "../primitives/TextLink";
|
||||
|
||||
const fallbackExamples = [
|
||||
{
|
||||
title: "Post to Slack when meetings are booked or cancelled.",
|
||||
slug: "cal-slack-meeting-alert",
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/cal-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Translate some text with DeepL.",
|
||||
slug: "translate-text-with-deepl",
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/deepl.ts",
|
||||
},
|
||||
{
|
||||
title: "Create a Discord bot and send a message to a channel.",
|
||||
slug: "discord-bot-send-message",
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/discord.ts",
|
||||
},
|
||||
{
|
||||
title: "Retrieve a Notion page by ID.",
|
||||
slug: "retrieve-notion-page",
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/notion.ts",
|
||||
},
|
||||
];
|
||||
|
||||
export function CustomHelp({ api }: { api: Api }) {
|
||||
const [selectedExample, setSelectedExample] = useState(0);
|
||||
|
||||
@@ -43,7 +16,7 @@ export function CustomHelp({ api }: { api: Api }) {
|
||||
|
||||
return (
|
||||
<div className="mt-4">
|
||||
<Header1 className="mb-2">Using an API with an SDK or requests</Header1>
|
||||
<Header1 className="mb-2">Using {api.name} with an SDK or requests</Header1>
|
||||
<Paragraph spacing>
|
||||
You can use Trigger.dev with any existing Node SDK or even just using fetch. You can
|
||||
subscribe to any API with{" "}
|
||||
@@ -87,9 +60,13 @@ export function CustomHelp({ api }: { api: Api }) {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Header2 className="mb-2">Example code using fetch / an existing SDK</Header2>
|
||||
<Header2 className="mb-2">Getting started with {api.name}</Header2>
|
||||
<Paragraph spacing className="mb-4">
|
||||
We recommend searching for the official {api.name} Node SDK. If they have one, you can
|
||||
install it and then use their API documentation to get started and create tasks. If they
|
||||
don't, there are often third party SDKs you can use instead.
|
||||
</Paragraph>
|
||||
<Paragraph spacing className="mb-4">
|
||||
You can use one of our examples below as a starting point / reference for your projects.
|
||||
Please{" "}
|
||||
<Feedback
|
||||
button={
|
||||
@@ -99,24 +76,9 @@ export function CustomHelp({ api }: { api: Api }) {
|
||||
}
|
||||
defaultValue="help"
|
||||
/>{" "}
|
||||
if you're having any issues.
|
||||
if you're having any issues connecting to {api.name}, we'll help you get set up as
|
||||
quickly as possible.
|
||||
</Paragraph>
|
||||
|
||||
<div className=" flex w-full flex-row gap-4 overflow-x-scroll scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700 sm:h-full">
|
||||
{fallbackExamples.map((example, index) => (
|
||||
<button
|
||||
onClick={() => changeCodeExample(index)}
|
||||
key={example.codeUrl}
|
||||
className={cn(
|
||||
"w-64 min-w-[16rem] p-2 transition-colors duration-300 sm:w-full sm:rounded",
|
||||
"border-px focus:border-px cursor-pointer border border-slate-900 bg-slate-900 text-slate-300 transition duration-300 hover:bg-slate-800 focus:border focus:border-indigo-600"
|
||||
)}
|
||||
>
|
||||
{example.title}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<CodeExample example={fallbackExamples[selectedExample]} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
ArrowRightIcon,
|
||||
ArrowRightOnRectangleIcon,
|
||||
ChartBarIcon,
|
||||
CursorArrowRaysIcon,
|
||||
EllipsisHorizontalIcon,
|
||||
} from "@heroicons/react/20/solid";
|
||||
import { UserGroupIcon, UserPlusIcon } from "@heroicons/react/24/solid";
|
||||
@@ -31,6 +32,7 @@ import {
|
||||
projectHttpEndpointsPath,
|
||||
projectPath,
|
||||
projectRunsPath,
|
||||
projectEventsPath,
|
||||
projectSetupPath,
|
||||
projectTriggersPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
@@ -144,6 +146,12 @@ export function SideMenu({ user, project, organization, organizations }: SideMen
|
||||
data-action="triggers"
|
||||
hasWarning={project.hasInactiveExternalTriggers}
|
||||
/>
|
||||
<SideMenuItem
|
||||
name="Events"
|
||||
icon={CursorArrowRaysIcon}
|
||||
iconColor="text-sky-500"
|
||||
to={projectEventsPath(organization, project)}
|
||||
/>
|
||||
<SideMenuItem
|
||||
name="HTTP endpoints"
|
||||
icon="http-endpoint"
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
useNavigate,
|
||||
useNavigation,
|
||||
} from "@remix-run/react";
|
||||
import { RuntimeEnvironmentType } from "@trigger.dev/database";
|
||||
import { RuntimeEnvironmentType, User } from "@trigger.dev/database";
|
||||
import { useMemo } from "react";
|
||||
import { usePathName } from "~/hooks/usePathName";
|
||||
import type { RunBasicStatus } from "~/models/jobRun.server";
|
||||
@@ -66,11 +66,12 @@ type RunOverviewProps = {
|
||||
run: string;
|
||||
runsPath: string;
|
||||
};
|
||||
currentUser: User;
|
||||
};
|
||||
|
||||
const taskPattern = /\/tasks\/(.*)/;
|
||||
|
||||
export function RunOverview({ run, trigger, showRerun, paths }: RunOverviewProps) {
|
||||
export function RunOverview({ run, trigger, showRerun, paths, currentUser }: RunOverviewProps) {
|
||||
const navigate = useNavigate();
|
||||
const pathName = usePathName();
|
||||
|
||||
@@ -90,6 +91,9 @@ export function RunOverview({ run, trigger, showRerun, paths }: RunOverviewProps
|
||||
}
|
||||
}, [pathName]);
|
||||
|
||||
const usernameForEnv =
|
||||
currentUser.id !== run.environment.userId ? run.environment.userName : undefined;
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageHeader>
|
||||
@@ -136,7 +140,7 @@ export function RunOverview({ run, trigger, showRerun, paths }: RunOverviewProps
|
||||
<PageInfoProperty icon={"property"} label={"Version"} value={`v${run.version}`} />
|
||||
<PageInfoProperty
|
||||
label={"Env"}
|
||||
value={<EnvironmentLabel environment={run.environment} />}
|
||||
value={<EnvironmentLabel environment={run.environment} userName={usernameForEnv} />}
|
||||
/>
|
||||
<PageInfoProperty
|
||||
icon={"clock"}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
import {
|
||||
CheckCircleIcon,
|
||||
ClockIcon,
|
||||
ExclamationTriangleIcon,
|
||||
NoSymbolIcon,
|
||||
PauseCircleIcon,
|
||||
XCircleIcon,
|
||||
} from "@heroicons/react/20/solid";
|
||||
import { useNavigate } from "@remix-run/react";
|
||||
import { useOptimisticLocation } from "~/hooks/useOptimisticLocation";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { EnvironmentLabel } from "../environments/EnvironmentLabel";
|
||||
import { Paragraph } from "../primitives/Paragraph";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../primitives/Select";
|
||||
import { Spinner } from "../primitives/Spinner";
|
||||
import {
|
||||
FilterableEnvironment,
|
||||
FilterableStatus,
|
||||
RunListSearchSchema,
|
||||
environmentKeys,
|
||||
statusKeys,
|
||||
} from "./RunStatuses";
|
||||
|
||||
export function RunsFilters() {
|
||||
const navigate = useNavigate();
|
||||
const location = useOptimisticLocation();
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const { environment, status } = RunListSearchSchema.parse(
|
||||
Object.fromEntries(searchParams.entries())
|
||||
);
|
||||
|
||||
const handleFilterChange = (filterType: string, value: string | undefined) => {
|
||||
if (value) {
|
||||
searchParams.set(filterType, value);
|
||||
} else {
|
||||
searchParams.delete(filterType);
|
||||
}
|
||||
searchParams.delete("cursor");
|
||||
searchParams.delete("direction");
|
||||
navigate(`${location.pathname}?${searchParams.toString()}`);
|
||||
};
|
||||
|
||||
const handleStatusChange = (value: FilterableStatus | "ALL") => {
|
||||
handleFilterChange("status", value === "ALL" ? undefined : value);
|
||||
};
|
||||
|
||||
const handleEnvironmentChange = (value: FilterableEnvironment | "ALL") => {
|
||||
handleFilterChange("environment", value === "ALL" ? undefined : value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-row justify-between gap-x-2">
|
||||
<SelectGroup>
|
||||
<Select
|
||||
name="environment"
|
||||
value={environment ?? "ALL"}
|
||||
onValueChange={handleEnvironmentChange}
|
||||
>
|
||||
<SelectTrigger size="secondary/small" width="full">
|
||||
<SelectValue placeholder={"Select environment"} className="ml-2 p-0" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={"ALL"}>
|
||||
<Paragraph variant="extra-small" className="pl-0.5">
|
||||
All environments
|
||||
</Paragraph>
|
||||
</SelectItem>
|
||||
{environmentKeys.map((env) => (
|
||||
<SelectItem key={env} value={env}>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<EnvironmentLabel environment={{ type: env }} />
|
||||
<Paragraph variant="extra-small">environment</Paragraph>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</SelectGroup>
|
||||
|
||||
<SelectGroup>
|
||||
<Select name="status" value={status ?? "ALL"} onValueChange={handleStatusChange}>
|
||||
<SelectTrigger size="secondary/small" width="full">
|
||||
<SelectValue placeholder="Select status" className="ml-2 p-0" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={"ALL"}>
|
||||
<Paragraph variant="extra-small" className="pl-0.5">
|
||||
All statuses
|
||||
</Paragraph>
|
||||
</SelectItem>
|
||||
{statusKeys.map((status) => (
|
||||
<SelectItem key={status} value={status}>
|
||||
{
|
||||
<span className="flex items-center gap-1 text-xs">
|
||||
<FilterStatusIcon status={status} className="h-4 w-4" />
|
||||
<FilterStatusLabel status={status} />
|
||||
</span>
|
||||
}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</SelectGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FilterStatusLabel({ status }: { status: FilterableStatus }) {
|
||||
return <span className={filterStatusClassNameColor(status)}>{filterStatusTitle(status)}</span>;
|
||||
}
|
||||
|
||||
export function FilterStatusIcon({
|
||||
status,
|
||||
className,
|
||||
}: {
|
||||
status: FilterableStatus;
|
||||
className: string;
|
||||
}) {
|
||||
switch (status) {
|
||||
case "COMPLETED":
|
||||
return <CheckCircleIcon className={cn(filterStatusClassNameColor(status), className)} />;
|
||||
case "WAITING":
|
||||
return <ClockIcon className={cn(filterStatusClassNameColor(status), className)} />;
|
||||
case "QUEUED":
|
||||
return <PauseCircleIcon className={cn(filterStatusClassNameColor(status), className)} />;
|
||||
case "IN_PROGRESS":
|
||||
return <Spinner className={cn(filterStatusClassNameColor(status), className)} />;
|
||||
case "TIMEDOUT":
|
||||
return (
|
||||
<ExclamationTriangleIcon className={cn(filterStatusClassNameColor(status), className)} />
|
||||
);
|
||||
case "CANCELED":
|
||||
return <NoSymbolIcon className={cn(filterStatusClassNameColor(status), className)} />;
|
||||
case "FAILED":
|
||||
return <XCircleIcon className={cn(filterStatusClassNameColor(status), className)} />;
|
||||
default: {
|
||||
const _exhaustiveCheck: never = status;
|
||||
throw new Error(`Non-exhaustive match for value: ${status}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function filterStatusTitle(status: FilterableStatus): string {
|
||||
switch (status) {
|
||||
case "QUEUED":
|
||||
return "Queued";
|
||||
case "IN_PROGRESS":
|
||||
return "In progress";
|
||||
case "WAITING":
|
||||
return "Waiting";
|
||||
case "COMPLETED":
|
||||
return "Completed";
|
||||
case "FAILED":
|
||||
return "Failed";
|
||||
case "CANCELED":
|
||||
return "Canceled";
|
||||
case "TIMEDOUT":
|
||||
return "Timed out";
|
||||
default: {
|
||||
const _exhaustiveCheck: never = status;
|
||||
throw new Error(`Non-exhaustive match for value: ${status}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function filterStatusClassNameColor(status: FilterableStatus): string {
|
||||
switch (status) {
|
||||
case "QUEUED":
|
||||
return "text-slate-500";
|
||||
case "IN_PROGRESS":
|
||||
return "text-blue-500";
|
||||
case "WAITING":
|
||||
return "text-blue-500";
|
||||
case "COMPLETED":
|
||||
return "text-green-500";
|
||||
case "FAILED":
|
||||
return "text-rose-500";
|
||||
case "CANCELED":
|
||||
return "text-slate-500";
|
||||
case "TIMEDOUT":
|
||||
return "text-amber-300";
|
||||
default: {
|
||||
const _exhaustiveCheck: never = status;
|
||||
throw new Error(`Non-exhaustive match for value: ${status}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import type { JobRunStatus } from "@trigger.dev/database";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { Spinner } from "../primitives/Spinner";
|
||||
import { z } from "zod";
|
||||
|
||||
export function RunStatus({ status }: { status: JobRunStatus }) {
|
||||
return (
|
||||
@@ -127,3 +128,44 @@ export function runStatusClassNameColor(status: JobRunStatus): string {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const DirectionSchema = z.union([z.literal("forward"), z.literal("backward")]);
|
||||
export type Direction = z.infer<typeof DirectionSchema>;
|
||||
|
||||
export const FilterableStatus = z.union([
|
||||
z.literal("QUEUED"),
|
||||
z.literal("IN_PROGRESS"),
|
||||
z.literal("WAITING"),
|
||||
z.literal("COMPLETED"),
|
||||
z.literal("FAILED"),
|
||||
z.literal("TIMEDOUT"),
|
||||
z.literal("CANCELED"),
|
||||
]);
|
||||
export type FilterableStatus = z.infer<typeof FilterableStatus>;
|
||||
|
||||
export const FilterableEnvironment = z.union([
|
||||
z.literal("DEVELOPMENT"),
|
||||
z.literal("STAGING"),
|
||||
z.literal("PRODUCTION"),
|
||||
]);
|
||||
export type FilterableEnvironment = z.infer<typeof FilterableEnvironment>;
|
||||
export const environmentKeys: FilterableEnvironment[] = ["DEVELOPMENT", "STAGING", "PRODUCTION"];
|
||||
|
||||
export const RunListSearchSchema = z.object({
|
||||
cursor: z.string().optional(),
|
||||
direction: DirectionSchema.optional(),
|
||||
status: FilterableStatus.optional(),
|
||||
environment: FilterableEnvironment.optional(),
|
||||
});
|
||||
|
||||
export const filterableStatuses: Record<FilterableStatus, JobRunStatus[]> = {
|
||||
QUEUED: ["QUEUED", "WAITING_TO_EXECUTE", "PENDING", "WAITING_ON_CONNECTIONS"],
|
||||
IN_PROGRESS: ["STARTED", "EXECUTING", "PREPROCESSING"],
|
||||
WAITING: ["WAITING_TO_CONTINUE"],
|
||||
COMPLETED: ["SUCCESS"],
|
||||
FAILED: ["FAILURE", "UNRESOLVED_AUTH", "INVALID_PAYLOAD", "ABORTED"],
|
||||
TIMEDOUT: ["TIMED_OUT"],
|
||||
CANCELED: ["CANCELED"],
|
||||
};
|
||||
|
||||
export const statusKeys: FilterableStatus[] = Object.keys(filterableStatuses) as FilterableStatus[];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { StopIcon } from "@heroicons/react/24/outline";
|
||||
import { CheckIcon } from "@heroicons/react/24/solid";
|
||||
import { JobRunStatus, RuntimeEnvironmentType } from "@trigger.dev/database";
|
||||
import { JobRunStatus, RuntimeEnvironmentType, User } from "@trigger.dev/database";
|
||||
import { formatDuration, formatDurationMilliseconds } from "~/utils";
|
||||
import { EnvironmentLabel } from "../environments/EnvironmentLabel";
|
||||
import { DateTime } from "../primitives/DateTime";
|
||||
@@ -23,6 +23,8 @@ type RunTableItem = {
|
||||
number: number | null;
|
||||
environment: {
|
||||
type: RuntimeEnvironmentType;
|
||||
userId?: string;
|
||||
userName?: string;
|
||||
};
|
||||
job: { title: string; slug: string };
|
||||
status: JobRunStatus;
|
||||
@@ -41,6 +43,7 @@ type RunsTableProps = {
|
||||
runs: RunTableItem[];
|
||||
isLoading?: boolean;
|
||||
runsParentPath: string;
|
||||
currentUser: User;
|
||||
};
|
||||
|
||||
export function RunsTable({
|
||||
@@ -50,6 +53,7 @@ export function RunsTable({
|
||||
isLoading = false,
|
||||
showJob = false,
|
||||
runsParentPath,
|
||||
currentUser,
|
||||
}: RunsTableProps) {
|
||||
return (
|
||||
<Table>
|
||||
@@ -84,6 +88,8 @@ export function RunsTable({
|
||||
const path = showJob
|
||||
? `${runsParentPath}/jobs/${run.job.slug}/runs/${run.id}/trigger`
|
||||
: `${runsParentPath}/${run.id}/trigger`;
|
||||
const usernameForEnv =
|
||||
currentUser.id !== run.environment.userId ? run.environment.userName : undefined;
|
||||
return (
|
||||
<TableRow key={run.id}>
|
||||
<TableCell to={path}>
|
||||
@@ -91,7 +97,7 @@ export function RunsTable({
|
||||
</TableCell>
|
||||
{showJob && <TableCell to={path}>{run.job.slug}</TableCell>}
|
||||
<TableCell to={path}>
|
||||
<EnvironmentLabel environment={run.environment} />
|
||||
<EnvironmentLabel environment={run.environment} userName={usernameForEnv} />
|
||||
</TableCell>
|
||||
<TableCell to={path}>
|
||||
<RunStatus status={run.status} />
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { useLocation, useNavigation } from "@remix-run/react";
|
||||
|
||||
export function useOptimisticLocation() {
|
||||
const navigation = useNavigation();
|
||||
const location = useLocation();
|
||||
|
||||
if (navigation.state === "idle" || !navigation.location) {
|
||||
return location;
|
||||
}
|
||||
|
||||
return navigation.location;
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export const usePostHog = (apiKey?: string, logging = false, debug = false): voi
|
||||
if (postHogInitialized.current === true) return;
|
||||
if (logging) console.log("Initializing PostHog");
|
||||
posthog.init(apiKey, {
|
||||
api_host: "https://app.posthog.com",
|
||||
api_host: "https://eu.posthog.com",
|
||||
opt_in_site_apps: true,
|
||||
debug,
|
||||
loaded: function (posthog) {
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { Direction, FilterableEnvironment } from "~/components/runs/RunStatuses";
|
||||
import { getUsername } from "~/utils/username";
|
||||
|
||||
type EventListOptions = {
|
||||
userId: string;
|
||||
organizationSlug: string;
|
||||
projectSlug: string;
|
||||
direction?: Direction;
|
||||
filterEnvironment?: FilterableEnvironment;
|
||||
cursor?: string;
|
||||
pageSize?: number;
|
||||
};
|
||||
|
||||
const DEFAULT_PAGE_SIZE = 20;
|
||||
|
||||
export type EventList = Awaited<ReturnType<EventListPresenter["call"]>>;
|
||||
|
||||
export class EventListPresenter {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call({
|
||||
userId,
|
||||
organizationSlug,
|
||||
projectSlug,
|
||||
filterEnvironment,
|
||||
direction = "forward",
|
||||
cursor,
|
||||
pageSize = DEFAULT_PAGE_SIZE,
|
||||
}: EventListOptions) {
|
||||
const directionMultiplier = direction === "forward" ? 1 : -1;
|
||||
|
||||
// Find the organization that the user is a member of
|
||||
const organization = await this.#prismaClient.organization.findFirstOrThrow({
|
||||
where: {
|
||||
slug: organizationSlug,
|
||||
members: { some: { userId } },
|
||||
},
|
||||
});
|
||||
|
||||
// Find the project scoped to the organization
|
||||
const project = await this.#prismaClient.project.findFirstOrThrow({
|
||||
where: {
|
||||
slug: projectSlug,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
// Find all runtimeEnvironments that the user has access to
|
||||
const environments = await this.#prismaClient.runtimeEnvironment.findMany({
|
||||
where: {
|
||||
projectId: project.id,
|
||||
},
|
||||
});
|
||||
|
||||
const events = await this.#prismaClient.eventRecord.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
deliverAt: true,
|
||||
deliveredAt: true,
|
||||
isTest: true,
|
||||
createdAt: true,
|
||||
cancelledAt: true,
|
||||
environment: {
|
||||
select: {
|
||||
type: true,
|
||||
slug: true,
|
||||
orgMember: {
|
||||
select: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
displayName: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
runs: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
internal: false,
|
||||
projectId: project.id,
|
||||
organizationId: organization.id,
|
||||
environmentId: {
|
||||
in: environments.map((environment) => environment.id),
|
||||
},
|
||||
environment: filterEnvironment ? { type: filterEnvironment } : undefined,
|
||||
},
|
||||
orderBy: [{ id: "desc" }],
|
||||
//take an extra record to tell if there are more
|
||||
take: directionMultiplier * (pageSize + 1),
|
||||
//skip the cursor if there is one
|
||||
skip: cursor ? 1 : 0,
|
||||
cursor: cursor
|
||||
? {
|
||||
id: cursor,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
const hasMore = events.length > pageSize;
|
||||
|
||||
//get cursors for next and previous pages
|
||||
let next: string | undefined;
|
||||
let previous: string | undefined;
|
||||
switch (direction) {
|
||||
case "forward":
|
||||
previous = cursor ? events.at(0)?.id : undefined;
|
||||
if (hasMore) {
|
||||
next = events[pageSize - 1]?.id;
|
||||
}
|
||||
break;
|
||||
case "backward":
|
||||
if (hasMore) {
|
||||
previous = events[1]?.id;
|
||||
next = events[pageSize]?.id;
|
||||
} else {
|
||||
next = events[pageSize - 1]?.id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const eventsToReturn =
|
||||
direction === "backward" && hasMore
|
||||
? events.slice(1, pageSize + 1)
|
||||
: events.slice(0, pageSize);
|
||||
|
||||
return {
|
||||
events: eventsToReturn.map((event) => ({
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
deliverAt: event.deliverAt,
|
||||
deliveredAt: event.deliveredAt,
|
||||
createdAt: event.createdAt,
|
||||
cancelledAt: event.cancelledAt,
|
||||
isTest: event.isTest,
|
||||
environment: {
|
||||
type: event.environment.type,
|
||||
slug: event.environment.slug,
|
||||
userId: event.environment.orgMember?.user.id,
|
||||
userName: getUsername(event.environment.orgMember?.user),
|
||||
},
|
||||
runs: event.runs.length,
|
||||
})),
|
||||
pagination: {
|
||||
next,
|
||||
previous,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
|
||||
export type Event = NonNullable<Awaited<ReturnType<EventPresenter["call"]>>>;
|
||||
|
||||
export class EventPresenter {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call({
|
||||
userId,
|
||||
projectSlug,
|
||||
organizationSlug,
|
||||
eventId,
|
||||
}: {
|
||||
userId: string;
|
||||
projectSlug: string;
|
||||
organizationSlug: string;
|
||||
eventId: string;
|
||||
}) {
|
||||
// Find the organization that the user is a member of
|
||||
const organization = await this.#prismaClient.organization.findFirstOrThrow({
|
||||
where: {
|
||||
slug: organizationSlug,
|
||||
members: { some: { userId } },
|
||||
},
|
||||
});
|
||||
|
||||
// Find the project scoped to the organization
|
||||
const project = await this.#prismaClient.project.findFirstOrThrow({
|
||||
where: {
|
||||
slug: projectSlug,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
const event = await this.#prismaClient.eventRecord.findFirst({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
payload: true,
|
||||
context: true,
|
||||
timestamp: true,
|
||||
deliveredAt: true,
|
||||
},
|
||||
where: {
|
||||
id: eventId,
|
||||
projectId: project.id,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!event) {
|
||||
throw new Error("Could not find Event");
|
||||
}
|
||||
|
||||
return {
|
||||
id: event.id,
|
||||
name: event.name,
|
||||
timestamp: event.timestamp,
|
||||
payload: JSON.stringify(event.payload, null, 2),
|
||||
context: JSON.stringify(event.context, null, 2),
|
||||
deliveredAt: event.deliveredAt,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,22 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
Direction,
|
||||
FilterableEnvironment,
|
||||
FilterableStatus,
|
||||
filterableStatuses,
|
||||
} from "~/components/runs/RunStatuses";
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { DirectionSchema } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/route";
|
||||
|
||||
export type Direction = z.infer<typeof DirectionSchema>;
|
||||
import { getUsername } from "~/utils/username";
|
||||
|
||||
type RunListOptions = {
|
||||
userId: string;
|
||||
eventId?: string;
|
||||
jobSlug?: string;
|
||||
organizationSlug: string;
|
||||
projectSlug: string;
|
||||
direction?: Direction;
|
||||
filterStatus?: FilterableStatus;
|
||||
filterEnvironment?: FilterableEnvironment;
|
||||
cursor?: string;
|
||||
pageSize?: number;
|
||||
};
|
||||
@@ -27,13 +34,18 @@ export class RunListPresenter {
|
||||
|
||||
public async call({
|
||||
userId,
|
||||
eventId,
|
||||
jobSlug,
|
||||
organizationSlug,
|
||||
projectSlug,
|
||||
filterEnvironment,
|
||||
filterStatus,
|
||||
direction = "forward",
|
||||
cursor,
|
||||
pageSize = DEFAULT_PAGE_SIZE,
|
||||
}: RunListOptions) {
|
||||
const filterStatuses = filterStatus ? filterableStatuses[filterStatus] : undefined;
|
||||
|
||||
const directionMultiplier = direction === "forward" ? 1 : -1;
|
||||
|
||||
// Find the organization that the user is a member of
|
||||
@@ -44,7 +56,6 @@ export class RunListPresenter {
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// Find the project scoped to the organization
|
||||
const project = await this.#prismaClient.project.findFirstOrThrow({
|
||||
where: {
|
||||
@@ -57,19 +68,21 @@ export class RunListPresenter {
|
||||
const environments = await this.#prismaClient.runtimeEnvironment.findMany({
|
||||
where: {
|
||||
projectId: project.id,
|
||||
OR: [
|
||||
{ orgMember: { userId } },
|
||||
{ orgMemberId: null },
|
||||
]
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const job = jobSlug ? await this.#prismaClient.job.findFirstOrThrow({
|
||||
where: {
|
||||
slug: jobSlug,
|
||||
projectId: project.id,
|
||||
},
|
||||
}) : undefined;
|
||||
const job = jobSlug
|
||||
? await this.#prismaClient.job.findFirstOrThrow({
|
||||
where: {
|
||||
slug: jobSlug,
|
||||
projectId: project.id,
|
||||
},
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const event = eventId
|
||||
? await this.#prismaClient.eventRecord.findUnique({ where: { id: eventId } })
|
||||
: undefined;
|
||||
|
||||
const runs = await this.#prismaClient.jobRun.findMany({
|
||||
select: {
|
||||
@@ -87,7 +100,13 @@ export class RunListPresenter {
|
||||
slug: true,
|
||||
orgMember: {
|
||||
select: {
|
||||
userId: true,
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
displayName: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -105,12 +124,15 @@ export class RunListPresenter {
|
||||
},
|
||||
},
|
||||
where: {
|
||||
eventId: event?.id,
|
||||
jobId: job?.id,
|
||||
projectId: project.id,
|
||||
organizationId: organization.id,
|
||||
environmentId: {
|
||||
in: environments.map((environment) => environment.id),
|
||||
},
|
||||
status: filterStatuses ? { in: filterStatuses } : undefined,
|
||||
environment: filterEnvironment ? { type: filterEnvironment } : undefined,
|
||||
},
|
||||
orderBy: [{ id: "desc" }],
|
||||
//take an extra record to tell if there are more
|
||||
@@ -119,8 +141,8 @@ export class RunListPresenter {
|
||||
skip: cursor ? 1 : 0,
|
||||
cursor: cursor
|
||||
? {
|
||||
id: cursor,
|
||||
}
|
||||
id: cursor,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
@@ -163,7 +185,8 @@ export class RunListPresenter {
|
||||
environment: {
|
||||
type: run.environment.type,
|
||||
slug: run.environment.slug,
|
||||
userId: run.environment.orgMember?.userId,
|
||||
userId: run.environment.orgMember?.user.id,
|
||||
userName: getUsername(run.environment.orgMember?.user),
|
||||
},
|
||||
job: run.job,
|
||||
})),
|
||||
|
||||
@@ -8,6 +8,7 @@ import { PrismaClient, prisma } from "~/db.server";
|
||||
import { isRunCompleted, runBasicStatus } from "~/models/jobRun.server";
|
||||
import { mergeProperties } from "~/utils/mergeProperties.server";
|
||||
import { taskListToTree } from "~/utils/taskListToTree";
|
||||
import { getUsername } from "~/utils/username";
|
||||
|
||||
type RunOptions = {
|
||||
id: string;
|
||||
@@ -79,6 +80,8 @@ export class RunPresenter {
|
||||
environment: {
|
||||
type: run.environment.type,
|
||||
slug: run.environment.slug,
|
||||
userId: run.environment.orgMember?.user.id,
|
||||
userName: getUsername(run.environment.orgMember?.user),
|
||||
},
|
||||
event: this.#prepareEventData(run.event),
|
||||
tasks,
|
||||
@@ -130,6 +133,17 @@ export class RunPresenter {
|
||||
select: {
|
||||
type: true,
|
||||
slug: true,
|
||||
orgMember: {
|
||||
select: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
displayName: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
event: {
|
||||
|
||||
@@ -2,7 +2,8 @@ import { TriggerSource, User } from "@trigger.dev/database";
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { Organization } from "~/models/organization.server";
|
||||
import { Project } from "~/models/project.server";
|
||||
import { Direction, RunList, RunListPresenter } from "./RunListPresenter.server";
|
||||
import { RunList, RunListPresenter } from "./RunListPresenter.server";
|
||||
import { Direction } from "~/components/runs/RunStatuses";
|
||||
|
||||
export class TriggerSourcePresenter {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Direction } from "~/components/runs/RunStatuses";
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { Direction } from "./RunListPresenter.server";
|
||||
|
||||
type RunListOptions = {
|
||||
userId: string;
|
||||
|
||||
@@ -2,9 +2,9 @@ import { User, Webhook } from "@trigger.dev/database";
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { Organization } from "~/models/organization.server";
|
||||
import { Project } from "~/models/project.server";
|
||||
import { Direction } from "./RunListPresenter.server";
|
||||
import { organizationPath, projectPath } from "~/utils/pathBuilder";
|
||||
import { WebhookDeliveryListPresenter } from "./WebhookDeliveryListPresenter.server";
|
||||
import { Direction } from "~/components/runs/RunStatuses";
|
||||
|
||||
export class WebhookDeliveryPresenter {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
@@ -2,8 +2,9 @@ import { User, Webhook } from "@trigger.dev/database";
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { Organization } from "~/models/organization.server";
|
||||
import { Project } from "~/models/project.server";
|
||||
import { Direction, RunListPresenter } from "./RunListPresenter.server";
|
||||
import { RunListPresenter } from "./RunListPresenter.server";
|
||||
import { organizationPath, projectPath } from "~/utils/pathBuilder";
|
||||
import { Direction } from "~/components/runs/RunStatuses";
|
||||
|
||||
export class WebhookSourcePresenter {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
import { PageHeader, PageTitle, PageTitleRow } from "~/components/primitives/PageHeader";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { EventParamSchema, projectEventsPath, projectPath } from "~/utils/pathBuilder";
|
||||
import { BreadcrumbLink } from "~/components/navigation/Breadcrumb";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import { EventDetail } from "~/components/event/EventDetail";
|
||||
import { EventPresenter } from "~/presenters/EventPresenter.server";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { Fragment } from "react";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { RunListSearchSchema } from "~/components/runs/RunStatuses";
|
||||
import { RunListPresenter } from "~/presenters/RunListPresenter.server";
|
||||
import { RunsTable } from "~/components/runs/RunsTable";
|
||||
import { RunsFilters } from "~/components/runs/RunFilters";
|
||||
import { ListPagination } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/ListPagination";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { useNavigation } from "@remix-run/react";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { eventParam, projectParam, organizationSlug } = EventParamSchema.parse(params);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const s = Object.fromEntries(url.searchParams.entries());
|
||||
const searchParams = RunListSearchSchema.parse(s);
|
||||
|
||||
const presenter = new EventPresenter();
|
||||
try {
|
||||
const event = await presenter.call({
|
||||
userId,
|
||||
projectSlug: projectParam,
|
||||
organizationSlug,
|
||||
eventId: eventParam,
|
||||
});
|
||||
|
||||
if (!event) {
|
||||
throw new Response("Not Found", { status: 404 });
|
||||
}
|
||||
|
||||
const runsPresenter = new RunListPresenter();
|
||||
|
||||
const list = await runsPresenter.call({
|
||||
userId,
|
||||
filterEnvironment: searchParams.environment,
|
||||
filterStatus: searchParams.status,
|
||||
eventId: event.id,
|
||||
projectSlug: projectParam,
|
||||
organizationSlug,
|
||||
direction: searchParams.direction,
|
||||
cursor: searchParams.cursor,
|
||||
});
|
||||
|
||||
return typedjson({ event, list });
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
throw new Response(e instanceof Error ? e.message : JSON.stringify(e), { status: 404 });
|
||||
}
|
||||
};
|
||||
|
||||
export const handle: Handle = {
|
||||
breadcrumb: (match) => {
|
||||
const eventData = useTypedMatchData<typeof loader>(match);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{eventData && eventData.event && (
|
||||
<BreadcrumbLink to={match.pathname} title={eventData.event.name} />
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const { event, list } = useTypedLoaderData<typeof loader>();
|
||||
const navigation = useNavigation();
|
||||
const isLoading = navigation.state !== "idle";
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageHeader>
|
||||
<PageTitleRow>
|
||||
<PageTitle
|
||||
title={event.name}
|
||||
backButton={{
|
||||
to: projectEventsPath(organization, project),
|
||||
text: "Events",
|
||||
}}
|
||||
/>
|
||||
</PageTitleRow>
|
||||
</PageHeader>
|
||||
|
||||
<PageBody scrollable={false}>
|
||||
<div className="grid h-full grid-cols-2">
|
||||
<div className="overflow-y-auto p-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700">
|
||||
<EventDetail event={event} />
|
||||
</div>
|
||||
|
||||
<div className="overflow-y-auto p-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700">
|
||||
<div className="mb-2 flex items-center justify-between gap-x-2">
|
||||
<RunsFilters />
|
||||
<div className="flex items-center justify-end gap-x-2">
|
||||
<ListPagination list={list} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RunsTable
|
||||
total={list.runs.length}
|
||||
hasFilters={false}
|
||||
runs={list.runs}
|
||||
isLoading={isLoading}
|
||||
showJob={true}
|
||||
runsParentPath={projectPath(organization, project)}
|
||||
currentUser={user}
|
||||
/>
|
||||
<ListPagination list={list} className="mt-2 justify-end" />
|
||||
</div>
|
||||
</div>
|
||||
</PageBody>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
import { useNavigation } from "@remix-run/react";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
import { LinkButton } from "~/components/primitives/Buttons";
|
||||
import {
|
||||
PageButtons,
|
||||
PageDescription,
|
||||
PageHeader,
|
||||
PageTitle,
|
||||
PageTitleRow,
|
||||
} from "~/components/primitives/PageHeader";
|
||||
import { EventsTable } from "~/components/events/EventsTable";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { EventListPresenter } from "~/presenters/EventListPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { ProjectParamSchema, docsPath, projectPath, trimTrailingSlash } from "~/utils/pathBuilder";
|
||||
import { ListPagination } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/ListPagination";
|
||||
import { EventListSearchSchema } from "~/components/events/EventStatuses";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { EventsFilters } from "~/components/events/EventsFilters";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { projectParam, organizationSlug } = ProjectParamSchema.parse(params);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const s = Object.fromEntries(url.searchParams.entries());
|
||||
const searchParams = EventListSearchSchema.parse(s);
|
||||
|
||||
const presenter = new EventListPresenter();
|
||||
const list = await presenter.call({
|
||||
userId,
|
||||
filterEnvironment: searchParams.environment,
|
||||
projectSlug: projectParam,
|
||||
organizationSlug,
|
||||
direction: searchParams.direction,
|
||||
cursor: searchParams.cursor,
|
||||
pageSize: 25,
|
||||
});
|
||||
|
||||
return typedjson({
|
||||
list,
|
||||
});
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const { list } = useTypedLoaderData<typeof loader>();
|
||||
const navigation = useNavigation();
|
||||
const isLoading = navigation.state !== "idle";
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageHeader>
|
||||
<PageTitleRow>
|
||||
<PageTitle title={`${project.name} events`} />
|
||||
<PageButtons>
|
||||
<LinkButton
|
||||
LeadingIcon={"docs"}
|
||||
to={docsPath("documentation/concepts/triggers/events")}
|
||||
variant="secondary/small"
|
||||
>
|
||||
Event documentation
|
||||
</LinkButton>
|
||||
</PageButtons>
|
||||
</PageTitleRow>
|
||||
<PageDescription>All events in this project</PageDescription>
|
||||
</PageHeader>
|
||||
|
||||
<PageBody scrollable={false}>
|
||||
<div className="h-full overflow-y-auto p-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700">
|
||||
<div className="mb-2 flex items-center justify-between gap-x-2">
|
||||
<EventsFilters />
|
||||
<ListPagination list={list} />
|
||||
</div>
|
||||
<EventsTable
|
||||
total={list.events.length}
|
||||
hasFilters={false}
|
||||
events={list.events}
|
||||
isLoading={isLoading}
|
||||
eventsParentPath={projectPath(organization, project)}
|
||||
currentUser={user}
|
||||
/>
|
||||
<ListPagination list={list} className="mt-2 justify-end" />
|
||||
</div>
|
||||
</PageBody>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { Outlet } from "@remix-run/react";
|
||||
import { BreadcrumbLink } from "~/components/navigation/Breadcrumb";
|
||||
import { Handle } from "~/utils/handle";
|
||||
|
||||
export const handle: Handle = {
|
||||
breadcrumb: (match) => <BreadcrumbLink to={match.pathname} title="Events" />,
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return <Outlet />;
|
||||
}
|
||||
+9
-9
@@ -1,16 +1,16 @@
|
||||
import { useLocation } from "@remix-run/react";
|
||||
import { LinkButton } from "~/components/primitives/Buttons";
|
||||
import { Direction, RunList } from "~/presenters/RunListPresenter.server";
|
||||
import { WebhookDeliveryList } from "~/presenters/WebhookDeliveryListPresenter.server";
|
||||
import { Direction } from "~/components/runs/RunStatuses";
|
||||
import { cn } from "~/utils/cn";
|
||||
|
||||
export function ListPagination({
|
||||
list,
|
||||
className,
|
||||
}: {
|
||||
list: RunList | WebhookDeliveryList;
|
||||
className?: string;
|
||||
}) {
|
||||
type List = {
|
||||
pagination: {
|
||||
next: string | undefined;
|
||||
previous: string | undefined;
|
||||
};
|
||||
};
|
||||
|
||||
export function ListPagination({ list, className }: { list: List; className?: string }) {
|
||||
return (
|
||||
<div className={cn("flex items-center gap-1", className)}>
|
||||
<PreviousButton cursor={list.pagination.previous} />
|
||||
|
||||
+14
-10
@@ -10,6 +10,7 @@ import { RunsTable } from "~/components/runs/RunsTable";
|
||||
import { useJob } from "~/hooks/useJob";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { RunListPresenter } from "~/presenters/RunListPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { cn } from "~/utils/cn";
|
||||
@@ -19,13 +20,8 @@ import {
|
||||
organizationIntegrationsPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
import { ListPagination } from "./ListPagination";
|
||||
|
||||
export const DirectionSchema = z.union([z.literal("forward"), z.literal("backward")]);
|
||||
|
||||
export const RunListSearchSchema = z.object({
|
||||
cursor: z.string().optional(),
|
||||
direction: DirectionSchema.optional(),
|
||||
});
|
||||
import { RunListSearchSchema } from "~/components/runs/RunStatuses";
|
||||
import { RunsFilters } from "~/components/runs/RunFilters";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
@@ -38,6 +34,8 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const presenter = new RunListPresenter();
|
||||
const list = await presenter.call({
|
||||
userId,
|
||||
filterEnvironment: searchParams.environment,
|
||||
filterStatus: searchParams.status,
|
||||
jobSlug: jobParam,
|
||||
projectSlug: projectParam,
|
||||
organizationSlug,
|
||||
@@ -57,6 +55,7 @@ export default function Page() {
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const job = useJob();
|
||||
const user = useUser();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -71,16 +70,21 @@ export default function Page() {
|
||||
{(open) => (
|
||||
<div className={cn("grid h-fit gap-4", open ? "grid-cols-2" : "grid-cols-1")}>
|
||||
<div>
|
||||
<div className="mb-2 flex items-center justify-end gap-x-2">
|
||||
<HelpTrigger title="How do I run my Job?" />
|
||||
<ListPagination list={list} />
|
||||
<div className="mb-2 flex items-center justify-between gap-x-2">
|
||||
<RunsFilters />
|
||||
<div className="flex items-center justify-end gap-x-2">
|
||||
<HelpTrigger title="How do I run my Job?" />
|
||||
<ListPagination list={list} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RunsTable
|
||||
total={list.runs.length}
|
||||
hasFilters={false}
|
||||
runs={list.runs}
|
||||
isLoading={isLoading}
|
||||
runsParentPath={jobRunsParentPath(organization, project, job)}
|
||||
currentUser={user}
|
||||
/>
|
||||
<ListPagination list={list} className="mt-2 justify-end" />
|
||||
</div>
|
||||
|
||||
+3
@@ -10,6 +10,7 @@ import { jobMatchId, useJob } from "~/hooks/useJob";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { RunPresenter } from "~/presenters/RunPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
@@ -63,6 +64,7 @@ export default function Page() {
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const job = useJob();
|
||||
const user = useUser();
|
||||
|
||||
const revalidator = useRevalidator();
|
||||
const events = useEventSource(runStreamingPath(organization, project, job, run), {
|
||||
@@ -86,6 +88,7 @@ export default function Page() {
|
||||
run: runPath(organization, project, job, run),
|
||||
runsPath: jobRunsParentPath(organization, project, job),
|
||||
}}
|
||||
currentUser={user}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+11
-3
@@ -1,4 +1,4 @@
|
||||
import { useNavigation } from "@remix-run/react";
|
||||
import { useLocation, useNavigate, useNavigation } from "@remix-run/react";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
@@ -13,11 +13,13 @@ import {
|
||||
import { RunsTable } from "~/components/runs/RunsTable";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { RunListPresenter } from "~/presenters/RunListPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { ProjectParamSchema, docsPath, projectPath } from "~/utils/pathBuilder";
|
||||
import { ListPagination } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/ListPagination";
|
||||
import { RunListSearchSchema } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/route";
|
||||
import { RunListSearchSchema } from "~/components/runs/RunStatuses";
|
||||
import { RunsFilters } from "~/components/runs/RunFilters";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
@@ -28,8 +30,11 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const searchParams = RunListSearchSchema.parse(s);
|
||||
|
||||
const presenter = new RunListPresenter();
|
||||
|
||||
const list = await presenter.call({
|
||||
userId,
|
||||
filterEnvironment: searchParams.environment,
|
||||
filterStatus: searchParams.status,
|
||||
projectSlug: projectParam,
|
||||
organizationSlug,
|
||||
direction: searchParams.direction,
|
||||
@@ -48,6 +53,7 @@ export default function Page() {
|
||||
const isLoading = navigation.state !== "idle";
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
@@ -69,7 +75,8 @@ export default function Page() {
|
||||
|
||||
<PageBody scrollable={false}>
|
||||
<div className="h-full overflow-y-auto p-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700">
|
||||
<div className="mb-2 flex items-center justify-end gap-x-2">
|
||||
<div className="mb-2 flex items-center justify-between gap-x-2">
|
||||
<RunsFilters />
|
||||
<ListPagination list={list} />
|
||||
</div>
|
||||
<RunsTable
|
||||
@@ -79,6 +86,7 @@ export default function Page() {
|
||||
runs={list.runs}
|
||||
isLoading={isLoading}
|
||||
runsParentPath={projectPath(organization, project)}
|
||||
currentUser={user}
|
||||
/>
|
||||
<ListPagination list={list} className="mt-2 justify-end" />
|
||||
</div>
|
||||
|
||||
+13
-12
@@ -1,11 +1,16 @@
|
||||
import { conform, useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { json } from "@remix-run/node";
|
||||
import { Form, useActionData, useNavigation } from "@remix-run/react";
|
||||
import type { ActionFunction, LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { Fragment } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { z } from "zod";
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
import { BreadcrumbLink } from "~/components/navigation/Breadcrumb";
|
||||
import { BreadcrumbIcon } from "~/components/primitives/BreadcrumbIcon";
|
||||
import { Button } from "~/components/primitives/Buttons";
|
||||
import { Callout, variantClasses } from "~/components/primitives/Callout";
|
||||
import { Header2 } from "~/components/primitives/Headers";
|
||||
import { NamedIcon } from "~/components/primitives/NamedIcon";
|
||||
@@ -18,32 +23,26 @@ import {
|
||||
PageTitleRow,
|
||||
} from "~/components/primitives/PageHeader";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
import { RunListSearchSchema } from "~/components/runs/RunStatuses";
|
||||
import { RunsTable } from "~/components/runs/RunsTable";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { redirectWithSuccessMessage } from "~/models/message.server";
|
||||
import { TriggerSourcePresenter } from "~/presenters/TriggerSourcePresenter.server";
|
||||
import { requireUser, requireUserId } from "~/services/session.server";
|
||||
import { ActivateSourceService } from "~/services/sources/activateSource.server";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import {
|
||||
TriggerSourceParamSchema,
|
||||
rootPath,
|
||||
projectTriggersPath,
|
||||
externalTriggerPath,
|
||||
externalTriggerRunsParentPath,
|
||||
projectTriggersPath,
|
||||
trimTrailingSlash,
|
||||
} from "~/utils/pathBuilder";
|
||||
import { ListPagination } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/ListPagination";
|
||||
import { RunListSearchSchema } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/route";
|
||||
import { Button } from "~/components/primitives/Buttons";
|
||||
import { Form, useActionData, useNavigation } from "@remix-run/react";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { conform, useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { z } from "zod";
|
||||
import { ActivateSourceService } from "~/services/sources/activateSource.server";
|
||||
import { redirectWithSuccessMessage } from "~/models/message.server";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
@@ -130,6 +129,7 @@ export default function Page() {
|
||||
const { trigger } = useTypedLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
const navigation = useNavigation();
|
||||
const lastSubmission = useActionData();
|
||||
|
||||
@@ -234,6 +234,7 @@ export default function Page() {
|
||||
total={trigger.runList.runs.length}
|
||||
hasFilters={false}
|
||||
runsParentPath={externalTriggerRunsParentPath(organization, project, trigger)}
|
||||
currentUser={user}
|
||||
/>
|
||||
<ListPagination list={trigger.runList} className="mt-2 justify-end" />
|
||||
</>
|
||||
|
||||
+3
@@ -10,6 +10,7 @@ import { prisma } from "~/db.server";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { RunPresenter } from "~/presenters/RunPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
@@ -97,6 +98,7 @@ export default function Page() {
|
||||
const { run, trigger } = useTypedLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
|
||||
const revalidator = useRevalidator();
|
||||
const events = useEventSource(
|
||||
@@ -124,6 +126,7 @@ export default function Page() {
|
||||
id: trigger.id,
|
||||
}),
|
||||
}}
|
||||
currentUser={user}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+25
-29
@@ -1,36 +1,32 @@
|
||||
import { json } from "@remix-run/node";
|
||||
import type { ActionFunction, LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { Form, useActionData, useNavigation } from "@remix-run/react";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { Fragment } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { z } from "zod";
|
||||
import { BreadcrumbLink } from "~/components/navigation/Breadcrumb";
|
||||
import { BreadcrumbIcon } from "~/components/primitives/BreadcrumbIcon";
|
||||
import { Callout, variantClasses } from "~/components/primitives/Callout";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
import { RunListSearchSchema } from "~/components/runs/RunStatuses";
|
||||
import { RunsTable } from "~/components/runs/RunsTable";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { requireUser, requireUserId } from "~/services/session.server";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { WebhookSourcePresenter } from "~/presenters/WebhookSourcePresenter.server";
|
||||
import { requireUser } from "~/services/session.server";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import {
|
||||
TriggerSourceParamSchema,
|
||||
projectTriggersPath,
|
||||
externalTriggerPath,
|
||||
projectWebhookTriggersPath,
|
||||
trimTrailingSlash,
|
||||
webhookTriggerRunsParentPath,
|
||||
projectWebhookTriggersPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
import { ListPagination } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/ListPagination";
|
||||
import { RunListSearchSchema } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/route";
|
||||
import { Button } from "~/components/primitives/Buttons";
|
||||
import { Form, useActionData, useNavigation } from "@remix-run/react";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { conform, useForm } from "@conform-to/react";
|
||||
import { parse } from "@conform-to/zod";
|
||||
import { z } from "zod";
|
||||
import { ActivateSourceService } from "~/services/sources/activateSource.server";
|
||||
import { redirectWithSuccessMessage } from "~/models/message.server";
|
||||
import { WebhookSourcePresenter } from "~/presenters/WebhookSourcePresenter.server";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
@@ -105,10 +101,7 @@ export const handle: Handle = {
|
||||
<BreadcrumbIcon />
|
||||
<BreadcrumbLink to={projectWebhookTriggersPath(org, project)} title="Webhook Triggers" />
|
||||
<BreadcrumbIcon />
|
||||
<BreadcrumbLink
|
||||
to={trimTrailingSlash(match.pathname)}
|
||||
title={data.trigger.key}
|
||||
/>
|
||||
<BreadcrumbLink to={trimTrailingSlash(match.pathname)} title={data.trigger.key} />
|
||||
</Fragment>
|
||||
);
|
||||
},
|
||||
@@ -118,6 +111,7 @@ export default function Page() {
|
||||
const { trigger } = useTypedLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
const navigation = useNavigation();
|
||||
const lastSubmission = useActionData();
|
||||
|
||||
@@ -135,17 +129,17 @@ export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<Paragraph variant="small" spacing>
|
||||
Webhook Triggers need to be registered with the external service. You can see the list
|
||||
of attempted registrations below.
|
||||
Webhook Triggers need to be registered with the external service. You can see the list of
|
||||
attempted registrations below.
|
||||
</Paragraph>
|
||||
|
||||
{!trigger.active &&
|
||||
{!trigger.active && (
|
||||
<Form method="post" {...form.props}>
|
||||
<Callout variant="error" className="justiy-between mb-4 items-center">
|
||||
<Paragraph variant="small" className={cn(variantClasses.error.textColor, "grow")}>
|
||||
Registration hasn't succeeded yet, check the runs below.
|
||||
</Paragraph>
|
||||
{/* <input
|
||||
<Callout variant="error" className="justiy-between mb-4 items-center">
|
||||
<Paragraph variant="small" className={cn(variantClasses.error.textColor, "grow")}>
|
||||
Registration hasn't succeeded yet, check the runs below.
|
||||
</Paragraph>
|
||||
{/* <input
|
||||
{...conform.input(jobId, { type: "hidden" })}
|
||||
defaultValue={trigger.registrationJob?.id}
|
||||
/>
|
||||
@@ -159,8 +153,9 @@ export default function Page() {
|
||||
>
|
||||
{isLoading ? "Retrying…" : "Retry now"}
|
||||
</Button> */}
|
||||
</Callout>
|
||||
</Form>}
|
||||
</Callout>
|
||||
</Form>
|
||||
)}
|
||||
|
||||
{trigger.runList ? (
|
||||
<>
|
||||
@@ -170,6 +165,7 @@ export default function Page() {
|
||||
total={trigger.runList.runs.length}
|
||||
hasFilters={false}
|
||||
runsParentPath={webhookTriggerRunsParentPath(organization, project, trigger)}
|
||||
currentUser={user}
|
||||
/>
|
||||
<ListPagination list={trigger.runList} className="mt-2 justify-end" />
|
||||
</>
|
||||
|
||||
+3
-3
@@ -5,9 +5,12 @@ import { BreadcrumbLink } from "~/components/navigation/Breadcrumb";
|
||||
import { BreadcrumbIcon } from "~/components/primitives/BreadcrumbIcon";
|
||||
import { Callout } from "~/components/primitives/Callout";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
import { RunListSearchSchema } from "~/components/runs/RunStatuses";
|
||||
import { WebhookDeliveryRunsTable } from "~/components/runs/WebhookDeliveryRunsTable";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { WebhookDeliveryPresenter } from "~/presenters/WebhookDeliveryPresenter.server";
|
||||
import { requireUser } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
import {
|
||||
@@ -19,9 +22,6 @@ import {
|
||||
webhookTriggerPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
import { ListPagination } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/ListPagination";
|
||||
import { RunListSearchSchema } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/route";
|
||||
import { WebhookDeliveryPresenter } from "~/presenters/WebhookDeliveryPresenter.server";
|
||||
import { WebhookDeliveryRunsTable } from "~/components/runs/WebhookDeliveryRunsTable";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
|
||||
+3
-8
@@ -2,7 +2,6 @@ import { Outlet } from "@remix-run/react";
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
import { NamedIcon } from "~/components/primitives/NamedIcon";
|
||||
import {
|
||||
PageHeader,
|
||||
PageInfoGroup,
|
||||
@@ -12,8 +11,10 @@ import {
|
||||
PageTitle,
|
||||
PageTitleRow,
|
||||
} from "~/components/primitives/PageHeader";
|
||||
import { RunListSearchSchema } from "~/components/runs/RunStatuses";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { WebhookSourcePresenter } from "~/presenters/WebhookSourcePresenter.server";
|
||||
import { requireUser } from "~/services/session.server";
|
||||
import {
|
||||
TriggerSourceParamSchema,
|
||||
@@ -21,8 +22,6 @@ import {
|
||||
webhookDeliveryPath,
|
||||
webhookTriggerPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
import { RunListSearchSchema } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam._index/route";
|
||||
import { WebhookSourcePresenter } from "~/presenters/WebhookSourcePresenter.server";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireUser(request);
|
||||
@@ -77,11 +76,7 @@ export default function Page() {
|
||||
value={trigger.integration.slug}
|
||||
to={trigger.integrationLink}
|
||||
/>
|
||||
<PageInfoProperty
|
||||
icon="webhook"
|
||||
label="HTTP Endpoint"
|
||||
to={trigger.httpEndpointLink}
|
||||
/>
|
||||
<PageInfoProperty icon="webhook" label="HTTP Endpoint" to={trigger.httpEndpointLink} />
|
||||
</PageInfoGroup>
|
||||
</PageInfoRow>
|
||||
<PageTabs
|
||||
|
||||
+3
@@ -10,6 +10,7 @@ import { prisma } from "~/db.server";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { RunPresenter } from "~/presenters/RunPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
@@ -103,6 +104,7 @@ export default function Page() {
|
||||
const { run, trigger } = useTypedLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
|
||||
const revalidator = useRevalidator();
|
||||
const events = useEventSource(
|
||||
@@ -130,6 +132,7 @@ export default function Page() {
|
||||
id: trigger.id,
|
||||
}),
|
||||
}}
|
||||
currentUser={user}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+7
-1
@@ -10,6 +10,7 @@ import { prisma } from "~/db.server";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { useTypedMatchData } from "~/hooks/useTypedMatchData";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { RunPresenter } from "~/presenters/RunPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { Handle } from "~/utils/handle";
|
||||
@@ -83,7 +84,10 @@ export const handle: Handle = {
|
||||
title={`${data.trigger.integration.title}: ${data.trigger.integration.slug}`}
|
||||
/>
|
||||
<BreadcrumbIcon />
|
||||
<BreadcrumbLink to={webhookDeliveryPath(org, project, { id: data.trigger.id })} title="Deliveries" />
|
||||
<BreadcrumbLink
|
||||
to={webhookDeliveryPath(org, project, { id: data.trigger.id })}
|
||||
title="Deliveries"
|
||||
/>
|
||||
<BreadcrumbIcon />
|
||||
{data && data.run && (
|
||||
<BreadcrumbLink
|
||||
@@ -100,6 +104,7 @@ export default function Page() {
|
||||
const { run, trigger } = useTypedLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const user = useUser();
|
||||
|
||||
const revalidator = useRevalidator();
|
||||
const events = useEventSource(
|
||||
@@ -127,6 +132,7 @@ export default function Page() {
|
||||
id: trigger.id,
|
||||
}),
|
||||
}}
|
||||
currentUser={user}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
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 { logger } from "~/services/logger.server";
|
||||
import { CancelRunsForJobService } from "~/services/jobs/cancelRunsForJob.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
jobSlug: 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 jobSlug" }, { status: 400 });
|
||||
}
|
||||
|
||||
const { jobSlug } = parsed.data;
|
||||
|
||||
const service = new CancelRunsForJobService();
|
||||
try {
|
||||
const res = await service.call(authenticatedEnv, jobSlug);
|
||||
|
||||
if (!res) {
|
||||
return json({ error: "Job not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
return json(res);
|
||||
} catch (err) {
|
||||
logger.error("CancelRunsForJobService.call() error", { error: err });
|
||||
return json({ error: "Internal Server Error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -48,18 +48,25 @@ export const apisList = [
|
||||
identifier: "anthropic",
|
||||
name: "Anthropic",
|
||||
},
|
||||
{
|
||||
identifier: "appsmith",
|
||||
name: "Appsmith",
|
||||
},
|
||||
{
|
||||
identifier: "appwrite",
|
||||
name: "Appwrite",
|
||||
},
|
||||
// {
|
||||
// identifier: "appsmith",
|
||||
// name: "Appsmith",
|
||||
// },
|
||||
// {
|
||||
// identifier: "appwrite",
|
||||
// name: "Appwrite",
|
||||
// },
|
||||
{
|
||||
identifier: "asana",
|
||||
name: "Asana",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Asana webhook.",
|
||||
slug: "asana-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/asana-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Get user details from Asana",
|
||||
slug: "get-user-details",
|
||||
@@ -68,10 +75,6 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "atlassian",
|
||||
name: "Atlassian",
|
||||
},
|
||||
{
|
||||
identifier: "aws",
|
||||
name: "AWS",
|
||||
@@ -82,12 +85,26 @@ export const apisList = [
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/aws.ts",
|
||||
},
|
||||
{
|
||||
title: "A job that is triggered by an AWS webhook.",
|
||||
slug: "aws-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/aws-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "brex",
|
||||
name: "Brex",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Brex webhook.",
|
||||
slug: "brex-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/brex-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Create a new title in a Brex account.",
|
||||
slug: "create-new-brex-title",
|
||||
@@ -151,38 +168,66 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
identifier: "digitalocean",
|
||||
name: "DigitalOcean",
|
||||
examples: [
|
||||
{
|
||||
title: "DigitalOcean create Uptime",
|
||||
slug: "digitalocean-create-uptime",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/digitalocean.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "discord",
|
||||
name: "Discord",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Discord webhook.",
|
||||
slug: "discord-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/discord-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Create a Discord bot and send a message to a channel.",
|
||||
slug: "discord-bot-send-message",
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/discord.ts",
|
||||
},
|
||||
{
|
||||
title: "A job that is triggered by a Discord webhook.",
|
||||
slug: "discord-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/discord-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "documenso",
|
||||
name: "Documenso",
|
||||
},
|
||||
{
|
||||
identifier: "dropbox",
|
||||
name: "Dropbox",
|
||||
},
|
||||
{
|
||||
identifier: "facebook",
|
||||
name: "Facebook",
|
||||
},
|
||||
{
|
||||
identifier: "fastify",
|
||||
name: "Fastify",
|
||||
},
|
||||
{
|
||||
identifier: "flickr",
|
||||
name: "Flickr",
|
||||
},
|
||||
// {
|
||||
// identifier: "documenso",
|
||||
// name: "Documenso",
|
||||
// },
|
||||
// {
|
||||
// identifier: "dropbox",
|
||||
// name: "Dropbox",
|
||||
// },
|
||||
// {
|
||||
// identifier: "facebook",
|
||||
// name: "Facebook",
|
||||
// },
|
||||
// {
|
||||
// identifier: "fastify",
|
||||
// name: "Fastify",
|
||||
// },
|
||||
// {
|
||||
// identifier: "flickr",
|
||||
// name: "Flickr",
|
||||
// },
|
||||
{
|
||||
identifier: "github",
|
||||
name: "GitHub",
|
||||
@@ -233,6 +278,13 @@ export const apisList = [
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/gmail.ts",
|
||||
},
|
||||
{
|
||||
title: "A job that is triggered by a Gmail webhook.",
|
||||
slug: "gmail-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/gmail-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -250,11 +302,27 @@ export const apisList = [
|
||||
{
|
||||
identifier: "googledocs",
|
||||
name: "Google Docs",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Google Docs webhook.",
|
||||
slug: "google-docs-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/google-docs-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "googledrive",
|
||||
name: "Google Drive",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Google Drive webhook.",
|
||||
slug: "google-drive-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/google-drive-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Update a filename in Google Drive.",
|
||||
slug: "update-google-drive-filename",
|
||||
@@ -279,6 +347,13 @@ export const apisList = [
|
||||
identifier: "googlesheets",
|
||||
name: "Google Sheets",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Google Sheets webhook.",
|
||||
slug: "google-sheets-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/google-sheets-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Insert data into a row in Google Sheets.",
|
||||
slug: "insert-data-into-google-sheets",
|
||||
@@ -333,6 +408,13 @@ export const apisList = [
|
||||
identifier: "instagram",
|
||||
name: "Instagram",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Instagram webhook.",
|
||||
slug: "instagram-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/instagram-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Post an image to Instagram",
|
||||
slug: "post-image-to-instagram",
|
||||
@@ -341,14 +423,14 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "instabug",
|
||||
name: "Instabug",
|
||||
},
|
||||
{
|
||||
identifier: "keep",
|
||||
name: "Keep",
|
||||
},
|
||||
// {
|
||||
// identifier: "instabug",
|
||||
// name: "Instabug",
|
||||
// },
|
||||
// {
|
||||
// identifier: "keep",
|
||||
// name: "Keep",
|
||||
// },
|
||||
{
|
||||
identifier: "lemonsqueezy",
|
||||
name: "Lemon Squeezy",
|
||||
@@ -361,10 +443,10 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "linkedin",
|
||||
name: "LinkedIn",
|
||||
},
|
||||
// {
|
||||
// identifier: "linkedin",
|
||||
// name: "LinkedIn",
|
||||
// },
|
||||
{
|
||||
identifier: "linear",
|
||||
name: "Linear",
|
||||
@@ -404,10 +486,10 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "lotus",
|
||||
name: "Lotus",
|
||||
},
|
||||
// {
|
||||
// identifier: "lotus",
|
||||
// name: "Lotus",
|
||||
// },
|
||||
{
|
||||
identifier: "mailchimp",
|
||||
name: "Mailchimp",
|
||||
@@ -434,6 +516,15 @@ export const apisList = [
|
||||
{
|
||||
identifier: "microsoftazure",
|
||||
name: "Microsoft Azure",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Microsoft Azure webhook.",
|
||||
slug: "microsoft-azure-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/azure-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "monday",
|
||||
@@ -503,6 +594,22 @@ export const apisList = [
|
||||
{
|
||||
identifier: "pagerduty",
|
||||
name: "PagerDuty",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a PagerDuty webhook.",
|
||||
slug: "pagerduty-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/pagerduty-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Install an addon in PagerDuty",
|
||||
slug: "pagerduty-install-addon",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/pagerduty.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "plain",
|
||||
@@ -517,10 +624,10 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "posthog",
|
||||
name: "Posthog",
|
||||
},
|
||||
// {
|
||||
// identifier: "posthog",
|
||||
// name: "Posthog",
|
||||
// },
|
||||
{
|
||||
identifier: "raycast",
|
||||
name: "Raycast",
|
||||
@@ -573,6 +680,13 @@ export const apisList = [
|
||||
identifier: "salesforce",
|
||||
name: "Salesforce",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Salesforce webhook.",
|
||||
slug: "salesforce-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/salesforce-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Create a new contact in Salesforce.",
|
||||
slug: "salesforce-create-contact",
|
||||
@@ -585,6 +699,13 @@ export const apisList = [
|
||||
identifier: "segment",
|
||||
name: "Segment",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Segment webhook.",
|
||||
slug: "segment-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/segment-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Get source information from Segment.",
|
||||
slug: "segment-get-source-information",
|
||||
@@ -671,6 +792,13 @@ export const apisList = [
|
||||
identifier: "snyk",
|
||||
name: "Snyk",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Snyk webhook.",
|
||||
slug: "snyk-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/snyk-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Get user details from Snyk.",
|
||||
slug: "snyk-get-user-details",
|
||||
@@ -679,6 +807,19 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "square",
|
||||
name: "Square",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Square webhook.",
|
||||
slug: "square-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/square-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "spotify",
|
||||
name: "Spotify",
|
||||
@@ -739,6 +880,16 @@ export const apisList = [
|
||||
identifier: "svix",
|
||||
name: "Svix",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Svix webhook.",
|
||||
slug: "svix-http-endpoint",
|
||||
version: "1.0.0",
|
||||
exampleType: ["http-endpoint"],
|
||||
apisUsed: ["svix"],
|
||||
tags: ["dev-ops"],
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/svix-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Create an application in Svix",
|
||||
slug: "svix-create-application",
|
||||
@@ -751,6 +902,13 @@ export const apisList = [
|
||||
identifier: "todoist",
|
||||
name: "Todoist",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a Todoist webhook.",
|
||||
slug: "todoist-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/todoist-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Add a new project in Todoist.",
|
||||
slug: "todoist-add-new-project",
|
||||
@@ -774,6 +932,13 @@ export const apisList = [
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://github.com/triggerdotdev/api-reference/raw/main/src/twilio.ts",
|
||||
},
|
||||
{
|
||||
title: "A job that is triggered by a Twilio webhook.",
|
||||
slug: "twilio-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/twilio-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -825,6 +990,13 @@ export const apisList = [
|
||||
identifier: "youtube",
|
||||
name: "YouTube",
|
||||
examples: [
|
||||
{
|
||||
title: "A job that is triggered by a YouTube webhook.",
|
||||
slug: "youtube-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/youtube-http-endpoint.ts",
|
||||
},
|
||||
{
|
||||
title: "Search for a YouTube video",
|
||||
slug: "youtube-search-video",
|
||||
@@ -833,6 +1005,25 @@ export const apisList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "zapier",
|
||||
name: "Zapier",
|
||||
examples: [
|
||||
{
|
||||
title: "Store name in Zapier",
|
||||
slug: "zapier-store-name",
|
||||
version: "1.0.0",
|
||||
codeUrl: "https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/zapier.ts",
|
||||
},
|
||||
{
|
||||
title: "A job that is triggered by a Zapier webhook.",
|
||||
slug: "zapier-http-endpoint",
|
||||
version: "1.0.0",
|
||||
codeUrl:
|
||||
"https://raw.githubusercontent.com/triggerdotdev/api-reference/main/src/zapier-http-endpoint.ts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
identifier: "zbd",
|
||||
name: "ZBD",
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { $transaction, PrismaClient, prisma } from "~/db.server";
|
||||
import { AuthenticatedEnvironment } from "../apiAuth.server";
|
||||
import { JobRunStatus } from "@trigger.dev/database";
|
||||
import { CancelRunService } from "../runs/cancelRun.server";
|
||||
import { logger } from "../logger.server";
|
||||
import { CancelRunsForJob } from "@trigger.dev/core";
|
||||
|
||||
const CANCELLABLE_JOB_RUN_STATUS: JobRunStatus[] = [
|
||||
JobRunStatus.PENDING,
|
||||
JobRunStatus.QUEUED,
|
||||
JobRunStatus.WAITING_ON_CONNECTIONS,
|
||||
JobRunStatus.PREPROCESSING,
|
||||
JobRunStatus.STARTED,
|
||||
JobRunStatus.EXECUTING,
|
||||
JobRunStatus.WAITING_TO_CONTINUE,
|
||||
JobRunStatus.WAITING_TO_EXECUTE,
|
||||
];
|
||||
|
||||
export class CancelRunsForJobService {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call(environment: AuthenticatedEnvironment, jobSlug: string) {
|
||||
return await $transaction<CancelRunsForJob | undefined>(this.#prismaClient, async (tx) => {
|
||||
const job = await tx.job.findUnique({
|
||||
where: {
|
||||
projectId_slug: {
|
||||
projectId: environment.projectId,
|
||||
slug: jobSlug,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!job) {
|
||||
return;
|
||||
}
|
||||
|
||||
const jobRuns = await tx.jobRun.findMany({
|
||||
where: {
|
||||
jobId: job.id,
|
||||
status: {
|
||||
in: CANCELLABLE_JOB_RUN_STATUS,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
const cancelRunService = new CancelRunService(this.#prismaClient);
|
||||
const cancelledRunIds: string[] = [];
|
||||
const failedToCancelRunIds: string[] = [];
|
||||
|
||||
for (const jobRun of jobRuns) {
|
||||
try {
|
||||
await cancelRunService.call({ runId: jobRun.id });
|
||||
cancelledRunIds.push(jobRun.id);
|
||||
} catch (err) {
|
||||
logger.debug(`failed to cancel job run with id ${jobRun.id} for job ${jobSlug}`);
|
||||
failedToCancelRunIds.push(jobRun.id);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
cancelledRunIds: cancelledRunIds,
|
||||
failedToCancelRunIds: failedToCancelRunIds,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class Telemetry {
|
||||
|
||||
constructor({ postHogApiKey, trigger }: Options) {
|
||||
if (postHogApiKey) {
|
||||
this.#posthogClient = new PostHog(postHogApiKey, { host: "https://app.posthog.com" });
|
||||
this.#posthogClient = new PostHog(postHogApiKey, { host: "https://eu.posthog.com" });
|
||||
} else {
|
||||
console.log("No PostHog API key, so analytics won't track");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type {
|
||||
EventRecord,
|
||||
Integration,
|
||||
TriggerHttpEndpoint,
|
||||
TriggerSource,
|
||||
@@ -15,6 +16,7 @@ export type JobForPath = Pick<Job, "slug">;
|
||||
export type RunForPath = Pick<Job, "id">;
|
||||
export type IntegrationForPath = Pick<Integration, "slug">;
|
||||
export type TriggerForPath = Pick<TriggerSource, "id">;
|
||||
export type EventForPath = Pick<EventRecord, "id">;
|
||||
export type WebhookForPath = Pick<Webhook, "id">;
|
||||
export type HttpEndpointForPath = Pick<TriggerHttpEndpoint, "key">;
|
||||
|
||||
@@ -46,6 +48,10 @@ export const TriggerSourceParamSchema = ProjectParamSchema.extend({
|
||||
triggerParam: z.string(),
|
||||
});
|
||||
|
||||
export const EventParamSchema = ProjectParamSchema.extend({
|
||||
eventParam: z.string(),
|
||||
});
|
||||
|
||||
export const TriggerSourceRunParamsSchema = TriggerSourceParamSchema.extend({
|
||||
runParam: z.string(),
|
||||
});
|
||||
@@ -202,6 +208,18 @@ export function projectTriggersPath(organization: OrgForPath, project: ProjectFo
|
||||
return `${projectPath(organization, project)}/triggers`;
|
||||
}
|
||||
|
||||
export function projectEventsPath(organization: OrgForPath, project: ProjectForPath) {
|
||||
return `${projectPath(organization, project)}/events`;
|
||||
}
|
||||
|
||||
export function projectEventPath(
|
||||
organization: OrgForPath,
|
||||
project: ProjectForPath,
|
||||
event: EventForPath
|
||||
) {
|
||||
return `${projectEventsPath(organization, project)}/${event.id}`;
|
||||
}
|
||||
|
||||
export function projectHttpEndpointsPath(organization: OrgForPath, project: ProjectForPath) {
|
||||
return `${projectPath(organization, project)}/http-endpoints`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { User as DBUser } from "~/models/user.server";
|
||||
|
||||
type User = Pick<DBUser, "name" | "displayName">;
|
||||
|
||||
// remove `null` from username
|
||||
export function getUsername(user?: User): string | undefined {
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
|
||||
// user.displayName is of type `string | null`
|
||||
if (user.displayName) {
|
||||
return user.displayName;
|
||||
}
|
||||
|
||||
// user.name is of type `string | null`
|
||||
if (user.name) {
|
||||
return user.name;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -66,8 +66,8 @@
|
||||
"@tabler/icons-react": "^2.39.0",
|
||||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@team-plain/typescript-sdk": "^3.5.0",
|
||||
"@trigger.dev/companyicons": "^1.5.35",
|
||||
"@trigger.dev/billing": "^1.0.10",
|
||||
"@trigger.dev/companyicons": "^1.5.32",
|
||||
"@trigger.dev/core": "workspace:*",
|
||||
"@trigger.dev/core-backend": "workspace:*",
|
||||
"@trigger.dev/database": "workspace:*",
|
||||
@@ -99,8 +99,8 @@
|
||||
"nanoid": "^3.3.4",
|
||||
"ohash": "^1.1.3",
|
||||
"postcss-import": "^14.1.0",
|
||||
"posthog-js": "^1.83.0",
|
||||
"posthog-node": "^3.1.1",
|
||||
"posthog-js": "^1.93.3",
|
||||
"posthog-node": "^3.1.3",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
"prismjs": "^1.29.0",
|
||||
"random-words": "^2.0.0",
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
FROM node:18.18.2-bullseye-slim@sha256:a50436b44fe3eb2ff72696fb394ad3cae45f06cb2a7468c5ef3f012d23d9888f AS pruner
|
||||
FROM node:18.18.2-bullseye-slim@sha256:21479df46c3173ee0cefc6b264928e10239152c4f74df872ca9369be01a245b7 AS pruner
|
||||
|
||||
WORKDIR /triggerdotdev
|
||||
|
||||
@@ -7,7 +7,7 @@ RUN npx -q turbo@1.10.9 prune --scope=webapp --docker
|
||||
RUN find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
||||
|
||||
# Base strategy to have layer caching
|
||||
FROM node:18.18.2-bullseye-slim@sha256:a50436b44fe3eb2ff72696fb394ad3cae45f06cb2a7468c5ef3f012d23d9888f AS base
|
||||
FROM node:18.18.2-bullseye-slim@sha256:21479df46c3173ee0cefc6b264928e10239152c4f74df872ca9369be01a245b7 AS base
|
||||
RUN apt-get update && apt-get install -y openssl dumb-init
|
||||
WORKDIR /triggerdotdev
|
||||
COPY --chown=node:node .gitignore .gitignore
|
||||
@@ -50,7 +50,7 @@ RUN pnpm run generate
|
||||
RUN pnpm run build --filter=webapp...
|
||||
|
||||
# Runner
|
||||
FROM node:18.18.2-bullseye-slim@sha256:a50436b44fe3eb2ff72696fb394ad3cae45f06cb2a7468c5ef3f012d23d9888f AS runner
|
||||
FROM node:18.18.2-bullseye-slim@sha256:21479df46c3173ee0cefc6b264928e10239152c4f74df872ca9369be01a245b7 AS runner
|
||||
RUN apt-get update && apt-get install -y openssl
|
||||
WORKDIR /triggerdotdev
|
||||
RUN corepack enable
|
||||
|
||||
@@ -81,6 +81,7 @@ const app: Express = express();
|
||||
|
||||
//add the middleware
|
||||
app.use(createMiddleware(client));
|
||||
// app.use(express.json()); //if you're parsing JSON, you need to add the Trigger middleware before this
|
||||
|
||||
//..the rest of your Express code
|
||||
```
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
>
|
||||
Learn more about how Trigger.dev works and how it can help you.
|
||||
</Card>
|
||||
<Card title="Examples" icon="slot-machine" href="/examples">
|
||||
One of the quickest ways to learn how Trigger.dev works is to view some example Jobs.
|
||||
<Card title="Examples" icon="slot-machine" href="https:/trigger.dev/apis">
|
||||
Find code examples for many popular APIs. These can be copied / modified for use in your own
|
||||
projects.
|
||||
</Card>
|
||||
<Card title="Get help" icon="hire-a-helper" href="/documentation/get-help">
|
||||
Struggling getting setup or have a question? We're here to help.
|
||||
|
||||
@@ -372,7 +372,7 @@ We recommend exploring all of the below sections to fully understand how to crea
|
||||
Integrations make it easy to authenticate and use APIs. Learn how to use and create integrations.
|
||||
</Card>
|
||||
<Card title="API catalog with code samples" icon="code" href="https://trigger.dev/apis">
|
||||
Find code examples for the API you need that you can copy and paste into your
|
||||
Find code examples for many popular APIs. These can be copied / modified for use in your own
|
||||
projects.
|
||||
</Card>
|
||||
<Card title="SDK reference" icon="book-open" href="/sdk">
|
||||
|
||||
@@ -30,8 +30,9 @@ You can use [Trigger.dev Cloud](https://cloud.trigger.dev) or [Self-host Trigger
|
||||
<Card title="Integrations" icon="grid-2" href="/integrations">
|
||||
Trigger.dev integrates with a wide range of services.
|
||||
</Card>
|
||||
<Card title="Examples" icon="slot-machine" href="/examples">
|
||||
One of the quickest ways to learn how Trigger.dev works is to view some example Jobs.
|
||||
<Card title="Examples - API catalog" icon="code" href="https://trigger.dev/apis">
|
||||
Find code examples for many popular APIs. These can be copied / modified for use in your own
|
||||
projects.
|
||||
</Card>
|
||||
<Card title="Manual Setup" icon="book-sparkles" href="guides/manual">
|
||||
For complete control, you can manually setup Trigger.dev using this guide.
|
||||
@@ -54,7 +55,10 @@ We'd love to hear from you or give you a hand getting started. Here are some way
|
||||
</Card>
|
||||
<Card
|
||||
title="Follow us on X (Twitter)"
|
||||
icon={<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 512 512"><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z"/></svg>
|
||||
icon={
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 512 512">
|
||||
<path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z" />
|
||||
</svg>
|
||||
}
|
||||
href="https://twitter.com/triggerdotdev"
|
||||
color="#1DA1F2"
|
||||
|
||||
@@ -213,20 +213,27 @@ export default app;
|
||||
|
||||
### Deno
|
||||
|
||||
Deno works similarly to Bun, but the imports are slightly different. First, import the `@trigger.dev/sdk` and `@trigger.dev/hono` packages using [npm: specifiers](https://docs.deno.com/runtime/manual/node/npm_specifiers)
|
||||
|
||||
Import trigger.dev packages with Deno using [npm: specifiers](https://docs.deno.com/runtime/manual/node/npm_specifiers):
|
||||
```ts index.ts
|
||||
import { createMiddleware } from "npm:@trigger.dev/hono@latest";
|
||||
import { TriggerClient, invokeTrigger } from "npm:@trigger.dev/sdk@latest";
|
||||
import { Hono } from "npm:hono"; // Make sure to use the npm specifier for hono as well
|
||||
```
|
||||
|
||||
Deno doesn't automatically load environment variables from a `.env` file, so you'll need to load them manually using the `dotenv` package:
|
||||
To load a `.env` file on startup, pass the `deno run` command a `--env` flag:
|
||||
```bash
|
||||
deno run --env --allow-net --watch index.ts
|
||||
```
|
||||
|
||||
You can also load an environment variables file in code using the `dotenv` package:
|
||||
```ts index.ts
|
||||
import { load } from "https://deno.land/std@0.208.0/dotenv/mod.ts";
|
||||
const env = await load();
|
||||
```
|
||||
In which case you need to pass the `--allow-env` and `--allow-read` flags:
|
||||
```bash
|
||||
deno run --allow-env --allow-net --allow-read --watch index.ts
|
||||
```
|
||||
|
||||
Now we can create the `TriggerClient`, define our jobs, and create the middleware:
|
||||
|
||||
@@ -373,7 +380,7 @@ yarn dlx @trigger.dev/cli@latest dev --client-id hono-client -p 8787 -H localhos
|
||||
Run your Hono app locally, like you normally would. For example:
|
||||
|
||||
```bash
|
||||
deno run --allow-net --allow-read --watch index.ts
|
||||
deno run --env --allow-net --watch index.ts
|
||||
```
|
||||
|
||||
In a **_separate terminal window or tab_** run:
|
||||
|
||||
@@ -5,7 +5,8 @@ description: "Jobs and code examples you can use to get started."
|
||||
|
||||
<CardGroup>
|
||||
<Card title="API catalog with code samples" icon="code" href="https://trigger.dev/apis">
|
||||
Find code examples for the API you need that you can copy and paste into your projects.
|
||||
Find code examples for many popular APIs. These can be copied / modified for use in your own
|
||||
projects.
|
||||
</Card>
|
||||
<Card
|
||||
title="Browse our Project Showcase"
|
||||
|
||||
+15
-43
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"$schema": "https://mintlify.com/schema.json",
|
||||
"name": "Trigger.dev",
|
||||
"openapi": [
|
||||
"/openapi.yml"
|
||||
],
|
||||
"openapi": ["/openapi.yml"],
|
||||
"logo": {
|
||||
"dark": "/logo/dark.png",
|
||||
"light": "/logo/light.png",
|
||||
@@ -49,8 +47,8 @@
|
||||
"url": "sdk"
|
||||
},
|
||||
{
|
||||
"name": "Example Jobs",
|
||||
"url": "examples"
|
||||
"name": "Examples",
|
||||
"url": "https://trigger.dev/apis"
|
||||
}
|
||||
],
|
||||
"redirects": [
|
||||
@@ -256,10 +254,7 @@
|
||||
"pages": [
|
||||
{
|
||||
"group": "Airtable",
|
||||
"pages": [
|
||||
"integrations/apis/airtable",
|
||||
"integrations/apis/airtable-tasks"
|
||||
]
|
||||
"pages": ["integrations/apis/airtable", "integrations/apis/airtable-tasks"]
|
||||
},
|
||||
{
|
||||
"group": "GitHub",
|
||||
@@ -285,25 +280,16 @@
|
||||
},
|
||||
{
|
||||
"group": "Plain",
|
||||
"pages": [
|
||||
"integrations/apis/plain",
|
||||
"integrations/apis/plain-tasks"
|
||||
]
|
||||
"pages": ["integrations/apis/plain", "integrations/apis/plain-tasks"]
|
||||
},
|
||||
"integrations/apis/replicate",
|
||||
{
|
||||
"group": "SendGrid",
|
||||
"pages": [
|
||||
"integrations/apis/sendgrid",
|
||||
"integrations/apis/sendgrid-tasks"
|
||||
]
|
||||
"pages": ["integrations/apis/sendgrid", "integrations/apis/sendgrid-tasks"]
|
||||
},
|
||||
{
|
||||
"group": "Resend",
|
||||
"pages": [
|
||||
"integrations/apis/resend",
|
||||
"integrations/apis/resend-tasks"
|
||||
]
|
||||
"pages": ["integrations/apis/resend", "integrations/apis/resend-tasks"]
|
||||
},
|
||||
{
|
||||
"group": "Shopify",
|
||||
@@ -315,10 +301,7 @@
|
||||
},
|
||||
{
|
||||
"group": "Slack",
|
||||
"pages": [
|
||||
"integrations/apis/slack",
|
||||
"integrations/apis/slack-tasks"
|
||||
]
|
||||
"pages": ["integrations/apis/slack", "integrations/apis/slack-tasks"]
|
||||
},
|
||||
"integrations/apis/stripe",
|
||||
{
|
||||
@@ -343,9 +326,7 @@
|
||||
"sdk/triggerclient/constructor",
|
||||
{
|
||||
"group": "Instance properties",
|
||||
"pages": [
|
||||
"sdk/triggerclient/store"
|
||||
]
|
||||
"pages": ["sdk/triggerclient/store"]
|
||||
},
|
||||
{
|
||||
"group": "Instance methods",
|
||||
@@ -355,6 +336,7 @@
|
||||
"sdk/triggerclient/instancemethods/getevent",
|
||||
"sdk/triggerclient/instancemethods/cancel-event",
|
||||
"sdk/triggerclient/instancemethods/cancel-runs-for-event",
|
||||
"sdk/triggerclient/instancemethods/cancel-runs-for-job",
|
||||
"sdk/triggerclient/instancemethods/getruns",
|
||||
"sdk/triggerclient/instancemethods/getrun",
|
||||
"sdk/triggerclient/instancemethods/define-job",
|
||||
@@ -407,10 +389,7 @@
|
||||
"sdk/dynamictrigger/constructor",
|
||||
{
|
||||
"group": "Instance methods",
|
||||
"pages": [
|
||||
"sdk/dynamictrigger/register",
|
||||
"sdk/dynamictrigger/unregister"
|
||||
]
|
||||
"pages": ["sdk/dynamictrigger/register", "sdk/dynamictrigger/unregister"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -421,10 +400,7 @@
|
||||
"sdk/dynamicschedule/constructor",
|
||||
{
|
||||
"group": "Instance methods",
|
||||
"pages": [
|
||||
"sdk/dynamicschedule/register",
|
||||
"sdk/dynamicschedule/unregister"
|
||||
]
|
||||
"pages": ["sdk/dynamicschedule/register", "sdk/dynamicschedule/unregister"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -436,9 +412,7 @@
|
||||
},
|
||||
{
|
||||
"group": "HTTP Reference",
|
||||
"pages": [
|
||||
"sdk/api-reference/events/create-an-event"
|
||||
]
|
||||
"pages": ["sdk/api-reference/events/create-an-event"]
|
||||
},
|
||||
{
|
||||
"group": "React SDK",
|
||||
@@ -452,9 +426,7 @@
|
||||
},
|
||||
{
|
||||
"group": "Overview",
|
||||
"pages": [
|
||||
"examples/introduction"
|
||||
]
|
||||
"pages": ["examples/introduction"]
|
||||
}
|
||||
],
|
||||
"footerSocials": {
|
||||
@@ -467,4 +439,4 @@
|
||||
"apiKey": "phc_hwYmedO564b3Ik8nhA4Csrb5SueY0EwFJWCbseGwWW"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,4 +10,4 @@
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"packageManager": "pnpm@7.13.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "TriggerClient: cancelRunsForJob() Instance Method"
|
||||
sidebarTitle: "cancelRunsForJob()"
|
||||
description: "The `cancelRunsForJob()` instance method will cancel all job runs (yet to be executed) with the given jobId."
|
||||
---
|
||||
|
||||
## Parameters
|
||||
|
||||
<ResponseField name="jobId" type="string" required>
|
||||
The job ID to cancel the job runs for. This is the `id` you set when using `client.defineJob()` or
|
||||
`new Job()`.
|
||||
</ResponseField>
|
||||
|
||||
## Returns
|
||||
|
||||
<ResponseField type="object">
|
||||
<Expandable title="properties" defaultOpen>
|
||||
<ResponseField name="cancelledRunIds" type="array" required>
|
||||
List of Job Run IDs that are cancelled.
|
||||
</ResponseField>
|
||||
<ResponseField name="failedToCancelRunIds" type="array" required>
|
||||
List of Job Run IDs that have failed to be cancelled.
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<RequestExample>
|
||||
|
||||
```ts Cancelling Runs for an Event
|
||||
//this is the job we want to cancel runs for
|
||||
client.defineJob({
|
||||
//this is the job id
|
||||
id: "my-job",
|
||||
name: "My first job",
|
||||
version: "1.0.0",
|
||||
trigger: invokeTrigger({ schema: z.number() }),
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.logger.info(`Hello World ${payload}`);
|
||||
},
|
||||
});
|
||||
|
||||
// Some time later...
|
||||
const res = await client.cancelRunsForJob("my-job");
|
||||
console.log(res.cancelledRunIds);
|
||||
console.log(res.failedToCancelRunIds);
|
||||
```
|
||||
|
||||
</RequestExample>
|
||||
@@ -60,6 +60,10 @@ The `cancelEvent()` method cancels an event that is scheduled to be delivered in
|
||||
|
||||
The `cancelRunsForEvent()` method cancels the job runs (yet to be executed) that are triggered by a given eventId.
|
||||
|
||||
### [cancelRunsForJob()](/sdk/triggerclient/instancemethods/cancel-runs-for-job)
|
||||
|
||||
The `cancelRunsForJob()` method cancels all runs for the specified job (yet to be executed).
|
||||
|
||||
### [getRuns()](/sdk/triggerclient/instancemethods/getruns)
|
||||
|
||||
The `getRuns()` method gets runs for a Job.
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/airtable
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/airtable",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Trigger.dev integration for airtable",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"airtable": "^0.12.1",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/github
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/github",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "The official GitHub integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -30,8 +30,8 @@
|
||||
"@octokit/request-error": "^5.0.1",
|
||||
"@octokit/webhooks": "^12.0.10",
|
||||
"octokit": "^3.1.2",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/linear
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/linear",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Trigger.dev integration for @linear/sdk",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@linear/sdk": "^8.0.0",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/slack
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/openai",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "The official OpenAI integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"openai": "^4.16.1",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8"
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/plain
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/plain",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "The official Plain.com integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"@team-plain/typescript-sdk": "^2.7.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/replicate
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/replicate",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Trigger.dev integration for replicate",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"replicate": "^0.18.1",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/resend
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/resend",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "The official Resend.com integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"resend": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/sendgrid
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/sendgrid",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Trigger.dev integration for @sendgrid/mail",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sendgrid/mail": "^7.7.0",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8"
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.8.0"
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/shopify
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/shopify",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Trigger.dev integration for @shopify/shopify-api",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@shopify/shopify-api": "^8.0.2",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# @trigger.dev/slack
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/slack",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "The official Slack integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@slack/web-api": "^6.8.1",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/stripe
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/stripe",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Trigger.dev integration for stripe",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"stripe": "^12.14.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/supabase
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/supabase",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Trigger.dev integration for @supabase/supabase-js",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@supabase/supabase-js": "^2.26.0",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"supabase-management-js": "^1.0.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @trigger.dev/typeform
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
- @trigger.dev/integration-kit@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
- @trigger.dev/integration-kit@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/typeform",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "The official Typeform integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/integration-kit": "workspace:^2.3.10",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"@typeform/api-client": "^1.8.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# @trigger.dev/astro
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@trigger.dev/astro",
|
||||
"description": "An Astro-native integration for Trigger.dev background jobs platform",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
@@ -20,7 +20,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8"
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^3.0.12",
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# create-trigger
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/core@2.3.10
|
||||
- @trigger.dev/yalt@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- aa97bf4a: Updated the telemetry API key
|
||||
- Updated dependencies [740b7b23]
|
||||
- @trigger.dev/core@2.3.9
|
||||
- @trigger.dev/yalt@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/cli",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "The Trigger.dev CLI",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getVersion } from "../utils/getVersion";
|
||||
import { DevCommandOptions } from "../commands/dev";
|
||||
import { ProjectInstallOptions } from "../frameworks";
|
||||
|
||||
const postHogApiKey = "phc_hwYmedO564b3Ik8nhA4Csrb5SueY0EwFJWCbseGwWW";
|
||||
const postHogApiKey = "phc_9aSDbJCaDUMdZdHxxMPTvcj7A9fsl3mCgM1RBPmPsl7";
|
||||
|
||||
export class TelemetryClient {
|
||||
#client: PostHog;
|
||||
@@ -14,7 +14,7 @@ export class TelemetryClient {
|
||||
|
||||
constructor() {
|
||||
this.#client = new PostHog(postHogApiKey, {
|
||||
host: "https://app.posthog.com",
|
||||
host: "https://eu.posthog.com",
|
||||
flushAt: 1,
|
||||
});
|
||||
this.#sessionId = `cli-${nanoid()}`;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# @trigger.dev/core-backend
|
||||
|
||||
## 2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
## 2.3.7
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/core-backend",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Core code used across `@trigger.dev/sdk` and Trigger.dev server",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# internal-platform
|
||||
|
||||
## 2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 740b7b23: feat: Add $not to eventFilters
|
||||
|
||||
## 2.3.8
|
||||
|
||||
## 2.3.7
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/core",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Core code used across the Trigger.dev SDK and platform",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -198,5 +198,15 @@ function contentFilterMatches(actualValue: any, contentFilter: ContentFilters[nu
|
||||
return actualValue !== null;
|
||||
}
|
||||
|
||||
if ("$not" in contentFilter) {
|
||||
if (Array.isArray(actualValue)) {
|
||||
return !actualValue.includes(contentFilter.$not);
|
||||
} else if (typeof actualValue === 'number' || typeof actualValue === 'boolean' || typeof actualValue === 'string') {
|
||||
return actualValue !== contentFilter.$not;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ const EventMatcherSchema = z.union([
|
||||
z.object({
|
||||
$includes: z.union([z.string(), z.number(), z.boolean()]),
|
||||
}),
|
||||
z.object({
|
||||
$not: z.union([z.string(), z.number(), z.boolean()])
|
||||
})
|
||||
])
|
||||
),
|
||||
]);
|
||||
|
||||
@@ -15,3 +15,4 @@ export * from "./runs";
|
||||
export * from "./addMissingVersionField";
|
||||
export * from "./statuses";
|
||||
export * from "./request";
|
||||
export * from "./jobs";
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const CancelRunsForJobSchema = z.object({
|
||||
cancelledRunIds: z.array(z.string()),
|
||||
failedToCancelRunIds: z.array(z.string()),
|
||||
});
|
||||
|
||||
export type CancelRunsForJob = z.infer<typeof CancelRunsForJobSchema>;
|
||||
@@ -252,6 +252,54 @@ describe("eventFilterMatches", () => {
|
||||
expect(eventFilterMatches(payload, filter)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return true when payload matches an not condition", () => {
|
||||
const payload = {
|
||||
name: "John",
|
||||
age: 30,
|
||||
score: 100,
|
||||
isAdmin: false,
|
||||
hobbies: ["reading", "swimming"],
|
||||
address: {
|
||||
street: "123 Main St",
|
||||
city: "Anytown",
|
||||
state: "CA",
|
||||
zip: "12345",
|
||||
},
|
||||
};
|
||||
const filter: EventFilter = {
|
||||
hobbies: [{ $not: "gaming" }],
|
||||
age: [{ $not: 39 }],
|
||||
isAdmin: [{ $not: true }],
|
||||
name: [{ $not: 'Test' }]
|
||||
};
|
||||
|
||||
expect(eventFilterMatches(payload, filter)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false when payload not matches an not condition", () => {
|
||||
const payload = {
|
||||
name: "John",
|
||||
age: 30,
|
||||
score: 100,
|
||||
isAdmin: false,
|
||||
hobbies: ["reading", "swimming"],
|
||||
address: {
|
||||
street: "123 Main St",
|
||||
city: "Anytown",
|
||||
state: "CA",
|
||||
zip: "12345",
|
||||
},
|
||||
};
|
||||
const filter: EventFilter = {
|
||||
hobbies: [{ $not: "reading" }],
|
||||
age: [{ $not: 30 }],
|
||||
isAdmin: [{ $not: false }],
|
||||
name: [{ $not: 'John' }]
|
||||
};
|
||||
|
||||
expect(eventFilterMatches(payload, filter)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true when payload matches an ignoreCaseEquals condition", () => {
|
||||
const payload = {
|
||||
name: "John",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# @trigger.dev/eslint-plugin
|
||||
|
||||
## 2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
## 2.3.7
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/eslint-plugin",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "ESLint plugin with trigger.dev best practices",
|
||||
"keywords": [
|
||||
"eslint",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# @trigger.dev/express
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/express",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "Official Express adapter for Trigger.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -23,7 +23,7 @@
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10",
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/express": "^4.17.13",
|
||||
@@ -39,7 +39,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8"
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# @trigger.dev/hono
|
||||
|
||||
## 2.3.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8277f4d2]
|
||||
- Updated dependencies [73cb8839]
|
||||
- @trigger.dev/sdk@2.3.10
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f7bf25f0]
|
||||
- @trigger.dev/sdk@2.3.9
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/hono",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.10",
|
||||
"description": "A Trigger.dev adapter for Hono.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hono": "3.x",
|
||||
"@trigger.dev/sdk": "workspace:^2.3.8"
|
||||
"@trigger.dev/sdk": "workspace:^2.3.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user