Added support for delaying delivery when sending custom events

This commit is contained in:
Eric Allam
2023-01-27 10:18:13 +00:00
parent 897724e883
commit 52d21ac84d
15 changed files with 475 additions and 210 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---
Added support for delaying delivery when sending custom events
+146 -4
View File
@@ -31,7 +31,7 @@ curl --request POST \
--header 'Authorization: Bearer <insert_api_key_here>' \ --header 'Authorization: Bearer <insert_api_key_here>' \
--header 'Content-Type: application/json' \ --header 'Content-Type: application/json' \
--data '{ --data '{
"id": "<insert_unique_event_id>", "id": "<optional unique event id>",
"event": { "event": {
"name": "user.created", "name": "user.created",
"payload": { "payload": {
@@ -48,12 +48,154 @@ If you are calling this from inside a workflow, ensure that the first parameter
## Sending events from other workflows ## Sending events from other workflows
It is useful to send events from workflows because you can split your logic into smaller chunks and reuse them. It is useful to send events from workflows because you can split your logic into smaller chunks and reuse them. The below example shows how a scheduled workflow delegates the work via sending a custom event:
## Writing a workflow that is triggered by an event <CodeGroup>
You should read [the documentation on custom events](/triggers/custom-events) to learn how to write a workflow that is triggered by an event. ```ts check-scheduler.ts
new Trigger({
id: "check-scheduler",
name: "Check Scheduler",
on: scheduleEvent({ rateOf: { minutes: 10 } }),
run: async (event, context) => {
await context.sendEvent("health.check trigger.dev", {
name: "health.check",
payload: {
url: "https://trigger.dev",
host: "trigger.dev",
},
});
await context.sendEvent("health.check docs.trigger.dev", {
name: "health.check",
payload: {
url: "https://docs.trigger.dev",
host: "docs.trigger.dev",
},
});
await context.sendEvent("health.check app.trigger.dev", {
name: "health.check",
payload: {
url: "https://app.trigger.dev/healthcheck",
host: "app.trigger.dev",
},
});
},
}).listen();
``` ```
```ts health-check.ts
export const healthCheck = new Trigger({
id: "health-check",
name: "Health Check",
on: customEvent({
name: "health.check",
schema: z.object({
url: z.string().url(),
host: z.string(),
}),
}),
run: async (event, context) => {
const response = await context.fetch("fetch site", event.url, {
method: "GET",
retry: {
enabled: false,
},
});
if (response.ok) {
await context.logger.info(`${event.host} is up!`);
return;
}
await slack.postMessage("Site is down", {
channelName: "health-checks",
text: `${event.host} is down: ${response.status}`,
});
},
}).listen();
```
</CodeGroup>
## Delaying event delivery
Through both our Node.js SDK and our HTTP API, you can delay the delivery of an event. This is useful if you want to send an event to trigger a workflow, but you want to wait for a certain amount of time before the event is delivered.
Using the health check example above, we can delay the delivery of the `health.check` event in various ways:
```ts
new Trigger({
id: "check-scheduler",
name: "Check Scheduler",
on: scheduleEvent({ rateOf: { minutes: 10 } }),
run: async (event, context) => {
await context.sendEvent("health.check trigger.dev", {
name: "health.check",
payload: {
url: "https://trigger.dev",
host: "trigger.dev",
},
delay: { until: new Date(Date.now() + 1000 * 60 * 5) }, // Delay until a specific date
});
await context.sendEvent("health.check docs.trigger.dev", {
name: "health.check",
payload: {
url: "https://docs.trigger.dev",
host: "docs.trigger.dev",
},
delay: { minutes: 5 }, // Delay for a specific amount of time
});
await context.sendEvent("health.check app.trigger.dev", {
name: "health.check",
payload: {
url: "https://app.trigger.dev/healthcheck",
host: "app.trigger.dev",
},
delay: { seconds: 30 }, // Delay for a specific amount of time
});
},
}).listen();
```
<Note>
When sending events in the context of a workflow run, adding a delay DOES NOT
add a delay to the workflow run, as sending a custom event is a
fire-and-forget action.
</Note>
You can add delays via the HTTP API by adding a `delay` object to the event:
```bash
curl --request POST \
--url https://app.trigger.dev/api/v1/events \
--header 'Authorization: Bearer <insert_api_key_here>' \
--header 'Content-Type: application/json' \
--data '{
"id": "<optional unique event id>",
"event": {
"name": "user.created",
"payload": {
"userId": "123456"
},
"delay": {
"seconds": 30
}
}
}'
```
## Event deduplication
When sending events, you can specify an `id` for the event. If you send an event with the same `id` multiple times, only the first event will be delivered. This is useful if you want to ensure that an event is only delivered once, even if you send it multiple times.
```ts
sendEvent({
id: "my-event-id",
name: "my-event",
payload: { foo: "bar" },
});
``` ```
+2 -1
View File
@@ -111,7 +111,8 @@
"reference/trigger", "reference/trigger",
"reference/custom-event", "reference/custom-event",
"reference/webhook-event", "reference/webhook-event",
"reference/schedule-event" "reference/schedule-event",
"reference/send-event"
] ]
}, },
{ {
+97
View File
@@ -0,0 +1,97 @@
---
title: "sendEvent"
sidebarTitle: "sendEvent"
description: "Send a custom event to Trigger, from inside or outside of a workflow."
---
## Usage
```ts
import { Trigger, customEvent } from "@trigger.dev/sdk";
new Trigger({
id: "usage",
name: "usage",
on: customEvent({
name: "user.created",
schema: z.any(),
}),
run: async (event, ctx) => {
await ctx.sendEvent("Sending context user.created event", {
name: "user.created",
payload: {
id: "1234_abc",
},
});
},
}).listen();
```
You can also use `sendEvent` by importing it from `@trigger.dev/sdk`:
```ts
import { sendEvent } from "@trigger.dev/sdk";
await sendEvent("Sending context user.created event", {
name: "user.created",
payload: {
id: "1234_abc",
},
});
```
<Note>
If calling `sendEvent` from outside of a workflow run, it will make an HTTP
API request to app.trigger.dev to send the event. Make sure you set the
`TRIGGER_API_KEY` environment variable if you will be using it this way.
</Note>
## Parameters
<ParamField path="key" type="string" required={true}>
A unique key for the event in the context of a workflow run. Please see the
[Keys and Resumability](/guides/resumability) guide for more info.
</ParamField>
<ParamField path="event" type="object" required={true}>
<Expandable title="properties" defaultOpen={true}>
<ParamField path="id" type="string" required={false}>
An optional unique ID for the event. If not provided, one will be
generated automatically (using `clid`). Set this field to perform event
deduplication.
</ParamField>
<ParamField path="name" type="string" required={true}>
The name of the event. This is the name you set when creating the
`customEvent` trigger.
</ParamField>
<ParamField path="payload" type="json object" required={true}>
The payload of the event.
</ParamField>
<ParamField path="timestamp" type="ISO8601 string" required={false}>
An optional timestamp for the event. If not provided, one will be generated. Must be in ISO 8601 format (e.g. `new Date().toISOString()`)
</ParamField>
<ParamField path="context" type="json object" required={false}>
An optional context object for the event. This can be used to pass
additional information about the event, such as the user who triggered
it. Note that this is not currently exposed to the workflow (coming soon).
</ParamField>
<ParamField path="delay" type="object" required={false}>
An optional delay object for the event. This can be used to delay the
event by a certain amount of time. Use one of the following options:
- `{ seconds: number }` - delay the event by a certain number of seconds
- `{ minutes: number }` - delay the event by a certain number of minutes
- `{ hours: number }` - delay the event by a certain number of hours
- `{ days: number }` - delay the event by a certain number of days
- `{ until: Date }` - delay the event until a certain date
See the [Delaying Event Delivery](/functions/send-event#delaying-event-delivery) docs for more info.
</ParamField>
</Expandable>
</ParamField>
+11 -17
View File
@@ -1,14 +1,16 @@
import type { WorkflowRun, WorkflowRunStep } from ".prisma/client"; import type {
import type { WorkflowRunStatus } from ".prisma/client"; WorkflowRun,
WorkflowRunStatus,
WorkflowRunStep,
} from ".prisma/client";
import type { import type {
CustomEventSchema, CustomEventSchema,
ErrorSchema, ErrorSchema,
LogMessageSchema, LogMessageSchema,
} from "@trigger.dev/common-schemas"; } from "@trigger.dev/common-schemas";
import { ulid } from "ulid";
import type { z } from "zod"; import type { z } from "zod";
import { prisma } from "~/db.server"; import { prisma } from "~/db.server";
import { IngestEvent } from "~/services/events/ingest.server"; import { IngestCustomEvent } from "~/services/events/ingestCustomEvent.server";
import { createStepOnce } from "./workflowRunStep.server"; import { createStepOnce } from "./workflowRunStep.server";
export type { WorkflowRun, WorkflowRunStep, WorkflowRunStatus }; export type { WorkflowRun, WorkflowRunStep, WorkflowRunStatus };
@@ -160,20 +162,12 @@ export async function triggerEventInRun(
return; return;
} }
const ingestService = new IngestEvent(); const ingestService = new IngestCustomEvent();
await ingestService.call( await ingestService.call({
{ apiKey: workflowRun.environment.apiKey,
id: ulid(), event,
name: event.name, });
type: "CUSTOM_EVENT",
service: "trigger",
payload: event.payload,
context: event.context,
apiKey: workflowRun.environment.apiKey,
},
workflowRun.environment.organization
);
await prisma.workflowRunStep.update({ await prisma.workflowRunStep.update({
where: { id: step.step.id }, where: { id: step.step.id },
@@ -9,10 +9,10 @@ import {
} from "@heroicons/react/24/outline"; } from "@heroicons/react/24/outline";
import { import {
ArrowPathRoundedSquareIcon, ArrowPathRoundedSquareIcon,
ChatBubbleOvalLeftEllipsisIcon,
CheckCircleIcon, CheckCircleIcon,
ExclamationCircleIcon, ExclamationCircleIcon,
ExclamationTriangleIcon, ExclamationTriangleIcon,
ChatBubbleOvalLeftEllipsisIcon,
} from "@heroicons/react/24/solid"; } from "@heroicons/react/24/solid";
import { useFetcher } from "@remix-run/react"; import { useFetcher } from "@remix-run/react";
import type { LoaderArgs } from "@remix-run/server-runtime"; import type { LoaderArgs } from "@remix-run/server-runtime";
@@ -623,6 +623,40 @@ function CustomEventStep({ event }: { event: StepType<Step, "CUSTOM_EVENT"> }) {
<Header2 size="small" className="text-slate-300 mb-2"> <Header2 size="small" className="text-slate-300 mb-2">
{event.input.name} {event.input.name}
</Header2> </Header2>
{"delay" in event.input && event.input.delay && (
<>
<Body size="extra-small" className={workflowNodeUppercaseClasses}>
Delay
</Body>
<Body size="small" className="text-slate-300 mb-2">
{"seconds" in event.input.delay ? (
<>
{event.input.delay.seconds}{" "}
{event.input.delay.seconds > 1 ? "seconds" : "second"}
</>
) : "minutes" in event.input.delay ? (
<>
{event.input.delay.minutes}{" "}
{event.input.delay.minutes > 1 ? "minutes" : "minute"}
</>
) : "hours" in event.input.delay ? (
<>
{event.input.delay.hours}{" "}
{event.input.delay.hours > 1 ? "hours" : "hour"}
</>
) : "days" in event.input.delay ? (
<>
{event.input.delay.days}{" "}
{event.input.delay.days > 1 ? "days" : "day"}
</>
) : "until" in event.input.delay ? (
<>Until {event.input.delay.until}</>
) : (
<></>
)}
</Body>
</>
)}
<Header4>Payload</Header4> <Header4>Payload</Header4>
<CodeBlock code={stringifyCode(event.input.payload)} align="top" /> <CodeBlock code={stringifyCode(event.input.payload)} align="top" />
{event.input.context && ( {event.input.context && (
+8 -15
View File
@@ -3,7 +3,7 @@ import { json } from "@remix-run/server-runtime";
import { CustomEventSchema } from "@trigger.dev/common-schemas"; import { CustomEventSchema } from "@trigger.dev/common-schemas";
import { z } from "zod"; import { z } from "zod";
import { authenticateApiRequest } from "~/services/apiAuth.server"; import { authenticateApiRequest } from "~/services/apiAuth.server";
import { IngestEvent } from "~/services/events/ingest.server"; import { IngestCustomEvent } from "~/services/events/ingestCustomEvent.server";
const EventBodySchema = z.object({ const EventBodySchema = z.object({
id: z.string(), id: z.string(),
@@ -32,20 +32,13 @@ export async function action({ request }: ActionArgs) {
return json({ error: eventBody.error.message }, { status: 400 }); return json({ error: eventBody.error.message }, { status: 400 });
} }
const service = new IngestEvent(); const service = new IngestCustomEvent();
const result = await service.call( await service.call({
{ id: eventBody.data.id,
id: eventBody.data.id, event: eventBody.data.event,
name: eventBody.data.event.name, apiKey: authenticatedEnv.apiKey,
type: "CUSTOM_EVENT", });
service: "trigger",
payload: eventBody.data.event.payload,
context: eventBody.data.event.context,
apiKey: authenticatedEnv.apiKey,
},
authenticatedEnv.organization
);
return json(result.data); return { status: 200 };
} }
@@ -13,6 +13,7 @@ import {
import { getWorkflowFromSlugs } from "~/models/workflow.server"; import { getWorkflowFromSlugs } from "~/models/workflow.server";
import { CreateWorkflowTestRun } from "~/services/runs/createTestRun.server"; import { CreateWorkflowTestRun } from "~/services/runs/createTestRun.server";
import { requireUserId } from "~/services/session.server"; import { requireUserId } from "~/services/session.server";
import { safeJsonParse } from "~/utils/json";
const requestSchema = z.object({ const requestSchema = z.object({
eventName: z.string(), eventName: z.string(),
@@ -39,7 +40,15 @@ export const action = async ({ request, params }: ActionArgs) => {
const body = Object.fromEntries(formData.entries()); const body = Object.fromEntries(formData.entries());
const { eventName, payload, source } = requestSchema.parse(body); const { eventName, payload, source } = requestSchema.parse(body);
const jsonPayload = JSON.parse(payload); const jsonPayload = safeJsonParse(payload);
if (!jsonPayload) {
return redirectWithErrorMessage(
redirectUriForSource(source, organizationSlug, workflowSlug),
request,
"Invalid JSON payload"
);
}
const workflow = await getWorkflowFromSlugs({ const workflow = await getWorkflowFromSlugs({
userId, userId,
@@ -98,6 +107,19 @@ export const action = async ({ request, params }: ActionArgs) => {
} }
}; };
function redirectUriForSource(
source: "rerun" | "test",
organizationSlug: string,
workflowSlug: string,
runId?: string
) {
if (source === "rerun") {
return `/orgs/${organizationSlug}/workflows/${workflowSlug}/runs/${runId}`;
} else {
return `/orgs/${organizationSlug}/workflows/${workflowSlug}/test`;
}
}
function errorMessageForSource(source: "rerun" | "test") { function errorMessageForSource(source: "rerun" | "test") {
if (source === "rerun") { if (source === "rerun") {
return "Unable to rerun this workflow. Please contact help@trigger.dev for assistance."; return "Unable to rerun this workflow. Please contact help@trigger.dev for assistance.";
@@ -0,0 +1,60 @@
import type { CustomEventSchema } from "@trigger.dev/common-schemas";
import type { PublishOptions } from "internal-platform";
import { ulid } from "ulid";
import type { z } from "zod";
import { taskQueue } from "~/services/messageBroker.server";
import { omit } from "~/utils/objects";
import { IngestEvent } from "./ingest.server";
export type IngestCustomEventOptions = {
id?: string;
apiKey: string;
event: z.infer<typeof CustomEventSchema>;
isTest?: boolean;
};
export class IngestCustomEvent {
public async call(options: IngestCustomEventOptions) {
if (options.event.delay) {
const deliveryOptions: PublishOptions =
"until" in options.event.delay
? { deliverAt: new Date(options.event.delay.until).getTime() }
: "seconds" in options.event.delay
? { deliverAfter: options.event.delay.seconds * 1000 }
: "minutes" in options.event.delay
? { deliverAfter: options.event.delay.minutes * 60 * 1000 }
: "hours" in options.event.delay
? { deliverAfter: options.event.delay.hours * 60 * 60 * 1000 }
: "days" in options.event.delay
? { deliverAfter: options.event.delay.days * 60 * 60 * 24 * 1000 }
: { deliverAfter: 0 };
await taskQueue.publish(
"INGEST_DELAYED_EVENT",
{
id: options.id,
apiKey: options.apiKey,
event: omit(options.event, ["delay"]),
},
{},
deliveryOptions
);
return;
}
const ingestService = new IngestEvent();
await ingestService.call({
id: options.id ?? ulid(),
name: options.event.name,
type: "CUSTOM_EVENT",
service: "trigger",
payload: options.event.payload,
context: options.event.context,
timestamp: options.event.timestamp,
apiKey: options.apiKey,
isTest: options.isTest,
});
}
}
@@ -35,7 +35,7 @@ import { InitiateDelay } from "./delays/initiateDelay.server";
import { ResolveDelay } from "./delays/resolveDelay.server"; import { ResolveDelay } from "./delays/resolveDelay.server";
import { sendEmail } from "./email.server"; import { sendEmail } from "./email.server";
import { DispatchEvent } from "./events/dispatch.server"; import { DispatchEvent } from "./events/dispatch.server";
import { IngestEvent } from "./events/ingest.server"; import { IngestCustomEvent } from "./events/ingestCustomEvent.server";
import { HandleNewServiceConnection } from "./externalServices/handleNewConnection.server"; import { HandleNewServiceConnection } from "./externalServices/handleNewConnection.server";
import { RegisterExternalSource } from "./externalSources/registerExternalSource.server"; import { RegisterExternalSource } from "./externalSources/registerExternalSource.server";
import { CreateFetchRequest } from "./fetches/createFetchRequest.server"; import { CreateFetchRequest } from "./fetches/createFetchRequest.server";
@@ -51,6 +51,7 @@ import { WorkflowRunDisconnected } from "./runs/runDisconnected.server";
import { WorkflowRunTriggerTimeout } from "./runs/runTriggerTimeout.server"; import { WorkflowRunTriggerTimeout } from "./runs/runTriggerTimeout.server";
import { DeliverScheduledEvent } from "./scheduler/deliverScheduledEvent.server"; import { DeliverScheduledEvent } from "./scheduler/deliverScheduledEvent.server";
import { RegisterSchedulerSource } from "./scheduler/registerSchedulerSource.server"; import { RegisterSchedulerSource } from "./scheduler/registerSchedulerSource.server";
import { omit } from "~/utils/objects";
let pulsarClient: PulsarClient; let pulsarClient: PulsarClient;
let triggerPublisher: ZodPublisher<TriggerCatalog>; let triggerPublisher: ZodPublisher<TriggerCatalog>;
@@ -374,6 +375,14 @@ const taskQueueCatalog = {
data: z.object({ id: z.string() }), data: z.object({ id: z.string() }),
properties: z.object({}), properties: z.object({}),
}, },
INGEST_DELAYED_EVENT: {
data: z.object({
id: z.string().optional(),
apiKey: z.string(),
event: CustomEventSchema.omit({ delay: true }),
}),
properties: z.object({}),
},
TRIGGER_WORKFLOW_RUN: { TRIGGER_WORKFLOW_RUN: {
data: z.object({ id: z.string() }), data: z.object({ id: z.string() }),
properties: z.object({}), properties: z.object({}),
@@ -646,6 +655,17 @@ function createTaskQueue() {
return true; return true;
}, },
INGEST_DELAYED_EVENT: async (id, data, properties, attributes) => {
if (attributes.redeliveryCount >= 4) {
return true;
}
const ingestService = new IngestCustomEvent();
await ingestService.call(data);
return true;
},
TRIGGER_WORKFLOW_RUN: async (id, data, properties) => { TRIGGER_WORKFLOW_RUN: async (id, data, properties) => {
const run = await findWorklowRunById(data.id); const run = await findWorklowRunById(data.id);
@@ -690,19 +710,19 @@ function createTaskQueue() {
return true; return true;
} }
const service = new IngestEvent(); if (!env.INTERNAL_TRIGGER_API_KEY) {
return true;
}
const result = await service.call({ const service = new IngestCustomEvent();
await service.call({
id: data.id, id: data.id,
name: data.name, event: omit(data, ["id"]),
type: "CUSTOM_EVENT",
service: "trigger",
payload: data.payload,
context: data.context,
apiKey: env.INTERNAL_TRIGGER_API_KEY, apiKey: env.INTERNAL_TRIGGER_API_KEY,
}); });
return result.status === "success"; return true;
}, },
}, },
}); });
+7
View File
@@ -0,0 +1,7 @@
export function safeJsonParse(json: string): unknown {
try {
return JSON.parse(json);
} catch (e) {
return null;
}
}
+14
View File
@@ -0,0 +1,14 @@
export function omit<T extends Record<string, unknown>, K extends keyof T>(
obj: T,
keys: K[]
): Omit<T, K> {
const result: any = {};
for (const key of Object.keys(obj)) {
if (!keys.includes(key as K)) {
result[key] = obj[key];
}
}
return result;
}
+20
View File
@@ -23,11 +23,13 @@ const trigger = new Trigger({
await ctx.sendEvent("start-fire", { await ctx.sendEvent("start-fire", {
name: "smoke.test", name: "smoke.test",
payload: { baz: "banana" }, payload: { baz: "banana" },
delay: { until: new Date(Date.now() + 1000 * 60) },
}); });
await sendEvent("start-fire-2", { await sendEvent("start-fire-2", {
name: "smoke.test2", name: "smoke.test2",
payload: { baz: "banana2" }, payload: { baz: "banana2" },
delay: { minutes: 1 },
}); });
return { foo: "bar" }; return { foo: "bar" };
@@ -36,6 +38,24 @@ const trigger = new Trigger({
trigger.listen(); trigger.listen();
new Trigger({
id: "smoke-test",
name: "Smoke Test",
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: customEvent({
name: "smoke.test",
schema: z.object({ baz: z.string() }),
}),
run: async (event, ctx) => {
await ctx.logger.info("Inside the smoke test workflow, received event", {
event,
myDate: new Date(),
});
},
}).listen();
new Trigger({ new Trigger({
id: "log-tests", id: "log-tests",
name: "My logs", name: "My logs",
+18
View File
@@ -6,6 +6,15 @@ export const CustomEventSchema = z.object({
payload: JsonSchema, payload: JsonSchema,
context: JsonSchema.optional(), context: JsonSchema.optional(),
timestamp: z.string().datetime().optional(), timestamp: z.string().datetime().optional(),
delay: z
.union([
z.object({ seconds: z.number().int() }),
z.object({ minutes: z.number().int() }),
z.object({ hours: z.number().int() }),
z.object({ days: z.number().int() }),
z.object({ until: z.string().datetime() }),
])
.optional(),
}); });
export const SerializableCustomEventSchema = z.object({ export const SerializableCustomEventSchema = z.object({
@@ -13,6 +22,15 @@ export const SerializableCustomEventSchema = z.object({
payload: SerializableJsonSchema, payload: SerializableJsonSchema,
context: SerializableJsonSchema.optional(), context: SerializableJsonSchema.optional(),
timestamp: z.string().datetime().optional(), timestamp: z.string().datetime().optional(),
delay: z
.union([
z.object({ seconds: z.number().int() }),
z.object({ minutes: z.number().int() }),
z.object({ hours: z.number().int() }),
z.object({ days: z.number().int() }),
z.object({ until: z.date() }),
])
.optional(),
}); });
const EventMatcherSchema = z.union([ const EventMatcherSchema = z.union([
-162
View File
@@ -35,33 +35,6 @@ importers:
devDependencies: devDependencies:
mintlify: 2.0.16 mintlify: 2.0.16
apps/internal-triggers:
specifiers:
'@trigger.dev/integrations': ^0.1.13
'@trigger.dev/sdk': ^0.2.10
'@trigger.dev/tsconfig': workspace:*
'@types/node': '16'
'@types/pg': ^8.6.6
dotenv: ^16.0.3
pg: ^8.8.0
rimraf: ^3.0.2
tsup: ^6.5.0
typescript: ^4.9.4
zod: ^3.20.2
dependencies:
'@trigger.dev/integrations': 0.1.13
'@trigger.dev/sdk': 0.2.10
pg: 8.8.0
zod: 3.20.2
devDependencies:
'@trigger.dev/tsconfig': link:../../config-packages/tsconfig
'@types/node': 16.18.11
'@types/pg': 8.6.6
dotenv: 16.0.3
rimraf: 3.0.2
tsup: 6.5.0_typescript@4.9.4
typescript: 4.9.4
apps/webapp: apps/webapp:
specifiers: specifiers:
'@aws-sdk/client-s3': ^3.186.0 '@aws-sdk/client-s3': ^3.186.0
@@ -5412,48 +5385,6 @@ packages:
engines: {node: '>= 6'} engines: {node: '>= 6'}
dev: true dev: true
/@trigger.dev/integrations/0.1.13:
resolution: {integrity: sha512-2CfQNGqdC82om8Zr+PAdZZWov5SPAAAuVGV39d/MTNFLHhJZmJx47nbc5nnT/ujPSkoRrvOolwl93rVeceYoYA==}
dependencies:
'@react-email/render': 0.0.3
'@trigger.dev/providers': 0.1.7
'@trigger.dev/sdk': 0.2.10
zod: 3.20.2
transitivePeerDependencies:
- bufferutil
- encoding
- react
- supports-color
- utf-8-validate
dev: false
/@trigger.dev/providers/0.1.7:
resolution: {integrity: sha512-wy7bh/bOGNgYbpUOJz59BkFU/0e3U0p7/5rClYY52QgAXZ9Z6c4JfocCqmYRxh+/Lb18N/wUd+vo5V9YfoyeIQ==}
dependencies:
'@shopify/admin-graphql-api-utilities': 2.0.1
tiny-invariant: 1.3.1
zod: 3.20.2
dev: false
/@trigger.dev/sdk/0.2.10:
resolution: {integrity: sha512-768mZmXi2iLgUfRIKOlpU3q9wRF6anhSnKoToJnRRzyAX3o6Kw5GkBXyM2QVuB5rt6psgbD+M4RKDaTnLpn/wQ==}
dependencies:
debug: 4.3.4
evt: 2.4.13
node-fetch: 2.6.7
slug: 6.1.0
ulid: 2.3.0
uuid: 9.0.0
ws: 8.12.0
zod: 3.20.2
zod-error: 1.1.0
transitivePeerDependencies:
- bufferutil
- encoding
- supports-color
- utf-8-validate
dev: false
/@tsconfig/node10/1.0.9: /@tsconfig/node10/1.0.9:
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
@@ -5724,14 +5655,6 @@ packages:
/@types/normalize-package-data/2.4.1: /@types/normalize-package-data/2.4.1:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
/@types/pg/8.6.6:
resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==}
dependencies:
'@types/node': 18.11.18
pg-protocol: 1.5.0
pg-types: 2.2.0
dev: true
/@types/prismjs/1.26.0: /@types/prismjs/1.26.0:
resolution: {integrity: sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==} resolution: {integrity: sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==}
dev: true dev: true
@@ -6837,11 +6760,6 @@ packages:
resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
/buffer-writer/2.0.0:
resolution: {integrity: sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==}
engines: {node: '>=4'}
dev: false
/buffer/5.7.1: /buffer/5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
dependencies: dependencies:
@@ -13195,10 +13113,6 @@ packages:
semver: 6.3.0 semver: 6.3.0
dev: true dev: true
/packet-reader/1.0.0:
resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==}
dev: false
/pako/0.2.9: /pako/0.2.9:
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
dev: true dev: true
@@ -13357,59 +13271,6 @@ packages:
is-reference: 3.0.1 is-reference: 3.0.1
dev: true dev: true
/pg-connection-string/2.5.0:
resolution: {integrity: sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==}
dev: false
/pg-int8/1.0.1:
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
engines: {node: '>=4.0.0'}
/pg-pool/3.5.2_pg@8.8.0:
resolution: {integrity: sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==}
peerDependencies:
pg: '>=8.0'
dependencies:
pg: 8.8.0
dev: false
/pg-protocol/1.5.0:
resolution: {integrity: sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==}
/pg-types/2.2.0:
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
engines: {node: '>=4'}
dependencies:
pg-int8: 1.0.1
postgres-array: 2.0.0
postgres-bytea: 1.0.0
postgres-date: 1.0.7
postgres-interval: 1.2.0
/pg/8.8.0:
resolution: {integrity: sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==}
engines: {node: '>= 8.0.0'}
peerDependencies:
pg-native: '>=3.0.1'
peerDependenciesMeta:
pg-native:
optional: true
dependencies:
buffer-writer: 2.0.0
packet-reader: 1.0.0
pg-connection-string: 2.5.0
pg-pool: 3.5.2_pg@8.8.0
pg-protocol: 1.5.0
pg-types: 2.2.0
pgpass: 1.0.5
dev: false
/pgpass/1.0.5:
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
dependencies:
split2: 4.1.0
dev: false
/picocolors/1.0.0: /picocolors/1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
@@ -13563,24 +13424,6 @@ packages:
picocolors: 1.0.0 picocolors: 1.0.0
source-map-js: 1.0.2 source-map-js: 1.0.2
/postgres-array/2.0.0:
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
engines: {node: '>=4'}
/postgres-bytea/1.0.0:
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
engines: {node: '>=0.10.0'}
/postgres-date/1.0.7:
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
engines: {node: '>=0.10.0'}
/postgres-interval/1.2.0:
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
engines: {node: '>=0.10.0'}
dependencies:
xtend: 4.0.2
/posthog-js/1.39.4: /posthog-js/1.39.4:
resolution: {integrity: sha512-Elpf1gwyuObueXi89iH+9pP+WhpkiivP8Qwej4RzOLwSTa7Floaa4rgAw7rnCnX1PtRoJ3F0kqb6q9T+aZjRiA==} resolution: {integrity: sha512-Elpf1gwyuObueXi89iH+9pP+WhpkiivP8Qwej4RzOLwSTa7Floaa4rgAw7rnCnX1PtRoJ3F0kqb6q9T+aZjRiA==}
dependencies: dependencies:
@@ -15112,11 +14955,6 @@ packages:
through: 2.3.8 through: 2.3.8
dev: true dev: true
/split2/4.1.0:
resolution: {integrity: sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==}
engines: {node: '>= 10.x'}
dev: false
/sprintf-js/1.0.3: /sprintf-js/1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}