Merge branch 'dev'
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Added some logging messages (and disabled any messages by default)
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Fixed issue with workflow runs not completing when the run function returned undefined or null
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Added triggerTTL option that prevents old events from running a workflow
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@trigger.dev/integrations": patch
|
||||
"@trigger.dev/providers": patch
|
||||
---
|
||||
|
||||
Added additional github webhook triggers, and improved the slack integration
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 32 KiB |
@@ -19,7 +19,7 @@ export default function CreateNewWorkflow() {
|
||||
<span>Documentation</span>
|
||||
</PrimaryA>
|
||||
<SecondaryA
|
||||
href="https://docs.trigger.dev"
|
||||
href="https://docs.trigger.dev/examples/github"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
@@ -51,7 +51,7 @@ export function CreateNewWorkflowNoWorkflows() {
|
||||
<span>Documentation</span>
|
||||
</PrimaryA>
|
||||
<SecondaryA
|
||||
href="https://docs.trigger.dev"
|
||||
href="https://docs.trigger.dev/examples/github"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import Prism from "prismjs";
|
||||
import "prismjs/components/prism-typescript";
|
||||
import "prismjs/components/prism-json";
|
||||
import "prismjs/plugins/line-numbers/prism-line-numbers";
|
||||
import "prismjs/plugins/line-numbers/prism-line-numbers.css";
|
||||
import { CopyTextButton } from "../CopyTextButton";
|
||||
import classNames from "classnames";
|
||||
|
||||
@@ -13,6 +15,7 @@ type CodeBlockProps = {
|
||||
showCopyButton?: boolean;
|
||||
align?: "top" | "center";
|
||||
maxHeight?: string;
|
||||
showLineNumbers?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
@@ -22,16 +25,19 @@ export default function CodeBlock({
|
||||
showCopyButton = true,
|
||||
align = "center",
|
||||
maxHeight,
|
||||
showLineNumbers = true,
|
||||
className,
|
||||
}: CodeBlockProps) {
|
||||
const [codeHtml, setCodeHtml] = useState(code);
|
||||
const codeRef = useRef<HTMLPreElement>(null);
|
||||
const [isCollapsed, setIsCollapsed] = useState(
|
||||
maxHeight === undefined ? false : true
|
||||
);
|
||||
useEffect(() => {
|
||||
const val = Prism.highlight(code, Prism.languages[language], language);
|
||||
setCodeHtml(val);
|
||||
}, [code, language]);
|
||||
if (!codeRef.current) {
|
||||
return;
|
||||
}
|
||||
Prism.highlightAllUnder(codeRef.current);
|
||||
}, [code, language, codeRef]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -42,10 +48,13 @@ export default function CodeBlock({
|
||||
)}
|
||||
style={{ maxHeight: isCollapsed ? maxHeight : undefined }}
|
||||
>
|
||||
<pre className={`language-${language}`}>
|
||||
<pre
|
||||
className={classNames(showLineNumbers && `line-numbers`)}
|
||||
ref={codeRef}
|
||||
>
|
||||
<code
|
||||
className={`language-${language}`}
|
||||
dangerouslySetInnerHTML={{ __html: codeHtml }}
|
||||
dangerouslySetInnerHTML={{ __html: code }}
|
||||
></code>
|
||||
</pre>
|
||||
{showCopyButton === true && (
|
||||
|
||||
@@ -117,6 +117,7 @@ export function AddApiKeyButton({
|
||||
name="api_key"
|
||||
placeholder="<api_key>"
|
||||
spellCheck={false}
|
||||
type="password"
|
||||
/>
|
||||
{errors && <FormError errors={errors} path={["api_key"]} />}
|
||||
</InputGroup>
|
||||
|
||||
@@ -55,7 +55,7 @@ export function ConnectionSelector({
|
||||
<Popover.Button
|
||||
className={`
|
||||
${open ? "" : ""}
|
||||
inline-flex justify-between items-center rounded text-white bg-slate-700 shadow pl-3 pr-2 py-1.5 gap-2 text-sm hover:bg-slate-600/80 transition focus:outline-none`}
|
||||
inline-flex justify-between items-center rounded text-slate-300 bg-slate-700 shadow pl-4 pr-3 py-2 gap-2 text-sm hover:bg-slate-600/80 transition focus:outline-none`}
|
||||
>
|
||||
<span className="transition text-sm text-slate-200">
|
||||
{selectedConnection ? (
|
||||
|
||||
@@ -26,7 +26,7 @@ export function Header({ children }: HeaderProps) {
|
||||
|
||||
<div className="flex flex-1 justify-center">{children}</div>
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="flex items-center gap-4">
|
||||
<TertiaryA href="https://docs.trigger.dev" target="_blank">
|
||||
<DocumentTextIcon className="h-5 w-5" />
|
||||
Docs
|
||||
@@ -60,7 +60,7 @@ export function BreadcrumbDivider() {
|
||||
y1="0.6286"
|
||||
x2="0.6286"
|
||||
y2="24.6762"
|
||||
opacity={0.5}
|
||||
opacity={0.3}
|
||||
stroke="white"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,7 @@ export type ListProps = {
|
||||
|
||||
export function List({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="overflow-hidden bg-slate-800 shadow-md sm:rounded-md mb-10">
|
||||
<div className="bg-slate-800 shadow-md sm:rounded-md mb-4">
|
||||
<ul className="divide-y divide-slate-850">{children}</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { InformationCircleIcon } from "@heroicons/react/24/solid";
|
||||
|
||||
export type PanelInfoProps = {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export function PanelInfo({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={`flex gap-2.5 items-center bg-slate-400/10 border border-slate-600 w-full shadow-md rounded-md p-3 ${className}`}
|
||||
>
|
||||
<InformationCircleIcon className="h-6 w-6 min-w-[24px] text-blue-500" />
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ export function PanelWarning({
|
||||
<div
|
||||
className={`flex gap-2.5 items-center bg-amber-400/10 border border-amber-500 w-full shadow-md rounded-md p-3 ${className}`}
|
||||
>
|
||||
<ExclamationTriangleIcon className="h-6 w-6 text-amber-500" />
|
||||
<ExclamationTriangleIcon className="h-6 w-6 min-w-[24px] text-amber-500" />
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
BeakerIcon,
|
||||
ClipboardDocumentCheckIcon,
|
||||
Squares2X2Icon,
|
||||
Cog6ToothIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { Link, NavLink } from "@remix-run/react";
|
||||
import {
|
||||
@@ -94,6 +95,11 @@ export function WorkflowsSideMenu() {
|
||||
icon: <Squares2X2Icon className={iconStyle} />,
|
||||
to: `integrations`,
|
||||
},
|
||||
{
|
||||
name: "Settings",
|
||||
icon: <Cog6ToothIcon className={iconStyle} />,
|
||||
to: `settings`,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -80,11 +80,12 @@ export function WorkflowMenu() {
|
||||
className={classNames(
|
||||
"flex items-center justify-between gap-1.5 mx-1 px-3 py-2 text-white rounded hover:bg-slate-800 transition",
|
||||
workflow.slug === currentWorkflow?.slug &&
|
||||
"!bg-slate-800"
|
||||
"!bg-slate-800",
|
||||
workflow.status === "DISABLED" && "opacity-50"
|
||||
)}
|
||||
>
|
||||
<div className="relative flex items-center gap-2">
|
||||
{workflow.status !== "READY" && (
|
||||
{workflow.status === "CREATED" && (
|
||||
<ExclamationTriangleIcon className="absolute -top-1.5 -left-2.5 h-3.5 w-3.5 text-amber-500" />
|
||||
)}
|
||||
<ArrowsRightLeftIcon
|
||||
|
||||
@@ -2,20 +2,23 @@ import { Link } from "@remix-run/react";
|
||||
import classnames from "classnames";
|
||||
|
||||
const commonClasses =
|
||||
"inline-flex items-center justify-center max-w-max rounded px-4 py-2 text-sm transition whitespace-nowrap";
|
||||
"inline-flex items-center justify-center max-w-max rounded text-sm transition whitespace-nowrap";
|
||||
const primaryClasses = classnames(
|
||||
commonClasses,
|
||||
"bg-indigo-700 text-white hover:bg-indigo-600 focus:ring-indigo-800 gap-2"
|
||||
"px-4 py-2 bg-indigo-700 text-white hover:bg-indigo-600 focus:ring-indigo-800 gap-2"
|
||||
);
|
||||
const secondaryClasses = classnames(
|
||||
commonClasses,
|
||||
"bg-transparent border border-slate-700 text-white hover:bg-white/5 hover:border-slate-700 focus:ring-slate-300 gap-2"
|
||||
"px-4 py-2 bg-transparent ring-1 ring-slate-700 ring-inset text-white hover:bg-white/5 hover:border-slate-700 focus:ring-slate-300 gap-2"
|
||||
);
|
||||
|
||||
const tertiaryClasses = classnames(
|
||||
commonClasses,
|
||||
"text-white/60 hover:text-white gap-1"
|
||||
);
|
||||
const dangerClasses = classnames(
|
||||
commonClasses,
|
||||
"px-4 py-2 bg-rose-700 text-white hover:bg-rose-600 focus:ring-rose-800 gap-2"
|
||||
);
|
||||
|
||||
type ButtonProps = React.DetailedHTMLProps<
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
@@ -57,6 +60,14 @@ export function TertiaryButton({ children, className, ...props }: ButtonProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export function DangerButton({ children, className, ...props }: ButtonProps) {
|
||||
return (
|
||||
<button className={classnames(dangerClasses, className)} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function PrimaryLink({ children, className, to, ...props }: LinkProps) {
|
||||
return (
|
||||
<Link to={to} className={classnames(primaryClasses, className)} {...props}>
|
||||
|
||||
@@ -6,10 +6,7 @@ const roundedStyles = {
|
||||
roundedFull: "rounded",
|
||||
};
|
||||
|
||||
type InputProps = React.DetailedHTMLProps<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
HTMLInputElement
|
||||
> & {
|
||||
type InputProps = JSX.IntrinsicElements["input"] & {
|
||||
roundedEdges?: "roundedLeft" | "roundedRight" | "roundedFull";
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ type ButtonProps = Parameters<typeof Listbox.Button>[0] & {
|
||||
};
|
||||
|
||||
const buttonClassName =
|
||||
"relative w-full rounded bg-slate-700 py-2 pl-3 pr-10 text-sm text-left shadow-md hover:cursor-pointer hover:bg-slate-600/80 transition";
|
||||
"relative w-full rounded bg-slate-700 py-2 pl-4 pr-10 text-slate-300 text-sm text-left shadow-md hover:cursor-pointer hover:bg-slate-600/80 transition";
|
||||
function Button({ children, ...props }: ButtonProps) {
|
||||
return (
|
||||
<Listbox.Button
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { BeakerIcon, InformationCircleIcon } from "@heroicons/react/24/outline";
|
||||
import { BeakerIcon } from "@heroicons/react/24/outline";
|
||||
import { Link } from "@remix-run/react";
|
||||
import classNames from "classnames";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import type { ReactNode } from "react";
|
||||
import type { WorkflowRunListPresenter } from "~/models/workflowRunListPresenter.server";
|
||||
import { dateDifference, formatDateTime } from "~/utils";
|
||||
import { PanelWarning } from "../layout/PanelWarning";
|
||||
import { Spinner } from "../primitives/Spinner";
|
||||
import { runStatusIcon, runStatusLabel } from "./runStatus";
|
||||
|
||||
@@ -151,10 +152,7 @@ function BlankRow({ children }: { children: ReactNode }) {
|
||||
export function NoRuns({ title }: { title: string }) {
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="flex items-center justify-center p-3 pr-4 gap-1 bg-yellow-200 border border-yellow-400 rounded-md text-yellow-700">
|
||||
<InformationCircleIcon className="w-5 h-5" />
|
||||
<span className="text-gray">{title}</span>
|
||||
</div>
|
||||
<PanelWarning className="max-w-max">{title}</PanelWarning>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ export function runStatusTitle(status: WorkflowRunStatus): string {
|
||||
return "Disconnected";
|
||||
case "ERROR":
|
||||
return "Error";
|
||||
case "TIMED_OUT":
|
||||
return "Timed out";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +38,8 @@ export function runStatusLabel(status: WorkflowRunStatus): ReactNode {
|
||||
return <span className="text-amber-300">{runStatusTitle(status)}</span>;
|
||||
case "ERROR":
|
||||
return <span className="text-rose-500">{runStatusTitle(status)}</span>;
|
||||
case "TIMED_OUT":
|
||||
return <span className="text-amber-300">{runStatusTitle(status)}</span>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,5 +95,14 @@ export function runStatusIcon(
|
||||
)}
|
||||
/>
|
||||
);
|
||||
case "TIMED_OUT":
|
||||
return (
|
||||
<ExclamationTriangleIcon
|
||||
className={classNames(
|
||||
iconSize === "small" ? smallClasses : largeClasses,
|
||||
"relative text-amber-300"
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
import type {
|
||||
CustomEventTrigger,
|
||||
ScheduledEventTrigger,
|
||||
ScheduleSourceCron,
|
||||
ScheduleSourceRate,
|
||||
TriggerMetadata,
|
||||
WebhookEventTrigger,
|
||||
} from "@trigger.dev/common-schemas";
|
||||
import { Body } from "../primitives/text/Body";
|
||||
import { Header2 } from "../primitives/text/Headers";
|
||||
import cronstrue from "cronstrue";
|
||||
|
||||
export function TriggerBody({ trigger }: { trigger: TriggerMetadata }) {
|
||||
switch (trigger.type) {
|
||||
case "WEBHOOK":
|
||||
return <Webhook webhook={trigger} />;
|
||||
case "SCHEDULE":
|
||||
break;
|
||||
return <Scheduled event={trigger} />;
|
||||
case "CUSTOM_EVENT":
|
||||
return <CustomEvent event={trigger} />;
|
||||
case "HTTP_ENDPOINT":
|
||||
@@ -57,3 +61,83 @@ function CustomEvent({ event }: { event: CustomEventTrigger }) {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Scheduled({ event }: { event: ScheduledEventTrigger }) {
|
||||
return (
|
||||
<>
|
||||
<Body size="extra-small" className={workflowNodeUppercaseClasses}>
|
||||
{"rateOf" in event.source ? (
|
||||
<RateOfScheduled source={event.source} />
|
||||
) : (
|
||||
<AtScheduled source={event.source} />
|
||||
)}
|
||||
</Body>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function RateOfScheduled({ source }: { source: ScheduleSourceRate }) {
|
||||
const unit =
|
||||
"minutes" in source.rateOf
|
||||
? source.rateOf.minutes > 1
|
||||
? "minutes"
|
||||
: "minute"
|
||||
: "hours" in source.rateOf
|
||||
? source.rateOf.hours > 1
|
||||
? "hours"
|
||||
: "hour"
|
||||
: source.rateOf.days > 1
|
||||
? "days"
|
||||
: "day";
|
||||
|
||||
const value =
|
||||
"minutes" in source.rateOf
|
||||
? source.rateOf.minutes
|
||||
: "hours" in source.rateOf
|
||||
? source.rateOf.hours
|
||||
: source.rateOf.days;
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 items-baseline">
|
||||
<Body size="extra-small" className={workflowNodeUppercaseClasses}>
|
||||
Runs
|
||||
</Body>
|
||||
<Body size="small" className="text-slate-300 normal-case tracking-normal">
|
||||
Every {value} {unit}
|
||||
</Body>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AtScheduled({ source }: { source: ScheduleSourceCron }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<Body size="extra-small" className={workflowNodeUppercaseClasses}>
|
||||
Runs
|
||||
</Body>
|
||||
<Body
|
||||
size="small"
|
||||
className="text-slate-300 normal-case tracking-normal"
|
||||
>
|
||||
{cronstrue.toString(source.cron, {
|
||||
throwExceptionOnParseError: false,
|
||||
verbose: false,
|
||||
use24HourTimeFormat: true,
|
||||
})}
|
||||
</Body>
|
||||
</div>
|
||||
<div className="flex items-baseline gap-2">
|
||||
<Body size="extra-small" className={workflowNodeUppercaseClasses}>
|
||||
Cron expression
|
||||
</Body>
|
||||
<Body
|
||||
size="small"
|
||||
className="text-slate-300 normal-case tracking-normal"
|
||||
>
|
||||
{source.cron}
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,3 +32,5 @@ export function useCurrentWorkflow() {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export type CurrentWorkflow = ReturnType<typeof useCurrentWorkflow>;
|
||||
|
||||
@@ -61,3 +61,19 @@ export async function redirectWithErrorMessage(
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function redirectBackWithErrorMessage(
|
||||
request: Request,
|
||||
message: string
|
||||
) {
|
||||
const url = new URL(request.url);
|
||||
return redirectWithErrorMessage(url.pathname, request, message);
|
||||
}
|
||||
|
||||
export async function redirectBackWithSuccessMessage(
|
||||
request: Request,
|
||||
message: string
|
||||
) {
|
||||
const url = new URL(request.url);
|
||||
return redirectWithSuccessMessage(url.pathname, request, message);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,11 @@ export function getOrganizationFromSlug({
|
||||
},
|
||||
},
|
||||
},
|
||||
where: { isArchived: false },
|
||||
orderBy: [
|
||||
{ disabledAt: { sort: "asc", nulls: "first" } },
|
||||
{ title: "asc" },
|
||||
],
|
||||
},
|
||||
environments: {
|
||||
select: {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { RuntimeEnvironment } from ".prisma/client";
|
||||
import type { Session } from "@remix-run/node";
|
||||
import { createCookieSessionStorage } from "@remix-run/node";
|
||||
import { prisma } from "~/db.server";
|
||||
import { env } from "~/env.server";
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import type { SchedulerSource } from ".prisma/client";
|
||||
import { ScheduleSourceSchema } from "@trigger.dev/common-schemas";
|
||||
import cronstrue from "cronstrue";
|
||||
import type { DisplayProperties } from "internal-integrations";
|
||||
import { github } from "internal-integrations";
|
||||
import invariant from "tiny-invariant";
|
||||
@@ -6,6 +9,7 @@ import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
import { getIntegration } from "~/utils/integrations";
|
||||
import { getIntegrations } from "./integrations.server";
|
||||
import { getRuntimeEnvironment } from "./runtimeEnvironment.server";
|
||||
import type { ExternalSource, Workflow } from "./workflow.server";
|
||||
|
||||
export type WorkflowListItem = Awaited<
|
||||
@@ -19,8 +23,24 @@ export class WorkflowListPresenter {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
async data(organizationSlug: string) {
|
||||
const workflows = await getWorkflows(this.#prismaClient, organizationSlug);
|
||||
async data(organizationSlug: string, environmentSlug: string) {
|
||||
const organization = await this.#prismaClient.organization.findUnique({
|
||||
where: { slug: organizationSlug },
|
||||
select: { id: true },
|
||||
});
|
||||
invariant(organization, "Organization not found");
|
||||
|
||||
const runtimeEnvironment = await getRuntimeEnvironment({
|
||||
organizationId: organization.id,
|
||||
slug: environmentSlug,
|
||||
});
|
||||
invariant(runtimeEnvironment, "Runtime environment not found");
|
||||
|
||||
const workflows = await getWorkflows(
|
||||
this.#prismaClient,
|
||||
organizationSlug,
|
||||
runtimeEnvironment.id
|
||||
);
|
||||
const integrations = getIntegrations(true);
|
||||
|
||||
return workflows.map((workflow) => {
|
||||
@@ -39,7 +59,8 @@ export class WorkflowListPresenter {
|
||||
status: workflow.status,
|
||||
trigger: triggerProperties(
|
||||
workflow,
|
||||
workflow.externalSource ?? undefined
|
||||
workflow.externalSource ?? undefined,
|
||||
workflow.schedulerSources[0] ?? undefined
|
||||
),
|
||||
integrations: {
|
||||
source: workflow.service
|
||||
@@ -55,9 +76,13 @@ export class WorkflowListPresenter {
|
||||
}
|
||||
}
|
||||
|
||||
function getWorkflows(prismaClient: PrismaClient, organizationSlug: string) {
|
||||
function getWorkflows(
|
||||
prismaClient: PrismaClient,
|
||||
organizationSlug: string,
|
||||
environmentId: string
|
||||
) {
|
||||
return prismaClient.workflow.findMany({
|
||||
where: { organization: { slug: organizationSlug } },
|
||||
where: { organization: { slug: organizationSlug }, isArchived: false },
|
||||
include: {
|
||||
externalServices: {
|
||||
select: {
|
||||
@@ -70,6 +95,16 @@ function getWorkflows(prismaClient: PrismaClient, organizationSlug: string) {
|
||||
source: true,
|
||||
},
|
||||
},
|
||||
schedulerSources: {
|
||||
select: {
|
||||
schedule: true,
|
||||
},
|
||||
where: {
|
||||
environmentId,
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 1,
|
||||
},
|
||||
runs: {
|
||||
select: {
|
||||
finishedAt: true,
|
||||
@@ -79,12 +114,17 @@ function getWorkflows(prismaClient: PrismaClient, organizationSlug: string) {
|
||||
orderBy: { finishedAt: { sort: "desc", nulls: "last" } },
|
||||
},
|
||||
},
|
||||
orderBy: [
|
||||
{ disabledAt: { sort: "asc", nulls: "first" } },
|
||||
{ title: "asc" },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function triggerProperties(
|
||||
workflow: Pick<Workflow, "type" | "eventNames">,
|
||||
externalSource?: Pick<ExternalSource, "service" | "source">
|
||||
externalSource?: Pick<ExternalSource, "service" | "source">,
|
||||
schedulerSource?: Pick<SchedulerSource, "schedule">
|
||||
): {
|
||||
type: Workflow["type"];
|
||||
typeTitle: string;
|
||||
@@ -113,6 +153,49 @@ function triggerProperties(
|
||||
properties: displayProperties.properties,
|
||||
};
|
||||
}
|
||||
case "SCHEDULE": {
|
||||
invariant(schedulerSource, "Scheduler source is required for schedule");
|
||||
const source = ScheduleSourceSchema.parse(schedulerSource.schedule);
|
||||
|
||||
if ("rateOf" in source) {
|
||||
const unit =
|
||||
"minutes" in source.rateOf
|
||||
? source.rateOf.minutes > 1
|
||||
? "minutes"
|
||||
: "minute"
|
||||
: "hours" in source.rateOf
|
||||
? source.rateOf.hours > 1
|
||||
? "hours"
|
||||
: "hour"
|
||||
: source.rateOf.days > 1
|
||||
? "days"
|
||||
: "day";
|
||||
|
||||
const value =
|
||||
"minutes" in source.rateOf
|
||||
? source.rateOf.minutes
|
||||
: "hours" in source.rateOf
|
||||
? source.rateOf.hours
|
||||
: source.rateOf.days;
|
||||
|
||||
return {
|
||||
type: workflow.type,
|
||||
typeTitle: "Schedule",
|
||||
title: `Every ${value} ${unit}`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: workflow.type,
|
||||
typeTitle: "Schedule",
|
||||
title: cronstrue.toString(source.cron, {
|
||||
throwExceptionOnParseError: false,
|
||||
verbose: false,
|
||||
use24HourTimeFormat: true,
|
||||
}),
|
||||
properties: [{ key: "Cron Expression", value: source.cron }],
|
||||
};
|
||||
}
|
||||
}
|
||||
case "CUSTOM_EVENT":
|
||||
return {
|
||||
type: workflow.type,
|
||||
|
||||
@@ -19,6 +19,7 @@ export async function findWorklowRunById(id: string) {
|
||||
include: {
|
||||
event: true,
|
||||
environment: true,
|
||||
workflow: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -80,10 +81,10 @@ export async function failWorkflowRun(
|
||||
}
|
||||
|
||||
export async function completeWorkflowRun(
|
||||
output: string,
|
||||
runId: string,
|
||||
apiKey: string,
|
||||
timestamp: string
|
||||
timestamp: string,
|
||||
output?: string | null
|
||||
) {
|
||||
const workflowRun = await findWorkflowRunScopedToApiKey(runId, apiKey);
|
||||
|
||||
@@ -104,6 +105,9 @@ export async function completeWorkflowRun(
|
||||
},
|
||||
});
|
||||
|
||||
const parsedOutput =
|
||||
typeof output === "string" ? JSON.parse(output) : undefined;
|
||||
|
||||
await tx.workflowRunStep.upsert({
|
||||
where: {
|
||||
runId_idempotencyKey: {
|
||||
@@ -115,7 +119,7 @@ export async function completeWorkflowRun(
|
||||
runId,
|
||||
idempotencyKey: "output",
|
||||
type: "OUTPUT",
|
||||
output: JSON.parse(output),
|
||||
output: parsedOutput === null ? undefined : parsedOutput,
|
||||
context: {},
|
||||
startedAt: new Date(),
|
||||
finishedAt: new Date(),
|
||||
@@ -170,6 +174,13 @@ export async function triggerEventInRun(
|
||||
},
|
||||
workflowRun.environment.organization
|
||||
);
|
||||
|
||||
await prisma.workflowRunStep.update({
|
||||
where: { id: step.step.id },
|
||||
data: {
|
||||
status: "SUCCESS",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function logMessageInRun(
|
||||
|
||||
@@ -62,6 +62,7 @@ export class WorkflowRunPresenter {
|
||||
error: workflowRun.error
|
||||
? await ErrorSchema.parseAsync(workflowRun.error)
|
||||
: undefined,
|
||||
timedOutReason: workflowRun.timedOutReason,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
} from "@heroicons/react/24/solid";
|
||||
import { Link } from "@remix-run/react";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import classNames from "classnames";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import { ApiLogoIcon } from "~/components/code/ApiLogoIcon";
|
||||
@@ -19,6 +20,7 @@ import { Title } from "~/components/primitives/text/Title";
|
||||
import { runStatusLabel } from "~/components/runs/runStatus";
|
||||
import { TriggerTypeIcon } from "~/components/triggers/TriggerIcons";
|
||||
import { useCurrentOrganization } from "~/hooks/useOrganizations";
|
||||
import { getRuntimeEnvironmentFromRequest } from "~/models/runtimeEnvironment.server";
|
||||
import type { WorkflowListItem } from "~/models/workflowListPresenter.server";
|
||||
import { WorkflowListPresenter } from "~/models/workflowListPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
@@ -28,10 +30,12 @@ export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
await requireUserId(request);
|
||||
invariant(params.organizationSlug, "Organization slug is required");
|
||||
|
||||
const currentEnv = await getRuntimeEnvironmentFromRequest(request);
|
||||
|
||||
const presenter = new WorkflowListPresenter();
|
||||
|
||||
try {
|
||||
const workflows = await presenter.data(params.organizationSlug);
|
||||
const workflows = await presenter.data(params.organizationSlug, currentEnv);
|
||||
return typedjson({ workflows });
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
@@ -84,13 +88,16 @@ function WorkflowList({
|
||||
<li key={workflow.id}>
|
||||
<Link
|
||||
to={`/orgs/${currentOrganizationSlug}/workflows/${workflow.slug}`}
|
||||
className="block hover:bg-slate-850/40 transition"
|
||||
className={classNames(
|
||||
"block hover:bg-slate-850/40 transition",
|
||||
workflow.status === "DISABLED" ? workflowDisabled : ""
|
||||
)}
|
||||
>
|
||||
<div className="flex justify-between lg:items-center flex-col lg:flex-row flex-wrap lg:flex-nowrap pl-4 pr-4 py-4">
|
||||
<div className="flex items-center flex-1 justify-between">
|
||||
<div className="relative flex items-center">
|
||||
{workflow.status !== "READY" && (
|
||||
<ExclamationTriangleIcon className="absolute -top-1.5 -left-1.5 h-6 w-6 text-amber-500" />
|
||||
{workflow.status === "CREATED" && (
|
||||
<ExclamationTriangleIcon className="absolute -top-1.5 -left-1.5 h-6 w-6 text-amber-400" />
|
||||
)}
|
||||
<div className="p-3 bg-slate-850 rounded-md flex-shrink-0 self-start h-20 w-20 mr-4">
|
||||
<TriggerTypeIcon
|
||||
@@ -114,7 +121,7 @@ function WorkflowList({
|
||||
{workflow.trigger.title}
|
||||
</Header3>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-x-2 items-baseline">
|
||||
<div className="flex flex-wrap gap-x-3 items-baseline">
|
||||
{workflow.trigger.properties &&
|
||||
workflow.trigger.properties.map((property) => (
|
||||
<WorkflowProperty
|
||||
@@ -215,3 +222,5 @@ function WorkflowProperty({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const workflowDisabled = "opacity-30";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SquaresPlusIcon } from "@heroicons/react/24/outline";
|
||||
import { EnvelopeIcon } from "@heroicons/react/24/outline";
|
||||
import { PlusCircleIcon } from "@heroicons/react/24/solid";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import type { Provider } from "@trigger.dev/providers";
|
||||
@@ -104,7 +104,7 @@ export default function Integrations() {
|
||||
className="flex flex-col group max-w-[160px] rounded-md bg-slate-800 border border-slate-800 gap-4 text-sm text-slate-200 items-center overflow-hidden hover:bg-slate-800/30 transition shadow-md disabled:opacity-50"
|
||||
>
|
||||
<div className="relative flex items-center justify-center w-full py-6 bg-black/20 border-b border-slate-800">
|
||||
<SquaresPlusIcon className="h-20 w-20 text-slate-400" />
|
||||
<EnvelopeIcon className="h-20 w-20 text-slate-400" />
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center text-center leading-relaxed text-slate-400">
|
||||
<span className="px-2.5">Need an integration?</span>
|
||||
@@ -129,7 +129,7 @@ function AddButtonContent({
|
||||
return (
|
||||
<>
|
||||
<div className="relative flex items-center justify-center w-full py-6 bg-black/20 border-b border-slate-800">
|
||||
<PlusCircleIcon className="absolute h-7 w-7 top-[6px] right-[6px] z-10 text-slate-500 shadow-md" />
|
||||
<PlusCircleIcon className="absolute h-7 w-7 top-[6px] right-[6px] z-10 text-green-600 shadow-md" />
|
||||
<img
|
||||
src={integration.icon}
|
||||
alt={integration.name}
|
||||
|
||||
@@ -4,8 +4,13 @@ import invariant from "tiny-invariant";
|
||||
import { WorkflowConnections } from "~/components/integrations/WorkflowConnections";
|
||||
import { Panel } from "~/components/layout/Panel";
|
||||
import { PanelHeader } from "~/components/layout/PanelHeader";
|
||||
import { PanelInfo } from "~/components/layout/PanelInfo";
|
||||
import { PanelWarning } from "~/components/layout/PanelWarning";
|
||||
import { PrimaryLink, SecondaryLink } from "~/components/primitives/Buttons";
|
||||
import {
|
||||
PrimaryLink,
|
||||
SecondaryLink,
|
||||
TertiaryLink,
|
||||
} from "~/components/primitives/Buttons";
|
||||
import { Body } from "~/components/primitives/text/Body";
|
||||
import { SubTitle } from "~/components/primitives/text/SubTitle";
|
||||
import { Title } from "~/components/primitives/text/Title";
|
||||
@@ -79,14 +84,25 @@ export default function Page() {
|
||||
{workflow.slug}
|
||||
</Body>
|
||||
</div>
|
||||
{workflow.status !== "READY" && (
|
||||
{workflow.status === "CREATED" && (
|
||||
<>
|
||||
<SubTitle>1 issue</SubTitle>
|
||||
<PanelWarning className="mb-6">
|
||||
This workflow requires its APIs to be connected before it can run.
|
||||
</PanelWarning>
|
||||
</>
|
||||
)}
|
||||
{workflow.status === "DISABLED" && (
|
||||
<PanelInfo className="mb-6">
|
||||
<Body className="flex grow items-center justify-between">
|
||||
This workflow is disabled. Runs cannot be triggered or tested while
|
||||
disabled. Runs in progress will continue until complete.
|
||||
</Body>
|
||||
|
||||
<TertiaryLink to="settings" className="mr-1">
|
||||
Settings
|
||||
</TertiaryLink>
|
||||
</PanelInfo>
|
||||
)}
|
||||
{apiConnectionCount > 0 && <WorkflowConnections />}
|
||||
{eventRule && (
|
||||
<>
|
||||
@@ -123,7 +139,7 @@ export default function Page() {
|
||||
View all
|
||||
</SecondaryLink>
|
||||
</div>
|
||||
<Panel className="p-0 overflow-hidden overflow-x-auto">
|
||||
<Panel className="p-0 overflow-hidden overflow-x-auto mb-6">
|
||||
<RunsTable
|
||||
runs={runs}
|
||||
total={total}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import invariant from "tiny-invariant";
|
||||
import { WorkflowConnections } from "~/components/integrations/WorkflowConnections";
|
||||
import { PanelInfo } from "~/components/layout/PanelInfo";
|
||||
import { PanelWarning } from "~/components/layout/PanelWarning";
|
||||
import { TertiaryLink } from "~/components/primitives/Buttons";
|
||||
import { Body } from "~/components/primitives/text/Body";
|
||||
import { SubTitle } from "~/components/primitives/text/SubTitle";
|
||||
import { Title } from "~/components/primitives/text/Title";
|
||||
import { useConnectionSlots } from "~/hooks/useConnectionSlots";
|
||||
@@ -16,14 +19,24 @@ export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<Title>Connected APIs</Title>
|
||||
{workflow.status !== "READY" && (
|
||||
{workflow.status === "CREATED" && (
|
||||
<>
|
||||
<SubTitle>1 issue</SubTitle>
|
||||
<PanelWarning className="mb-6">
|
||||
This workflow requires its APIs to be connected before it can run.
|
||||
</PanelWarning>
|
||||
</>
|
||||
)}
|
||||
{workflow.status === "DISABLED" && (
|
||||
<PanelInfo className="mb-6">
|
||||
<Body className="flex grow items-center justify-between">
|
||||
This workflow is disabled. Runs cannot be triggered or tested while
|
||||
disabled. Runs in progress will continue until complete.
|
||||
</Body>
|
||||
<TertiaryLink to="settings" className="mr-1">
|
||||
Settings
|
||||
</TertiaryLink>
|
||||
</PanelInfo>
|
||||
)}
|
||||
{connectionSlots.source || connectionSlots.services.length > 0 ? (
|
||||
<WorkflowConnections />
|
||||
) : (
|
||||
|
||||
@@ -40,7 +40,7 @@ import { TriggerTypeIcon } from "~/components/triggers/TriggerIcons";
|
||||
import { triggerLabel } from "~/components/triggers/triggerLabel";
|
||||
import { useCurrentOrganization } from "~/hooks/useOrganizations";
|
||||
import { useCurrentWorkflow } from "~/hooks/useWorkflows";
|
||||
import type { WorkflowRunStatus } from "~/models/workflowRun.server";
|
||||
import { WorkflowRunStatus } from "~/models/workflowRun.server";
|
||||
import { WorkflowRunPresenter } from "~/models/workflowRunPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { dateDifference, formatDateTime } from "~/utils";
|
||||
@@ -218,6 +218,29 @@ export default function Page() {
|
||||
<div className="h-10 w-full ml-[10px] border-dashed border-l border-gradient border-slate-700"></div>
|
||||
)}
|
||||
|
||||
{run.status === "TIMED_OUT" && (
|
||||
<>
|
||||
<div className="h-3 w-full ml-[10px] -mr-[10px] border-l border-slate-700"></div>
|
||||
<Panel>
|
||||
<PanelHeader
|
||||
icon={
|
||||
<ExclamationTriangleIcon className="h-6 w-6 text-amber-300" />
|
||||
}
|
||||
title="Run timed out"
|
||||
runId={run.id}
|
||||
/>
|
||||
<div className="flex flex-col gap-1 text-slate-300">
|
||||
<Body size="extra-small" className={workflowNodeUppercaseClasses}>
|
||||
Reason
|
||||
</Body>
|
||||
<Body className={workflowNodeDelayClasses} size="small">
|
||||
{run.timedOutReason}
|
||||
</Body>
|
||||
</div>
|
||||
</Panel>
|
||||
</>
|
||||
)}
|
||||
|
||||
{run.error && <Error error={run.error} />}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -7,23 +7,25 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import { Panel } from "~/components/layout/Panel";
|
||||
import { PanelInfo } from "~/components/layout/PanelInfo";
|
||||
import { PanelWarning } from "~/components/layout/PanelWarning";
|
||||
import { PaginationControls } from "~/components/Pagination";
|
||||
import { TertiaryLink } from "~/components/primitives/Buttons";
|
||||
import { StyledListBox } from "~/components/primitives/ListBox";
|
||||
import { Body } from "~/components/primitives/text/Body";
|
||||
import { Title } from "~/components/primitives/text/Title";
|
||||
import { RunsTable } from "~/components/runs/RunsTable";
|
||||
import {
|
||||
runStatusIcon,
|
||||
runStatusLabel,
|
||||
runStatusTitle,
|
||||
} from "~/components/runs/runStatus";
|
||||
import { RunsTable } from "~/components/runs/RunsTable";
|
||||
import { useCurrentWorkflow } from "~/hooks/useWorkflows";
|
||||
import { getRuntimeEnvironmentFromRequest } from "~/models/runtimeEnvironment.server";
|
||||
import type { WorkflowRunStatus } from "~/models/workflowRun.server";
|
||||
import { WorkflowRunListPresenter } from "~/models/workflowRunListPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { getRuntimeEnvironmentFromRequest } from "~/models/runtimeEnvironment.server";
|
||||
import { allStatuses } from "~/models/workflowRunStatus";
|
||||
import { Title } from "~/components/primitives/text/Title";
|
||||
import { useCurrentWorkflow } from "~/hooks/useWorkflows";
|
||||
import { PanelWarning } from "~/components/layout/PanelWarning";
|
||||
import { SubTitle } from "~/components/primitives/text/SubTitle";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
@@ -77,14 +79,24 @@ export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<Title>Runs</Title>
|
||||
{workflow.status !== "READY" && (
|
||||
{workflow.status === "CREATED" && (
|
||||
<>
|
||||
<SubTitle>1 issue</SubTitle>
|
||||
<PanelWarning className="mb-6">
|
||||
This workflow requires its APIs to be connected before it can run.
|
||||
</PanelWarning>
|
||||
</>
|
||||
)}
|
||||
{workflow.status === "DISABLED" && (
|
||||
<PanelInfo className="mb-6">
|
||||
<Body className="flex grow items-center justify-between">
|
||||
This workflow is disabled. Runs cannot be triggered or tested while
|
||||
disabled. Runs in progress will continue until complete.
|
||||
</Body>
|
||||
<TertiaryLink to="settings" className="mr-1">
|
||||
Settings
|
||||
</TertiaryLink>
|
||||
</PanelInfo>
|
||||
)}
|
||||
<fetcher.Form
|
||||
method="get"
|
||||
className="pb-4 flex gap-2"
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
import { ApiLogoIcon } from "~/components/code/ApiLogoIcon";
|
||||
import { Panel } from "~/components/layout/Panel";
|
||||
import {
|
||||
DangerButton,
|
||||
PrimaryButton,
|
||||
SecondaryButton,
|
||||
} from "~/components/primitives/Buttons";
|
||||
import { Header3 } from "~/components/primitives/text/Headers";
|
||||
import { SubTitle } from "~/components/primitives/text/SubTitle";
|
||||
import { Title } from "~/components/primitives/text/Title";
|
||||
import type { CurrentWorkflow } from "~/hooks/useWorkflows";
|
||||
import { useCurrentWorkflow } from "~/hooks/useWorkflows";
|
||||
import invariant from "tiny-invariant";
|
||||
import { Form } from "@remix-run/react";
|
||||
import type { ActionArgs } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import {
|
||||
redirectBackWithErrorMessage,
|
||||
redirectBackWithSuccessMessage,
|
||||
redirectWithSuccessMessage,
|
||||
} from "~/models/message.server";
|
||||
import { DisableWorkflow } from "~/services/workflows/disableWorkflow.server";
|
||||
import { EnableWorkflow } from "~/services/workflows/enableWorkflow.server";
|
||||
import { ArchiveWorkflow } from "~/services/workflows/archiveWorkflow.server";
|
||||
import { UnarchiveWorkflow } from "~/services/workflows/unarchiveWorkflow.server";
|
||||
|
||||
const ActionSchema = z.enum(["disable", "enable", "archive", "unarchive"]);
|
||||
const FormSchema = z.object({
|
||||
action: ActionSchema,
|
||||
});
|
||||
const ParamsSchema = z.object({
|
||||
organizationSlug: z.string(),
|
||||
workflowSlug: z.string(),
|
||||
});
|
||||
|
||||
export async function action({ params, request }: ActionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
|
||||
const formData = Object.fromEntries(await request.formData());
|
||||
const { action } = FormSchema.parse(formData);
|
||||
const { organizationSlug, workflowSlug } = ParamsSchema.parse(params);
|
||||
|
||||
switch (action) {
|
||||
case "disable":
|
||||
return disableAction(userId, organizationSlug, workflowSlug, request);
|
||||
case "enable":
|
||||
return enableAction(userId, organizationSlug, workflowSlug, request);
|
||||
case "archive":
|
||||
return archiveAction(userId, organizationSlug, workflowSlug, request);
|
||||
case "unarchive":
|
||||
return unarchiveAction(userId, organizationSlug, workflowSlug, request);
|
||||
}
|
||||
}
|
||||
|
||||
async function disableAction(
|
||||
userId: string,
|
||||
organizationSlug: string,
|
||||
workflowSlug: string,
|
||||
request: Request
|
||||
) {
|
||||
const service = new DisableWorkflow();
|
||||
const result = await service.call(userId, organizationSlug, workflowSlug);
|
||||
|
||||
if (result.status === "error") {
|
||||
return redirectBackWithErrorMessage(request, result.message);
|
||||
}
|
||||
|
||||
return redirectBackWithSuccessMessage(
|
||||
request,
|
||||
"Workflow successfully disabled. We will stop triggering it for new events."
|
||||
);
|
||||
}
|
||||
|
||||
async function enableAction(
|
||||
userId: string,
|
||||
organizationSlug: string,
|
||||
workflowSlug: string,
|
||||
request: Request
|
||||
) {
|
||||
const service = new EnableWorkflow();
|
||||
const result = await service.call(userId, organizationSlug, workflowSlug);
|
||||
|
||||
if (result.status === "error") {
|
||||
return redirectBackWithErrorMessage(request, result.message);
|
||||
}
|
||||
|
||||
return redirectBackWithSuccessMessage(
|
||||
request,
|
||||
"Workflow successfully enabled. Triggering of new events will resume."
|
||||
);
|
||||
}
|
||||
|
||||
async function archiveAction(
|
||||
userId: string,
|
||||
organizationSlug: string,
|
||||
workflowSlug: string,
|
||||
request: Request
|
||||
) {
|
||||
const service = new ArchiveWorkflow();
|
||||
const result = await service.call(userId, organizationSlug, workflowSlug);
|
||||
|
||||
if (result.status === "error") {
|
||||
return redirectBackWithErrorMessage(request, result.message);
|
||||
}
|
||||
|
||||
return redirectWithSuccessMessage(
|
||||
`/orgs/${organizationSlug}`,
|
||||
request,
|
||||
"Workflow successfully archived."
|
||||
);
|
||||
}
|
||||
|
||||
async function unarchiveAction(
|
||||
userId: string,
|
||||
organizationSlug: string,
|
||||
workflowSlug: string,
|
||||
request: Request
|
||||
) {
|
||||
const service = new UnarchiveWorkflow();
|
||||
const result = await service.call(userId, organizationSlug, workflowSlug);
|
||||
|
||||
if (result.status === "error") {
|
||||
return redirectBackWithErrorMessage(request, result.message);
|
||||
}
|
||||
|
||||
return redirectBackWithSuccessMessage(
|
||||
request,
|
||||
"Workflow successfully unarchived. Enable it to resume triggering of new events."
|
||||
);
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
const workflow = useCurrentWorkflow();
|
||||
invariant(workflow, "Workflow not found");
|
||||
|
||||
const panel =
|
||||
workflow.status === "READY" ? (
|
||||
<WorkflowReadyPanel workflow={workflow} />
|
||||
) : workflow.isArchived ? (
|
||||
<WorkflowArchivedPanel workflow={workflow} />
|
||||
) : workflow.status === "DISABLED" ? (
|
||||
<WorkflowDisabledPanel workflow={workflow} />
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title>Settings</Title>
|
||||
<SubTitle>Workflow status</SubTitle>
|
||||
{panel}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function WorkflowReadyPanel({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: NonNullable<CurrentWorkflow>;
|
||||
}) {
|
||||
return (
|
||||
<Panel className="flex items-center justify-between !p-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<ApiLogoIcon size="regular" />
|
||||
<Header3 size="small" className="text-slate-300">
|
||||
{workflow.title} <span className="text-green-500">is active.</span>
|
||||
</Header3>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<Form
|
||||
method="post"
|
||||
onSubmit={(e) =>
|
||||
!confirm(
|
||||
"Disabling this workflow will prevent any new triggers from running, but will not stop in-progress runs from completing. Are you sure you want to disable this workflow?"
|
||||
) && e.preventDefault()
|
||||
}
|
||||
>
|
||||
<SecondaryButton name="action" value="disable" type="submit">
|
||||
Disable
|
||||
</SecondaryButton>
|
||||
</Form>
|
||||
|
||||
<Form
|
||||
method="post"
|
||||
onSubmit={(e) =>
|
||||
!confirm(
|
||||
"Archiving this workflow disables it and removes it from your list of workflows. Are you sure you want to archive this workflow?"
|
||||
) && e.preventDefault()
|
||||
}
|
||||
>
|
||||
<DangerButton name="action" value="archive" type="submit">
|
||||
Archive
|
||||
</DangerButton>
|
||||
</Form>
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
|
||||
function WorkflowDisabledPanel({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: NonNullable<CurrentWorkflow>;
|
||||
}) {
|
||||
return (
|
||||
<Panel className="flex items-center justify-between !p-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<ApiLogoIcon size="regular" />
|
||||
<Header3 size="small" className="text-slate-300">
|
||||
{workflow.title} <span className="text-amber-300">is disabled.</span>
|
||||
</Header3>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<Form
|
||||
method="post"
|
||||
onSubmit={(e) =>
|
||||
!confirm(
|
||||
"Enabling this workflow will resume triggering workflows from new events. Are you sure you want to enable this workflow?"
|
||||
) && e.preventDefault()
|
||||
}
|
||||
>
|
||||
<PrimaryButton name="action" value="enable" type="submit">
|
||||
Enable
|
||||
</PrimaryButton>
|
||||
</Form>
|
||||
|
||||
<Form
|
||||
method="post"
|
||||
onSubmit={(e) =>
|
||||
!confirm(
|
||||
"Archiving this workflow will remove it from your list of workflows. Are you sure you want to archive this workflow?"
|
||||
) && e.preventDefault()
|
||||
}
|
||||
>
|
||||
<DangerButton name="action" value="archive" type="submit">
|
||||
Archive
|
||||
</DangerButton>
|
||||
</Form>
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
|
||||
function WorkflowArchivedPanel({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: NonNullable<CurrentWorkflow>;
|
||||
}) {
|
||||
return (
|
||||
<Panel className="flex items-center justify-between !p-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<ApiLogoIcon size="regular" />
|
||||
<Header3 size="small" className="text-slate-300">
|
||||
{workflow.title} <span className="text-rose-500">is archived.</span>
|
||||
</Header3>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<Form
|
||||
method="post"
|
||||
onSubmit={(e) =>
|
||||
!confirm(
|
||||
"Unarchiving this workflow will add it back to your list of workflows, but not enable it. Are you sure you want to unarchive this workflow?"
|
||||
) && e.preventDefault()
|
||||
}
|
||||
>
|
||||
<PrimaryButton name="action" value="unarchive" type="submit">
|
||||
Unarchive
|
||||
</PrimaryButton>
|
||||
</Form>
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
@@ -5,10 +5,11 @@ import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import { JSONEditor } from "~/components/code/JSONEditor";
|
||||
import { Panel } from "~/components/layout/Panel";
|
||||
import { PanelInfo } from "~/components/layout/PanelInfo";
|
||||
import { PanelWarning } from "~/components/layout/PanelWarning";
|
||||
import { PrimaryButton } from "~/components/primitives/Buttons";
|
||||
import { PrimaryButton, TertiaryLink } from "~/components/primitives/Buttons";
|
||||
import { Select } from "~/components/primitives/Select";
|
||||
import { SubTitle } from "~/components/primitives/text/SubTitle";
|
||||
import { Body } from "~/components/primitives/text/Body";
|
||||
import { Title } from "~/components/primitives/text/Title";
|
||||
import { useCurrentOrganization } from "~/hooks/useOrganizations";
|
||||
import { useCurrentWorkflow } from "~/hooks/useWorkflows";
|
||||
@@ -40,14 +41,25 @@ export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<Title>Test</Title>
|
||||
{workflow.status !== "READY" && (
|
||||
{workflow.status === "CREATED" && (
|
||||
<>
|
||||
<SubTitle>1 issue</SubTitle>
|
||||
<PanelWarning className="mb-6">
|
||||
This workflow requires its APIs to be connected before it can run.
|
||||
</PanelWarning>
|
||||
</>
|
||||
)}
|
||||
{workflow.status === "DISABLED" && (
|
||||
<PanelInfo className="mb-6">
|
||||
<Body className="flex grow items-center justify-between">
|
||||
This workflow is disabled. Runs cannot be triggered or tested while
|
||||
disabled. Runs in progress will continue until complete.
|
||||
</Body>
|
||||
<TertiaryLink to="settings" className="mr-1">
|
||||
Settings
|
||||
</TertiaryLink>
|
||||
</PanelInfo>
|
||||
)}
|
||||
|
||||
{workflow.status === "READY" && (
|
||||
<Panel className="mt-4">
|
||||
<Tester
|
||||
|
||||
@@ -33,6 +33,7 @@ export class DispatchEvent {
|
||||
organizationId: event.organizationId ?? undefined,
|
||||
environmentId: event.environmentId ?? undefined,
|
||||
type: event.type,
|
||||
enabled: true,
|
||||
},
|
||||
include: {
|
||||
workflow: true,
|
||||
@@ -135,6 +136,10 @@ export class DispatchWorkflowRun {
|
||||
event: TriggerEvent,
|
||||
environment: RuntimeEnvironment
|
||||
) {
|
||||
if (workflow.status === "DISABLED") {
|
||||
return true;
|
||||
}
|
||||
|
||||
const workflowRun = await this.#prismaClient.workflowRun.create({
|
||||
data: {
|
||||
workflow: {
|
||||
|
||||
@@ -43,6 +43,7 @@ import { WaitForConnection } from "./requests/waitForConnection.server";
|
||||
import { WorkflowRunDisconnected } from "./runs/runDisconnected.server";
|
||||
import { DeliverScheduledEvent } from "./scheduler/deliverScheduledEvent.server";
|
||||
import { RegisterSchedulerSource } from "./scheduler/registerSchedulerSource.server";
|
||||
import { WorkflowRunTriggerTimeout } from "./runs/runTriggerTimeout.server";
|
||||
|
||||
let pulsarClient: PulsarClient;
|
||||
let triggerPublisher: ZodPublisher<TriggerCatalog>;
|
||||
@@ -130,6 +131,9 @@ export async function init() {
|
||||
function createClient() {
|
||||
const client = createPulsarClient({
|
||||
serviceUrl: env.PULSAR_SERVICE_URL,
|
||||
ioThreads: 5,
|
||||
messageListenerThreads: 5,
|
||||
operationTimeoutSeconds: 30,
|
||||
});
|
||||
|
||||
console.log(`📡 Connected to pulsar at ${env.PULSAR_SERVICE_URL}`);
|
||||
@@ -142,6 +146,7 @@ function createTriggerPublisher() {
|
||||
client: pulsarClient,
|
||||
config: {
|
||||
topic: Topics.triggers,
|
||||
batchingEnabled: false,
|
||||
},
|
||||
schema: triggerCatalog,
|
||||
});
|
||||
@@ -187,10 +192,10 @@ function createCommandSubscriber() {
|
||||
},
|
||||
WORKFLOW_RUN_COMPLETE: async (id, data, properties) => {
|
||||
await completeWorkflowRun(
|
||||
data.output,
|
||||
properties["x-workflow-run-id"],
|
||||
properties["x-api-key"],
|
||||
properties["x-timestamp"]
|
||||
properties["x-timestamp"],
|
||||
data.output
|
||||
);
|
||||
|
||||
return true;
|
||||
@@ -202,6 +207,13 @@ function createCommandSubscriber() {
|
||||
|
||||
return !!success;
|
||||
},
|
||||
WORKFLOW_RUN_TRIGGER_TIMEOUT: async (id, data, properties) => {
|
||||
const service = new WorkflowRunTriggerTimeout();
|
||||
|
||||
await service.call(data);
|
||||
|
||||
return true;
|
||||
},
|
||||
SEND_INTEGRATION_REQUEST: async (id, data, properties) => {
|
||||
const service = new CreateIntegrationRequest();
|
||||
|
||||
@@ -251,6 +263,7 @@ function createCommandResponsePublisher() {
|
||||
client: pulsarClient,
|
||||
config: {
|
||||
topic: Topics.runCommandResponses,
|
||||
batchingEnabled: false,
|
||||
},
|
||||
schema: commandResponseCatalog,
|
||||
});
|
||||
@@ -521,6 +534,10 @@ function createTaskQueue() {
|
||||
"x-workflow-id": run.workflowId,
|
||||
"x-env": run.environment.slug,
|
||||
"x-workflow-run-id": run.id,
|
||||
"x-ttl": run.workflow.triggerTtlInSeconds,
|
||||
},
|
||||
{
|
||||
eventTimestamp: run.event.timestamp.getTime(),
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
|
||||
export class WorkflowRunTriggerTimeout {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
async call(data: { id: string; ttl: number; elapsedSeconds: number }) {
|
||||
const workflowRun = await this.#prismaClient.workflowRun.findUnique({
|
||||
where: { id: data.id },
|
||||
include: {
|
||||
event: true,
|
||||
environment: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!workflowRun) {
|
||||
throw new Error("Workflow run not found");
|
||||
}
|
||||
|
||||
if (workflowRun.status !== "PENDING") {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.#prismaClient.workflowRun.update({
|
||||
where: { id: data.id },
|
||||
data: {
|
||||
status: "TIMED_OUT",
|
||||
timedOutAt: new Date(),
|
||||
timedOutReason: `Trigger timed out after ${data.elapsedSeconds}s because it exceeded the TTL of ${data.ttl}s`,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,10 @@ export class DeliverScheduledEvent {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!eventRule.enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1. Create a TriggerEvent
|
||||
const triggerEvent = await this.#prismaClient.triggerEvent.create({
|
||||
data: {
|
||||
@@ -63,6 +67,7 @@ export class DeliverScheduledEvent {
|
||||
context: {},
|
||||
organizationId: schedulerSource.organizationId,
|
||||
environmentId: schedulerSource.environmentId,
|
||||
timestamp: payload.scheduledTime,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
import { DisableWorkflow } from "./disableWorkflow.server";
|
||||
|
||||
export class ArchiveWorkflow {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call(userId: string, organizationSlug: string, slug: string) {
|
||||
const organization = await this.#prismaClient.organization.findFirst({
|
||||
where: {
|
||||
slug: organizationSlug,
|
||||
users: {
|
||||
some: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue archiving this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
const workflow = await this.#prismaClient.workflow.findFirst({
|
||||
where: {
|
||||
slug,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!workflow) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue archiving this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
if (workflow.isArchived) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message: "This workflow is already archived",
|
||||
};
|
||||
}
|
||||
|
||||
const disableService = new DisableWorkflow();
|
||||
await disableService.call(userId, organizationSlug, slug);
|
||||
|
||||
await this.#prismaClient.workflow.update({
|
||||
where: {
|
||||
id: workflow.id,
|
||||
},
|
||||
data: {
|
||||
isArchived: true,
|
||||
archivedAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
status: "success" as const,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
|
||||
export class DisableWorkflow {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call(userId: string, organizationSlug: string, slug: string) {
|
||||
const organization = await this.#prismaClient.organization.findFirst({
|
||||
where: {
|
||||
slug: organizationSlug,
|
||||
users: {
|
||||
some: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue disabling this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
const workflow = await this.#prismaClient.workflow.findFirst({
|
||||
where: {
|
||||
slug,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!workflow) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue disabling this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
if (workflow.status === "DISABLED") {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message: "This workflow is already disabled",
|
||||
};
|
||||
}
|
||||
|
||||
if (workflow.isArchived) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message: "This workflow is already archived, and cannot be disabled",
|
||||
};
|
||||
}
|
||||
|
||||
const updatedWorkflow = await this.#prismaClient.workflow.update({
|
||||
where: {
|
||||
id: workflow.id,
|
||||
},
|
||||
data: {
|
||||
status: "DISABLED",
|
||||
disabledAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
await this.#prismaClient.eventRule.updateMany({
|
||||
where: {
|
||||
workflowId: workflow.id,
|
||||
},
|
||||
data: {
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
status: "success" as const,
|
||||
workflow: updatedWorkflow,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
import { ScheduleNextEvent } from "../scheduler/scheduleNextEvent.server";
|
||||
|
||||
export class EnableWorkflow {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call(userId: string, organizationSlug: string, slug: string) {
|
||||
const organization = await this.#prismaClient.organization.findFirst({
|
||||
where: {
|
||||
slug: organizationSlug,
|
||||
users: {
|
||||
some: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue enabling this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
const workflow = await this.#prismaClient.workflow.findFirst({
|
||||
where: {
|
||||
slug,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!workflow) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue enabling this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
if (workflow.status === "READY" || workflow.status === "CREATED") {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message: "This workflow is already enabled",
|
||||
};
|
||||
}
|
||||
|
||||
if (workflow.isArchived) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message: "This workflow is already archived, and cannot be enabled",
|
||||
};
|
||||
}
|
||||
|
||||
await this.#prismaClient.workflow.update({
|
||||
where: {
|
||||
id: workflow.id,
|
||||
},
|
||||
data: {
|
||||
status: "READY",
|
||||
disabledAt: null,
|
||||
},
|
||||
});
|
||||
|
||||
await this.#prismaClient.eventRule.updateMany({
|
||||
where: {
|
||||
workflowId: workflow.id,
|
||||
},
|
||||
data: {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (workflow.type === "SCHEDULE") {
|
||||
const schedulers = await this.#prismaClient.schedulerSource.findMany({
|
||||
where: {
|
||||
workflowId: workflow.id,
|
||||
},
|
||||
});
|
||||
|
||||
for (const scheduler of schedulers) {
|
||||
const scheduleNextEvent = new ScheduleNextEvent();
|
||||
await scheduleNextEvent.call(scheduler);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: "success" as const,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,13 @@ export class RegisterWorkflow {
|
||||
organization
|
||||
);
|
||||
|
||||
if (workflow.isArchived) {
|
||||
return {
|
||||
status: "success" as const,
|
||||
data: { id: workflow.id },
|
||||
};
|
||||
}
|
||||
|
||||
if (validation.data.trigger.service !== "trigger") {
|
||||
await this.#upsertExternalSource(
|
||||
validation.data,
|
||||
@@ -73,6 +80,7 @@ export class RegisterWorkflow {
|
||||
},
|
||||
update: {
|
||||
filter: "filter" in payload.trigger ? payload.trigger.filter : {},
|
||||
trigger: payload.trigger,
|
||||
},
|
||||
create: {
|
||||
workflowId: workflow.id,
|
||||
@@ -103,6 +111,7 @@ export class RegisterWorkflow {
|
||||
type: payload.trigger.type,
|
||||
service: payload.trigger.service,
|
||||
eventNames: payload.trigger.name,
|
||||
triggerTtlInSeconds: payload.triggerTTL,
|
||||
},
|
||||
create: {
|
||||
organizationId: organization.id,
|
||||
@@ -113,6 +122,7 @@ export class RegisterWorkflow {
|
||||
status: payload.trigger.service === "trigger" ? "READY" : "CREATED",
|
||||
service: payload.trigger.service,
|
||||
eventNames: payload.trigger.name,
|
||||
triggerTtlInSeconds: payload.triggerTTL,
|
||||
},
|
||||
include: {
|
||||
externalSource: true,
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
import { DisableWorkflow } from "./disableWorkflow.server";
|
||||
|
||||
export class UnarchiveWorkflow {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call(userId: string, organizationSlug: string, slug: string) {
|
||||
const organization = await this.#prismaClient.organization.findFirst({
|
||||
where: {
|
||||
slug: organizationSlug,
|
||||
users: {
|
||||
some: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue unarchiving this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
const workflow = await this.#prismaClient.workflow.findFirst({
|
||||
where: {
|
||||
slug,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!workflow) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message:
|
||||
"There was an issue unarchiving this workflow. Please contact help@trigger.dev for assistance.",
|
||||
};
|
||||
}
|
||||
|
||||
if (!workflow.isArchived) {
|
||||
return {
|
||||
status: "error" as const,
|
||||
message: "This workflow is not currently archived",
|
||||
};
|
||||
}
|
||||
|
||||
await this.#prismaClient.workflow.update({
|
||||
where: {
|
||||
id: workflow.id,
|
||||
},
|
||||
data: {
|
||||
isArchived: false,
|
||||
archivedAt: null,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
status: "success" as const,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,208 @@
|
||||
/* PrismJS 1.29.0
|
||||
https://prismjs.com/download.html#themes=prism-tomorrow */
|
||||
/* PrismJS 1.14.0
|
||||
http://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+abap+actionscript+ada+apacheconf+apl+applescript+c+arff+asciidoc+asm6502+aspnet+autohotkey+autoit+bash+basic+batch+bison+brainfuck+bro+cpp+csharp+arduino+coffeescript+clojure+ruby+csp+css-extras+d+dart+diff+django+docker+eiffel+elixir+elm+markup-templating+erlang+fsharp+flow+fortran+gedcom+gherkin+git+glsl+go+graphql+groovy+haml+handlebars+haskell+haxe+http+hpkp+hsts+ichigojam+icon+inform7+ini+io+j+java+jolie+json+julia+keyman+kotlin+latex+less+liquid+lisp+livescript+lolcode+lua+makefile+markdown+erb+matlab+mel+mizar+monkey+n4js+nasm+nginx+nim+nix+nsis+objectivec+ocaml+opencl+oz+parigp+parser+pascal+perl+php+php-extras+sql+powershell+processing+prolog+properties+protobuf+pug+puppet+pure+python+q+qore+r+jsx+typescript+renpy+reason+rest+rip+roboconf+crystal+rust+sas+sass+scss+scala+scheme+smalltalk+smarty+plsql+soy+stylus+swift+tcl+textile+twig+tsx+vbnet+velocity+verilog+vhdl+vim+visual-basic+wasm+wiki+xeora+xojo+yaml&plugins=line-numbers+toolbar+show-language */
|
||||
/**
|
||||
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
|
||||
* Based on https://github.com/chriskempson/tomorrow-theme
|
||||
* @author Rose Pritchard
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dracula Theme for Prism.JS
|
||||
*
|
||||
* @author Gustavo Costa
|
||||
* e-mail: gusbemacbe@gmail.com
|
||||
*
|
||||
* @contributor Jon Leopard
|
||||
* e-mail: jonlprd@gmail.com
|
||||
*
|
||||
* @license MIT 2016-2020
|
||||
*/
|
||||
|
||||
/* Scrollbars */
|
||||
|
||||
:root {
|
||||
--background: #0f172a;
|
||||
--comment: #6272a4;
|
||||
--foreground: #f8f8f2;
|
||||
--selection: #44475a;
|
||||
|
||||
--cyan: #8be9fd;
|
||||
--green: #50fa7b;
|
||||
--orange: #ffb86c;
|
||||
--pink: #ff79c6;
|
||||
--purple: #bd93f9;
|
||||
--red: #ff5555;
|
||||
--yellow: #f1fa8c;
|
||||
|
||||
/* Transparency */
|
||||
|
||||
/** 30% of transparency **/
|
||||
--background-30: #282a3633;
|
||||
--comment-30: #6272a433;
|
||||
--foreground-30: #f8f8f233;
|
||||
--selection-30: #44475a33;
|
||||
|
||||
--cyan-30: #8be9fd33;
|
||||
--green-30: #50fa7b33;
|
||||
--orange-30: #ffb86c33;
|
||||
--pink-30: #ff79c633;
|
||||
--purple-30: #bd93f933;
|
||||
--red-30: #ff555533;
|
||||
--yellow-30: #f1fa8c33;
|
||||
|
||||
/** 40% of transparency **/
|
||||
--background-40: #282a3666;
|
||||
--comment-40: #6272a466;
|
||||
--foreground-40: #f8f8f266;
|
||||
--selection-40: #44475a66;
|
||||
|
||||
--cyan-40: #8be9fd66;
|
||||
--green-40: #50fa7b66;
|
||||
--orange-40: #ffb86c66;
|
||||
--pink-40: #ff79c666;
|
||||
--purple-40: #bd93f966;
|
||||
--red-40: #ff555566;
|
||||
--yellow-40: #f1fa8c66;
|
||||
}
|
||||
|
||||
/* Selection */
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background-color: var(--selection);
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background-color: var(--selection);
|
||||
}
|
||||
|
||||
/* Line numbers */
|
||||
|
||||
pre.line-numbers {
|
||||
position: relative;
|
||||
padding-left: 3.8em;
|
||||
counter-reset: linenumber;
|
||||
}
|
||||
|
||||
pre.line-numbers > code {
|
||||
position: relative;
|
||||
white-space: inherit;
|
||||
}
|
||||
|
||||
.line-numbers .line-numbers-rows {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
font-size: 100%;
|
||||
left: -3.8em;
|
||||
width: 3em; /* works for line-numbers below 1000 lines */
|
||||
letter-spacing: -1px;
|
||||
border-right: 1px solid rgb(153, 153, 153);
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.line-numbers-rows > span {
|
||||
pointer-events: none;
|
||||
display: block;
|
||||
counter-increment: linenumber;
|
||||
}
|
||||
|
||||
.line-numbers-rows > span:before {
|
||||
content: counter(linenumber);
|
||||
color: #999;
|
||||
display: block;
|
||||
padding-right: 0.8em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Toolbar for copying */
|
||||
|
||||
div.code-toolbar {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar {
|
||||
position: absolute;
|
||||
top: 0.3em;
|
||||
right: 0.2em;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
div.code-toolbar:hover > .toolbar {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar .toolbar-item {
|
||||
display: inline-block;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar button {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
line-height: normal;
|
||||
overflow: visible;
|
||||
padding: 0;
|
||||
-webkit-user-select: none; /* for button */
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar a,
|
||||
div.code-toolbar > .toolbar button,
|
||||
div.code-toolbar > .toolbar span {
|
||||
color: var(--foreground);
|
||||
font-size: 0.8em;
|
||||
padding: 0.5em;
|
||||
background: var(--comment);
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar a:hover,
|
||||
div.code-toolbar > .toolbar a:focus,
|
||||
div.code-toolbar > .toolbar button:hover,
|
||||
div.code-toolbar > .toolbar button:focus,
|
||||
div.code-toolbar > .toolbar span:hover,
|
||||
div.code-toolbar > .toolbar span:focus {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
background-color: var(--green);
|
||||
}
|
||||
|
||||
/* Remove text shadow for printing */
|
||||
|
||||
@media print {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: #ccc;
|
||||
background: none;
|
||||
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||
font-size: 0.95em;
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
text-shadow: none;
|
||||
font-family: PT Mono, Consolas, Monaco, "Andale Mono", "Ubuntu Mono",
|
||||
monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
@@ -19,9 +210,9 @@ pre[class*="language-"] {
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 2;
|
||||
-o-tab-size: 2;
|
||||
tab-size: 2;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
@@ -30,94 +221,273 @@ pre[class*="language-"] {
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
|
||||
pre[class*="language-"] {
|
||||
padding: 0.5em;
|
||||
background: var(--background);
|
||||
border-radius: 0.5em;
|
||||
padding: 1em;
|
||||
margin: 0.5em 0;
|
||||
overflow: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #0f172a;
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: 0.1em;
|
||||
padding: 4px 7px;
|
||||
border-radius: 0.3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.block-comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: #999;
|
||||
/* Code box limit */
|
||||
|
||||
.limit-300 {
|
||||
height: 300px !important;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #ccc;
|
||||
.limit-300 {
|
||||
height: 400px !important;
|
||||
}
|
||||
|
||||
.token.tag,
|
||||
.token.attr-name,
|
||||
.token.namespace,
|
||||
.token.deleted {
|
||||
color: #e2777a;
|
||||
.limit-500 {
|
||||
height: 500px !important;
|
||||
}
|
||||
|
||||
.token.function-name {
|
||||
color: #6196cc;
|
||||
.limit-600 {
|
||||
height: 600px !important;
|
||||
}
|
||||
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.function {
|
||||
color: #f08d49;
|
||||
.limit-700 {
|
||||
height: 700px !important;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.class-name,
|
||||
.token.constant,
|
||||
.token.symbol {
|
||||
color: #f8c555;
|
||||
.limit-800 {
|
||||
height: 800px !important;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.important,
|
||||
.token.atrule,
|
||||
.token.keyword,
|
||||
.token.builtin {
|
||||
color: #cc99cd;
|
||||
.language-css {
|
||||
color: var(--purple);
|
||||
}
|
||||
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.attr-value,
|
||||
.token.regex,
|
||||
.token.variable {
|
||||
color: #7ec699;
|
||||
.token {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url {
|
||||
color: #67cdcc;
|
||||
.language-css .token {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.token.script {
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
.token.atrule,
|
||||
.token.attr-name,
|
||||
.token.attr-value {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
color: green;
|
||||
.language-css .token.atrule {
|
||||
color: var(--purple);
|
||||
}
|
||||
|
||||
.language-html .token.attr-value,
|
||||
.language-markup .token.attr-value {
|
||||
color: var(--yellow);
|
||||
}
|
||||
|
||||
.token.boolean {
|
||||
color: var(--purple);
|
||||
}
|
||||
|
||||
.token.builtin,
|
||||
.token.class-name {
|
||||
color: var(--cyan);
|
||||
}
|
||||
|
||||
.token.comment {
|
||||
color: var(--comment);
|
||||
}
|
||||
|
||||
.token.constant {
|
||||
color: var(--purple);
|
||||
}
|
||||
|
||||
.language-javascript .token.constant {
|
||||
color: var(--orange);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.language-css .token.entity {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.language-html .token.entity.named-entity {
|
||||
color: var(--purple);
|
||||
}
|
||||
|
||||
.language-html .token.entity:not(.named-entity) {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.language-markup .token.entity.named-entity {
|
||||
color: var(--purple);
|
||||
}
|
||||
|
||||
.language-markup .token.entity:not(.named-entity) {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.language-css .token.function {
|
||||
color: var(--cyan);
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.keyword {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.token.prolog {
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.token.property {
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
.language-css .token.property {
|
||||
color: var(--cyan);
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.language-css .token.punctuation {
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
.language-html .token.punctuation,
|
||||
.language-markup .token.punctuation {
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.token.selector {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.language-css .token.selector {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.token.regex {
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
.language-css .token.rule:not(.atrule) {
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.token.string {
|
||||
color: var(--yellow);
|
||||
}
|
||||
|
||||
.token.tag {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
.token.url {
|
||||
color: var(--cyan);
|
||||
}
|
||||
|
||||
.language-css .token.url {
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
.token.variable {
|
||||
color: var(--comment);
|
||||
}
|
||||
|
||||
.token.number {
|
||||
color: rgba(189, 147, 249, 1);
|
||||
}
|
||||
|
||||
.token.operator {
|
||||
color: rgba(139, 233, 253, 1);
|
||||
}
|
||||
|
||||
.token.char {
|
||||
color: rgba(255, 135, 157, 1);
|
||||
}
|
||||
|
||||
.token.symbol {
|
||||
color: rgba(255, 184, 108, 1);
|
||||
}
|
||||
|
||||
.token.deleted {
|
||||
color: #e2777a;
|
||||
}
|
||||
|
||||
.token.namespace {
|
||||
color: #e2777a;
|
||||
}
|
||||
|
||||
/* Line Highlighter */
|
||||
|
||||
.highlight-line {
|
||||
color: inherit;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
|
||||
border-radius: 4px;
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
.highlight-line:empty:before {
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.highlight-line:not(:last-child) {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.highlight-line .highlight-line:not(:last-child) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.highlight-line-isdir {
|
||||
color: var(--foreground);
|
||||
background-color: var(--selection-30);
|
||||
}
|
||||
|
||||
.highlight-line-active {
|
||||
background-color: var(--comment-30);
|
||||
}
|
||||
|
||||
.highlight-line-add {
|
||||
background-color: var(--green-30);
|
||||
}
|
||||
|
||||
.highlight-line-remove {
|
||||
background-color: var(--red-30);
|
||||
}
|
||||
|
||||
@@ -63,12 +63,14 @@
|
||||
"@tailwindcss/forms": "^0.5.2",
|
||||
"@tanstack/react-table": "^8.0.0-alpha.87",
|
||||
"@trigger.dev/common-schemas": "workspace:*",
|
||||
"@trigger.dev/providers": "workspace:*",
|
||||
"@uiw/react-codemirror": "^4.13.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"classnames": "^2.3.1",
|
||||
"clsx": "^1.2.1",
|
||||
"compression": "^1.7.4",
|
||||
"cron-parser": "^4.7.1",
|
||||
"cronstrue": "^2.21.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"csstype": "^3.0.10",
|
||||
"cuid": "^2.1.8",
|
||||
@@ -78,7 +80,6 @@
|
||||
"humanize-duration": "^3.27.3",
|
||||
"internal-integrations": "workspace:*",
|
||||
"internal-platform": "workspace:*",
|
||||
"@trigger.dev/providers": "workspace:*",
|
||||
"internal-pulsar": "workspace:*",
|
||||
"ioredis": "^5.2.4",
|
||||
"javascript-time-ago": "^2.5.7",
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
-- AlterEnum
|
||||
-- This migration adds more than one value to an enum.
|
||||
-- With PostgreSQL versions 11 and earlier, this is not possible
|
||||
-- in a single migration. This can be worked around by creating
|
||||
-- multiple migrations, each migration adding only one value to
|
||||
-- the enum.
|
||||
|
||||
|
||||
ALTER TYPE "WorkflowStatus" ADD VALUE 'DISABLED';
|
||||
ALTER TYPE "WorkflowStatus" ADD VALUE 'ARCHIVED';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "EventRule" ADD COLUMN "archivedAt" TIMESTAMP(3),
|
||||
ADD COLUMN "disabledAt" TIMESTAMP(3);
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `archivedAt` on the `EventRule` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `disabledAt` on the `EventRule` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "EventRule" DROP COLUMN "archivedAt",
|
||||
DROP COLUMN "disabledAt";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Workflow" ADD COLUMN "archivedAt" TIMESTAMP(3),
|
||||
ADD COLUMN "disabledAt" TIMESTAMP(3);
|
||||
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "EventRule" ADD COLUMN "enabled" BOOLEAN NOT NULL DEFAULT true;
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The values [ARCHIVED] on the enum `WorkflowStatus` will be removed. If these variants are still used in the database, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterEnum
|
||||
BEGIN;
|
||||
CREATE TYPE "WorkflowStatus_new" AS ENUM ('CREATED', 'READY', 'DISABLED');
|
||||
ALTER TABLE "Workflow" ALTER COLUMN "status" DROP DEFAULT;
|
||||
ALTER TABLE "Workflow" ALTER COLUMN "status" TYPE "WorkflowStatus_new" USING ("status"::text::"WorkflowStatus_new");
|
||||
ALTER TYPE "WorkflowStatus" RENAME TO "WorkflowStatus_old";
|
||||
ALTER TYPE "WorkflowStatus_new" RENAME TO "WorkflowStatus";
|
||||
DROP TYPE "WorkflowStatus_old";
|
||||
ALTER TABLE "Workflow" ALTER COLUMN "status" SET DEFAULT 'CREATED';
|
||||
COMMIT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Workflow" ADD COLUMN "isArchived" BOOLEAN NOT NULL DEFAULT false;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Workflow" ADD COLUMN "triggerTtlInSeconds" INTEGER NOT NULL DEFAULT 3600;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "WorkflowRunStatus" ADD VALUE 'TIMED_OUT';
|
||||
@@ -0,0 +1,3 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "WorkflowRun" ADD COLUMN "timedOutAt" TIMESTAMP(3),
|
||||
ADD COLUMN "timedOutReason" TEXT;
|
||||
@@ -138,6 +138,12 @@ model Workflow {
|
||||
service String @default("trigger")
|
||||
eventNames String[]
|
||||
|
||||
disabledAt DateTime?
|
||||
archivedAt DateTime?
|
||||
isArchived Boolean @default(false)
|
||||
|
||||
triggerTtlInSeconds Int @default(3600)
|
||||
|
||||
@@unique([organizationId, slug])
|
||||
}
|
||||
|
||||
@@ -161,6 +167,8 @@ model EventRule {
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
enabled Boolean @default(true)
|
||||
|
||||
runs WorkflowRun[]
|
||||
|
||||
@@unique([workflowId, environmentId])
|
||||
@@ -178,6 +186,7 @@ enum TriggerType {
|
||||
enum WorkflowStatus {
|
||||
CREATED
|
||||
READY
|
||||
DISABLED
|
||||
}
|
||||
|
||||
model ExternalSource {
|
||||
@@ -399,6 +408,9 @@ model WorkflowRun {
|
||||
startedAt DateTime?
|
||||
finishedAt DateTime?
|
||||
|
||||
timedOutAt DateTime?
|
||||
timedOutReason String?
|
||||
|
||||
isTest Boolean @default(false)
|
||||
requests IntegrationRequest[]
|
||||
delays DurableDelay[]
|
||||
@@ -410,6 +422,7 @@ enum WorkflowRunStatus {
|
||||
DISCONNECTED
|
||||
SUCCESS
|
||||
ERROR
|
||||
TIMED_OUT
|
||||
}
|
||||
|
||||
model WorkflowRunStep {
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -58,6 +58,7 @@ async function main() {
|
||||
client: pulsarClient,
|
||||
config: {
|
||||
topic: Topics.runCommands,
|
||||
batchingEnabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -72,4 +72,8 @@ function oauth2AuthenticationFromEnv(): AuthenticationOauth2 | undefined {
|
||||
});
|
||||
}
|
||||
|
||||
export const pulsarClient = createPulsarClient();
|
||||
export const pulsarClient = createPulsarClient({
|
||||
ioThreads: 4,
|
||||
messageListenerThreads: 4,
|
||||
operationTimeoutSeconds: 30,
|
||||
});
|
||||
|
||||
@@ -296,7 +296,7 @@ export class TriggerServer {
|
||||
}
|
||||
|
||||
async #initializeWorkflow(
|
||||
data: z.infer<typeof ServerRPCSchema["INITIALIZE_HOST"]["request"]>
|
||||
data: z.infer<(typeof ServerRPCSchema)["INITIALIZE_HOST"]["request"]>
|
||||
) {
|
||||
if (this.#isInitialized) {
|
||||
throw new Error(
|
||||
@@ -324,6 +324,7 @@ export class TriggerServer {
|
||||
name: data.packageName,
|
||||
version: data.packageVersion,
|
||||
},
|
||||
triggerTTL: data.triggerTTL,
|
||||
});
|
||||
|
||||
this.#workflowId = response.id;
|
||||
@@ -340,7 +341,7 @@ export class TriggerServer {
|
||||
subscriptionInitialPosition: "Earliest",
|
||||
},
|
||||
handlers: {
|
||||
TRIGGER_WORKFLOW: async (id, data, properties) => {
|
||||
TRIGGER_WORKFLOW: async (id, data, properties, messageAttributes) => {
|
||||
this.#logger.debug("Received trigger", id, data, properties);
|
||||
// If the API keys don't match, then we should ignore it
|
||||
// This ensures the workflow is triggered for the correct environment
|
||||
@@ -366,6 +367,33 @@ export class TriggerServer {
|
||||
);
|
||||
}
|
||||
|
||||
if (properties["x-ttl"] && messageAttributes.eventTimestamp) {
|
||||
const ttl = properties["x-ttl"];
|
||||
const eventTimestamp = messageAttributes.eventTimestamp;
|
||||
const now = Date.now();
|
||||
const elapsedMilliseconds = now - eventTimestamp.getTime();
|
||||
const elapsedSeconds = elapsedMilliseconds / 1000;
|
||||
|
||||
if (elapsedSeconds > ttl) {
|
||||
this.#logger.debug("Message is expired, ignoring", {
|
||||
messageAttributes,
|
||||
properties,
|
||||
});
|
||||
|
||||
await this.#commandPublisher.publish(
|
||||
"WORKFLOW_RUN_TRIGGER_TIMEOUT",
|
||||
{
|
||||
id: data.id,
|
||||
ttl,
|
||||
elapsedSeconds,
|
||||
},
|
||||
{ ...properties, "x-timestamp": String(Date.now()) }
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
this.#logger.debug("Triggering workflow", data, properties);
|
||||
|
||||
const runController = new WorkflowRunController({
|
||||
@@ -502,6 +530,7 @@ function createForwardHandler<
|
||||
client: pulsarClient,
|
||||
config: {
|
||||
topic: topicName,
|
||||
batchingEnabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,31 +1,98 @@
|
||||
import { Trigger } from "@trigger.dev/sdk";
|
||||
import { github } from "@trigger.dev/integrations";
|
||||
|
||||
const trigger = new Trigger({
|
||||
new Trigger({
|
||||
id: "github-webhook-9",
|
||||
name: "GitHub Issue changes for trigger.dev",
|
||||
name: "GitHub issue: triggerdotdev/trigger.dev-examples",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: github.events.repoIssueEvent({ repo: "triggerdotdev/trigger.dev" }),
|
||||
on: github.events.issueEvent({
|
||||
repo: "triggerdotdev/trigger.dev-examples",
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(
|
||||
"Inside the github-webhook workflow, received event",
|
||||
{
|
||||
event,
|
||||
}
|
||||
);
|
||||
await ctx.logger.info(`Action was ${event.action}`);
|
||||
|
||||
if (event.action === "assigned") {
|
||||
await ctx.logger.info(`New assignee: ${event.assignee.login}`);
|
||||
// await slack.sendMessage({
|
||||
// channel: "C01BQKZJZ7M",
|
||||
// text: `New issue: ${event.issue.title}`,
|
||||
// });
|
||||
}
|
||||
|
||||
return event;
|
||||
return {};
|
||||
},
|
||||
});
|
||||
}).listen();
|
||||
|
||||
trigger.listen();
|
||||
new Trigger({
|
||||
id: "github-webhook-pull_request",
|
||||
name: "GitHub PR: triggerdotdev/trigger.dev-examples",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: github.events.pullRequestEvent({
|
||||
repo: "triggerdotdev/trigger.dev-examples",
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(`Action was ${event.action}`);
|
||||
|
||||
return {};
|
||||
},
|
||||
}).listen();
|
||||
|
||||
new Trigger({
|
||||
id: "github-webhook-pull_request_comment",
|
||||
name: "GitHub PR review comment: triggerdotdev/trigger.dev-examples",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: github.events.pullRequestCommentEvent({
|
||||
repo: "triggerdotdev/trigger.dev-examples",
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(`Action was ${event.action}`);
|
||||
|
||||
return {};
|
||||
},
|
||||
}).listen();
|
||||
|
||||
new Trigger({
|
||||
id: "github-webhook-pull_request_review",
|
||||
name: "GitHub PR review: triggerdotdev/trigger.dev-examples",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: github.events.pullRequestReviewEvent({
|
||||
repo: "triggerdotdev/trigger.dev-examples",
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(`Action was ${event.action}`);
|
||||
|
||||
return {};
|
||||
},
|
||||
}).listen();
|
||||
|
||||
new Trigger({
|
||||
id: "github-webhook-push",
|
||||
name: "GitHub push: triggerdotdev/trigger.dev-examples",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: github.events.pushEvent({
|
||||
repo: "triggerdotdev/trigger.dev-examples",
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(`Push with commits`, event.commits);
|
||||
|
||||
return {};
|
||||
},
|
||||
}).listen();
|
||||
|
||||
new Trigger({
|
||||
id: "github-webhook-commit_comment",
|
||||
name: "GitHub commit comment: triggerdotdev/trigger.dev-examples",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: github.events.commitCommentEvent({
|
||||
repo: "triggerdotdev/trigger.dev-examples",
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(`Push with action ${event.action}`);
|
||||
|
||||
return {};
|
||||
},
|
||||
}).listen();
|
||||
|
||||
@@ -2,8 +2,23 @@ import { Trigger, customEvent, scheduleEvent } from "@trigger.dev/sdk";
|
||||
import { github, slack } from "@trigger.dev/integrations";
|
||||
import { z } from "zod";
|
||||
|
||||
// Workflow that sends a message to Slack
|
||||
// // Workflow that sends a message to Slack
|
||||
|
||||
// // new Trigger({
|
||||
// // id: "playground-1",
|
||||
// // name: "Post to Slack immediately",
|
||||
// // apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // endpoint: "ws://localhost:8889/ws",
|
||||
// // on: customEvent({
|
||||
// // name: "playground",
|
||||
// // schema: z.object({
|
||||
// // id: z.string(),
|
||||
// // }),
|
||||
// // }),
|
||||
// // run: async (event, ctx) => {
|
||||
// // await ctx.logger.info(
|
||||
// // "This workflow will post a message to Slack immediately and display an Error, Info, Debug, and Warning message."
|
||||
// // );
|
||||
// new Trigger({
|
||||
// id: "playground-1",
|
||||
// name: "Post to Slack immediately",
|
||||
@@ -19,113 +34,6 @@ import { z } from "zod";
|
||||
// await ctx.logger.info(
|
||||
// "This workflow will post a message to Slack immediately and display an Error, Info, Debug, and Warning message."
|
||||
// );
|
||||
new Trigger({
|
||||
id: "playground-1",
|
||||
name: "Post to Slack immediately",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
on: customEvent({
|
||||
name: "playground",
|
||||
schema: z.object({
|
||||
id: z.string(),
|
||||
}),
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(
|
||||
"This workflow will post a message to Slack immediately and display an Error, Info, Debug, and Warning message."
|
||||
);
|
||||
|
||||
await ctx.logger.error("Error message!", { event });
|
||||
|
||||
await ctx.logger.info("Info message", { event });
|
||||
|
||||
await ctx.logger.debug("Debug message");
|
||||
|
||||
await ctx.logger.warn("Warning message!");
|
||||
|
||||
const response = await slack.postMessage("send-to-slack", {
|
||||
channel: "test-integrations",
|
||||
text: `This is a message from the "Posts to Slack" workflow ${event.id}`,
|
||||
});
|
||||
|
||||
return response.message;
|
||||
},
|
||||
}).listen();
|
||||
|
||||
// Webhook workflow that sends a message to Slack when a Github issue is created after 2 delays
|
||||
|
||||
new Trigger({
|
||||
id: "playground-2",
|
||||
name: "Posts to Slack after a GitHub Issue created",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
on: github.events.repoIssueEvent({ repo: "triggerdotdev/trigger.dev" }),
|
||||
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(
|
||||
"This workflow will post to Slack when a GitHub Issue created or modified after 2 delays."
|
||||
);
|
||||
|
||||
await ctx.waitFor("initial-wait", { seconds: 30 });
|
||||
|
||||
await ctx.waitUntil("wait-until", new Date(Date.now() + 1000 * 30));
|
||||
|
||||
await ctx.logger.info("Both types of delay happened");
|
||||
|
||||
const response = await slack.postMessage("send-to-slack", {
|
||||
channel: "test-integrations",
|
||||
text: `This is a message posts after an Issue was created on GitHub ${event.action}`,
|
||||
});
|
||||
|
||||
await ctx.logger.debug("Debug message");
|
||||
|
||||
await ctx.logger.warn("Warning message!");
|
||||
|
||||
return response.message;
|
||||
},
|
||||
}).listen();
|
||||
|
||||
// Workflow that shows all the log types with a 5 second delay between each
|
||||
|
||||
new Trigger({
|
||||
id: "playground-3",
|
||||
name: "All log types with a 5 second delay between each",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
on: customEvent({
|
||||
name: "playground",
|
||||
schema: z.object({
|
||||
id: z.string(),
|
||||
}),
|
||||
}),
|
||||
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info(
|
||||
"This workflow prints all the log types with a 5 second delay between each."
|
||||
);
|
||||
|
||||
await ctx.logger.info(
|
||||
"Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it. Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it. Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it. Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it."
|
||||
);
|
||||
|
||||
await ctx.waitFor("first-wait", { seconds: 5 });
|
||||
|
||||
await ctx.logger.error(
|
||||
"This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message!",
|
||||
{ event }
|
||||
);
|
||||
|
||||
await ctx.waitFor("second-wait", { seconds: 5 });
|
||||
|
||||
await ctx.logger.info(
|
||||
"This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message."
|
||||
);
|
||||
|
||||
await ctx.waitFor("third-wait", { seconds: 5 });
|
||||
|
||||
await ctx.logger.debug(
|
||||
"This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. "
|
||||
);
|
||||
|
||||
// await ctx.logger.error("Error message!", { event });
|
||||
|
||||
@@ -219,129 +127,276 @@ new Trigger({
|
||||
// "This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. "
|
||||
// );
|
||||
|
||||
// await ctx.waitFor("fourth-wait", { seconds: 5 });
|
||||
// // await ctx.logger.error("Error message!", { event });
|
||||
|
||||
// await ctx.logger.warn(
|
||||
// "This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! "
|
||||
// );
|
||||
// // await ctx.logger.info("Info message", { event });
|
||||
|
||||
// await ctx.waitFor("fifth-wait", { seconds: 5 });
|
||||
// // await ctx.logger.debug("Debug message");
|
||||
|
||||
// const response = await slack.postMessage("send-to-slack", {
|
||||
// channel: "test-integrations",
|
||||
// text: `This test displays all the log types in the webapp ${event.id}`,
|
||||
// });
|
||||
// // await ctx.logger.warn("Warning message!");
|
||||
|
||||
// return response.message;
|
||||
// },
|
||||
// }).listen();
|
||||
// // const response = await slack.postMessage("send-to-slack", {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This is a message from the "Posts to Slack" workflow ${event.id}`,
|
||||
// // });
|
||||
|
||||
// // Workflow that sends 2 messages to Slack with a 10 second delay between both
|
||||
// // return response.message;
|
||||
// // },
|
||||
// // }).listen();
|
||||
|
||||
// new Trigger({
|
||||
// id: "playground-4",
|
||||
// name: "Post to Slack twice after 10 second delays",
|
||||
// apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // // Webhook workflow that sends a message to Slack when a Github issue is created after 2 delays
|
||||
|
||||
// // new Trigger({
|
||||
// // id: "playground-2",
|
||||
// // name: "Posts to Slack after a GitHub Issue created",
|
||||
// // apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // endpoint: "ws://localhost:8889/ws",
|
||||
// // on: github.events.repoIssueEvent({ repo: "triggerdotdev/trigger.dev" }),
|
||||
|
||||
// // run: async (event, ctx) => {
|
||||
// // await ctx.logger.info(
|
||||
// // "This workflow will post to Slack when a GitHub Issue created or modified after 2 delays."
|
||||
// // );
|
||||
|
||||
// // await ctx.waitFor("initial-wait", { seconds: 30 });
|
||||
|
||||
// // await ctx.waitUntil("wait-until", new Date(Date.now() + 1000 * 30));
|
||||
|
||||
// // await ctx.logger.info("Both types of delay happened");
|
||||
|
||||
// // const response = await slack.postMessage("send-to-slack", {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This is a message posts after an Issue was created on GitHub ${event.action}`,
|
||||
// // });
|
||||
|
||||
// // await ctx.logger.debug("Debug message");
|
||||
|
||||
// // await ctx.logger.warn("Warning message!");
|
||||
|
||||
// // return response.message;
|
||||
// // },
|
||||
// // }).listen();
|
||||
|
||||
// // // Workflow that shows all the log types with a 5 second delay between each
|
||||
|
||||
// // new Trigger({
|
||||
// // id: "playground-3",
|
||||
// // name: "All log types with a 5 second delay between each",
|
||||
// // apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // endpoint: "ws://localhost:8889/ws",
|
||||
// // on: customEvent({
|
||||
// // name: "playground",
|
||||
// // schema: z.object({
|
||||
// // id: z.string(),
|
||||
// // }),
|
||||
// // }),
|
||||
|
||||
// // run: async (event, ctx) => {
|
||||
// // await ctx.logger.info(
|
||||
// // "This workflow prints all the log types with a 5 second delay between each."
|
||||
// // );
|
||||
|
||||
// // await ctx.logger.info(
|
||||
// // "Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it. Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it. Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it. Hey there! This is a really long message to see how the layout handles it. If this breaks the layout, I will fix it."
|
||||
// // );
|
||||
|
||||
// // await ctx.waitFor("first-wait", { seconds: 5 });
|
||||
|
||||
// // await ctx.logger.error(
|
||||
// // "This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message! This is a really long Error message!",
|
||||
// // { event }
|
||||
// // );
|
||||
|
||||
// // await ctx.waitFor("second-wait", { seconds: 5 });
|
||||
|
||||
// // await ctx.logger.info(
|
||||
// // "This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message. This is a really long Info message."
|
||||
// // );
|
||||
|
||||
// // await ctx.waitFor("third-wait", { seconds: 5 });
|
||||
|
||||
// // await ctx.logger.debug(
|
||||
// // "This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. This is a really long Debug message. "
|
||||
// // );
|
||||
|
||||
// // await ctx.waitFor("fourth-wait", { seconds: 5 });
|
||||
|
||||
// // await ctx.logger.warn(
|
||||
// // "This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! This is a really long Warning message! "
|
||||
// // );
|
||||
|
||||
// // await ctx.waitFor("fifth-wait", { seconds: 5 });
|
||||
|
||||
// // const response = await slack.postMessage("send-to-slack", {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This test displays all the log types in the webapp ${event.id}`,
|
||||
// // });
|
||||
|
||||
// // return response.message;
|
||||
// // },
|
||||
// // }).listen();
|
||||
|
||||
// // // Workflow that sends 2 messages to Slack with a 10 second delay between both
|
||||
|
||||
// // new Trigger({
|
||||
// // id: "playground-4",
|
||||
// // name: "Post to Slack twice after 10 second delays",
|
||||
// // apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // endpoint: "ws://localhost:8889/ws",
|
||||
// // on: customEvent({
|
||||
// // name: "playground",
|
||||
// // schema: z.object({
|
||||
// // id: z.string(),
|
||||
// // }),
|
||||
// // }),
|
||||
// // run: async (event, ctx) => {
|
||||
// // await ctx.logger.info(
|
||||
// // "This workflow sends 2 messages to Slack with a 10 second delay between both."
|
||||
// // );
|
||||
|
||||
// // await ctx.waitFor("initial-wait", { seconds: 10 });
|
||||
|
||||
// // await slack.postMessage("send-to-slack-1", {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This is test message 1/2 from "Post to Slack twice after 10 second delays" workflow ${event.id}`,
|
||||
// // });
|
||||
|
||||
// // await ctx.waitFor("second-wait", { seconds: 10 });
|
||||
|
||||
// // const response = await slack.postMessage("send-to-slack-2", {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This is test message 2/2 from "Post to Slack twice after 10 second delays" workflow ${event.id}`,
|
||||
// // });
|
||||
|
||||
// // return response.message;
|
||||
// // },
|
||||
// // }).listen();
|
||||
|
||||
// // // Workflow that send a message to Slack after 1 hour
|
||||
|
||||
// // new Trigger({
|
||||
// // id: "playground-5",
|
||||
// // name: "Post to Slack after 1 hour",
|
||||
// // apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // endpoint: "ws://localhost:8889/ws",
|
||||
// // on: customEvent({
|
||||
// // name: "playground",
|
||||
// // schema: z.object({
|
||||
// // id: z.string(),
|
||||
// // }),
|
||||
// // }),
|
||||
// // run: async (event, ctx) => {
|
||||
// // await ctx.logger.info(
|
||||
// // "This workflow posts a message to Slack after a 1 hour delay"
|
||||
// // );
|
||||
|
||||
// // await ctx.waitUntil("wait-until", new Date(Date.now() + 1000 * 60 * 60));
|
||||
|
||||
// // await ctx.logger.info("The workflow resumed after the 1 hour delay", {
|
||||
// // event,
|
||||
// // });
|
||||
|
||||
// // const response = await slack.postMessage("send-to-slack", {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This message was sent after a 1 hour delay ${event.id}`,
|
||||
// // });
|
||||
|
||||
// // return response.message;
|
||||
// // },
|
||||
// // }).listen();
|
||||
|
||||
// // // Workflow that send a message to Slack after 24 hours
|
||||
|
||||
// // new Trigger({
|
||||
// // id: "playground-6",
|
||||
// // name: "Post to Slack after a 24 hour delay",
|
||||
// // apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // endpoint: "ws://localhost:8889/ws",
|
||||
// // on: customEvent({
|
||||
// // name: "playground",
|
||||
// // schema: z.object({
|
||||
// // id: z.string(),
|
||||
// // }),
|
||||
// // }),
|
||||
// // run: async (event, ctx) => {
|
||||
// // await ctx.logger.info(
|
||||
// // "This workflow posts a message to Slack after a 24 hour delay"
|
||||
// // );
|
||||
|
||||
// // await ctx.waitUntil(
|
||||
// // "wait-until",
|
||||
// // new Date(Date.now() + 1000 * 60 * 60 * 24)
|
||||
// // );
|
||||
|
||||
// // await ctx.logger.info("The workflow resumed after the 24 hour delay", {
|
||||
// // event,
|
||||
// // });
|
||||
|
||||
// // const response = await slack.postMessage("send-to-slack", {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This message was sent after a 24 hour delay ${event.id}`,
|
||||
// // });
|
||||
|
||||
// // return response.message;
|
||||
// // },
|
||||
// // }).listen();
|
||||
|
||||
// // // Workflow that send a message to Slack after 24 hours
|
||||
|
||||
// // new Trigger({
|
||||
// // id: "playground-7",
|
||||
// // name: "Post to Slack many times in a loop",
|
||||
// // apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// // endpoint: "ws://localhost:8889/ws",
|
||||
// // on: customEvent({
|
||||
// // name: "playground",
|
||||
// // schema: z.object({
|
||||
// // id: z.string(),
|
||||
// // }),
|
||||
// // }),
|
||||
// // run: async (event, ctx) => {
|
||||
// // for (let index = 0; index < 4; index++) {
|
||||
// // const response = await slack.postMessage(`send-to-slack-${index}`, {
|
||||
// // channel: "test-integrations",
|
||||
// // text: `This is a post to Slack many times in a loop ${index} ${event.id}`,
|
||||
// // });
|
||||
// // }
|
||||
|
||||
// // return {};
|
||||
// // },
|
||||
// // }).listen();
|
||||
|
||||
// const postMessage = new Trigger({
|
||||
// id: "new-user",
|
||||
// name: "New user slack message",
|
||||
// apiKey: "trigger_development_lwlXEjyhSNF4",
|
||||
// endpoint: "ws://localhost:8889/ws",
|
||||
// logLevel: "info",
|
||||
// on: customEvent({
|
||||
// name: "playground",
|
||||
// name: "user.created",
|
||||
// schema: z.object({
|
||||
// id: z.string(),
|
||||
// name: z.string(),
|
||||
// email: z.string(),
|
||||
// paidPlan: z.boolean(),
|
||||
// }),
|
||||
// }),
|
||||
// run: async (event, ctx) => {
|
||||
// await ctx.logger.info(
|
||||
// "This workflow sends 2 messages to Slack with a 10 second delay between both."
|
||||
// );
|
||||
|
||||
// await ctx.waitFor("initial-wait", { seconds: 10 });
|
||||
|
||||
// await slack.postMessage("send-to-slack-1", {
|
||||
// channel: "test-integrations",
|
||||
// text: `This is test message 1/2 from "Post to Slack twice after 10 second delays" workflow ${event.id}`,
|
||||
// });
|
||||
|
||||
// await ctx.waitFor("second-wait", { seconds: 10 });
|
||||
|
||||
// const response = await slack.postMessage("send-to-slack-2", {
|
||||
// channel: "test-integrations",
|
||||
// text: `This is test message 2/2 from "Post to Slack twice after 10 second delays" workflow ${event.id}`,
|
||||
// });
|
||||
|
||||
// return response.message;
|
||||
// },
|
||||
// }).listen();
|
||||
|
||||
// // Workflow that send a message to Slack after 1 hour
|
||||
|
||||
// new Trigger({
|
||||
// id: "playground-5",
|
||||
// name: "Post to Slack after 1 hour",
|
||||
// apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// endpoint: "ws://localhost:8889/ws",
|
||||
// on: customEvent({
|
||||
// name: "playground",
|
||||
// schema: z.object({
|
||||
// id: z.string(),
|
||||
// }),
|
||||
// }),
|
||||
// run: async (event, ctx) => {
|
||||
// await ctx.logger.info(
|
||||
// "This workflow posts a message to Slack after a 1 hour delay"
|
||||
// );
|
||||
|
||||
// await ctx.waitUntil("wait-until", new Date(Date.now() + 1000 * 60 * 60));
|
||||
|
||||
// await ctx.logger.info("The workflow resumed after the 1 hour delay", {
|
||||
// event,
|
||||
// });
|
||||
// await ctx.logger.info("This log will appear on the Trigger.dev run page");
|
||||
|
||||
// //send a message to the #new-users Slack channel with user details
|
||||
// const response = await slack.postMessage("send-to-slack", {
|
||||
// channel: "test-integrations",
|
||||
// text: `This message was sent after a 1 hour delay ${event.id}`,
|
||||
// channel: "new-users",
|
||||
// text: `New user: ${event.name} (${event.email}) signed up. ${
|
||||
// event.paidPlan ? "They are paying" : "They are on the free plan"
|
||||
// }.`,
|
||||
// });
|
||||
|
||||
// return response.message;
|
||||
// },
|
||||
// }).listen();
|
||||
// });
|
||||
|
||||
// // Workflow that send a message to Slack after 24 hours
|
||||
|
||||
// new Trigger({
|
||||
// id: "playground-6",
|
||||
// name: "Post to Slack after a 24 hour delay",
|
||||
// apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
// endpoint: "ws://localhost:8889/ws",
|
||||
// on: customEvent({
|
||||
// name: "playground",
|
||||
// schema: z.object({
|
||||
// id: z.string(),
|
||||
// }),
|
||||
// }),
|
||||
// run: async (event, ctx) => {
|
||||
// await ctx.logger.info(
|
||||
// "This workflow posts a message to Slack after a 24 hour delay"
|
||||
// );
|
||||
|
||||
// await ctx.waitUntil(
|
||||
// "wait-until",
|
||||
// new Date(Date.now() + 1000 * 60 * 60 * 24)
|
||||
// );
|
||||
|
||||
// await ctx.logger.info("The workflow resumed after the 24 hour delay", {
|
||||
// event,
|
||||
// });
|
||||
|
||||
// const response = await slack.postMessage("send-to-slack", {
|
||||
// channel: "test-integrations",
|
||||
// text: `This message was sent after a 24 hour delay ${event.id}`,
|
||||
// });
|
||||
|
||||
// return response.message;
|
||||
// },
|
||||
// }).listen();
|
||||
|
||||
// // Workflow that send a message to Slack after 24 hours
|
||||
// //this workflow will now connect and start listening for events
|
||||
// postMessage.listen();
|
||||
|
||||
// new Trigger({
|
||||
// id: "playground-7",
|
||||
@@ -366,68 +421,14 @@ new Trigger({
|
||||
// },
|
||||
// }).listen();
|
||||
|
||||
const postMessage = new Trigger({
|
||||
id: "new-user",
|
||||
name: "New user slack message",
|
||||
apiKey: "trigger_development_lwlXEjyhSNF4",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "info",
|
||||
on: customEvent({
|
||||
name: "user.created",
|
||||
schema: z.object({
|
||||
name: z.string(),
|
||||
email: z.string(),
|
||||
paidPlan: z.boolean(),
|
||||
}),
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info("This log will appear on the Trigger.dev run page");
|
||||
|
||||
//send a message to the #new-users Slack channel with user details
|
||||
const response = await slack.postMessage("send-to-slack", {
|
||||
channel: "new-users",
|
||||
text: `New user: ${event.name} (${event.email}) signed up. ${
|
||||
event.paidPlan ? "They are paying" : "They are on the free plan"
|
||||
}.`,
|
||||
});
|
||||
|
||||
return response.message;
|
||||
},
|
||||
});
|
||||
|
||||
//this workflow will now connect and start listening for events
|
||||
postMessage.listen();
|
||||
|
||||
new Trigger({
|
||||
id: "playground-7",
|
||||
name: "Post to Slack many times in a loop",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
on: customEvent({
|
||||
name: "playground",
|
||||
schema: z.object({
|
||||
id: z.string(),
|
||||
}),
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
for (let index = 0; index < 4; index++) {
|
||||
const response = await slack.postMessage(`send-to-slack-${index}`, {
|
||||
channel: "test-integrations",
|
||||
text: `This is a post to Slack many times in a loop ${index} ${event.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
}).listen();
|
||||
|
||||
new Trigger({
|
||||
id: "scheduled-workflow",
|
||||
name: "Scheduled Workflow",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: scheduleEvent({ rateOf: { minutes: 5 } }),
|
||||
triggerTTL: 5,
|
||||
on: scheduleEvent({ rateOf: { minutes: 4 } }),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info("Received the scheduled event", {
|
||||
event,
|
||||
|
||||
@@ -21,11 +21,11 @@ const trigger = new Trigger({
|
||||
"Received domain.created event, waiting for 1 minutes..."
|
||||
);
|
||||
|
||||
await ctx.waitFor("initial-wait", { minutes: 1 });
|
||||
await ctx.waitFor("initial-wait", { seconds: 5 });
|
||||
|
||||
const response = await slack.postMessage("send-to-slack", {
|
||||
channel: "test-integrations",
|
||||
text: `New domain created: ${event.domain} by customer ${event.customerId}`,
|
||||
text: `New domain created: ${event.domain} by customer ${event.customerId} cc @Eric #general`,
|
||||
});
|
||||
|
||||
await ctx.logger.debug("Debug message");
|
||||
|
||||
@@ -11,7 +11,8 @@ const trigger = new Trigger({
|
||||
name: "My workflow",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
logLevel: "log",
|
||||
triggerTTL: 60 * 60 * 24,
|
||||
on: customEvent({ name: "user.created", schema: userCreatedEvent }),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info("Inside the smoke test workflow, received event", {
|
||||
@@ -34,12 +35,3 @@ const trigger = new Trigger({
|
||||
});
|
||||
|
||||
trigger.listen();
|
||||
|
||||
(async () => {
|
||||
process.env.TRIGGER_API_KEY = "trigger_dev_zC25mKNn6c0q";
|
||||
process.env.TRIGGER_API_URL = "http://localhost:3000";
|
||||
await sendEvent(ulid(), {
|
||||
name: "user.created",
|
||||
payload: { id: "123" },
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -62,7 +62,9 @@
|
||||
"packages/internal-pulsar/src/**",
|
||||
"./pnpm-lock.yaml"
|
||||
],
|
||||
"dependsOn": ["p-db"],
|
||||
"dependsOn": [
|
||||
"p-db"
|
||||
],
|
||||
"envVariables": {
|
||||
"FROM_EMAIL": "hello@email.trigger.dev",
|
||||
"REPLY_TO_EMAIL": "hello@trigger.dev",
|
||||
@@ -170,6 +172,178 @@
|
||||
"connectionStringEnvVarName": "REDIS_URL"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "staging",
|
||||
"name": "Staging",
|
||||
"region": "us-east-1",
|
||||
"source": {
|
||||
"branch": "dev",
|
||||
"trigger": "manual"
|
||||
},
|
||||
"envVariables": {
|
||||
"PULSAR_ISSUER_URL": "https://auth.streamnative.cloud/",
|
||||
"PULSAR_AUDIENCE": {
|
||||
"fromParameterStore": "/Staging/Pulsar/Audience"
|
||||
},
|
||||
"PULSAR_TENANT": "triggerdotdev",
|
||||
"PULSAR_WORKFLOWS_NAMESPACE": "workflows",
|
||||
"PULSAR_QUEUES_NAMESPACE": "queues",
|
||||
"PULSAR_SERVICE_URL": {
|
||||
"fromParameterStore": "/Staging/Pulsar/ServiceURL"
|
||||
},
|
||||
"DOCKER_USERNAME": "maverickdotdev",
|
||||
"DOCKER_PASSWORD": {
|
||||
"fromParameterStore": "/Docker/Password"
|
||||
}
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"id": "s-webapp",
|
||||
"name": "Staging Webapp",
|
||||
"type": "fargate",
|
||||
"buildType": "docker",
|
||||
"dockerfilePath": "./apps/webapp/Dockerfile",
|
||||
"dockerContext": ".",
|
||||
"cpu": 0.5,
|
||||
"memory": 2,
|
||||
"minInstances": 1,
|
||||
"maxInstances": 2,
|
||||
"domain": "app-staging.trigger.dev",
|
||||
"port": 3000,
|
||||
"healthCheckPath": "/healthcheck",
|
||||
"watchPaths": [
|
||||
"apps/webapp/app/**",
|
||||
"apps/webapp/public/**",
|
||||
"apps/webapp/Dockerfile",
|
||||
"apps/webapp/package.json",
|
||||
"apps/webapp/server.ts",
|
||||
"apps/webapp/remix.config.js",
|
||||
"apps/webapp/tailwind.config.js",
|
||||
"apps/webapp/tsconfig.json",
|
||||
"apps/webapp/postcss.config.js",
|
||||
"apps/webapp/styles/**",
|
||||
"apps/webapp/prisma/**",
|
||||
"apps/webapp/types/**",
|
||||
"packages/internal-platform/src/**",
|
||||
"packages/common-schemas/src/**",
|
||||
"packages/internal-integrations/src/**",
|
||||
"packages/trigger-providers/src/**",
|
||||
"packages/emails/src/**",
|
||||
"packages/emails/emails/**",
|
||||
"packages/internal-pulsar/src/**",
|
||||
"./pnpm-lock.yaml"
|
||||
],
|
||||
"dependsOn": [
|
||||
"s-db"
|
||||
],
|
||||
"envVariables": {
|
||||
"FROM_EMAIL": "hello@email.trigger.dev",
|
||||
"REPLY_TO_EMAIL": "hello@trigger.dev",
|
||||
"RESEND_API_KEY": {
|
||||
"fromParameterStore": "/Staging/webapp/RESEND_API_KEY"
|
||||
},
|
||||
"SENTRY_DSN": {
|
||||
"fromParameterStore": "SENTRY_DSN"
|
||||
},
|
||||
"SESSION_SECRET": {
|
||||
"fromParameterStore": "/Staging/webapp/SESSION_SECRET"
|
||||
},
|
||||
"MAGIC_LINK_SECRET": {
|
||||
"fromParameterStore": "/Staging/webapp/MAGIC_LINK_SECRET"
|
||||
},
|
||||
"GITHUB_CLIENT_ID": "724e56fcebe940eb5b22",
|
||||
"GITHUB_SECRET": {
|
||||
"fromParameterStore": "/Staging/webapp/GITHUB_SECRET"
|
||||
},
|
||||
"DATABASE_URL": {
|
||||
"fromService": {
|
||||
"id": "s-db",
|
||||
"value": "dbConnectionString"
|
||||
}
|
||||
},
|
||||
"PULSAR_CLIENT_ID": {
|
||||
"fromParameterStore": "/Staging/Pulsar/webapp/ClientId"
|
||||
},
|
||||
"PULSAR_CLIENT_SECRET": {
|
||||
"fromParameterStore": "/Staging/Pulsar/webapp/ClientSecret"
|
||||
},
|
||||
"PULSAR_ROLE": {
|
||||
"fromParameterStore": "/Staging/Pulsar/webapp/Role"
|
||||
},
|
||||
"PIZZLY_HOST": "https://staging-auth.trigger.dev",
|
||||
"PIZZLY_SECRET_KEY": {
|
||||
"fromParameterStore": "/Staging/webapp/PIZZLY_SECRET_KEY"
|
||||
},
|
||||
"TRIGGER_LOG_LEVEL": "debug",
|
||||
"PULSAR_ENABLED": "1",
|
||||
"PULSAR_DEBUG": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "s-wss",
|
||||
"name": "Staging WSS",
|
||||
"type": "fargate",
|
||||
"buildType": "docker",
|
||||
"dockerfilePath": "./apps/wss/Dockerfile",
|
||||
"dockerContext": ".",
|
||||
"cpu": 1,
|
||||
"memory": 2,
|
||||
"minInstances": 1,
|
||||
"maxInstances": 2,
|
||||
"domain": "wss-staging.trigger.dev",
|
||||
"port": 8889,
|
||||
"healthCheckPath": "/healthcheck",
|
||||
"watchPaths": [
|
||||
"apps/wss/src/**",
|
||||
"apps/wss/tsconfig.json",
|
||||
"apps/wss/tsup.config.ts",
|
||||
"apps/wss/package.json",
|
||||
"packages/internal-platform/src/**",
|
||||
"packages/internal-bridge/src/**",
|
||||
"packages/common-schemas/src/**",
|
||||
"packages/internal-pulsar/src/**",
|
||||
"./pnpm-lock.yaml"
|
||||
],
|
||||
"envVariables": {
|
||||
"PULSAR_CLIENT_ID": {
|
||||
"fromParameterStore": "/Staging/Pulsar/wss/ClientId"
|
||||
},
|
||||
"PULSAR_CLIENT_SECRET": {
|
||||
"fromParameterStore": "/Staging/Pulsar/wss/ClientSecret"
|
||||
},
|
||||
"PULSAR_ROLE": {
|
||||
"fromParameterStore": "/Staging/Pulsar/wss/Role"
|
||||
},
|
||||
"PLATFORM_API_URL": "https://app.trigger.dev",
|
||||
"TRIGGER_LOG_LEVEL": "debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "s-db",
|
||||
"name": "Staging Database",
|
||||
"type": "rds",
|
||||
"engine": "postgres",
|
||||
"applyChangesImmediately": true,
|
||||
"engineVersion": "14",
|
||||
"autoUpgradeMinorVersions": true,
|
||||
"instanceSize": "db.t3.large",
|
||||
"storage": 100,
|
||||
"maxStorage": 400,
|
||||
"private": false,
|
||||
"deletionProtection": true,
|
||||
"port": 5432
|
||||
},
|
||||
{
|
||||
"id": "s-redis",
|
||||
"name": "Staging Redis",
|
||||
"type": "elasticache",
|
||||
"engine": "redis",
|
||||
"engineVersion": "7.0",
|
||||
"instanceSize": "cache.t3.small",
|
||||
"connectionStringEnvVarName": "REDIS_URL"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { EventFilterSchema } from "./events";
|
||||
import { EventFilterSchema, ScheduleSourceSchema } from "./events";
|
||||
import { JsonSchema } from "./json";
|
||||
|
||||
export const CustomEventTriggerSchema = z.object({
|
||||
@@ -31,7 +31,7 @@ export const ScheduledEventTriggerSchema = z.object({
|
||||
type: z.literal("SCHEDULE"),
|
||||
service: z.literal("scheduler"),
|
||||
name: z.string(),
|
||||
source: JsonSchema,
|
||||
source: ScheduleSourceSchema,
|
||||
});
|
||||
export type ScheduledEventTrigger = z.infer<typeof ScheduledEventTriggerSchema>;
|
||||
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
// Create a logger class that uses the debug package internally
|
||||
|
||||
export type LogLevel = "log" | "error" | "warn" | "info" | "debug";
|
||||
const logLevels = [
|
||||
"disabled",
|
||||
"log",
|
||||
"error",
|
||||
"warn",
|
||||
"info",
|
||||
"debug",
|
||||
] as const;
|
||||
|
||||
const logLevels: Array<LogLevel> = ["log", "error", "warn", "info", "debug"];
|
||||
export type LogLevel = (typeof logLevels)[number];
|
||||
|
||||
export class Logger {
|
||||
#name: string;
|
||||
readonly #level: number;
|
||||
|
||||
constructor(name: string, level: LogLevel = "info") {
|
||||
constructor(name: string, level: LogLevel = "disabled") {
|
||||
this.#name = name;
|
||||
this.#level = logLevels.indexOf(
|
||||
(process.env.TRIGGER_LOG_LEVEL ?? level) as LogLevel
|
||||
@@ -16,31 +23,31 @@ export class Logger {
|
||||
}
|
||||
|
||||
log(...args: any[]) {
|
||||
if (this.#level < 0) return;
|
||||
if (this.#level < 1) return;
|
||||
|
||||
console.log(`[${formattedDateTime()}] [${this.#name}] `, ...args);
|
||||
console.log(`[${this.#name}] `, ...args);
|
||||
}
|
||||
|
||||
error(...args: any[]) {
|
||||
if (this.#level < 1) return;
|
||||
if (this.#level < 2) return;
|
||||
|
||||
console.error(`[${formattedDateTime()}] [${this.#name}] `, ...args);
|
||||
}
|
||||
|
||||
warn(...args: any[]) {
|
||||
if (this.#level < 2) return;
|
||||
if (this.#level < 3) return;
|
||||
|
||||
console.warn(`[${formattedDateTime()}] [${this.#name}] `, ...args);
|
||||
}
|
||||
|
||||
info(...args: any[]) {
|
||||
if (this.#level < 3) return;
|
||||
if (this.#level < 4) return;
|
||||
|
||||
console.info(`[${formattedDateTime()}] [${this.#name}] `, ...args);
|
||||
}
|
||||
|
||||
debug(...args: any[]) {
|
||||
if (this.#level < 4) return;
|
||||
if (this.#level < 5) return;
|
||||
|
||||
console.debug(`[${formattedDateTime()}] [${this.#name}] `, ...args);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ export const ServerRPCSchema = {
|
||||
trigger: TriggerMetadataSchema,
|
||||
packageVersion: z.string(),
|
||||
packageName: z.string(),
|
||||
triggerTTL: z.number().optional(),
|
||||
}),
|
||||
response: z
|
||||
.discriminatedUnion("type", [
|
||||
@@ -81,7 +82,7 @@ export const ServerRPCSchema = {
|
||||
COMPLETE_WORKFLOW_RUN: {
|
||||
request: z.object({
|
||||
runId: z.string(),
|
||||
output: z.string(),
|
||||
output: z.string().optional(),
|
||||
timestamp: z.string(),
|
||||
}),
|
||||
response: z.boolean(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z, ZodError } from "zod";
|
||||
import { createHash } from "node:crypto";
|
||||
import { IConnection } from "./types";
|
||||
import { Logger } from "./logger";
|
||||
|
||||
export const RPCMessageSchema = z.object({
|
||||
id: z.string(),
|
||||
@@ -45,6 +46,7 @@ export class ZodRPC<
|
||||
#receiver: ReceiverSchema;
|
||||
#handlers: ZodRPCHandlers<ReceiverSchema>;
|
||||
#pendingCalls = new Map<string, onResponseCallback>();
|
||||
#logger: Logger = new Logger("ZodRPC");
|
||||
|
||||
constructor(options: ZodRPCOptions<SenderSchema, ReceiverSchema>) {
|
||||
this.#connection = options.connection;
|
||||
@@ -73,7 +75,7 @@ export class ZodRPC<
|
||||
await this.#onResponse(data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.#logger.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,14 +84,12 @@ export class ZodRPC<
|
||||
await this.#handleCall(message);
|
||||
} catch (callError) {
|
||||
if (callError instanceof ZodError) {
|
||||
console.error(
|
||||
`[ZodRPC][foobar] Received invalid call:\n${JSON.stringify(
|
||||
message
|
||||
)}: `,
|
||||
this.#logger.error(
|
||||
`[ZodRPC] Received invalid call:\n${JSON.stringify(message)}: `,
|
||||
callError.errors
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
this.#logger.error(
|
||||
`[ZodRPC] Error handling call:\n${JSON.stringify(message)}: `,
|
||||
callError
|
||||
);
|
||||
@@ -102,12 +102,12 @@ export class ZodRPC<
|
||||
await this.#handleResponse(message);
|
||||
} catch (callError) {
|
||||
if (callError instanceof ZodError) {
|
||||
console.error(
|
||||
this.#logger.error(
|
||||
`[ZodRPC] Received invalid response\n\n${JSON.stringify(message)}: `,
|
||||
callError.flatten()
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
this.#logger.error(
|
||||
`[ZodRPC] Error handling response\n\n${JSON.stringify(message)}: `,
|
||||
callError
|
||||
);
|
||||
@@ -153,6 +153,8 @@ export class ZodRPC<
|
||||
throw new Error(`There is no method for ${message.methodName}`);
|
||||
}
|
||||
|
||||
this.#logger.debug("Received call", { message });
|
||||
|
||||
// struggling to get real inference here
|
||||
const inputs = method.request.parse(message.data);
|
||||
|
||||
@@ -169,7 +171,7 @@ export class ZodRPC<
|
||||
try {
|
||||
await this.#connection.send(preparedResponseText);
|
||||
} catch (err) {
|
||||
console.error("Failed sending response", preparedResponseText, err);
|
||||
this.#logger.error("Failed sending response", preparedResponseText, err);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -8,14 +8,15 @@ import { Webhooks } from "@octokit/webhooks";
|
||||
import { z } from "zod";
|
||||
import { github } from "@trigger.dev/providers";
|
||||
import { getAccessToken } from "../accessInfo";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
export class GitHubWebhookIntegration implements WebhookIntegration {
|
||||
keyForSource(source: unknown): string {
|
||||
const githubSource = parseWebhookSource(source);
|
||||
|
||||
if (githubSource.subresource === "repository") {
|
||||
return `repository.${githubSource.repo}`;
|
||||
return `repository.${githubSource.repo}.${githubSource.events.join(
|
||||
"."
|
||||
)}}`;
|
||||
} else if (githubSource.subresource === "organization") {
|
||||
return `organization.${githubSource.org}`;
|
||||
} else {
|
||||
|
||||
@@ -11,9 +11,15 @@ import { slack } from "@trigger.dev/providers";
|
||||
|
||||
import debug from "debug";
|
||||
import { getAccessToken } from "../accessInfo";
|
||||
import { z } from "zod";
|
||||
|
||||
const log = debug("trigger:integrations:slack");
|
||||
|
||||
const SendSlackMessageRequestBodySchema =
|
||||
slack.schemas.PostMessageBodySchema.extend({
|
||||
link_names: z.literal(1),
|
||||
});
|
||||
|
||||
class SlackRequestIntegration implements RequestIntegration {
|
||||
#joinChannelEndpoint = new HttpEndpoint<
|
||||
typeof slack.schemas.JoinConversationResponseSchema,
|
||||
@@ -32,7 +38,7 @@ class SlackRequestIntegration implements RequestIntegration {
|
||||
|
||||
#postMessageEndpoint = new HttpEndpoint<
|
||||
typeof slack.schemas.PostMessageResponseSchema,
|
||||
typeof slack.schemas.PostMessageBodySchema
|
||||
typeof SendSlackMessageRequestBodySchema
|
||||
>({
|
||||
response: slack.schemas.PostMessageResponseSchema,
|
||||
method: "POST",
|
||||
@@ -101,6 +107,7 @@ class SlackRequestIntegration implements RequestIntegration {
|
||||
|
||||
const response = await service.performRequest(this.#postMessageEndpoint, {
|
||||
...parsedParams,
|
||||
link_names: 1,
|
||||
channel,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { z } from "zod";
|
||||
import { TriggerWorkflowMessageSchema } from "../schemas/workflows";
|
||||
import { WorkflowRunEventPropertiesSchema } from "../sharedSchemas";
|
||||
|
||||
const Catalog = {
|
||||
TRIGGER_WORKFLOW: {
|
||||
data: TriggerWorkflowMessageSchema,
|
||||
properties: WorkflowRunEventPropertiesSchema,
|
||||
properties: WorkflowRunEventPropertiesSchema.extend({
|
||||
"x-ttl": z.coerce.number().optional(),
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { WorkflowSendRunEventPropertiesSchema } from "../sharedSchemas";
|
||||
export const commands = {
|
||||
WORKFLOW_RUN_COMPLETE: {
|
||||
data: z.object({
|
||||
output: z.string(),
|
||||
output: z.string().optional(),
|
||||
}),
|
||||
properties: WorkflowSendRunEventPropertiesSchema,
|
||||
},
|
||||
@@ -27,4 +27,12 @@ export const commands = {
|
||||
}),
|
||||
properties: WorkflowSendRunEventPropertiesSchema,
|
||||
},
|
||||
WORKFLOW_RUN_TRIGGER_TIMEOUT: {
|
||||
data: z.object({
|
||||
id: z.string(),
|
||||
ttl: z.number(),
|
||||
elapsedSeconds: z.number(),
|
||||
}),
|
||||
properties: WorkflowSendRunEventPropertiesSchema,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -27,7 +27,11 @@ export class ZodPubSub<TPubSubSchema extends MessageCatalogSchema> {
|
||||
constructor(options: ZodPubSubOptions<TPubSubSchema>) {
|
||||
this.#publisher = new ZodPublisher({
|
||||
client: options.client,
|
||||
config: { ...options.publisherConfig, topic: options.topic },
|
||||
config: {
|
||||
...options.publisherConfig,
|
||||
topic: options.topic,
|
||||
batchingEnabled: false,
|
||||
},
|
||||
schema: options.schema,
|
||||
});
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ export type PublishOptions = {
|
||||
partitionKey?: string;
|
||||
orderingKey?: string;
|
||||
id?: string;
|
||||
eventTimestamp?: number;
|
||||
};
|
||||
|
||||
type PendingMessages<PublisherSchema extends MessageCatalogSchema> = Array<{
|
||||
@@ -216,6 +217,7 @@ export class ZodPublisher<PublisherSchema extends MessageCatalogSchema> {
|
||||
deliverAt: options?.deliverAt,
|
||||
partitionKey: options?.partitionKey,
|
||||
orderingKey: options?.orderingKey,
|
||||
eventTimestamp: options?.eventTimestamp,
|
||||
});
|
||||
|
||||
return response.toString();
|
||||
|
||||
@@ -14,13 +14,21 @@ import {
|
||||
import { z, ZodError } from "zod";
|
||||
import { ZodPubSubStatus } from "./types";
|
||||
|
||||
export type SubscriberMessageAttributes = {
|
||||
messageId: string;
|
||||
eventTimestamp?: Date;
|
||||
publishedTimestamp: Date;
|
||||
redeliveryCount: number;
|
||||
};
|
||||
|
||||
export type ZodSubscriberHandlers<
|
||||
TConsumerSchema extends MessageCatalogSchema
|
||||
> = {
|
||||
[K in keyof TConsumerSchema]: (
|
||||
id: string,
|
||||
data: z.infer<TConsumerSchema[K]["data"]>,
|
||||
properties: z.infer<TConsumerSchema[K]["properties"]>
|
||||
properties: z.infer<TConsumerSchema[K]["properties"]>,
|
||||
attributes: SubscriberMessageAttributes
|
||||
) => Promise<boolean>;
|
||||
};
|
||||
|
||||
@@ -109,8 +117,32 @@ export class ZodSubscriber<SubscriberSchema extends MessageCatalogSchema> {
|
||||
|
||||
const properties = this.#getRawProperties(msg);
|
||||
|
||||
const messageId = msg.getMessageId();
|
||||
const publishedTimestamp = msg.getPublishTimestamp();
|
||||
const eventTimestamp = msg.getEventTimestamp();
|
||||
const redeliveryCount = msg.getRedeliveryCount();
|
||||
|
||||
this.#logger.debug("#onMessage", {
|
||||
messageId,
|
||||
publishedTimestamp,
|
||||
eventTimestamp,
|
||||
redeliveryCount,
|
||||
});
|
||||
|
||||
const messageAttributes = {
|
||||
eventTimestamp:
|
||||
eventTimestamp === 0 ? undefined : new Date(eventTimestamp),
|
||||
messageId: messageId.toString(),
|
||||
publishedTimestamp: new Date(publishedTimestamp),
|
||||
redeliveryCount,
|
||||
};
|
||||
|
||||
try {
|
||||
const wasHandled = await this.#handleMessage(messageData, properties);
|
||||
const wasHandled = await this.#handleMessage(
|
||||
messageData,
|
||||
properties,
|
||||
messageAttributes
|
||||
);
|
||||
|
||||
if (wasHandled) {
|
||||
await consumer.acknowledge(msg);
|
||||
@@ -134,7 +166,8 @@ export class ZodSubscriber<SubscriberSchema extends MessageCatalogSchema> {
|
||||
|
||||
async #handleMessage<K extends keyof SubscriberSchema>(
|
||||
rawMessage: MessageData,
|
||||
rawProperties: Record<string, string> = {}
|
||||
rawProperties: Record<string, string> = {},
|
||||
messageAttributes: SubscriberMessageAttributes
|
||||
): Promise<boolean> {
|
||||
const subscriberSchema = this.#schema;
|
||||
type TypeKeys = keyof typeof subscriberSchema;
|
||||
@@ -160,7 +193,12 @@ export class ZodSubscriber<SubscriberSchema extends MessageCatalogSchema> {
|
||||
|
||||
const handler = this.#handlers[typeName];
|
||||
|
||||
const returnValue = await handler(rawMessage.id, message, properties);
|
||||
const returnValue = await handler(
|
||||
rawMessage.id,
|
||||
message,
|
||||
properties,
|
||||
messageAttributes
|
||||
);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ export const WorkflowMetadataSchema = z.object({
|
||||
name: z.string(),
|
||||
trigger: TriggerMetadataSchema,
|
||||
package: PackageMetadataSchema,
|
||||
triggerTTL: z.number().optional(),
|
||||
});
|
||||
|
||||
export type WorkflowMetadata = z.infer<typeof WorkflowMetadataSchema>;
|
||||
|
||||
@@ -1,9 +1,39 @@
|
||||
import { TriggerEvent } from "@trigger.dev/sdk";
|
||||
import { github } from "@trigger.dev/providers";
|
||||
|
||||
export function repoIssueEvent(params: {
|
||||
export function commitCommentEvent(params: {
|
||||
repo: string;
|
||||
}): TriggerEvent<typeof github.schemas.IssueEventSchema> {
|
||||
}): TriggerEvent<
|
||||
typeof github.schemas.commitComments.commitCommentEventSchema
|
||||
> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
service: "github",
|
||||
name: "commit_comment",
|
||||
filter: {
|
||||
service: ["github"],
|
||||
payload: {
|
||||
repository: {
|
||||
full_name: [params.repo],
|
||||
},
|
||||
},
|
||||
event: ["commit_comment"],
|
||||
},
|
||||
source: github.schemas.WebhookSourceSchema.parse({
|
||||
subresource: "repository",
|
||||
scopes: ["repo"],
|
||||
repo: params.repo,
|
||||
events: ["commit_comment"],
|
||||
}),
|
||||
},
|
||||
schema: github.schemas.commitComments.commitCommentEventSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export function issueEvent(params: {
|
||||
repo: string;
|
||||
}): TriggerEvent<typeof github.schemas.issues.issuesEventSchema> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
@@ -25,34 +55,151 @@ export function repoIssueEvent(params: {
|
||||
events: ["issues"],
|
||||
}),
|
||||
},
|
||||
schema: github.schemas.IssueEventSchema,
|
||||
schema: github.schemas.issues.issuesEventSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export function orgIssueEvent(params: {
|
||||
org: string;
|
||||
}): TriggerEvent<typeof github.schemas.IssueEventSchema> {
|
||||
export function issueCommentEvent(params: {
|
||||
repo: string;
|
||||
}): TriggerEvent<typeof github.schemas.issuesComments.issueCommentEventSchema> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
service: "github",
|
||||
name: "issues",
|
||||
name: "issue_comment",
|
||||
filter: {
|
||||
service: ["github"],
|
||||
payload: {
|
||||
organizaton: {
|
||||
name: [params.org],
|
||||
repository: {
|
||||
full_name: [params.repo],
|
||||
},
|
||||
},
|
||||
event: ["issues"],
|
||||
event: ["issue_comment"],
|
||||
},
|
||||
source: github.schemas.WebhookSourceSchema.parse({
|
||||
subresource: "organization",
|
||||
subresource: "repository",
|
||||
scopes: ["repo"],
|
||||
org: params.org,
|
||||
events: ["issues"],
|
||||
repo: params.repo,
|
||||
events: ["issue_comment"],
|
||||
}),
|
||||
},
|
||||
schema: github.schemas.IssueEventSchema,
|
||||
schema: github.schemas.issuesComments.issueCommentEventSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export function pullRequestEvent(params: {
|
||||
repo: string;
|
||||
}): TriggerEvent<typeof github.schemas.pullRequest.pullRequestEventSchema> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
service: "github",
|
||||
name: "pull_request",
|
||||
filter: {
|
||||
service: ["github"],
|
||||
payload: {
|
||||
repository: {
|
||||
full_name: [params.repo],
|
||||
},
|
||||
},
|
||||
event: ["pull_request"],
|
||||
},
|
||||
source: github.schemas.WebhookSourceSchema.parse({
|
||||
subresource: "repository",
|
||||
scopes: ["repo"],
|
||||
repo: params.repo,
|
||||
events: ["pull_request"],
|
||||
}),
|
||||
},
|
||||
schema: github.schemas.pullRequest.pullRequestEventSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export function pullRequestCommentEvent(params: {
|
||||
repo: string;
|
||||
}): TriggerEvent<
|
||||
typeof github.schemas.pullRequestComments.pullRequestReviewCommentEventSchema
|
||||
> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
service: "github",
|
||||
name: "pull_request_review_comment",
|
||||
filter: {
|
||||
service: ["github"],
|
||||
payload: {
|
||||
repository: {
|
||||
full_name: [params.repo],
|
||||
},
|
||||
},
|
||||
event: ["pull_request_review_comment"],
|
||||
},
|
||||
source: github.schemas.WebhookSourceSchema.parse({
|
||||
subresource: "repository",
|
||||
scopes: ["repo"],
|
||||
repo: params.repo,
|
||||
events: ["pull_request_review_comment"],
|
||||
}),
|
||||
},
|
||||
schema:
|
||||
github.schemas.pullRequestComments.pullRequestReviewCommentEventSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export function pullRequestReviewEvent(params: {
|
||||
repo: string;
|
||||
}): TriggerEvent<
|
||||
typeof github.schemas.pullRequestReviews.pullRequestReviewEventSchema
|
||||
> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
service: "github",
|
||||
name: "pull_request_review",
|
||||
filter: {
|
||||
service: ["github"],
|
||||
payload: {
|
||||
repository: {
|
||||
full_name: [params.repo],
|
||||
},
|
||||
},
|
||||
event: ["pull_request_review"],
|
||||
},
|
||||
source: github.schemas.WebhookSourceSchema.parse({
|
||||
subresource: "repository",
|
||||
scopes: ["repo"],
|
||||
repo: params.repo,
|
||||
events: ["pull_request_review"],
|
||||
}),
|
||||
},
|
||||
schema: github.schemas.pullRequestReviews.pullRequestReviewEventSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export function pushEvent(params: {
|
||||
repo: string;
|
||||
}): TriggerEvent<typeof github.schemas.push.pushEventSchema> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
service: "github",
|
||||
name: "push",
|
||||
filter: {
|
||||
service: ["github"],
|
||||
payload: {
|
||||
repository: {
|
||||
full_name: [params.repo],
|
||||
},
|
||||
},
|
||||
event: ["push"],
|
||||
},
|
||||
source: github.schemas.WebhookSourceSchema.parse({
|
||||
subresource: "repository",
|
||||
scopes: ["repo"],
|
||||
repo: params.repo,
|
||||
events: ["push"],
|
||||
}),
|
||||
},
|
||||
schema: github.schemas.push.pushEventSchema,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const WebhookRepoSourceSchema = z.object({
|
||||
subresource: z.literal("repository"),
|
||||
scopes: z.array(z.string()),
|
||||
repo: z.string(),
|
||||
events: z.array(z.string()),
|
||||
});
|
||||
|
||||
export const WebhookOrganizationSourceSchema = z.object({
|
||||
subresource: z.literal("organization"),
|
||||
scopes: z.array(z.string()),
|
||||
org: z.string(),
|
||||
events: z.array(z.string()),
|
||||
});
|
||||
|
||||
export const WebhookSourceSchema = z.union([
|
||||
WebhookRepoSourceSchema,
|
||||
WebhookOrganizationSourceSchema,
|
||||
]);
|
||||
|
||||
const ReactionsSchema = z.object({
|
||||
"+1": z.number().int(),
|
||||
"-1": z.number().int(),
|
||||
url: z.string().url(),
|
||||
eyes: z.number().int(),
|
||||
heart: z.number().int(),
|
||||
laugh: z.number().int(),
|
||||
hooray: z.number().int(),
|
||||
rocket: z.number().int(),
|
||||
confused: z.number().int(),
|
||||
total_count: z.number().int(),
|
||||
});
|
||||
|
||||
const UserSchema = z.object({
|
||||
id: z.number().int(),
|
||||
url: z.string().url(),
|
||||
type: z.string(),
|
||||
login: z.string(),
|
||||
node_id: z.string(),
|
||||
html_url: z.string().url(),
|
||||
gists_url: z.string().url(),
|
||||
repos_url: z.string().url(),
|
||||
avatar_url: z.string().url(),
|
||||
events_url: z.string().url(),
|
||||
site_admin: z.boolean(),
|
||||
gravatar_id: z.string(),
|
||||
starred_url: z.string().url(),
|
||||
followers_url: z.string().url(),
|
||||
following_url: z.string().url(),
|
||||
organizations_url: z.string().url(),
|
||||
subscriptions_url: z.string().url(),
|
||||
received_events_url: z.string().url(),
|
||||
});
|
||||
|
||||
const RepositorySchema = z.object({
|
||||
id: z.number().int(),
|
||||
url: z.string().url(),
|
||||
fork: z.boolean(),
|
||||
name: z.string(),
|
||||
size: z.number().int(),
|
||||
forks: z.number().int(),
|
||||
owner: UserSchema,
|
||||
topics: z.array(z.string()),
|
||||
git_url: z.string().url(),
|
||||
license: z.object({
|
||||
key: z.string(),
|
||||
url: z.string().url(),
|
||||
name: z.string(),
|
||||
node_id: z.string(),
|
||||
spdx_id: z.string(),
|
||||
}),
|
||||
node_id: z.string(),
|
||||
private: z.boolean(),
|
||||
ssh_url: z.string(),
|
||||
svn_url: z.string().url(),
|
||||
archived: z.boolean(),
|
||||
disabled: z.boolean(),
|
||||
has_wiki: z.boolean(),
|
||||
homepage: z.string().url(),
|
||||
html_url: z.string().url(),
|
||||
keys_url: z.string().url(),
|
||||
language: z.string(),
|
||||
tags_url: z.string().url(),
|
||||
watchers: z.number().int(),
|
||||
blobs_url: z.string().url(),
|
||||
clone_url: z.string().url(),
|
||||
forks_url: z.string().url(),
|
||||
full_name: z.string(),
|
||||
has_pages: z.boolean(),
|
||||
hooks_url: z.string().url(),
|
||||
pulls_url: z.string().url(),
|
||||
pushed_at: z.string(),
|
||||
teams_url: z.string().url(),
|
||||
trees_url: z.string().url(),
|
||||
created_at: z.string(),
|
||||
events_url: z.string().url(),
|
||||
has_issues: z.boolean(),
|
||||
issues_url: z.string().url(),
|
||||
labels_url: z.string().url(),
|
||||
merges_url: z.string().url(),
|
||||
mirror_url: z.null(),
|
||||
updated_at: z.string(),
|
||||
visibility: z.string(),
|
||||
archive_url: z.string().url(),
|
||||
commits_url: z.string().url(),
|
||||
compare_url: z.string().url(),
|
||||
description: z.string(),
|
||||
forks_count: z.number().int(),
|
||||
is_template: z.boolean(),
|
||||
open_issues: z.number().int(),
|
||||
branches_url: z.string().url(),
|
||||
comments_url: z.string().url(),
|
||||
contents_url: z.string().url(),
|
||||
git_refs_url: z.string().url(),
|
||||
git_tags_url: z.string().url(),
|
||||
has_projects: z.boolean(),
|
||||
releases_url: z.string().url(),
|
||||
statuses_url: z.string().url(),
|
||||
allow_forking: z.boolean(),
|
||||
assignees_url: z.string().url(),
|
||||
downloads_url: z.string().url(),
|
||||
has_downloads: z.boolean(),
|
||||
languages_url: z.string().url(),
|
||||
default_branch: z.string(),
|
||||
milestones_url: z.string().url(),
|
||||
stargazers_url: z.string().url(),
|
||||
watchers_count: z.number().int(),
|
||||
deployments_url: z.string().url(),
|
||||
git_commits_url: z.string().url(),
|
||||
has_discussions: z.boolean(),
|
||||
subscribers_url: z.string().url(),
|
||||
contributors_url: z.string().url(),
|
||||
issue_events_url: z.string().url(),
|
||||
stargazers_count: z.number().int(),
|
||||
subscription_url: z.string().url(),
|
||||
collaborators_url: z.string().url(),
|
||||
issue_comment_url: z.string().url(),
|
||||
notifications_url: z.string().url(),
|
||||
open_issues_count: z.number().int(),
|
||||
web_commit_signoff_required: z.boolean(),
|
||||
});
|
||||
|
||||
const IssueSchema = z.object({
|
||||
id: z.number().int(),
|
||||
url: z.string().url(),
|
||||
body: z.string(),
|
||||
user: UserSchema,
|
||||
state: z.string(),
|
||||
title: z.string(),
|
||||
labels: z.array(z.any()),
|
||||
locked: z.boolean(),
|
||||
number: z.number().int(),
|
||||
node_id: z.string(),
|
||||
assignee: UserSchema.optional(),
|
||||
comments: z.number().int(),
|
||||
html_url: z.string().url(),
|
||||
assignees: z.array(UserSchema),
|
||||
closed_at: z.null(),
|
||||
milestone: z.null(),
|
||||
reactions: ReactionsSchema,
|
||||
created_at: z.string(),
|
||||
events_url: z.string().url(),
|
||||
labels_url: z.string().url(),
|
||||
updated_at: z.string(),
|
||||
comments_url: z.string().url(),
|
||||
state_reason: z.null(),
|
||||
timeline_url: z.string().url(),
|
||||
repository_url: z.string().url(),
|
||||
active_lock_reason: z.null(),
|
||||
author_association: z.string(),
|
||||
performed_via_github_app: z.null(),
|
||||
});
|
||||
|
||||
const LabelSchema = z.object({
|
||||
id: z.number().int(),
|
||||
url: z.string().url(),
|
||||
name: z.string(),
|
||||
color: z.string(),
|
||||
default: z.boolean(),
|
||||
node_id: z.string(),
|
||||
description: z.string(),
|
||||
});
|
||||
|
||||
const OrganizationSchema = z.object({
|
||||
id: z.number().int(),
|
||||
url: z.string().url(),
|
||||
login: z.string(),
|
||||
node_id: z.string(),
|
||||
hooks_url: z.string().url(),
|
||||
repos_url: z.string().url(),
|
||||
avatar_url: z.string().url(),
|
||||
events_url: z.string().url(),
|
||||
issues_url: z.string().url(),
|
||||
description: z.string(),
|
||||
members_url: z.string().url(),
|
||||
public_members_url: z.string().url(),
|
||||
});
|
||||
|
||||
const SharedIssueEventSchema = z.object({
|
||||
issue: IssueSchema,
|
||||
sender: UserSchema,
|
||||
repository: RepositorySchema,
|
||||
organization: OrganizationSchema,
|
||||
});
|
||||
|
||||
const LabeledIssueEventSchema = z
|
||||
.object({
|
||||
action: z.literal("labeled"),
|
||||
label: LabelSchema,
|
||||
})
|
||||
.merge(SharedIssueEventSchema);
|
||||
|
||||
const UnlabeledIssueEventSchema = z
|
||||
.object({
|
||||
action: z.literal("unlabeled"),
|
||||
label: LabelSchema,
|
||||
})
|
||||
.merge(SharedIssueEventSchema);
|
||||
|
||||
const AssignedIssueEventSchema = z
|
||||
.object({
|
||||
action: z.literal("assigned"),
|
||||
assignee: UserSchema,
|
||||
})
|
||||
.merge(SharedIssueEventSchema);
|
||||
|
||||
const UnassignedIssueEventSchema = z
|
||||
.object({
|
||||
action: z.literal("unassigned"),
|
||||
assignee: UserSchema,
|
||||
})
|
||||
.merge(SharedIssueEventSchema);
|
||||
|
||||
export const IssueEventSchema = z.discriminatedUnion("action", [
|
||||
LabeledIssueEventSchema,
|
||||
UnlabeledIssueEventSchema,
|
||||
AssignedIssueEventSchema,
|
||||
UnassignedIssueEventSchema,
|
||||
]);
|
||||
@@ -0,0 +1,31 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
userSchema,
|
||||
authorAssociationSchema,
|
||||
repositorySchema,
|
||||
installationLiteSchema,
|
||||
organizationSchema,
|
||||
} from "./shared";
|
||||
|
||||
export const commitCommentEventSchema = z.object({
|
||||
action: z.literal("created"),
|
||||
comment: z.object({
|
||||
url: z.string(),
|
||||
html_url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
user: userSchema,
|
||||
position: z.number().nullable(),
|
||||
line: z.number().nullable(),
|
||||
path: z.string().nullable(),
|
||||
commit_id: z.string(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
author_association: authorAssociationSchema,
|
||||
body: z.string(),
|
||||
}),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { z } from "zod";
|
||||
import * as commitComments from "./commitComments";
|
||||
import * as issuesComments from "./issueComments";
|
||||
import * as issues from "./issues";
|
||||
import * as pullRequestComments from "./pullRequestComments";
|
||||
import * as pullRequestReviews from "./pullRequestReviews";
|
||||
import * as pullRequest from "./pullRequests";
|
||||
import * as push from "./pushes";
|
||||
|
||||
export const WebhookRepoSourceSchema = z.object({
|
||||
subresource: z.literal("repository"),
|
||||
scopes: z.array(z.string()),
|
||||
repo: z.string(),
|
||||
events: z.array(z.string()),
|
||||
});
|
||||
|
||||
export const WebhookOrganizationSourceSchema = z.object({
|
||||
subresource: z.literal("organization"),
|
||||
scopes: z.array(z.string()),
|
||||
org: z.string(),
|
||||
events: z.array(z.string()),
|
||||
});
|
||||
|
||||
export const WebhookSourceSchema = z.union([
|
||||
WebhookRepoSourceSchema,
|
||||
WebhookOrganizationSourceSchema,
|
||||
]);
|
||||
|
||||
export {
|
||||
commitComments,
|
||||
issues,
|
||||
issuesComments,
|
||||
pullRequest,
|
||||
pullRequestComments,
|
||||
pullRequestReviews,
|
||||
push,
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
import { z } from "zod";
|
||||
import { issueSchema } from "./issues";
|
||||
import {
|
||||
appSchema,
|
||||
authorAssociationSchema,
|
||||
installationLiteSchema,
|
||||
labelSchema,
|
||||
organizationSchema,
|
||||
reactionsSchema,
|
||||
repositorySchema,
|
||||
userSchema,
|
||||
} from "./shared";
|
||||
|
||||
export const issueCommentSchema = z.object({
|
||||
url: z.string(),
|
||||
html_url: z.string(),
|
||||
issue_url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
user: userSchema,
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
author_association: authorAssociationSchema,
|
||||
body: z.string(),
|
||||
reactions: reactionsSchema,
|
||||
performed_via_github_app: appSchema.nullable(),
|
||||
});
|
||||
|
||||
export const issueCommentCreatedEventSchema = z.object({
|
||||
action: z.literal("created"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
assignee: userSchema.nullable(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
labels: z.array(labelSchema),
|
||||
})
|
||||
),
|
||||
comment: issueCommentSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issueCommentDeletedEventSchema = z.object({
|
||||
action: z.literal("deleted"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
assignee: userSchema.nullable(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
labels: z.array(labelSchema),
|
||||
})
|
||||
),
|
||||
comment: issueCommentSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issueCommentEditedEventSchema = z.object({
|
||||
action: z.literal("edited"),
|
||||
changes: z.object({
|
||||
body: z
|
||||
.object({
|
||||
from: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
assignee: userSchema.nullable(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
labels: z.array(labelSchema),
|
||||
})
|
||||
),
|
||||
comment: issueCommentSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issueCommentEventSchema = z.discriminatedUnion("action", [
|
||||
issueCommentCreatedEventSchema,
|
||||
issueCommentDeletedEventSchema,
|
||||
issueCommentEditedEventSchema,
|
||||
]);
|
||||
@@ -0,0 +1,311 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
appSchema,
|
||||
authorAssociationSchema,
|
||||
installationLiteSchema,
|
||||
labelSchema,
|
||||
milestoneSchema,
|
||||
organizationSchema,
|
||||
reactionsSchema,
|
||||
repositorySchema,
|
||||
userSchema,
|
||||
} from "./shared";
|
||||
|
||||
export const issueSchema = z.object({
|
||||
url: z.string(),
|
||||
repository_url: z.string(),
|
||||
labels_url: z.string(),
|
||||
comments_url: z.string(),
|
||||
events_url: z.string(),
|
||||
html_url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
number: z.number(),
|
||||
title: z.string(),
|
||||
user: userSchema,
|
||||
labels: z.array(labelSchema).optional(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]).optional(),
|
||||
locked: z.boolean().optional(),
|
||||
assignee: userSchema.optional().nullable(),
|
||||
assignees: z.array(userSchema),
|
||||
milestone: milestoneSchema.nullable(),
|
||||
comments: z.number(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
closed_at: z.string().nullable(),
|
||||
author_association: authorAssociationSchema,
|
||||
active_lock_reason: z
|
||||
.union([
|
||||
z.literal("resolved"),
|
||||
z.literal("off-topic"),
|
||||
z.literal("too heated"),
|
||||
z.literal("spam"),
|
||||
])
|
||||
.nullable(),
|
||||
draft: z.boolean().optional(),
|
||||
performed_via_github_app: appSchema.optional().nullable(),
|
||||
pull_request: z
|
||||
.object({
|
||||
url: z.string().optional(),
|
||||
html_url: z.string().optional(),
|
||||
diff_url: z.string().optional(),
|
||||
patch_url: z.string().optional(),
|
||||
merged_at: z.string().optional().nullable(),
|
||||
})
|
||||
.optional(),
|
||||
body: z.string().nullable(),
|
||||
reactions: reactionsSchema,
|
||||
timeline_url: z.string().optional(),
|
||||
state_reason: z.string().optional().nullable(),
|
||||
});
|
||||
|
||||
export const issuesAssignedEventSchema = z.object({
|
||||
action: z.literal("assigned"),
|
||||
issue: issueSchema,
|
||||
assignee: userSchema.optional().nullable(),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesClosedEventSchema = z.object({
|
||||
action: z.literal("closed"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
state: z.literal("closed"),
|
||||
closed_at: z.string(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesDeletedEventSchema = z.object({
|
||||
action: z.literal("deleted"),
|
||||
issue: issueSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesDemilestonedEventSchema = z.object({
|
||||
action: z.literal("demilestoned"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
milestone: z.null(),
|
||||
})
|
||||
),
|
||||
milestone: milestoneSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesEditedEventSchema = z.object({
|
||||
action: z.literal("edited"),
|
||||
issue: issueSchema,
|
||||
label: labelSchema.optional(),
|
||||
changes: z.object({
|
||||
body: z
|
||||
.object({
|
||||
from: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
title: z
|
||||
.object({
|
||||
from: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesLabeledEventSchema = z.object({
|
||||
action: z.literal("labeled"),
|
||||
issue: issueSchema,
|
||||
label: labelSchema.optional(),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesLockedEventSchema = z.object({
|
||||
action: z.literal("locked"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
locked: z.literal(true),
|
||||
active_lock_reason: z
|
||||
.union([
|
||||
z.literal("resolved"),
|
||||
z.literal("off-topic"),
|
||||
z.literal("too heated"),
|
||||
z.literal("spam"),
|
||||
])
|
||||
.nullable(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesMilestonedEventSchema = z.object({
|
||||
action: z.literal("milestoned"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
milestone: milestoneSchema,
|
||||
})
|
||||
),
|
||||
milestone: milestoneSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesOpenedEventSchema = z.object({
|
||||
action: z.literal("opened"),
|
||||
changes: z
|
||||
.object({
|
||||
old_issue: issueSchema,
|
||||
old_repository: repositorySchema,
|
||||
})
|
||||
.optional(),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
state: z.literal("open"),
|
||||
closed_at: z.null(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesPinnedEventSchema = z.object({
|
||||
action: z.literal("pinned"),
|
||||
issue: issueSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesReopenedEventSchema = z.object({
|
||||
action: z.literal("reopened"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
state: z.literal("open"),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesTransferredEventSchema = z.object({
|
||||
action: z.literal("transferred"),
|
||||
changes: z.object({
|
||||
new_issue: issueSchema,
|
||||
new_repository: repositorySchema,
|
||||
}),
|
||||
issue: issueSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesUnassignedEventSchema = z.object({
|
||||
action: z.literal("unassigned"),
|
||||
issue: issueSchema,
|
||||
assignee: userSchema.optional().nullable(),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesUnlabeledEventSchema = z.object({
|
||||
action: z.literal("unlabeled"),
|
||||
issue: issueSchema,
|
||||
label: labelSchema.optional(),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesUnlockedEventSchema = z.object({
|
||||
action: z.literal("unlocked"),
|
||||
issue: issueSchema.and(
|
||||
z.object({
|
||||
locked: z.literal(false),
|
||||
active_lock_reason: z.null(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesUnpinnedEventSchema = z.object({
|
||||
action: z.literal("unpinned"),
|
||||
issue: issueSchema,
|
||||
repository: repositorySchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
|
||||
export const issuesEventSchema: z.ZodDiscriminatedUnion<
|
||||
"action",
|
||||
[
|
||||
typeof issuesAssignedEventSchema,
|
||||
typeof issuesClosedEventSchema,
|
||||
typeof issuesDeletedEventSchema,
|
||||
typeof issuesDemilestonedEventSchema,
|
||||
typeof issuesEditedEventSchema,
|
||||
typeof issuesLabeledEventSchema,
|
||||
typeof issuesLockedEventSchema,
|
||||
typeof issuesMilestonedEventSchema,
|
||||
typeof issuesOpenedEventSchema,
|
||||
typeof issuesPinnedEventSchema,
|
||||
typeof issuesReopenedEventSchema,
|
||||
typeof issuesTransferredEventSchema,
|
||||
typeof issuesUnassignedEventSchema,
|
||||
typeof issuesUnlabeledEventSchema,
|
||||
typeof issuesUnlockedEventSchema,
|
||||
typeof issuesUnpinnedEventSchema
|
||||
]
|
||||
> = z.discriminatedUnion("action", [
|
||||
issuesAssignedEventSchema,
|
||||
issuesClosedEventSchema,
|
||||
issuesDeletedEventSchema,
|
||||
issuesDemilestonedEventSchema,
|
||||
issuesEditedEventSchema,
|
||||
issuesLabeledEventSchema,
|
||||
issuesLockedEventSchema,
|
||||
issuesMilestonedEventSchema,
|
||||
issuesOpenedEventSchema,
|
||||
issuesPinnedEventSchema,
|
||||
issuesReopenedEventSchema,
|
||||
issuesTransferredEventSchema,
|
||||
issuesUnassignedEventSchema,
|
||||
issuesUnlabeledEventSchema,
|
||||
issuesUnlockedEventSchema,
|
||||
issuesUnpinnedEventSchema,
|
||||
]);
|
||||
@@ -0,0 +1,285 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
userSchema,
|
||||
teamSchema,
|
||||
labelSchema,
|
||||
milestoneSchema,
|
||||
repositorySchema,
|
||||
linkSchema,
|
||||
authorAssociationSchema,
|
||||
installationLiteSchema,
|
||||
organizationSchema,
|
||||
reactionsSchema,
|
||||
pullRequestAutoMergeSchema,
|
||||
} from "./shared";
|
||||
|
||||
export const pullRequestReviewCommentSchema = z.object({
|
||||
url: z.string(),
|
||||
pull_request_review_id: z.number(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
diff_hunk: z.string(),
|
||||
path: z.string(),
|
||||
position: z.number().nullable(),
|
||||
original_position: z.number(),
|
||||
commit_id: z.string(),
|
||||
original_commit_id: z.string(),
|
||||
user: userSchema,
|
||||
body: z.string(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
html_url: z.string(),
|
||||
pull_request_url: z.string(),
|
||||
author_association: authorAssociationSchema,
|
||||
_links: z.object({
|
||||
self: linkSchema,
|
||||
html: linkSchema,
|
||||
pull_request: linkSchema,
|
||||
}),
|
||||
reactions: reactionsSchema,
|
||||
start_line: z.number().nullable(),
|
||||
original_start_line: z.number().nullable(),
|
||||
start_side: z.union([z.literal("LEFT"), z.literal("RIGHT")]).nullable(),
|
||||
line: z.number().nullable(),
|
||||
original_line: z.number(),
|
||||
side: z.union([z.literal("LEFT"), z.literal("RIGHT")]),
|
||||
in_reply_to_id: z.number().optional(),
|
||||
});
|
||||
|
||||
export const pullRequestReviewCommentCreatedEventSchema = z.object({
|
||||
action: z.literal("created"),
|
||||
comment: pullRequestReviewCommentSchema,
|
||||
pull_request: z.object({
|
||||
url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
html_url: z.string(),
|
||||
diff_url: z.string(),
|
||||
patch_url: z.string(),
|
||||
issue_url: z.string(),
|
||||
number: z.number(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
title: z.string(),
|
||||
user: userSchema,
|
||||
body: z.string().nullable(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
closed_at: z.string().nullable(),
|
||||
merged_at: z.string().nullable(),
|
||||
merge_commit_sha: z.string().nullable(),
|
||||
assignee: userSchema.nullable(),
|
||||
assignees: z.array(userSchema),
|
||||
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
|
||||
requested_teams: z.array(teamSchema),
|
||||
labels: z.array(labelSchema),
|
||||
milestone: milestoneSchema.nullable(),
|
||||
draft: z.boolean().optional(),
|
||||
commits_url: z.string(),
|
||||
review_comments_url: z.string(),
|
||||
review_comment_url: z.string(),
|
||||
comments_url: z.string(),
|
||||
statuses_url: z.string(),
|
||||
head: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
base: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
_links: z.object({
|
||||
self: linkSchema,
|
||||
html: linkSchema,
|
||||
issue: linkSchema,
|
||||
comments: linkSchema,
|
||||
review_comments: linkSchema,
|
||||
review_comment: linkSchema,
|
||||
commits: linkSchema,
|
||||
statuses: linkSchema,
|
||||
}),
|
||||
auto_merge: pullRequestAutoMergeSchema.optional().nullable(),
|
||||
author_association: authorAssociationSchema,
|
||||
active_lock_reason: z
|
||||
.union([
|
||||
z.literal("resolved"),
|
||||
z.literal("off-topic"),
|
||||
z.literal("too heated"),
|
||||
z.literal("spam"),
|
||||
])
|
||||
.nullable(),
|
||||
}),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewCommentDeletedEventSchema = z.object({
|
||||
action: z.literal("deleted"),
|
||||
comment: pullRequestReviewCommentSchema,
|
||||
pull_request: z.object({
|
||||
url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
html_url: z.string(),
|
||||
diff_url: z.string(),
|
||||
patch_url: z.string(),
|
||||
issue_url: z.string(),
|
||||
number: z.number(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
title: z.string(),
|
||||
user: userSchema,
|
||||
body: z.string().nullable(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
closed_at: z.string().nullable(),
|
||||
merged_at: z.string().nullable(),
|
||||
merge_commit_sha: z.string().nullable(),
|
||||
assignee: userSchema.nullable(),
|
||||
assignees: z.array(userSchema),
|
||||
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
|
||||
requested_teams: z.array(teamSchema),
|
||||
labels: z.array(labelSchema),
|
||||
milestone: milestoneSchema.nullable(),
|
||||
draft: z.boolean().optional(),
|
||||
commits_url: z.string(),
|
||||
review_comments_url: z.string(),
|
||||
review_comment_url: z.string(),
|
||||
comments_url: z.string(),
|
||||
statuses_url: z.string(),
|
||||
head: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
base: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
_links: z.object({
|
||||
self: linkSchema,
|
||||
html: linkSchema,
|
||||
issue: linkSchema,
|
||||
comments: linkSchema,
|
||||
review_comments: linkSchema,
|
||||
review_comment: linkSchema,
|
||||
commits: linkSchema,
|
||||
statuses: linkSchema,
|
||||
}),
|
||||
auto_merge: pullRequestAutoMergeSchema.optional().nullable(),
|
||||
author_association: authorAssociationSchema,
|
||||
active_lock_reason: z
|
||||
.union([
|
||||
z.literal("resolved"),
|
||||
z.literal("off-topic"),
|
||||
z.literal("too heated"),
|
||||
z.literal("spam"),
|
||||
])
|
||||
.nullable(),
|
||||
}),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewCommentEditedEventSchema = z.object({
|
||||
action: z.literal("edited"),
|
||||
changes: z.object({
|
||||
body: z
|
||||
.object({
|
||||
from: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
comment: pullRequestReviewCommentSchema,
|
||||
pull_request: z.object({
|
||||
url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
html_url: z.string(),
|
||||
diff_url: z.string(),
|
||||
patch_url: z.string(),
|
||||
issue_url: z.string(),
|
||||
number: z.number(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
title: z.string(),
|
||||
user: userSchema,
|
||||
body: z.string().nullable(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
closed_at: z.string().nullable(),
|
||||
merged_at: z.string().nullable(),
|
||||
merge_commit_sha: z.string().nullable(),
|
||||
assignee: userSchema.nullable(),
|
||||
assignees: z.array(userSchema),
|
||||
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
|
||||
requested_teams: z.array(teamSchema),
|
||||
labels: z.array(labelSchema),
|
||||
milestone: milestoneSchema.nullable(),
|
||||
draft: z.boolean().optional(),
|
||||
commits_url: z.string(),
|
||||
review_comments_url: z.string(),
|
||||
review_comment_url: z.string(),
|
||||
comments_url: z.string(),
|
||||
statuses_url: z.string(),
|
||||
head: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
base: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
_links: z.object({
|
||||
self: linkSchema,
|
||||
html: linkSchema,
|
||||
issue: linkSchema,
|
||||
comments: linkSchema,
|
||||
review_comments: linkSchema,
|
||||
review_comment: linkSchema,
|
||||
commits: linkSchema,
|
||||
statuses: linkSchema,
|
||||
}),
|
||||
auto_merge: pullRequestAutoMergeSchema.optional().nullable(),
|
||||
author_association: authorAssociationSchema,
|
||||
active_lock_reason: z
|
||||
.union([
|
||||
z.literal("resolved"),
|
||||
z.literal("off-topic"),
|
||||
z.literal("too heated"),
|
||||
z.literal("spam"),
|
||||
])
|
||||
.nullable(),
|
||||
}),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewCommentEventSchema = z.union([
|
||||
pullRequestReviewCommentCreatedEventSchema,
|
||||
pullRequestReviewCommentDeletedEventSchema,
|
||||
pullRequestReviewCommentEditedEventSchema,
|
||||
]);
|
||||
@@ -0,0 +1,79 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
repositorySchema,
|
||||
installationLiteSchema,
|
||||
organizationSchema,
|
||||
userSchema,
|
||||
authorAssociationSchema,
|
||||
linkSchema,
|
||||
simplePullRequestSchema,
|
||||
} from "./shared";
|
||||
|
||||
export const pullRequestReviewSchema = z.object({
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
user: userSchema,
|
||||
body: z.string().nullable(),
|
||||
commit_id: z.string(),
|
||||
submitted_at: z.string().nullable(),
|
||||
state: z.union([
|
||||
z.literal("commented"),
|
||||
z.literal("changes_requested"),
|
||||
z.literal("approved"),
|
||||
z.literal("dismissed"),
|
||||
]),
|
||||
html_url: z.string(),
|
||||
pull_request_url: z.string(),
|
||||
author_association: authorAssociationSchema,
|
||||
_links: z.object({
|
||||
html: linkSchema,
|
||||
pull_request: linkSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
export const pullRequestReviewDismissedEventSchema = z.object({
|
||||
action: z.literal("dismissed"),
|
||||
review: pullRequestReviewSchema.and(
|
||||
z.object({
|
||||
state: z.literal("dismissed"),
|
||||
})
|
||||
),
|
||||
pull_request: simplePullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewEditedEventSchema = z.object({
|
||||
action: z.literal("edited"),
|
||||
changes: z.object({
|
||||
body: z
|
||||
.object({
|
||||
from: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
review: pullRequestReviewSchema,
|
||||
pull_request: simplePullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewSubmittedEventSchema = z.object({
|
||||
action: z.literal("submitted"),
|
||||
review: pullRequestReviewSchema,
|
||||
pull_request: simplePullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewEventSchema = z.union([
|
||||
pullRequestReviewDismissedEventSchema,
|
||||
pullRequestReviewEditedEventSchema,
|
||||
pullRequestReviewSubmittedEventSchema,
|
||||
]);
|
||||
@@ -0,0 +1,401 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
authorAssociationSchema,
|
||||
installationLiteSchema,
|
||||
labelSchema,
|
||||
linkSchema,
|
||||
milestoneSchema,
|
||||
organizationSchema,
|
||||
pullRequestAutoMergeSchema,
|
||||
repositorySchema,
|
||||
teamSchema,
|
||||
userSchema,
|
||||
} from "./shared";
|
||||
|
||||
export const pullRequestSchema = z.object({
|
||||
url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
html_url: z.string(),
|
||||
diff_url: z.string(),
|
||||
patch_url: z.string(),
|
||||
issue_url: z.string(),
|
||||
number: z.number(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
title: z.string(),
|
||||
user: userSchema,
|
||||
body: z.string().nullable(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
closed_at: z.string().nullable(),
|
||||
merged_at: z.string().nullable(),
|
||||
merge_commit_sha: z.string().nullable(),
|
||||
assignee: userSchema.nullable(),
|
||||
assignees: z.array(userSchema),
|
||||
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
|
||||
requested_teams: z.array(teamSchema),
|
||||
labels: z.array(labelSchema),
|
||||
milestone: milestoneSchema.nullable(),
|
||||
commits_url: z.string(),
|
||||
review_comments_url: z.string(),
|
||||
review_comment_url: z.string(),
|
||||
comments_url: z.string(),
|
||||
statuses_url: z.string(),
|
||||
head: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
base: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
_links: z.object({
|
||||
self: linkSchema,
|
||||
html: linkSchema,
|
||||
issue: linkSchema,
|
||||
comments: linkSchema,
|
||||
review_comments: linkSchema,
|
||||
review_comment: linkSchema,
|
||||
commits: linkSchema,
|
||||
statuses: linkSchema,
|
||||
}),
|
||||
author_association: authorAssociationSchema,
|
||||
auto_merge: pullRequestAutoMergeSchema.nullable(),
|
||||
active_lock_reason: z
|
||||
.union([
|
||||
z.literal("resolved"),
|
||||
z.literal("off-topic"),
|
||||
z.literal("too heated"),
|
||||
z.literal("spam"),
|
||||
])
|
||||
.nullable(),
|
||||
draft: z.boolean(),
|
||||
merged: z.boolean().nullable(),
|
||||
mergeable: z.boolean().nullable(),
|
||||
rebaseable: z.boolean().nullable(),
|
||||
mergeable_state: z.string(),
|
||||
merged_by: userSchema.nullable(),
|
||||
comments: z.number(),
|
||||
review_comments: z.number(),
|
||||
maintainer_can_modify: z.boolean(),
|
||||
commits: z.number(),
|
||||
additions: z.number(),
|
||||
deletions: z.number(),
|
||||
changed_files: z.number(),
|
||||
});
|
||||
|
||||
export const pullRequestAssignedEventSchema = z.object({
|
||||
action: z.literal("assigned"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
assignee: userSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestAutoMergeDisabledEventSchema = z.object({
|
||||
action: z.literal("auto_merge_disabled"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
reason: z.string(),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestAutoMergeEnabledEventSchema = z.object({
|
||||
action: z.literal("auto_merge_enabled"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
reason: z.string(),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestClosedEventSchema = z.object({
|
||||
action: z.literal("closed"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema.and(
|
||||
z.object({
|
||||
state: z.literal("closed"),
|
||||
closed_at: z.string(),
|
||||
merged: z.boolean(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestConvertedToDraftEventSchema = z.object({
|
||||
action: z.literal("converted_to_draft"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema.and(
|
||||
z.object({
|
||||
closed_at: z.null(),
|
||||
merged_at: z.null(),
|
||||
draft: z.literal(true),
|
||||
merged: z.literal(false),
|
||||
merged_by: z.null(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestDequeuedEventSchema = z.object({
|
||||
action: z.literal("dequeued"),
|
||||
number: z.number(),
|
||||
reason: z.string(),
|
||||
pull_request: pullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestEditedEventSchema = z.object({
|
||||
action: z.literal("edited"),
|
||||
number: z.number(),
|
||||
changes: z.object({
|
||||
body: z
|
||||
.object({
|
||||
from: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
title: z
|
||||
.object({
|
||||
from: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
base: z
|
||||
.object({
|
||||
ref: z.object({
|
||||
from: z.string(),
|
||||
}),
|
||||
sha: z.object({
|
||||
from: z.string(),
|
||||
}),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
pull_request: pullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestLabeledEventSchema = z.object({
|
||||
action: z.literal("labeled"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
label: labelSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestLockedEventSchema = z.object({
|
||||
action: z.literal("locked"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestOpenedEventSchema = z.object({
|
||||
action: z.literal("opened"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema.and(
|
||||
z.object({
|
||||
state: z.literal("open"),
|
||||
closed_at: z.null(),
|
||||
merged_at: z.null(),
|
||||
active_lock_reason: z.null(),
|
||||
merged_by: z.null(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestQueuedEventSchema = z.object({
|
||||
action: z.literal("queued"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReadyForReviewEventSchema = z.object({
|
||||
action: z.literal("ready_for_review"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema.and(
|
||||
z.object({
|
||||
state: z.literal("open"),
|
||||
closed_at: z.null(),
|
||||
merged_at: z.null(),
|
||||
draft: z.literal(false),
|
||||
merged: z.boolean(),
|
||||
merged_by: z.null(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReopenedEventSchema = z.object({
|
||||
action: z.literal("reopened"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema.and(
|
||||
z.object({
|
||||
state: z.literal("open"),
|
||||
closed_at: z.null(),
|
||||
merged_at: z.null(),
|
||||
merged: z.boolean(),
|
||||
merged_by: z.null(),
|
||||
})
|
||||
),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestSynchronizeEventSchema = z.object({
|
||||
action: z.literal("synchronize"),
|
||||
number: z.number(),
|
||||
before: z.string(),
|
||||
after: z.string(),
|
||||
pull_request: pullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestUnassignedEventSchema = z.object({
|
||||
action: z.literal("unassigned"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
assignee: userSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestUnlabeledEventSchema = z.object({
|
||||
action: z.literal("unlabeled"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
label: labelSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestUnlockedEventSchema = z.object({
|
||||
action: z.literal("unlocked"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewRequestRemovedEventSchema = z.object({
|
||||
action: z.literal("review_request_removed"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
requested_reviewer: userSchema.optional(),
|
||||
requested_team: teamSchema.optional(),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestReviewRequestedEventSchema = z.object({
|
||||
action: z.literal("review_requested"),
|
||||
number: z.number(),
|
||||
pull_request: pullRequestSchema,
|
||||
requested_reviewer: userSchema.optional(),
|
||||
requested_team: teamSchema.optional(),
|
||||
repository: repositorySchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
sender: userSchema,
|
||||
});
|
||||
|
||||
export const pullRequestEventSchema: z.ZodDiscriminatedUnion<
|
||||
"action",
|
||||
[
|
||||
typeof pullRequestAssignedEventSchema,
|
||||
typeof pullRequestAutoMergeDisabledEventSchema,
|
||||
typeof pullRequestAutoMergeEnabledEventSchema,
|
||||
typeof pullRequestClosedEventSchema,
|
||||
typeof pullRequestConvertedToDraftEventSchema,
|
||||
typeof pullRequestDequeuedEventSchema,
|
||||
typeof pullRequestEditedEventSchema,
|
||||
typeof pullRequestLabeledEventSchema,
|
||||
typeof pullRequestLockedEventSchema,
|
||||
typeof pullRequestOpenedEventSchema,
|
||||
typeof pullRequestQueuedEventSchema,
|
||||
typeof pullRequestReadyForReviewEventSchema,
|
||||
typeof pullRequestReopenedEventSchema,
|
||||
typeof pullRequestReviewRequestRemovedEventSchema,
|
||||
typeof pullRequestReviewRequestedEventSchema,
|
||||
typeof pullRequestSynchronizeEventSchema,
|
||||
typeof pullRequestUnassignedEventSchema,
|
||||
typeof pullRequestUnlabeledEventSchema,
|
||||
typeof pullRequestUnlockedEventSchema
|
||||
]
|
||||
> = z.discriminatedUnion("action", [
|
||||
pullRequestAssignedEventSchema,
|
||||
pullRequestAutoMergeDisabledEventSchema,
|
||||
pullRequestAutoMergeEnabledEventSchema,
|
||||
pullRequestClosedEventSchema,
|
||||
pullRequestConvertedToDraftEventSchema,
|
||||
pullRequestDequeuedEventSchema,
|
||||
pullRequestEditedEventSchema,
|
||||
pullRequestLabeledEventSchema,
|
||||
pullRequestLockedEventSchema,
|
||||
pullRequestOpenedEventSchema,
|
||||
pullRequestQueuedEventSchema,
|
||||
pullRequestReadyForReviewEventSchema,
|
||||
pullRequestReopenedEventSchema,
|
||||
pullRequestReviewRequestRemovedEventSchema,
|
||||
pullRequestReviewRequestedEventSchema,
|
||||
pullRequestSynchronizeEventSchema,
|
||||
pullRequestUnassignedEventSchema,
|
||||
pullRequestUnlabeledEventSchema,
|
||||
pullRequestUnlockedEventSchema,
|
||||
]);
|
||||
@@ -0,0 +1,27 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
repositorySchema,
|
||||
userSchema,
|
||||
installationLiteSchema,
|
||||
organizationSchema,
|
||||
commitSchema,
|
||||
committerSchema,
|
||||
} from "./shared";
|
||||
|
||||
export const pushEventSchema = z.object({
|
||||
ref: z.string(),
|
||||
before: z.string(),
|
||||
after: z.string(),
|
||||
created: z.boolean(),
|
||||
deleted: z.boolean(),
|
||||
forced: z.boolean(),
|
||||
base_ref: z.string().nullable(),
|
||||
compare: z.string(),
|
||||
commits: z.array(commitSchema),
|
||||
head_commit: commitSchema.nullable(),
|
||||
repository: repositorySchema,
|
||||
pusher: committerSchema,
|
||||
sender: userSchema,
|
||||
installation: installationLiteSchema.optional(),
|
||||
organization: organizationSchema.optional(),
|
||||
});
|
||||
@@ -0,0 +1,507 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const userSchema = z.object({
|
||||
login: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
name: z.string().optional(),
|
||||
email: z.string().optional().nullable(),
|
||||
avatar_url: z.string(),
|
||||
gravatar_id: z.string(),
|
||||
url: z.string(),
|
||||
html_url: z.string(),
|
||||
followers_url: z.string(),
|
||||
following_url: z.string(),
|
||||
gists_url: z.string(),
|
||||
starred_url: z.string(),
|
||||
subscriptions_url: z.string(),
|
||||
organizations_url: z.string(),
|
||||
repos_url: z.string(),
|
||||
events_url: z.string(),
|
||||
received_events_url: z.string(),
|
||||
type: z.union([
|
||||
z.literal("Bot"),
|
||||
z.literal("User"),
|
||||
z.literal("Organization"),
|
||||
]),
|
||||
site_admin: z.boolean(),
|
||||
});
|
||||
|
||||
export const licenseSchema = z.object({
|
||||
key: z.string(),
|
||||
name: z.string(),
|
||||
spdx_id: z.string(),
|
||||
url: z.string().nullable(),
|
||||
node_id: z.string(),
|
||||
});
|
||||
|
||||
export const installationLiteSchema = z.object({
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
});
|
||||
|
||||
export const organizationSchema = z.object({
|
||||
login: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
url: z.string(),
|
||||
html_url: z.string().optional(),
|
||||
repos_url: z.string(),
|
||||
events_url: z.string(),
|
||||
hooks_url: z.string(),
|
||||
issues_url: z.string(),
|
||||
members_url: z.string(),
|
||||
public_members_url: z.string(),
|
||||
avatar_url: z.string(),
|
||||
description: z.string().nullable(),
|
||||
});
|
||||
|
||||
export const repositorySchema = z.object({
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
name: z.string(),
|
||||
full_name: z.string(),
|
||||
private: z.boolean(),
|
||||
owner: userSchema,
|
||||
html_url: z.string(),
|
||||
description: z.string().nullable(),
|
||||
fork: z.boolean(),
|
||||
url: z.string(),
|
||||
forks_url: z.string(),
|
||||
keys_url: z.string(),
|
||||
collaborators_url: z.string(),
|
||||
teams_url: z.string(),
|
||||
hooks_url: z.string(),
|
||||
issue_events_url: z.string(),
|
||||
events_url: z.string(),
|
||||
assignees_url: z.string(),
|
||||
branches_url: z.string(),
|
||||
tags_url: z.string(),
|
||||
blobs_url: z.string(),
|
||||
git_tags_url: z.string(),
|
||||
git_refs_url: z.string(),
|
||||
trees_url: z.string(),
|
||||
statuses_url: z.string(),
|
||||
languages_url: z.string(),
|
||||
stargazers_url: z.string(),
|
||||
contributors_url: z.string(),
|
||||
subscribers_url: z.string(),
|
||||
subscription_url: z.string(),
|
||||
commits_url: z.string(),
|
||||
git_commits_url: z.string(),
|
||||
comments_url: z.string(),
|
||||
issue_comment_url: z.string(),
|
||||
contents_url: z.string(),
|
||||
compare_url: z.string(),
|
||||
merges_url: z.string(),
|
||||
archive_url: z.string(),
|
||||
downloads_url: z.string(),
|
||||
issues_url: z.string(),
|
||||
pulls_url: z.string(),
|
||||
milestones_url: z.string(),
|
||||
notifications_url: z.string(),
|
||||
labels_url: z.string(),
|
||||
releases_url: z.string(),
|
||||
deployments_url: z.string(),
|
||||
created_at: z.union([z.number(), z.string()]),
|
||||
updated_at: z.string(),
|
||||
pushed_at: z.union([z.number(), z.string()]).nullable(),
|
||||
git_url: z.string(),
|
||||
ssh_url: z.string(),
|
||||
clone_url: z.string(),
|
||||
svn_url: z.string(),
|
||||
homepage: z.string().nullable(),
|
||||
size: z.number(),
|
||||
stargazers_count: z.number(),
|
||||
watchers_count: z.number(),
|
||||
language: z.string().nullable(),
|
||||
has_issues: z.boolean(),
|
||||
has_projects: z.boolean(),
|
||||
has_downloads: z.boolean(),
|
||||
has_wiki: z.boolean(),
|
||||
has_pages: z.boolean(),
|
||||
forks_count: z.number(),
|
||||
mirror_url: z.string().nullable(),
|
||||
archived: z.boolean(),
|
||||
disabled: z.boolean().optional(),
|
||||
open_issues_count: z.number(),
|
||||
license: licenseSchema.nullable(),
|
||||
forks: z.number(),
|
||||
open_issues: z.number(),
|
||||
watchers: z.number(),
|
||||
stargazers: z.number().optional(),
|
||||
default_branch: z.string(),
|
||||
allow_squash_merge: z.boolean().optional(),
|
||||
allow_merge_commit: z.boolean().optional(),
|
||||
allow_rebase_merge: z.boolean().optional(),
|
||||
allow_auto_merge: z.boolean().optional(),
|
||||
allow_forking: z.boolean().optional(),
|
||||
allow_update_branch: z.boolean().optional(),
|
||||
use_squash_pr_title_as_default: z.boolean().optional(),
|
||||
squash_merge_commit_message: z.string().optional(),
|
||||
squash_merge_commit_title: z.string().optional(),
|
||||
merge_commit_message: z.string().optional(),
|
||||
merge_commit_title: z.string().optional(),
|
||||
is_template: z.boolean(),
|
||||
web_commit_signoff_required: z.boolean(),
|
||||
topics: z.array(z.string()),
|
||||
visibility: z.union([
|
||||
z.literal("public"),
|
||||
z.literal("private"),
|
||||
z.literal("internal"),
|
||||
]),
|
||||
delete_branch_on_merge: z.boolean().optional(),
|
||||
master_branch: z.string().optional(),
|
||||
permissions: z
|
||||
.object({
|
||||
pull: z.boolean(),
|
||||
push: z.boolean(),
|
||||
admin: z.boolean(),
|
||||
maintain: z.boolean().optional(),
|
||||
triage: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
public: z.boolean().optional(),
|
||||
organization: z.string().optional(),
|
||||
});
|
||||
|
||||
export const teamSchema = z.object({
|
||||
name: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
slug: z.string(),
|
||||
description: z.string().nullable(),
|
||||
privacy: z.union([
|
||||
z.literal("open"),
|
||||
z.literal("closed"),
|
||||
z.literal("secret"),
|
||||
]),
|
||||
url: z.string(),
|
||||
html_url: z.string(),
|
||||
members_url: z.string(),
|
||||
repositories_url: z.string(),
|
||||
permission: z.string(),
|
||||
parent: z
|
||||
.object({
|
||||
name: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
slug: z.string(),
|
||||
description: z.string().nullable(),
|
||||
privacy: z.union([
|
||||
z.literal("open"),
|
||||
z.literal("closed"),
|
||||
z.literal("secret"),
|
||||
]),
|
||||
url: z.string(),
|
||||
html_url: z.string(),
|
||||
members_url: z.string(),
|
||||
repositories_url: z.string(),
|
||||
permission: z.string(),
|
||||
})
|
||||
.optional()
|
||||
.nullable(),
|
||||
});
|
||||
|
||||
export const linkSchema = z.object({
|
||||
href: z.string(),
|
||||
});
|
||||
|
||||
export const appSchema = z.object({
|
||||
id: z.number(),
|
||||
slug: z.string().optional(),
|
||||
node_id: z.string(),
|
||||
owner: userSchema,
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
external_url: z.string(),
|
||||
html_url: z.string(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
permissions: z
|
||||
.object({
|
||||
actions: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
administration: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
blocking: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
checks: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
content_references: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
contents: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
deployments: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
discussions: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
emails: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
environments: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
issues: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
keys: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
members: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
merge_queues: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
metadata: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
organization_administration: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
organization_hooks: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
organization_packages: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
organization_plan: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
organization_projects: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
organization_secrets: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
organization_self_hosted_runners: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
organization_user_blocking: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
packages: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
pages: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
pull_requests: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
repository_hooks: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
repository_projects: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
secret_scanning_alerts: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
secrets: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
security_events: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
security_scanning_alert: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
single_file: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
statuses: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
team_discussions: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
vulnerability_alerts: z
|
||||
.union([z.literal("read"), z.literal("write")])
|
||||
.optional(),
|
||||
workflows: z.union([z.literal("read"), z.literal("write")]).optional(),
|
||||
})
|
||||
.optional(),
|
||||
events: z
|
||||
.array(
|
||||
z.union([
|
||||
z.literal("branch_protection_rule"),
|
||||
z.literal("check_run"),
|
||||
z.literal("check_suite"),
|
||||
z.literal("code_scanning_alert"),
|
||||
z.literal("commit_comment"),
|
||||
z.literal("content_reference"),
|
||||
z.literal("create"),
|
||||
z.literal("delete"),
|
||||
z.literal("deployment"),
|
||||
z.literal("deployment_review"),
|
||||
z.literal("deployment_status"),
|
||||
z.literal("deploy_key"),
|
||||
z.literal("discussion"),
|
||||
z.literal("discussion_comment"),
|
||||
z.literal("fork"),
|
||||
z.literal("gollum"),
|
||||
z.literal("issues"),
|
||||
z.literal("issue_comment"),
|
||||
z.literal("label"),
|
||||
z.literal("member"),
|
||||
z.literal("membership"),
|
||||
z.literal("merge_group"),
|
||||
z.literal("merge_queue_entry"),
|
||||
z.literal("milestone"),
|
||||
z.literal("organization"),
|
||||
z.literal("org_block"),
|
||||
z.literal("page_build"),
|
||||
z.literal("project"),
|
||||
z.literal("projects_v2_item"),
|
||||
z.literal("project_card"),
|
||||
z.literal("project_column"),
|
||||
z.literal("public"),
|
||||
z.literal("pull_request"),
|
||||
z.literal("pull_request_review"),
|
||||
z.literal("pull_request_review_comment"),
|
||||
z.literal("push"),
|
||||
z.literal("registry_package"),
|
||||
z.literal("release"),
|
||||
z.literal("repository"),
|
||||
z.literal("repository_dispatch"),
|
||||
z.literal("secret_scanning_alert"),
|
||||
z.literal("secret_scanning_alert_location"),
|
||||
z.literal("security_and_analysis"),
|
||||
z.literal("star"),
|
||||
z.literal("status"),
|
||||
z.literal("team"),
|
||||
z.literal("team_add"),
|
||||
z.literal("watch"),
|
||||
z.literal("workflow_dispatch"),
|
||||
z.literal("workflow_run"),
|
||||
z.literal("workflow_job"),
|
||||
])
|
||||
)
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const reactionsSchema = z.object({
|
||||
url: z.string(),
|
||||
total_count: z.number(),
|
||||
"+1": z.number(),
|
||||
"-1": z.number(),
|
||||
laugh: z.number(),
|
||||
hooray: z.number(),
|
||||
confused: z.number(),
|
||||
heart: z.number(),
|
||||
rocket: z.number(),
|
||||
eyes: z.number(),
|
||||
});
|
||||
|
||||
export const authorAssociationSchema = z.union([
|
||||
z.literal("COLLABORATOR"),
|
||||
z.literal("CONTRIBUTOR"),
|
||||
z.literal("FIRST_TIMER"),
|
||||
z.literal("FIRST_TIME_CONTRIBUTOR"),
|
||||
z.literal("MANNEQUIN"),
|
||||
z.literal("MEMBER"),
|
||||
z.literal("NONE"),
|
||||
z.literal("OWNER"),
|
||||
]);
|
||||
|
||||
export const milestoneSchema = z.object({
|
||||
url: z.string(),
|
||||
html_url: z.string(),
|
||||
labels_url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
number: z.number(),
|
||||
title: z.string(),
|
||||
description: z.string().nullable(),
|
||||
creator: userSchema,
|
||||
open_issues: z.number(),
|
||||
closed_issues: z.number(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
due_on: z.string().nullable(),
|
||||
closed_at: z.string().nullable(),
|
||||
});
|
||||
|
||||
export const labelSchema = z.object({
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
url: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
color: z.string(),
|
||||
default: z.boolean(),
|
||||
});
|
||||
|
||||
export const pullRequestAutoMergeSchema = z.object({
|
||||
enabled_by: userSchema,
|
||||
merge_method: z.union([
|
||||
z.literal("merge"),
|
||||
z.literal("squash"),
|
||||
z.literal("rebase"),
|
||||
]),
|
||||
commit_title: z.string(),
|
||||
commit_message: z.string(),
|
||||
});
|
||||
|
||||
export const simplePullRequestSchema = z.object({
|
||||
url: z.string(),
|
||||
id: z.number(),
|
||||
node_id: z.string(),
|
||||
html_url: z.string(),
|
||||
diff_url: z.string(),
|
||||
patch_url: z.string(),
|
||||
issue_url: z.string(),
|
||||
number: z.number(),
|
||||
state: z.union([z.literal("open"), z.literal("closed")]),
|
||||
locked: z.boolean(),
|
||||
title: z.string(),
|
||||
user: userSchema,
|
||||
body: z.string().nullable(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
closed_at: z.string().nullable(),
|
||||
merged_at: z.string().nullable(),
|
||||
merge_commit_sha: z.string().nullable(),
|
||||
assignee: userSchema.nullable(),
|
||||
assignees: z.array(userSchema),
|
||||
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
|
||||
requested_teams: z.array(teamSchema),
|
||||
labels: z.array(labelSchema),
|
||||
milestone: milestoneSchema.nullable(),
|
||||
draft: z.boolean(),
|
||||
commits_url: z.string(),
|
||||
review_comments_url: z.string(),
|
||||
review_comment_url: z.string(),
|
||||
comments_url: z.string(),
|
||||
statuses_url: z.string(),
|
||||
head: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
base: z.object({
|
||||
label: z.string(),
|
||||
ref: z.string(),
|
||||
sha: z.string(),
|
||||
user: userSchema,
|
||||
repo: repositorySchema,
|
||||
}),
|
||||
_links: z.object({
|
||||
self: linkSchema,
|
||||
html: linkSchema,
|
||||
issue: linkSchema,
|
||||
comments: linkSchema,
|
||||
review_comments: linkSchema,
|
||||
review_comment: linkSchema,
|
||||
commits: linkSchema,
|
||||
statuses: linkSchema,
|
||||
}),
|
||||
author_association: authorAssociationSchema,
|
||||
auto_merge: pullRequestAutoMergeSchema.nullable(),
|
||||
active_lock_reason: z
|
||||
.union([
|
||||
z.literal("resolved"),
|
||||
z.literal("off-topic"),
|
||||
z.literal("too heated"),
|
||||
z.literal("spam"),
|
||||
])
|
||||
.nullable(),
|
||||
});
|
||||
|
||||
export const committerSchema = z.object({
|
||||
name: z.string(),
|
||||
email: z.string().nullable(),
|
||||
date: z.string().optional(),
|
||||
username: z.string().optional(),
|
||||
});
|
||||
|
||||
export const commitSchema = z.object({
|
||||
id: z.string(),
|
||||
tree_id: z.string(),
|
||||
distinct: z.boolean(),
|
||||
message: z.string(),
|
||||
timestamp: z.string(),
|
||||
url: z.string(),
|
||||
author: committerSchema,
|
||||
committer: committerSchema,
|
||||
added: z.array(z.string()),
|
||||
modified: z.array(z.string()),
|
||||
removed: z.array(z.string()),
|
||||
});
|
||||
@@ -362,6 +362,12 @@ export class TriggerClient<TSchema extends z.ZodTypeAny> {
|
||||
return this.#trigger.options
|
||||
.run(eventData, ctx)
|
||||
.then((output) => {
|
||||
this.#logger.log(
|
||||
`Completed workflow '${this.#options.name}', run ${
|
||||
data.id
|
||||
} 🏃`
|
||||
);
|
||||
|
||||
return serverRPC.send("COMPLETE_WORKFLOW_RUN", {
|
||||
runId: data.id,
|
||||
output: JSON.stringify(output),
|
||||
@@ -437,6 +443,7 @@ export class TriggerClient<TSchema extends z.ZodTypeAny> {
|
||||
trigger: this.#trigger.on.metadata,
|
||||
packageVersion: pkg.version,
|
||||
packageName: pkg.name,
|
||||
triggerTTL: this.#options.triggerTTL,
|
||||
});
|
||||
|
||||
if (response?.type === "error") {
|
||||
|
||||
@@ -12,6 +12,13 @@ export type TriggerOptions<TSchema extends z.ZodTypeAny> = {
|
||||
apiKey?: string;
|
||||
endpoint?: string;
|
||||
logLevel?: LogLevel;
|
||||
|
||||
/**
|
||||
* The TTL for the trigger in seconds. If the trigger is not run within this time, it will be aborted. Defaults to 3600 seconds (1 hour).
|
||||
* @type {number}
|
||||
*/
|
||||
triggerTTL?: number;
|
||||
|
||||
run: (event: z.infer<TSchema>, ctx: TriggerContext) => Promise<any>;
|
||||
};
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ importers:
|
||||
clsx: ^1.2.1
|
||||
compression: ^1.7.4
|
||||
cron-parser: ^4.7.1
|
||||
cronstrue: ^2.21.0
|
||||
cross-env: ^7.0.3
|
||||
csstype: ^3.0.10
|
||||
cuid: ^2.1.8
|
||||
@@ -210,6 +211,7 @@ importers:
|
||||
clsx: 1.2.1
|
||||
compression: 1.7.4
|
||||
cron-parser: 4.7.1
|
||||
cronstrue: 2.21.0
|
||||
cross-env: 7.0.3
|
||||
csstype: 3.1.1
|
||||
cuid: 2.1.8
|
||||
@@ -647,7 +649,7 @@ importers:
|
||||
'@urql/core': 3.1.1_graphql@16.6.0
|
||||
debug: 4.3.4
|
||||
graphql: 16.6.0
|
||||
urql: 3.0.3_graphql@16.6.0
|
||||
urql: 3.0.3_onqnqwb3ubg5opvemcqf7c2qhy
|
||||
zod: 3.20.2
|
||||
devDependencies:
|
||||
'@trigger.dev/providers': link:../trigger-providers
|
||||
@@ -3506,7 +3508,6 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
dev: true
|
||||
|
||||
/@cush/relative/1.0.0:
|
||||
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
|
||||
@@ -4116,7 +4117,6 @@ packages:
|
||||
/@jridgewell/resolve-uri/3.1.0:
|
||||
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/set-array/1.1.2:
|
||||
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
|
||||
@@ -4125,7 +4125,6 @@ packages:
|
||||
|
||||
/@jridgewell/sourcemap-codec/1.4.14:
|
||||
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/trace-mapping/0.3.17:
|
||||
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
|
||||
@@ -4139,7 +4138,6 @@ packages:
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.0
|
||||
'@jridgewell/sourcemap-codec': 1.4.14
|
||||
dev: true
|
||||
|
||||
/@jsdevtools/ono/7.1.3:
|
||||
resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
|
||||
@@ -5028,7 +5026,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-darwin-x64/1.3.26:
|
||||
@@ -5037,7 +5034,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm-gnueabihf/1.3.26:
|
||||
@@ -5046,7 +5042,6 @@ packages:
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-gnu/1.3.26:
|
||||
@@ -5055,7 +5050,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-musl/1.3.26:
|
||||
@@ -5064,7 +5058,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-gnu/1.3.26:
|
||||
@@ -5073,7 +5066,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-musl/1.3.26:
|
||||
@@ -5082,7 +5074,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-arm64-msvc/1.3.26:
|
||||
@@ -5091,7 +5082,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-ia32-msvc/1.3.26:
|
||||
@@ -5100,7 +5090,6 @@ packages:
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-x64-msvc/1.3.26:
|
||||
@@ -5109,7 +5098,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core/1.3.26:
|
||||
@@ -5127,7 +5115,6 @@ packages:
|
||||
'@swc/core-win32-arm64-msvc': 1.3.26
|
||||
'@swc/core-win32-ia32-msvc': 1.3.26
|
||||
'@swc/core-win32-x64-msvc': 1.3.26
|
||||
dev: true
|
||||
|
||||
/@swc/helpers/0.4.14:
|
||||
resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==}
|
||||
@@ -5155,7 +5142,7 @@ packages:
|
||||
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1'
|
||||
dependencies:
|
||||
mini-svg-data-uri: 1.4.4
|
||||
tailwindcss: 3.1.8_postcss@8.4.21
|
||||
tailwindcss: 3.1.8_aesdjsunmf4wiehhujt67my7tu
|
||||
|
||||
/@tailwindcss/typography/0.5.9_tailwindcss@3.1.8:
|
||||
resolution: {integrity: sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==}
|
||||
@@ -5166,7 +5153,7 @@ packages:
|
||||
lodash.isplainobject: 4.0.6
|
||||
lodash.merge: 4.6.2
|
||||
postcss-selector-parser: 6.0.10
|
||||
tailwindcss: 3.1.8_postcss@8.4.21
|
||||
tailwindcss: 3.1.8_aesdjsunmf4wiehhujt67my7tu
|
||||
dev: true
|
||||
|
||||
/@tanstack/react-table/8.7.6_biqbaboplfbrettd7655fr4n2y:
|
||||
@@ -5256,19 +5243,15 @@ packages:
|
||||
|
||||
/@tsconfig/node10/1.0.9:
|
||||
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node12/1.0.11:
|
||||
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node14/1.0.3:
|
||||
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node16/1.0.3:
|
||||
resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==}
|
||||
dev: true
|
||||
|
||||
/@types/acorn/4.0.6:
|
||||
resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==}
|
||||
@@ -5932,7 +5915,6 @@ packages:
|
||||
/acorn-walk/8.2.0:
|
||||
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/acorn/7.4.1:
|
||||
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
|
||||
@@ -5943,7 +5925,6 @@ packages:
|
||||
resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/agent-base/6.0.2:
|
||||
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
||||
@@ -6109,7 +6090,6 @@ packages:
|
||||
|
||||
/arg/4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
dev: true
|
||||
|
||||
/arg/5.0.2:
|
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||
@@ -7402,7 +7382,6 @@ packages:
|
||||
|
||||
/create-require/1.1.1:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
dev: true
|
||||
|
||||
/crelt/1.0.5:
|
||||
resolution: {integrity: sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==}
|
||||
@@ -7415,6 +7394,11 @@ packages:
|
||||
luxon: 3.2.1
|
||||
dev: false
|
||||
|
||||
/cronstrue/2.21.0:
|
||||
resolution: {integrity: sha512-YxabE1ZSHA1zJZMPCTSEbc0u4cRRenjqqTgCwJT7OvkspPSvfYFITuPFtsT+VkBuavJtFv2kJXT+mKSnlUJxfg==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/cross-env/7.0.3:
|
||||
resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
|
||||
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
|
||||
@@ -7896,7 +7880,6 @@ packages:
|
||||
/diff/4.0.2:
|
||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
dev: true
|
||||
|
||||
/diff/5.1.0:
|
||||
resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
|
||||
@@ -8479,7 +8462,7 @@ packages:
|
||||
eslint: 8.31.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-import-resolver-typescript: 2.7.1_hnftvkj7qg3s6bbigj4pr6djxy
|
||||
eslint-plugin-import: 2.27.4_2es4x7ly2gmvaoztzzbbx3tgsy
|
||||
eslint-plugin-import: 2.27.4_eslint@8.31.0
|
||||
eslint-plugin-jsx-a11y: 6.7.1_eslint@8.31.0
|
||||
eslint-plugin-react: 7.31.8_eslint@8.31.0
|
||||
eslint-plugin-react-hooks: 4.6.0_eslint@8.31.0
|
||||
@@ -8535,7 +8518,7 @@ packages:
|
||||
dependencies:
|
||||
debug: 4.3.4
|
||||
eslint: 8.31.0
|
||||
eslint-plugin-import: 2.27.4_2es4x7ly2gmvaoztzzbbx3tgsy
|
||||
eslint-plugin-import: 2.27.4_eslint@8.31.0
|
||||
glob: 7.2.3
|
||||
is-glob: 4.0.3
|
||||
resolve: 1.22.1
|
||||
@@ -8564,7 +8547,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-module-utils/2.7.4_co4ldsxivxjwelu6vt6qmibemq:
|
||||
/eslint-module-utils/2.7.4_py7h5widiydke2tta7oabbx7ru:
|
||||
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@@ -8585,11 +8568,9 @@ packages:
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.48.1_iukboom6ndih5an6iafl45j2fe
|
||||
debug: 3.2.7
|
||||
eslint: 8.31.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-import-resolver-typescript: 2.7.1_hnftvkj7qg3s6bbigj4pr6djxy
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@@ -8677,7 +8658,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import/2.27.4_2es4x7ly2gmvaoztzzbbx3tgsy:
|
||||
/eslint-plugin-import/2.27.4_eslint@8.31.0:
|
||||
resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@@ -8687,7 +8668,6 @@ packages:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.48.1_iukboom6ndih5an6iafl45j2fe
|
||||
array-includes: 3.1.6
|
||||
array.prototype.flat: 1.3.1
|
||||
array.prototype.flatmap: 1.3.1
|
||||
@@ -8695,7 +8675,7 @@ packages:
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.31.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-module-utils: 2.7.4_co4ldsxivxjwelu6vt6qmibemq
|
||||
eslint-module-utils: 2.7.4_py7h5widiydke2tta7oabbx7ru
|
||||
has: 1.0.3
|
||||
is-core-module: 2.11.0
|
||||
is-glob: 4.0.3
|
||||
@@ -11577,7 +11557,6 @@ packages:
|
||||
|
||||
/make-error/1.3.6:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: true
|
||||
|
||||
/make-iterator/0.1.1:
|
||||
resolution: {integrity: sha512-s8tbTxYqrfcXYHAPxUecPxgBnWod7yFShdSOWiV17WRM87bBH2mzr24A4tpUDv9SqebaV6JsPApwKXnisMmMBA==}
|
||||
@@ -13224,7 +13203,6 @@ packages:
|
||||
postcss: 8.4.21
|
||||
ts-node: 10.9.1_fodzh64fuekdilycyvke2qmf2e
|
||||
yaml: 1.10.2
|
||||
dev: true
|
||||
|
||||
/postcss-load-config/3.1.4_postcss@8.4.21:
|
||||
resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
|
||||
@@ -13241,6 +13219,7 @@ packages:
|
||||
lilconfig: 2.0.6
|
||||
postcss: 8.4.21
|
||||
yaml: 1.10.2
|
||||
dev: true
|
||||
|
||||
/postcss-nested/5.0.6_postcss@8.4.21:
|
||||
resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==}
|
||||
@@ -15118,7 +15097,6 @@ packages:
|
||||
resolve: 1.22.1
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/tailwindcss/3.1.8_postcss@8.4.21:
|
||||
resolution: {integrity: sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==}
|
||||
@@ -15151,6 +15129,7 @@ packages:
|
||||
resolve: 1.22.1
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/tapable/2.2.1:
|
||||
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
|
||||
@@ -15432,7 +15411,6 @@ packages:
|
||||
typescript: 4.9.4
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
dev: true
|
||||
|
||||
/ts-toolbelt/9.6.0:
|
||||
resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==}
|
||||
@@ -15934,7 +15912,7 @@ packages:
|
||||
prepend-http: 2.0.0
|
||||
dev: true
|
||||
|
||||
/urql/3.0.3_graphql@16.6.0:
|
||||
/urql/3.0.3_onqnqwb3ubg5opvemcqf7c2qhy:
|
||||
resolution: {integrity: sha512-aVUAMRLdc5AOk239DxgXt6ZxTl/fEmjr7oyU5OGo8uvpqu42FkeJErzd2qBzhAQ3DyusoZIbqbBLPlnKo/yy2A==}
|
||||
peerDependencies:
|
||||
graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
|
||||
@@ -15942,6 +15920,7 @@ packages:
|
||||
dependencies:
|
||||
'@urql/core': 3.1.1_graphql@16.6.0
|
||||
graphql: 16.6.0
|
||||
react: 18.2.0
|
||||
wonka: 6.1.2
|
||||
dev: false
|
||||
|
||||
@@ -16027,7 +16006,6 @@ packages:
|
||||
|
||||
/v8-compile-cache-lib/3.0.1:
|
||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||
dev: true
|
||||
|
||||
/v8-to-istanbul/9.0.1:
|
||||
resolution: {integrity: sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==}
|
||||
@@ -16551,7 +16529,6 @@ packages:
|
||||
/yn/3.1.1:
|
||||
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/yocto-queue/0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
|
||||