Add support for webhookEvent, a manual webhook trigger
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@trigger.dev/integrations": patch
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Added support for webhookEvent trigger
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
@@ -103,6 +103,14 @@
|
||||
"guides/event-driven"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Reference",
|
||||
"pages": [
|
||||
"reference/event-filters",
|
||||
"reference/custom-event",
|
||||
"reference/webhook-event"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Webhook Catalog",
|
||||
"pages": [
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "customEvent Trigger"
|
||||
sidebarTitle: "customEvent"
|
||||
description: "Trigger a workflow when a custom event is received."
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
new Trigger({
|
||||
id: "user-created-notify-slack",
|
||||
name: "User Created - Notify Slack",
|
||||
on: customEvent({
|
||||
name: "user.created",
|
||||
schema: z.object({ id: z.string(), admin: z.boolean() }),
|
||||
filter: {
|
||||
admin: [false],
|
||||
},
|
||||
}),
|
||||
run: async (event, ctx) => {},
|
||||
}).listen();
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
<ParamField path="name" type="string" required={true}>
|
||||
The name of the custom event to listen for.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="filter" type="object" required={false}>
|
||||
An event filter to apply to the custom event payload. See the [event filter
|
||||
documentation](/reference/event-filters) for more information.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="schema" type="Zod Schema" required={true}>
|
||||
A Zod schema to validate the webhook event payload against. See our [Zod
|
||||
guide](/guides/zod) for more information.
|
||||
</ParamField>
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "Event Filters"
|
||||
sidebarTitle: "Event Filters"
|
||||
description: "Event filters are used to filter events based on their attributes."
|
||||
---
|
||||
|
||||
Event filters are used to filter events based on their attributes in the [`customEvent`](/reference/custom-event) and [`webhookEvent`](/reference/webhook-event) triggers.
|
||||
|
||||
They are declarative pattern-matching rules, modeled after [AWS EventBridge patterns](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html).
|
||||
|
||||
Given the following custom event payload:
|
||||
|
||||
```json
|
||||
{
|
||||
{
|
||||
"uid": "jexAgaeJFJsrGfans1pxqm",
|
||||
"type": "15 Min Meeting",
|
||||
"price": 0,
|
||||
"title": "15 Min Meeting between Eric Allam and John Doe",
|
||||
"length": 15,
|
||||
"status": "ACCEPTED",
|
||||
"endTime": "2023-01-25T16:00:00Z",
|
||||
"bookingId": 198052,
|
||||
"organizer": {
|
||||
"id": 32794,
|
||||
"name": "Eric Allam",
|
||||
"email": "eric@trigger.dev",
|
||||
"language": { "locale": "en" },
|
||||
"timeZone": "Europe/London"
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The following event filter would match the event:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": ["15 Min Meeting"],
|
||||
"status": ["ACCEPTED", "REJECTED"],
|
||||
"organizer": {
|
||||
"name": ["Eric Allam"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For an event pattern to match an event, the event must contain all the field names listed in the event pattern. The field names must also appear in the event with the same nesting structure.
|
||||
|
||||
The value of each field name in the event pattern must be an array of strings, numbers, or booleans. The event pattern matches the event if the value of the field name in the event is equal to any of the values in the array.
|
||||
|
||||
Effectively, each array is an OR condition, and the entire event pattern is an AND condition.
|
||||
|
||||
So the above event filter will match because `status == "ACCEPTED"`, and it would also match if `status == "REJECTED"`.
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: "webhookEvent Trigger"
|
||||
sidebarTitle: "webhookEvent"
|
||||
description: "Trigger a workflow when a webhook event is received"
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
new Trigger({
|
||||
id: "caldotcom-to-slack",
|
||||
name: "Cal.com To Slack",
|
||||
on: webhookEvent({
|
||||
service: "cal.com",
|
||||
eventName: "BOOKING_CREATED",
|
||||
filter: {
|
||||
triggerEvent: ["BOOKING_CREATED"],
|
||||
},
|
||||
schema: z.any(),
|
||||
verifyPayload: {
|
||||
enabled: true,
|
||||
header: "X-Cal-Signature-256",
|
||||
},
|
||||
}),
|
||||
run: async (event, ctx) => {},
|
||||
}).listen();
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
<ParamField path="service" type="string" required={true}>
|
||||
The name of the service that will be sending the webhook event.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="name" type="string" required={true}>
|
||||
The name of the event that will be sent by the service.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="filter" type="object" required={false}>
|
||||
An event filter to apply to the webhook event. See the [event filter
|
||||
documentation](/reference/event-filters) for more information.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="schema" type="Zod Schema" required={true}>
|
||||
A Zod schema to validate the webhook event payload against. See our [Zod
|
||||
guide](/guides/zod) for more information.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="verifyPayload" type="object" required={false}>
|
||||
Verify the payload of the webhook event. Currently only supports sha256 HMAC
|
||||
signatures.
|
||||
<Expandable title="properties">
|
||||
<ParamField path="enabled" type="boolean" required={false}>
|
||||
Whether to verify the payload of the webhook event. Defaults to `false`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="header" type="string" required={false}>
|
||||
The name of the header that contains the signature to verify the payload
|
||||
against. e.g. `X-Webhook-Signature`.
|
||||
</ParamField>
|
||||
|
||||
</Expandable>
|
||||
</ParamField>
|
||||
@@ -4,7 +4,7 @@ sidebarTitle: "Webhooks"
|
||||
description: "Webhooks allow you to subscribe to events from APIs you use."
|
||||
---
|
||||
|
||||
If you want your server to be notified when one of your users has subscribed to your product, or someone has made a change to a support ticket, then you should use webhooks.
|
||||
Webhooks are a crucial part of API development, allowing for real-time reactions to various events across different systems, such as when a Stripe Payment is made, or when a GitHub issue is created.
|
||||
|
||||
## Advantages of using Trigger.dev for webhooks
|
||||
|
||||
@@ -14,9 +14,74 @@ Webhooks can be difficult to work with, especially when developing locally. We m
|
||||
- They work locally during development without needing to use tunnels (e.g. Ngrok)
|
||||
- We receive the webhook, then keep trying to send it to you until you receive it. If your server goes down, no problem.
|
||||
|
||||
## Send a Slack message when a GitHub issue is labeled as Critical
|
||||
## Usage
|
||||
|
||||
There are two ways to use webhooks with Trigger.dev:
|
||||
|
||||
1. Use one of our built-in integrations, such as [GitHub](/integrations/github). We'll take care of registering the webhook for you.
|
||||
2. Use our [webhookEvent](/reference/webhook-event) function to create a webhook subscription and you'll register the webhook yourself.
|
||||
|
||||
## Webhook integrations
|
||||
|
||||
We currently have built in integrations for the following webhooks:
|
||||
|
||||
- [GitHub](/integrations/apis/github)
|
||||
|
||||
Please [join our discord community](https://discord.gg/kA47vcd8P6) and let us know which integration you'd like us to add.
|
||||
|
||||
We've documented all the support webhooks for each integration in the sidebar, for example the GitHub [newStarEvent](/integrations/apis/github/events/new-star) webhook:
|
||||
|
||||
```ts
|
||||
import { github } from "@trigger.dev/integrations";
|
||||
|
||||
new Trigger({
|
||||
id: "demo",
|
||||
on: github.events.newStarEvent({
|
||||
repo: "triggerdotdev/trigger.dev",
|
||||
}),
|
||||
run: async (event, ctx) => {},
|
||||
}).listen();
|
||||
```
|
||||
|
||||
Once you've connected to Trigger.dev, and authorized your GitHub account, we'll go ahead and register the webhook in the repository you've specified and start triggering your `Trigger.run` function when new stars roll in.
|
||||
|
||||
## Manual Webhooks
|
||||
|
||||
If we haven't built out the integration you need, you can use our `webhookEvent` function to create a webhook subscription. You'll need to register the webhook yourself, but we'll take care of the rest. Here's an example for triggering events when a new booking happens in [Cal.com](https://cal.com):
|
||||
|
||||
```ts
|
||||
new Trigger({
|
||||
id: "caldotcom-to-slack",
|
||||
name: "Cal.com To Slack",
|
||||
on: webhookEvent({
|
||||
service: "cal.com",
|
||||
eventName: "BOOKING_CREATED",
|
||||
filter: {
|
||||
triggerEvent: ["BOOKING_CREATED"],
|
||||
},
|
||||
schema: z.any(),
|
||||
verifyPayload: {
|
||||
enabled: true,
|
||||
header: "X-Cal-Signature-256",
|
||||
},
|
||||
}),
|
||||
run: async (event, ctx) => {},
|
||||
}).listen();
|
||||
```
|
||||
|
||||
For more information on the various options for `webhookEvent`, see the [webhookEvent reference](/reference/webhook-event).
|
||||
|
||||
Once you connect to Trigger.dev, we will display the URL and (optionally) the secret you need to register with the webhook provider on the workflow overview page:
|
||||
|
||||

|
||||
|
||||
Copy the URL and secret, and register the webhook with the provider (in this case, Cal.com). Once you've done that, we'll start triggering your `Trigger.run` function when the webhook fires.
|
||||
|
||||
## Examples
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```ts Github
|
||||
import { Trigger } from "@trigger.dev/sdk";
|
||||
import { github, slack } from "@trigger.dev/integrations";
|
||||
|
||||
@@ -47,3 +112,5 @@ new Trigger({
|
||||
},
|
||||
}).listen();
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
@@ -36,6 +36,7 @@ function Webhook({ webhook }: { webhook: WebhookEventTrigger }) {
|
||||
</Header2>
|
||||
<div className="flex flex-col gap-1">
|
||||
{webhook.source &&
|
||||
!webhook.manualRegistration &&
|
||||
Object.entries(webhook.source).map(([key, value]) => (
|
||||
<div key={key} className="flex gap-2 items-baseline">
|
||||
<Body size="extra-small" className={workflowNodeUppercaseClasses}>
|
||||
|
||||
@@ -47,6 +47,14 @@ export function TriggerTypeIcon({
|
||||
return (
|
||||
<img src={Schedule} alt={triggerLabel(type)} className={iconClasses} />
|
||||
);
|
||||
case "WEBHOOK":
|
||||
return (
|
||||
<img
|
||||
src={CustomEvent}
|
||||
alt={triggerLabel(type)}
|
||||
className={iconClasses}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { prisma } from "~/db.server";
|
||||
export type { ExternalSource } from ".prisma/client";
|
||||
import type { ExternalSource } from ".prisma/client";
|
||||
import { env } from "process";
|
||||
|
||||
export type { ExternalSource };
|
||||
|
||||
export type ExternalSourceWithConnection = Awaited<
|
||||
ReturnType<typeof findExternalSourceById>
|
||||
@@ -31,3 +34,7 @@ export async function connectExternalSource({
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function buildExternalSourceUrl(id: string, serviceIdentifier: string) {
|
||||
return `${env.APP_ORIGIN}/api/v1/internal/webhooks/${serviceIdentifier}/${id}`;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ export function getWorkflowFromSlugs({
|
||||
connection: true,
|
||||
key: true,
|
||||
service: true,
|
||||
manualRegistration: true,
|
||||
secret: true,
|
||||
},
|
||||
},
|
||||
externalServices: {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Outlet } from "@remix-run/react";
|
||||
import type { LoaderArgs } from "@remix-run/server-runtime";
|
||||
import { TriggerMetadataSchema } from "@trigger.dev/common-schemas";
|
||||
import {
|
||||
ManualWebhookSourceSchema,
|
||||
TriggerMetadataSchema,
|
||||
} from "@trigger.dev/common-schemas";
|
||||
import { typedjson } from "remix-typedjson";
|
||||
import invariant from "tiny-invariant";
|
||||
import { Container } from "~/components/layout/Container";
|
||||
@@ -9,6 +12,7 @@ import {
|
||||
WorkflowsSideMenu,
|
||||
} from "~/components/navigation/SideMenu";
|
||||
import { getConnectedApiConnectionsForOrganizationSlug } from "~/models/apiConnection.server";
|
||||
import { buildExternalSourceUrl } from "~/models/externalSource.server";
|
||||
import { getIntegrations } from "~/models/integrations.server";
|
||||
import { getRuntimeEnvironmentFromRequest } from "~/models/runtimeEnvironment.server";
|
||||
import { getWorkflowFromSlugs } from "~/models/workflow.server";
|
||||
@@ -78,8 +82,28 @@ export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
}),
|
||||
};
|
||||
|
||||
const externalSourceSecret =
|
||||
workflow.externalSource &&
|
||||
workflow.externalSource.manualRegistration &&
|
||||
ManualWebhookSourceSchema.safeParse(workflow.externalSource.source)
|
||||
.success &&
|
||||
ManualWebhookSourceSchema.parse(workflow.externalSource.source)
|
||||
.verifyPayload.enabled
|
||||
? workflow.externalSource.secret
|
||||
: undefined;
|
||||
|
||||
return typedjson({
|
||||
workflow: { ...workflow, rules },
|
||||
workflow: {
|
||||
...workflow,
|
||||
rules,
|
||||
externalSourceUrl: workflow.externalSource
|
||||
? buildExternalSourceUrl(
|
||||
workflow.externalSource.id,
|
||||
workflow.externalSource.service
|
||||
)
|
||||
: undefined,
|
||||
externalSourceSecret: externalSourceSecret,
|
||||
},
|
||||
currentEnvironmentSlug,
|
||||
connectionSlots,
|
||||
});
|
||||
|
||||
+16
-3
@@ -86,9 +86,22 @@ export default function Page() {
|
||||
</div>
|
||||
{workflow.status === "CREATED" && (
|
||||
<>
|
||||
<PanelWarning className="mb-6">
|
||||
This workflow requires its APIs to be connected before it can run.
|
||||
</PanelWarning>
|
||||
{eventRule &&
|
||||
eventRule.trigger.type === "WEBHOOK" &&
|
||||
eventRule.trigger.manualRegistration &&
|
||||
workflow.externalSourceUrl ? (
|
||||
<PanelInfo className="mb-6">
|
||||
Register webhook to activate this workflow:{" "}
|
||||
{workflow.externalSourceUrl}{" "}
|
||||
{workflow.externalSourceSecret && (
|
||||
<>and secret {workflow.externalSourceSecret}</>
|
||||
)}
|
||||
</PanelInfo>
|
||||
) : (
|
||||
<PanelWarning className="mb-6">
|
||||
This workflow requires its APIs to be connected before it can run.
|
||||
</PanelWarning>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{workflow.status === "DISABLED" && (
|
||||
|
||||
@@ -17,7 +17,10 @@ export async function action({ request, params }: ActionArgs) {
|
||||
};
|
||||
}
|
||||
|
||||
if (externalSource.connection?.apiIdentifier !== serviceIdentifier) {
|
||||
if (
|
||||
!externalSource.manualRegistration &&
|
||||
externalSource.connection?.apiIdentifier !== serviceIdentifier
|
||||
) {
|
||||
return { status: 500, body: "Service identifier does not match" };
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,10 @@ export async function action({ request, params }: ActionArgs) {
|
||||
);
|
||||
|
||||
switch (result.status) {
|
||||
case "validationError":
|
||||
return json({ error: result.data }, { status: 400 });
|
||||
case "validationError": {
|
||||
return json({ error: result.errors }, { status: 400 });
|
||||
}
|
||||
|
||||
case "success":
|
||||
return json(result.data);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { prisma } from "~/db.server";
|
||||
import type { RuntimeEnvironment } from "~/models/runtimeEnvironment.server";
|
||||
import type { Workflow } from "~/models/workflow.server";
|
||||
import { taskQueue } from "../messageBroker.server";
|
||||
import { generateErrorMessage } from "zod-error";
|
||||
|
||||
export class DispatchEvent {
|
||||
#prismaClient: PrismaClient;
|
||||
@@ -41,8 +42,16 @@ export class DispatchEvent {
|
||||
},
|
||||
});
|
||||
|
||||
console.log(
|
||||
`Found ${eventRules.length} event rules to check for event ${
|
||||
event.id
|
||||
}: ${eventRules.map((eventRule) => eventRule.id).join(", ")}`
|
||||
);
|
||||
|
||||
const matcher = new EventMatcher(event);
|
||||
|
||||
console.log(`Matching event rules for event`, matcher.json);
|
||||
|
||||
const matchingEventRules = eventRules.filter((eventRule) => {
|
||||
return matcher.matches(eventRule);
|
||||
});
|
||||
@@ -77,20 +86,28 @@ export class DispatchEvent {
|
||||
}
|
||||
|
||||
class EventMatcher {
|
||||
#json: any;
|
||||
json: any;
|
||||
|
||||
constructor(event: TriggerEvent) {
|
||||
this.#json = this.#createEventJsonFromEvent(event);
|
||||
this.json = this.#createEventJsonFromEvent(event);
|
||||
}
|
||||
|
||||
public matches(eventRule: EventRule) {
|
||||
console.log(`Matching against event rule ${eventRule.id}`);
|
||||
|
||||
const filter = this.#parseFilter(eventRule);
|
||||
|
||||
if (!filter.success) {
|
||||
console.error(
|
||||
`Could not parse filter for event rule ${
|
||||
eventRule.id
|
||||
}, returning false: ${generateErrorMessage(filter.error.issues)}`
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return patternMatches(this.#json, filter.data);
|
||||
return patternMatches(this.json, filter.data);
|
||||
}
|
||||
|
||||
#parseFilter(eventRule: EventRule) {
|
||||
@@ -104,6 +121,7 @@ class EventMatcher {
|
||||
event: event.name,
|
||||
service: event.service,
|
||||
payload: event.payload,
|
||||
context: event.context,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -165,8 +183,40 @@ export class DispatchWorkflowRun {
|
||||
status: "PENDING",
|
||||
isTest: event.isTest,
|
||||
},
|
||||
include: {
|
||||
workflow: {
|
||||
include: {
|
||||
externalSource: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
workflowRun.workflow.externalSource &&
|
||||
workflowRun.workflow.externalSource.status === "CREATED"
|
||||
) {
|
||||
await this.#prismaClient.externalSource.update({
|
||||
where: {
|
||||
id: workflowRun.workflow.externalSource.id,
|
||||
},
|
||||
data: {
|
||||
status: "READY",
|
||||
},
|
||||
});
|
||||
|
||||
if (workflowRun.workflow.status === "CREATED") {
|
||||
await this.#prismaClient.workflow.update({
|
||||
where: {
|
||||
id: workflowRun.workflow.id,
|
||||
},
|
||||
data: {
|
||||
status: "READY",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Created workflow run ${workflowRun.id} for event rule ${eventRule.id}`
|
||||
);
|
||||
|
||||
@@ -4,6 +4,9 @@ import { github } from "internal-integrations";
|
||||
import type { ExternalSourceWithConnection } from "~/models/externalSource.server";
|
||||
import type { NormalizedRequest } from "internal-integrations";
|
||||
import { IngestEvent } from "../events/ingest.server";
|
||||
import { ManualWebhookSourceSchema } from "@trigger.dev/common-schemas";
|
||||
import { createHmac, timingSafeEqual } from "node:crypto";
|
||||
import { ulid } from "ulid";
|
||||
|
||||
type IgnoredEventResponse = {
|
||||
status: "ignored";
|
||||
@@ -41,16 +44,25 @@ export class HandleExternalSource {
|
||||
async #createNormalizedRequest(request: Request): Promise<NormalizedRequest> {
|
||||
const requestUrl = new URL(request.url);
|
||||
const rawSearchParams = requestUrl.searchParams;
|
||||
const rawBody = await request.json();
|
||||
const rawBody = await request.text();
|
||||
const rawHeaders = Object.fromEntries(request.headers.entries());
|
||||
|
||||
return {
|
||||
body: rawBody,
|
||||
rawBody,
|
||||
body: this.#safeJsonParse(rawBody),
|
||||
headers: rawHeaders,
|
||||
searchParams: rawSearchParams,
|
||||
};
|
||||
}
|
||||
|
||||
#safeJsonParse(json: string): any {
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async call(
|
||||
externalSource: NonNullable<ExternalSourceWithConnection>,
|
||||
serviceIdentifier: string,
|
||||
@@ -123,6 +135,14 @@ export class HandleExternalSource {
|
||||
serviceIdentifier: string,
|
||||
request: NormalizedRequest
|
||||
): Promise<HandledExternalEventResponse> {
|
||||
if (externalSource.manualRegistration) {
|
||||
return this.#handleManualWebhook(
|
||||
externalSource,
|
||||
serviceIdentifier,
|
||||
request
|
||||
);
|
||||
}
|
||||
|
||||
switch (serviceIdentifier) {
|
||||
case "github": {
|
||||
return github.webhooks.handleWebhookRequest({
|
||||
@@ -137,4 +157,48 @@ export class HandleExternalSource {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async #handleManualWebhook(
|
||||
externalSource: NonNullable<ExternalSourceWithConnection>,
|
||||
serviceIdentifier: string,
|
||||
request: NormalizedRequest
|
||||
): Promise<HandledExternalEventResponse> {
|
||||
const source = ManualWebhookSourceSchema.parse(externalSource.source);
|
||||
|
||||
if (source.verifyPayload.enabled && source.verifyPayload.header) {
|
||||
const hmac = createHmac("sha256", externalSource.secret!);
|
||||
const digest = Buffer.from(
|
||||
hmac.update(request.rawBody).digest("hex"),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
const providerSigString =
|
||||
request.headers[source.verifyPayload.header.toLowerCase()] || "";
|
||||
|
||||
const providerSig = Buffer.from(providerSigString, "utf8");
|
||||
|
||||
if (
|
||||
digest.length !== providerSig.length ||
|
||||
!timingSafeEqual(digest, providerSig)
|
||||
) {
|
||||
return {
|
||||
status: "error",
|
||||
error: "Payload signature did not match",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: "ok",
|
||||
data: {
|
||||
id: ulid(),
|
||||
payload: request.body,
|
||||
event: source.event,
|
||||
context: {
|
||||
headers: request.headers,
|
||||
externalSourceId: externalSource.id,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import crypto from "node:crypto";
|
||||
import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
import { env } from "~/env.server";
|
||||
import { findExternalSourceById } from "~/models/externalSource.server";
|
||||
import {
|
||||
buildExternalSourceUrl,
|
||||
findExternalSourceById,
|
||||
} from "~/models/externalSource.server";
|
||||
import { getAccessInfo } from "../accessInfo.server";
|
||||
|
||||
export class RegisterExternalSource {
|
||||
@@ -26,6 +29,10 @@ export class RegisterExternalSource {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (externalSource.manualRegistration) {
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log("[RegisterExternalSource] registering external source", {
|
||||
externalSource,
|
||||
});
|
||||
@@ -56,9 +63,13 @@ export class RegisterExternalSource {
|
||||
throw new Error("No access token found for webhook");
|
||||
}
|
||||
|
||||
const secret = crypto.randomBytes(32).toString("hex");
|
||||
const secret =
|
||||
externalSource.secret ?? crypto.randomBytes(32).toString("hex");
|
||||
|
||||
const webhookUrl = `${env.APP_ORIGIN}/api/v1/internal/webhooks/${connection.apiIdentifier}/${externalSource.id}`;
|
||||
const webhookUrl = buildExternalSourceUrl(
|
||||
externalSource,
|
||||
connection.apiIdentifier
|
||||
);
|
||||
|
||||
const serviceWebhook = await this.#registerWebhookWithConnection(
|
||||
externalSource.service,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { github } from "internal-integrations";
|
||||
import type { WorkflowMetadata } from "internal-platform";
|
||||
import { WorkflowMetadataSchema } from "internal-platform";
|
||||
import crypto from "node:crypto";
|
||||
import type { PrismaClient } from "~/db.server";
|
||||
import { prisma } from "~/db.server";
|
||||
import type { Organization } from "~/models/organization.server";
|
||||
@@ -140,48 +141,16 @@ export class RegisterWorkflow {
|
||||
) {
|
||||
switch (payload.trigger.type) {
|
||||
case "WEBHOOK": {
|
||||
if (!payload.trigger.source) {
|
||||
const externalSource = await this.#upsertWebhookSource(
|
||||
payload,
|
||||
organization,
|
||||
workflow
|
||||
);
|
||||
|
||||
if (!externalSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingConnection =
|
||||
await this.#findLatestExistingConnectionInOrg(
|
||||
payload.trigger.service,
|
||||
organization
|
||||
);
|
||||
|
||||
const externalSource = await this.#prismaClient.externalSource.upsert({
|
||||
where: {
|
||||
organizationId_key: {
|
||||
key: this.#keyForExternalSource(payload),
|
||||
organizationId: organization.id,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
source: payload.trigger.source,
|
||||
},
|
||||
create: {
|
||||
organizationId: organization.id,
|
||||
key: this.#keyForExternalSource(payload),
|
||||
type: "WEBHOOK",
|
||||
source: payload.trigger.source,
|
||||
status: "CREATED",
|
||||
connectionId: existingConnection?.id,
|
||||
service: payload.trigger.service,
|
||||
},
|
||||
});
|
||||
|
||||
if (!externalSource.connectionId && existingConnection) {
|
||||
await this.#prismaClient.externalSource.update({
|
||||
where: {
|
||||
id: externalSource.id,
|
||||
},
|
||||
data: {
|
||||
connectionId: existingConnection.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await this.#prismaClient.workflow.update({
|
||||
where: {
|
||||
id: workflow.id,
|
||||
@@ -235,6 +204,89 @@ export class RegisterWorkflow {
|
||||
}
|
||||
}
|
||||
|
||||
async #upsertWebhookSource(
|
||||
payload: WorkflowMetadata,
|
||||
organization: Organization,
|
||||
workflow: Workflow
|
||||
) {
|
||||
if (payload.trigger.type !== "WEBHOOK") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!payload.trigger.source) {
|
||||
return;
|
||||
}
|
||||
|
||||
const secret = crypto.randomBytes(16).toString("hex");
|
||||
|
||||
if (payload.trigger.manualRegistration) {
|
||||
const externalSource = await this.#prismaClient.externalSource.upsert({
|
||||
where: {
|
||||
organizationId_key: {
|
||||
key: `${workflow.id}-${payload.trigger.service}`,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
source: payload.trigger.source,
|
||||
},
|
||||
create: {
|
||||
organizationId: organization.id,
|
||||
key: `${workflow.id}-${payload.trigger.service}`,
|
||||
type: "WEBHOOK",
|
||||
source: payload.trigger.source,
|
||||
status: "CREATED",
|
||||
service: payload.trigger.service,
|
||||
manualRegistration: true,
|
||||
secret,
|
||||
},
|
||||
});
|
||||
|
||||
return externalSource;
|
||||
} else {
|
||||
const existingConnection = await this.#findLatestExistingConnectionInOrg(
|
||||
payload.trigger.service,
|
||||
organization
|
||||
);
|
||||
|
||||
const externalSource = await this.#prismaClient.externalSource.upsert({
|
||||
where: {
|
||||
organizationId_key: {
|
||||
key: this.#keyForExternalSource(payload),
|
||||
organizationId: organization.id,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
source: payload.trigger.source,
|
||||
},
|
||||
create: {
|
||||
organizationId: organization.id,
|
||||
key: this.#keyForExternalSource(payload),
|
||||
type: "WEBHOOK",
|
||||
source: payload.trigger.source,
|
||||
status: "CREATED",
|
||||
connectionId: existingConnection?.id,
|
||||
service: payload.trigger.service,
|
||||
manualRegistration: false,
|
||||
secret,
|
||||
},
|
||||
});
|
||||
|
||||
if (!externalSource.connectionId && existingConnection) {
|
||||
await this.#prismaClient.externalSource.update({
|
||||
where: {
|
||||
id: externalSource.id,
|
||||
},
|
||||
data: {
|
||||
connectionId: existingConnection.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return externalSource;
|
||||
}
|
||||
}
|
||||
|
||||
#keyForExternalSource(payload: WorkflowMetadata): string {
|
||||
if (payload.trigger.type === "WEBHOOK") {
|
||||
switch (payload.trigger.service) {
|
||||
|
||||
@@ -115,7 +115,8 @@
|
||||
"tiny-invariant": "^1.2.0",
|
||||
"tsx": "^3.4.3",
|
||||
"ulid": "^2.3.0",
|
||||
"zod": "^3.20.2"
|
||||
"zod": "^3.20.2",
|
||||
"zod-error": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^7.5.0",
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "ExternalSource" ADD COLUMN "manualRegistration" BOOLEAN NOT NULL DEFAULT false;
|
||||
@@ -197,13 +197,14 @@ model ExternalSource {
|
||||
|
||||
service String
|
||||
|
||||
workflows Workflow[]
|
||||
type ExternalSourceType
|
||||
key String
|
||||
source Json
|
||||
status ExternalSourceStatus @default(CREATED)
|
||||
externalData Json?
|
||||
secret String?
|
||||
workflows Workflow[]
|
||||
type ExternalSourceType
|
||||
key String
|
||||
source Json
|
||||
status ExternalSourceStatus @default(CREATED)
|
||||
externalData Json?
|
||||
secret String?
|
||||
manualRegistration Boolean @default(false)
|
||||
|
||||
readyAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { Trigger, customEvent } from "@trigger.dev/sdk";
|
||||
import { slack } from "@trigger.dev/integrations";
|
||||
import { Trigger, customEvent, webhookEvent } from "@trigger.dev/sdk";
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
const TOKEN = "abc123";
|
||||
|
||||
new Trigger({
|
||||
id: "fetch-playground",
|
||||
name: "Fetch Playground",
|
||||
@@ -54,3 +53,106 @@ new Trigger({
|
||||
});
|
||||
},
|
||||
}).listen();
|
||||
|
||||
export const bookingPayloadSchema = z.object({
|
||||
triggerEvent: z.string(),
|
||||
createdAt: z.coerce.date(),
|
||||
payload: z.object({
|
||||
type: z.string(),
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
additionalNotes: z.string(),
|
||||
customInputs: z.object({}),
|
||||
startTime: z.coerce.date(),
|
||||
endTime: z.coerce.date(),
|
||||
organizer: z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
email: z.string(),
|
||||
timeZone: z.string(),
|
||||
language: z.object({ locale: z.string() }),
|
||||
}),
|
||||
attendees: z.array(
|
||||
z.object({
|
||||
email: z.string(),
|
||||
name: z.string(),
|
||||
timeZone: z.string(),
|
||||
language: z.object({ locale: z.string() }),
|
||||
})
|
||||
),
|
||||
location: z.string(),
|
||||
destinationCalendar: z.object({
|
||||
id: z.number(),
|
||||
integration: z.string(),
|
||||
externalId: z.string(),
|
||||
userId: z.number(),
|
||||
eventTypeId: z.null(),
|
||||
credentialId: z.number(),
|
||||
}),
|
||||
hideCalendarNotes: z.boolean(),
|
||||
requiresConfirmation: z.null(),
|
||||
eventTypeId: z.number(),
|
||||
seatsShowAttendees: z.boolean(),
|
||||
uid: z.string(),
|
||||
conferenceData: z.object({
|
||||
createRequest: z.object({ requestId: z.string() }),
|
||||
}),
|
||||
videoCallData: z.object({
|
||||
type: z.string(),
|
||||
id: z.string(),
|
||||
password: z.string(),
|
||||
url: z.string(),
|
||||
}),
|
||||
appsStatus: z.array(
|
||||
z.object({
|
||||
appName: z.string(),
|
||||
type: z.string(),
|
||||
success: z.number(),
|
||||
failures: z.number(),
|
||||
errors: z.array(z.any()).optional(),
|
||||
warnings: z.array(z.any()).optional(),
|
||||
})
|
||||
),
|
||||
eventTitle: z.string(),
|
||||
eventDescription: z.null(),
|
||||
price: z.number(),
|
||||
currency: z.string(),
|
||||
length: z.number(),
|
||||
bookingId: z.number(),
|
||||
metadata: z.object({ videoCallUrl: z.string() }),
|
||||
status: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
new Trigger({
|
||||
id: "caldotcom-to-slack-2",
|
||||
name: "Cal.com To Slack",
|
||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||
endpoint: "ws://localhost:8889/ws",
|
||||
logLevel: "debug",
|
||||
on: webhookEvent({
|
||||
service: "cal.com",
|
||||
eventName: "BOOKING_CREATED",
|
||||
filter: {
|
||||
triggerEvent: ["BOOKING_CREATED"],
|
||||
},
|
||||
schema: bookingPayloadSchema,
|
||||
verifyPayload: {
|
||||
enabled: true,
|
||||
header: "X-Cal-Signature-256",
|
||||
},
|
||||
}),
|
||||
run: async (event, ctx) => {
|
||||
await ctx.logger.info("Received a cal.com booking", {
|
||||
event,
|
||||
wallTime: new Date(),
|
||||
});
|
||||
|
||||
await slack.postMessage(`Cal.com booking yo`, {
|
||||
channelName: "customers",
|
||||
text: `New Booking: ${
|
||||
event.payload.title
|
||||
} at ${event.payload.startTime.toLocaleDateString()}`,
|
||||
});
|
||||
},
|
||||
}).listen();
|
||||
|
||||
@@ -62,3 +62,11 @@ export const ScheduleSourceSchema = z.union([
|
||||
]);
|
||||
|
||||
export type ScheduleSource = z.infer<typeof ScheduleSourceSchema>;
|
||||
|
||||
export const ManualWebhookSourceSchema = z.object({
|
||||
verifyPayload: z.object({
|
||||
enabled: z.boolean(),
|
||||
header: z.string().optional(),
|
||||
}),
|
||||
event: z.string(),
|
||||
});
|
||||
|
||||
@@ -15,7 +15,8 @@ export const WebhookEventTriggerSchema = z.object({
|
||||
service: z.string(),
|
||||
name: z.string(),
|
||||
filter: EventFilterSchema,
|
||||
source: JsonSchema,
|
||||
source: JsonSchema.optional(),
|
||||
manualRegistration: z.boolean().default(false),
|
||||
});
|
||||
export type WebhookEventTrigger = z.infer<typeof WebhookEventTriggerSchema>;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface WebhookConfig {
|
||||
}
|
||||
|
||||
export interface NormalizedRequest {
|
||||
rawBody: string;
|
||||
body: any;
|
||||
headers: Record<string, string>;
|
||||
searchParams: URLSearchParams;
|
||||
|
||||
@@ -26,6 +26,7 @@ export function commitCommentEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["commit_comment"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema: github.schemas.commitComments.commitCommentEventSchema,
|
||||
};
|
||||
@@ -54,6 +55,7 @@ export function issueEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["issues"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema: github.schemas.issues.issuesEventSchema,
|
||||
};
|
||||
@@ -82,6 +84,7 @@ export function issueCommentEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["issue_comment"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema: github.schemas.issuesComments.issueCommentEventSchema,
|
||||
};
|
||||
@@ -110,6 +113,7 @@ export function pullRequestEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["pull_request"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema: github.schemas.pullRequest.pullRequestEventSchema,
|
||||
};
|
||||
@@ -140,6 +144,7 @@ export function pullRequestCommentEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["pull_request_review_comment"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema:
|
||||
github.schemas.pullRequestComments.pullRequestReviewCommentEventSchema,
|
||||
@@ -171,6 +176,7 @@ export function pullRequestReviewEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["pull_request_review"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema: github.schemas.pullRequestReviews.pullRequestReviewEventSchema,
|
||||
};
|
||||
@@ -199,6 +205,7 @@ export function pushEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["push"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema: github.schemas.push.pushEventSchema,
|
||||
};
|
||||
@@ -228,6 +235,7 @@ export function newStarEvent(params: {
|
||||
repo: params.repo,
|
||||
events: ["star"],
|
||||
}),
|
||||
manualRegistration: false,
|
||||
},
|
||||
schema: github.schemas.stars.starCreatedEventSchema,
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/node": "16",
|
||||
"@types/node-fetch": "2.6.x",
|
||||
"@types/slug": "^5.0.3",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@types/ws": "^8.5.3",
|
||||
"internal-bridge": "workspace:*",
|
||||
@@ -39,6 +40,7 @@
|
||||
"debug": "^4.3.4",
|
||||
"evt": "^2.4.13",
|
||||
"node-fetch": "2.6.x",
|
||||
"slug": "^6.0.0",
|
||||
"ulid": "^2.3.0",
|
||||
"uuid": "^9.0.0",
|
||||
"ws": "^8.11.0",
|
||||
|
||||
@@ -3,8 +3,10 @@ import {
|
||||
TriggerMetadataSchema,
|
||||
ScheduleSourceSchema,
|
||||
ScheduledEventPayloadSchema,
|
||||
EventFilter,
|
||||
} from "@trigger.dev/common-schemas";
|
||||
import { z } from "zod";
|
||||
import slugify from "slug";
|
||||
|
||||
export type EventRule = z.infer<typeof EventFilterSchema>;
|
||||
|
||||
@@ -16,6 +18,7 @@ export type TriggerEvent<TSchema extends z.ZodTypeAny> = {
|
||||
export type TriggerCustomEventOptions<TSchema extends z.ZodTypeAny> = {
|
||||
name: string;
|
||||
schema: TSchema;
|
||||
filter?: EventFilter;
|
||||
};
|
||||
|
||||
export function customEvent<TSchema extends z.ZodTypeAny>(
|
||||
@@ -26,7 +29,7 @@ export function customEvent<TSchema extends z.ZodTypeAny>(
|
||||
type: "CUSTOM_EVENT",
|
||||
service: "trigger",
|
||||
name: options.name,
|
||||
filter: { event: [options.name] },
|
||||
filter: { event: [options.name], payload: options.filter ?? {} },
|
||||
},
|
||||
schema: options.schema,
|
||||
};
|
||||
@@ -47,3 +50,37 @@ export function scheduleEvent(
|
||||
schema: ScheduledEventPayloadSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export type TriggerWebhookEventOptions<TSchema extends z.ZodTypeAny> = {
|
||||
schema: TSchema;
|
||||
service: string;
|
||||
eventName: string;
|
||||
filter?: EventFilter;
|
||||
verifyPayload?: {
|
||||
enabled: boolean;
|
||||
header: string;
|
||||
};
|
||||
};
|
||||
|
||||
export function webhookEvent<TSchema extends z.ZodTypeAny>(
|
||||
options: TriggerWebhookEventOptions<TSchema>
|
||||
): TriggerEvent<TSchema> {
|
||||
return {
|
||||
metadata: {
|
||||
type: "WEBHOOK",
|
||||
service: slugify(options.service),
|
||||
name: options.eventName,
|
||||
filter: {
|
||||
service: [slugify(options.service)],
|
||||
payload: options.filter ?? {},
|
||||
event: [options.eventName],
|
||||
},
|
||||
source: {
|
||||
verifyPayload: options.verifyPayload ?? { enabled: false },
|
||||
event: options.eventName,
|
||||
},
|
||||
manualRegistration: true,
|
||||
},
|
||||
schema: options.schema,
|
||||
};
|
||||
}
|
||||
|
||||
Generated
+58
-87
@@ -176,11 +176,12 @@ importers:
|
||||
vite-tsconfig-paths: ^3.5.1
|
||||
vitest: ^0.23.4
|
||||
zod: ^3.20.2
|
||||
zod-error: ^1.1.0
|
||||
dependencies:
|
||||
'@aws-sdk/client-s3': 3.245.0
|
||||
'@aws-sdk/s3-request-presigner': 3.245.0
|
||||
'@cfworker/json-schema': 1.12.5
|
||||
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
|
||||
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
|
||||
'@codemirror/commands': 6.1.3
|
||||
'@codemirror/lang-javascript': 6.1.2
|
||||
'@codemirror/lang-json': 6.0.1
|
||||
@@ -205,7 +206,7 @@ importers:
|
||||
'@tanstack/react-table': 8.7.6_biqbaboplfbrettd7655fr4n2y
|
||||
'@trigger.dev/common-schemas': link:../../packages/common-schemas
|
||||
'@trigger.dev/providers': link:../../packages/trigger-providers
|
||||
'@uiw/react-codemirror': 4.19.5_aguurb4bmecpxzejz52amioxne
|
||||
'@uiw/react-codemirror': 4.19.5_k4ec5g7vuuzzonc3d6xbjnmmle
|
||||
bcryptjs: 2.4.3
|
||||
classnames: 2.3.2
|
||||
clsx: 1.2.1
|
||||
@@ -257,6 +258,7 @@ importers:
|
||||
tsx: 3.12.2
|
||||
ulid: 2.3.0
|
||||
zod: 3.20.2
|
||||
zod-error: 1.1.0
|
||||
devDependencies:
|
||||
'@faker-js/faker': 7.6.0
|
||||
'@remix-run/dev': 1.10.0_biqbaboplfbrettd7655fr4n2y
|
||||
@@ -810,6 +812,7 @@ importers:
|
||||
'@types/debug': ^4.1.7
|
||||
'@types/node': '16'
|
||||
'@types/node-fetch': 2.6.x
|
||||
'@types/slug': ^5.0.3
|
||||
'@types/uuid': ^9.0.0
|
||||
'@types/ws': ^8.5.3
|
||||
debug: ^4.3.4
|
||||
@@ -817,6 +820,7 @@ importers:
|
||||
internal-bridge: workspace:*
|
||||
node-fetch: 2.6.x
|
||||
rimraf: ^3.0.2
|
||||
slug: ^6.0.0
|
||||
tsup: ^6.5.0
|
||||
tsx: ^3.12.1
|
||||
ulid: ^2.3.0
|
||||
@@ -828,6 +832,7 @@ importers:
|
||||
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
|
||||
@@ -839,6 +844,7 @@ importers:
|
||||
'@types/debug': 4.1.7
|
||||
'@types/node': 16.18.11
|
||||
'@types/node-fetch': 2.6.2
|
||||
'@types/slug': 5.0.3
|
||||
'@types/uuid': 9.0.0
|
||||
'@types/ws': 8.5.4
|
||||
internal-bridge: link:../internal-bridge
|
||||
@@ -3471,13 +3477,12 @@ packages:
|
||||
prettier: 2.8.2
|
||||
dev: false
|
||||
|
||||
/@codemirror/autocomplete/6.4.0_eo6pz6bvsllvatnnwfprpuflde:
|
||||
/@codemirror/autocomplete/6.4.0_czcfkg2f66rxeiodoti7r2gulu:
|
||||
resolution: {integrity: sha512-HLF2PnZAm1s4kGs30EiqKMgD7XsYaQ0XJnMR0rofEWQ5t5D60SfqpDIkIh1ze5tiEbyUWm8+VJ6W1/erVvBMIA==}
|
||||
peerDependencies:
|
||||
'@codemirror/language': ^6.0.0
|
||||
'@codemirror/state': ^6.0.0
|
||||
'@codemirror/view': ^6.0.0
|
||||
'@lezer/common': ^1.0.0
|
||||
dependencies:
|
||||
'@codemirror/language': 6.3.2
|
||||
'@codemirror/state': 6.2.0
|
||||
@@ -3497,7 +3502,7 @@ packages:
|
||||
/@codemirror/lang-javascript/6.1.2:
|
||||
resolution: {integrity: sha512-OcwLfZXdQ1OHrLiIcKCn7MqZ7nx205CMKlhe+vL88pe2ymhT9+2P+QhwkYGxMICj8TDHyp8HFKVwpiisUT7iEQ==}
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
|
||||
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
|
||||
'@codemirror/language': 6.3.2
|
||||
'@codemirror/lint': 6.1.0
|
||||
'@codemirror/state': 6.2.0
|
||||
@@ -3580,7 +3585,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==}
|
||||
@@ -4168,7 +4172,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==}
|
||||
@@ -4177,7 +4180,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==}
|
||||
@@ -4191,7 +4193,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==}
|
||||
@@ -4820,7 +4821,7 @@ packages:
|
||||
eslint: 8.31.0
|
||||
eslint-import-resolver-node: 0.3.6
|
||||
eslint-import-resolver-typescript: 3.5.3_hnftvkj7qg3s6bbigj4pr6djxy
|
||||
eslint-plugin-import: 2.27.4_qdjeohovcytra7xto5vgmxssaq
|
||||
eslint-plugin-import: 2.27.4_2ac3tknkazjoq5fxmuugu665ny
|
||||
eslint-plugin-jest: 26.9.0_ohsifnwenhmxgcp7mend4dnv74
|
||||
eslint-plugin-jest-dom: 4.0.3_eslint@8.31.0
|
||||
eslint-plugin-jsx-a11y: 6.7.1_eslint@8.31.0
|
||||
@@ -5187,7 +5188,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-darwin-x64/1.3.26:
|
||||
@@ -5196,7 +5196,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm-gnueabihf/1.3.26:
|
||||
@@ -5205,7 +5204,6 @@ packages:
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-gnu/1.3.26:
|
||||
@@ -5214,7 +5212,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-musl/1.3.26:
|
||||
@@ -5223,7 +5220,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-gnu/1.3.26:
|
||||
@@ -5232,7 +5228,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-musl/1.3.26:
|
||||
@@ -5241,7 +5236,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-arm64-msvc/1.3.26:
|
||||
@@ -5250,7 +5244,6 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-ia32-msvc/1.3.26:
|
||||
@@ -5259,7 +5252,6 @@ packages:
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-x64-msvc/1.3.26:
|
||||
@@ -5268,7 +5260,6 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core/1.3.26:
|
||||
@@ -5286,7 +5277,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==}
|
||||
@@ -5314,7 +5304,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==}
|
||||
@@ -5325,7 +5315,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:
|
||||
@@ -5415,19 +5405,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==}
|
||||
@@ -5950,18 +5936,17 @@ packages:
|
||||
eslint-visitor-keys: 3.3.0
|
||||
dev: true
|
||||
|
||||
/@uiw/codemirror-extensions-basic-setup/4.19.5_tbeldtdcrf45b35pezgkzq2u4e:
|
||||
/@uiw/codemirror-extensions-basic-setup/4.19.5_wd2tsis3in55bkaiwnc2c46tom:
|
||||
resolution: {integrity: sha512-1zt7ZPJ01xKkSW/KDy0FZNga0bngN1fC594wCVG7FBi60ehfcAucpooQ+JSPScKXopxcb+ugPKZvVLzr9/OfzA==}
|
||||
peerDependencies:
|
||||
'@codemirror/autocomplete': '>=6.0.0'
|
||||
'@codemirror/commands': '>=6.0.0'
|
||||
'@codemirror/language': '>=6.0.0'
|
||||
'@codemirror/lint': '>=6.0.0'
|
||||
'@codemirror/search': '>=6.0.0'
|
||||
'@codemirror/state': '>=6.0.0'
|
||||
'@codemirror/view': '>=6.0.0'
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
|
||||
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
|
||||
'@codemirror/commands': 6.1.3
|
||||
'@codemirror/language': 6.3.2
|
||||
'@codemirror/lint': 6.1.0
|
||||
@@ -5970,14 +5955,11 @@ packages:
|
||||
'@codemirror/view': 6.7.2
|
||||
dev: false
|
||||
|
||||
/@uiw/react-codemirror/4.19.5_aguurb4bmecpxzejz52amioxne:
|
||||
/@uiw/react-codemirror/4.19.5_k4ec5g7vuuzzonc3d6xbjnmmle:
|
||||
resolution: {integrity: sha512-ZCHh8d7beXbF8/t7F1+yHht6A9Y6CdKeOkZq4A09lxJEnyTQrj1FMf2zvfaqc7K23KNjkTCtSlbqKKbVDgrWaw==}
|
||||
peerDependencies:
|
||||
'@babel/runtime': '>=7.11.0'
|
||||
'@codemirror/state': '>=6.0.0'
|
||||
'@codemirror/theme-one-dark': '>=6.0.0'
|
||||
'@codemirror/view': '>=6.0.0'
|
||||
codemirror: '>=6.0.0'
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
dependencies:
|
||||
@@ -5986,14 +5968,13 @@ packages:
|
||||
'@codemirror/state': 6.2.0
|
||||
'@codemirror/theme-one-dark': 6.1.0
|
||||
'@codemirror/view': 6.7.2
|
||||
'@uiw/codemirror-extensions-basic-setup': 4.19.5_tbeldtdcrf45b35pezgkzq2u4e
|
||||
codemirror: 6.0.1_@lezer+common@1.0.2
|
||||
'@uiw/codemirror-extensions-basic-setup': 4.19.5_wd2tsis3in55bkaiwnc2c46tom
|
||||
codemirror: 6.0.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
transitivePeerDependencies:
|
||||
- '@codemirror/autocomplete'
|
||||
- '@codemirror/language'
|
||||
- '@codemirror/lint'
|
||||
- '@codemirror/search'
|
||||
dev: false
|
||||
|
||||
@@ -6095,7 +6076,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==}
|
||||
@@ -6106,7 +6086,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==}
|
||||
@@ -6272,7 +6251,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==}
|
||||
@@ -7307,18 +7285,16 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/codemirror/6.0.1_@lezer+common@1.0.2:
|
||||
/codemirror/6.0.1:
|
||||
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
|
||||
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
|
||||
'@codemirror/commands': 6.1.3
|
||||
'@codemirror/language': 6.3.2
|
||||
'@codemirror/lint': 6.1.0
|
||||
'@codemirror/search': 6.2.3
|
||||
'@codemirror/state': 6.2.0
|
||||
'@codemirror/view': 6.7.2
|
||||
transitivePeerDependencies:
|
||||
- '@lezer/common'
|
||||
dev: false
|
||||
|
||||
/collection-visit/1.0.0:
|
||||
@@ -7549,7 +7525,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==}
|
||||
@@ -8045,7 +8020,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==}
|
||||
@@ -8699,7 +8673,7 @@ packages:
|
||||
debug: 4.3.4
|
||||
enhanced-resolve: 5.12.0
|
||||
eslint: 8.31.0
|
||||
eslint-plugin-import: 2.27.4_qdjeohovcytra7xto5vgmxssaq
|
||||
eslint-plugin-import: 2.27.4_2ac3tknkazjoq5fxmuugu665ny
|
||||
get-tsconfig: 4.3.0
|
||||
globby: 13.1.3
|
||||
is-core-module: 2.11.0
|
||||
@@ -8737,7 +8711,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-module-utils/2.7.4_sqt5xxn4ciiurbqrzlaarm6ama:
|
||||
/eslint-module-utils/2.7.4_v73lhamtbyinynmwa5fn7kpmfq:
|
||||
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@@ -8762,6 +8736,7 @@ packages:
|
||||
debug: 3.2.7
|
||||
eslint: 8.31.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-import-resolver-typescript: 3.5.3_hnftvkj7qg3s6bbigj4pr6djxy
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@@ -8786,6 +8761,39 @@ packages:
|
||||
regexpp: 3.2.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import/2.27.4_2ac3tknkazjoq5fxmuugu665ny:
|
||||
resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@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
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.31.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-module-utils: 2.7.4_v73lhamtbyinynmwa5fn7kpmfq
|
||||
has: 1.0.3
|
||||
is-core-module: 2.11.0
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.6
|
||||
resolve: 1.22.1
|
||||
semver: 6.3.0
|
||||
tsconfig-paths: 3.14.1
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import/2.27.4_eslint@8.31.0:
|
||||
resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -8818,39 +8826,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import/2.27.4_qdjeohovcytra7xto5vgmxssaq:
|
||||
resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@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
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.31.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-module-utils: 2.7.4_sqt5xxn4ciiurbqrzlaarm6ama
|
||||
has: 1.0.3
|
||||
is-core-module: 2.11.0
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.6
|
||||
resolve: 1.22.1
|
||||
semver: 6.3.0
|
||||
tsconfig-paths: 3.14.1
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jest-dom/4.0.3_eslint@8.31.0:
|
||||
resolution: {integrity: sha512-9j+n8uj0+V0tmsoS7bYC7fLhQmIvjRqRYEcbDSi+TKPsTThLLXCyj5swMSSf/hTleeMktACnn+HFqXBr5gbcbA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6', yarn: '>=1'}
|
||||
@@ -11712,7 +11687,6 @@ packages:
|
||||
|
||||
/make-error/1.3.6:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: true
|
||||
|
||||
/make-iterator/0.1.1:
|
||||
resolution: {integrity: sha512-s8tbTxYqrfcXYHAPxUecPxgBnWod7yFShdSOWiV17WRM87bBH2mzr24A4tpUDv9SqebaV6JsPApwKXnisMmMBA==}
|
||||
@@ -13520,7 +13494,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==}
|
||||
@@ -13537,6 +13510,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==}
|
||||
@@ -15444,7 +15418,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==}
|
||||
@@ -15477,6 +15450,7 @@ packages:
|
||||
resolve: 1.22.1
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/tapable/2.2.1:
|
||||
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
|
||||
@@ -15756,7 +15730,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==}
|
||||
@@ -16354,7 +16327,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==}
|
||||
@@ -16878,7 +16850,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==}
|
||||
|
||||
Reference in New Issue
Block a user