Zod guide and better handling of Zod event parsing errors
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@trigger.dev/sdk": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Better handle event parsing errors from Zod
|
||||||
@@ -201,13 +201,13 @@ Triggers are what cause your workflows to run.
|
|||||||
<Card title="Webhooks" icon="rectangle-terminal" href="/triggers/webhooks">
|
<Card title="Webhooks" icon="rectangle-terminal" href="/triggers/webhooks">
|
||||||
Easily subscribe to the APIs you're using
|
Easily subscribe to the APIs you're using
|
||||||
</Card>
|
</Card>
|
||||||
<Card title="Scheduled" icon="sliders" href="/triggers/scheduled">
|
<Card title="Scheduled" icon="clock" href="/triggers/scheduled">
|
||||||
Trigger your workflows on a repeating schedule
|
Trigger your workflows on a repeating schedule
|
||||||
</Card>
|
</Card>
|
||||||
<Card title="Custom events" icon="heading" href="/triggers/custom-events">
|
<Card title="Custom events" icon="code" href="/triggers/custom-events">
|
||||||
More details on custom events
|
More details on custom events
|
||||||
</Card>
|
</Card>
|
||||||
<Card title="More coming soon" icon="heading">
|
<Card title="More coming soon" icon="bookmark">
|
||||||
On received email, HTTP endpoint and AWS Event Bridge
|
On received email, HTTP endpoint and AWS Event Bridge
|
||||||
</Card>
|
</Card>
|
||||||
</CardGroup>
|
</CardGroup>
|
||||||
@@ -222,11 +222,14 @@ Triggers are what cause your workflows to run.
|
|||||||
>
|
>
|
||||||
We are making it easy to use lots of APIs by adding integrations.
|
We are making it easy to use lots of APIs by adding integrations.
|
||||||
</Card>
|
</Card>
|
||||||
<Card title="Delays" icon="sliders" href="/functions/delays">
|
<Card title="Fetch" icon="server" href="/functions/fetch">
|
||||||
|
Call any API from your workflow
|
||||||
|
</Card>
|
||||||
|
<Card title="Delays" icon="alarm-clock" href="/functions/delays">
|
||||||
Add delays to your workflows. They're resilient so it doesn't matter if your
|
Add delays to your workflows. They're resilient so it doesn't matter if your
|
||||||
server goes down.
|
server goes down.
|
||||||
</Card>
|
</Card>
|
||||||
<Card title="Send event" icon="heading" href="/functions/send-event">
|
<Card title="Send event" icon="code" href="/functions/send-event">
|
||||||
Send an event, to trigger a custom event workflow
|
Send an event, to trigger a custom event workflow
|
||||||
</Card>
|
</Card>
|
||||||
</CardGroup>
|
</CardGroup>
|
||||||
|
|||||||
+301
-2
@@ -1,7 +1,306 @@
|
|||||||
---
|
---
|
||||||
title: "Zod"
|
title: "Zod Guide"
|
||||||
sidebarTitle: "Zod"
|
sidebarTitle: "Zod"
|
||||||
description: "TypeScript-first schema validation with static type inference"
|
description: "TypeScript-first schema validation with static type inference"
|
||||||
---
|
---
|
||||||
|
|
||||||
## Coming soon
|
## Intro
|
||||||
|
|
||||||
|
Zod is a fantastic utility package by [@colinhacks](https://twitter.com/colinhacks) that allows for defining runtime schema validation and type-safety.
|
||||||
|
|
||||||
|
We use it [extensively](https://github.com/search?q=repo%3Atriggerdotdev%2Ftrigger.dev+%22zod%22%3B&type=code) internally at Trigger.dev to ensure we never trigger your workflows with invalid data (and more).
|
||||||
|
|
||||||
|
But there are a few places where we ask you to provide us with a Zod schema, for example when defining a [Custom Event Trigger](/triggers/custom-events):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Trigger, customEvent } from "@trigger.dev/sdk";
|
||||||
|
import { slack } from "@trigger.dev/integrations";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
//this workflow will run when a "user.created" event is sent
|
||||||
|
new Trigger({
|
||||||
|
id: "zod",
|
||||||
|
name: "Zod custom event",
|
||||||
|
//this is the custom event subscription
|
||||||
|
on: customEvent({
|
||||||
|
name: "user.created",
|
||||||
|
schema: z.object({
|
||||||
|
name: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
paidPlan: z.boolean(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
//this function is run when the custom event is received
|
||||||
|
run: async (event, ctx) => {
|
||||||
|
console.log(event); // Has name, email, paidPlan
|
||||||
|
},
|
||||||
|
}).listen();
|
||||||
|
```
|
||||||
|
|
||||||
|
So it will help to know a little about Zod and how to use it. We definitely recommend the well written [Zod README](https://github.com/colinhacks/zod#readme) but we've included a short primer below.
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
Wherever we require you to pass in a Zod schema, you can always start with
|
||||||
|
`z.any()` which accepts `any` type and then add more strict validations later.
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
There are three main steps to using Zod:
|
||||||
|
|
||||||
|
1. Define a schema
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const mySchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
paidPlan: z.boolean(),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Infer TypeScript types from the schema
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type MySchema = z.infer<typeof mySchema>;
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Validate data against the schema
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const data: unknown = {
|
||||||
|
name: "Eric",
|
||||||
|
email: "eric@trigger.dev",
|
||||||
|
paidPlan: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = mySchema.parse(data);
|
||||||
|
```
|
||||||
|
|
||||||
|
When using Zod with Trigger.dev, you'll only really need to do the first step, and by passing it to us (through the `schema` property of the `customEvent` function), we'll do the second and third steps for you.
|
||||||
|
|
||||||
|
## Defining Schemas
|
||||||
|
|
||||||
|
### Primitives
|
||||||
|
|
||||||
|
Zod schemas are a way to define the shape of an object. They can be as simple as a single type, or as complex as a nested object.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Primitives
|
||||||
|
z.string();
|
||||||
|
z.number();
|
||||||
|
z.boolean();
|
||||||
|
z.date();
|
||||||
|
z.undefined();
|
||||||
|
z.null();
|
||||||
|
```
|
||||||
|
|
||||||
|
Any schema can be marked as optional, which means the schema can be `undefined` or `null`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
z.string().optional();
|
||||||
|
```
|
||||||
|
|
||||||
|
Schemas can also be marked optional by providing a default value:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const optionalString = z.string().default("default value");
|
||||||
|
|
||||||
|
const value = optionalString.parse(undefined); // value === "default value"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to allow a value to be `null`, you can use `nullable()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const nullableString = z.string().nullable();
|
||||||
|
|
||||||
|
const value = nullableString.parse(null);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use Zod to coerce primites into other types. For example, you can coerce a string into a number:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const numberString = z.coerce.number();
|
||||||
|
|
||||||
|
const value = numberString.parse("123"); // value === 123
|
||||||
|
```
|
||||||
|
|
||||||
|
The following primitives are supported:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
z.coerce.string();
|
||||||
|
z.coerce.number();
|
||||||
|
z.coerce.boolean();
|
||||||
|
z.coerce.bigint();
|
||||||
|
z.coerce.date();
|
||||||
|
```
|
||||||
|
|
||||||
|
Coercing dates are especially useful when you are receiving a `string` from an API and want to convert it to a JavaScript `Date` object:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const date = z.coerce.date();
|
||||||
|
|
||||||
|
const value = date.parse("2021-01-01T00:00:00.000Z"); // value === Date object
|
||||||
|
```
|
||||||
|
|
||||||
|
### Objects
|
||||||
|
|
||||||
|
Object schemas are the most common type of schema. They allow you to define the shape of an object, and the types of each property.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mySchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
paidPlan: z.boolean(),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
All properties are required by default, although you can make them all optional using `partial()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mySchema = z
|
||||||
|
.object({
|
||||||
|
name: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
paidPlan: z.boolean(),
|
||||||
|
})
|
||||||
|
.partial();
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also make individual properties optional:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mySchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
paidPlan: z.boolean().optional(),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
By default an object schema will strip out any extra properties that are not defined in the schema. You can disable this behavior using `passthrough()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mySchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
mySchema.parse({ name: "Eric", email: "eric@trigger.dev" }); // { name: "Eric" }
|
||||||
|
mySchema.passthrough().parse({ name: "Eric", email: "eric@trigger.dev" }); // { name: "Eric", email: "eric@trigger.dev" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can use `strict()` to make the schema throw an error if there are any extra properties:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mySchema = z
|
||||||
|
.object({
|
||||||
|
name: z.string(),
|
||||||
|
})
|
||||||
|
.strict();
|
||||||
|
|
||||||
|
mySchema.parse({ name: "Eric", email: "eric@trigger.dev" }); // throws error
|
||||||
|
```
|
||||||
|
|
||||||
|
Zod includes a few useful object schema utilities to help with reusing schemas, `extends()` and `merge()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const baseSchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const extendedSchema = baseSchema.extend({
|
||||||
|
email: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const mergedSchema = baseSchema.merge(
|
||||||
|
z.object({
|
||||||
|
email: z.string(),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use `pick()` and `omit()` to create a new schema that only includes or excludes certain properties:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mySchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
paidPlan: z.boolean(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const pickedSchema = mySchema.pick({ name: true, email: true });
|
||||||
|
const omittedSchema = mySchema.omit({ paidPlan: true });
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arrays
|
||||||
|
|
||||||
|
You can specify the schema of an array using `z.array()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
z.array(z.string()); // string[]
|
||||||
|
z.array(z.number()); // number[]
|
||||||
|
z.array(z.object({ name: z.string() })); // Array<{ name: string }>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also specify the type of array that has a fixed number of elements using `z.tuple()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
z.tuple([z.string(), z.number(), z.boolean()]); // [string, number, boolean]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unions
|
||||||
|
|
||||||
|
You can specify a union of schemas using `z.union()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
z.union([z.string(), z.number(), z.boolean()]); // string | number | boolean
|
||||||
|
```
|
||||||
|
|
||||||
|
Discriminating unions are also supported, and especially useful when paired with type narrowing:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mySchema = z.discriminatingUnion("type", [
|
||||||
|
z.object({
|
||||||
|
type: z.literal("a"),
|
||||||
|
data: z.string(),
|
||||||
|
}),
|
||||||
|
z.object({
|
||||||
|
type: z.literal("b"),
|
||||||
|
data: z.number(),
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const value = mySchema.parse({ type: "a", data: "hello" });
|
||||||
|
|
||||||
|
if (type.a) {
|
||||||
|
// value is { type: "a", data: string }
|
||||||
|
} else if (type.b) {
|
||||||
|
// value is { type: "b", data: number }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Records
|
||||||
|
|
||||||
|
You can specify a record of schemas using `z.record()`, useful for when you have a map of values but don't care about the keys:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
z.record(z.string()); // Record<string, string>
|
||||||
|
z.record(z.number()); // Record<string, number>
|
||||||
|
```
|
||||||
|
|
||||||
|
### JSON type
|
||||||
|
|
||||||
|
If you want to accept any valid JSON value, you can use the following schema:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
||||||
|
type Literal = z.infer<typeof literalSchema>;
|
||||||
|
type Json = Literal | { [key: string]: Json } | Json[];
|
||||||
|
const jsonSchema: z.ZodType<Json> = z.lazy(() =>
|
||||||
|
z.union([literalSchema, z.array(jsonSchema), z.record(jsonSchema)])
|
||||||
|
);
|
||||||
|
|
||||||
|
jsonSchema.parse(data);
|
||||||
|
```
|
||||||
|
|
||||||
|
Hat tip to [ggoodman](https://github.com/ggoodman) for this one.
|
||||||
|
|||||||
@@ -4,27 +4,28 @@ sidebarTitle: "Custom events"
|
|||||||
description: "Custom event triggers allow you to run workflows from your own code (or your other workflows)"
|
description: "Custom event triggers allow you to run workflows from your own code (or your other workflows)"
|
||||||
---
|
---
|
||||||
|
|
||||||
[Send an event](/functions/send-event) and any workflows that subscribe to that Custom event will get triggered.
|
[Send an event](/functions/send-event) and any workflows that subscribe to that custom event will get triggered.
|
||||||
|
|
||||||
## Name and Schemas
|
## Name and Schemas
|
||||||
|
|
||||||
### Name
|
### Name
|
||||||
|
|
||||||
Custom event triggers have a `name`. They will only get triggered when a custom even with that name are sent.
|
Custom event triggers have a `name`. They will only get triggered when a custom event with that name are sent.
|
||||||
|
|
||||||
### Schema
|
### Schema
|
||||||
|
|
||||||
Custom event triggers have a schema. This is used to validate the data that is sent with the event. If the data does not match the schema, the workflow will not run.
|
Custom event triggers take a [Zod](https://github.com/colinhacks/zod) schema. This is used to validate the data that is sent with the event. If the data does not match the schema, the workflow will not run.
|
||||||
|
|
||||||
It also means that inside your run function you will have type safety for the data you receive. We use [Zod](https://github.com/colinhacks/zod#installation) for our schemas – it's a fantastic library that allows you to define schemas in a very simple way.
|
It also means that inside your run function the event param will be typed correctly. We use [Zod](https://github.com/colinhacks/zod#installation) for our schemas – it's a fantastic library that allows you to define schemas in a very simple way.
|
||||||
|
|
||||||
You can always start out by using `z.any()` as your schema, and then later on you can add more strict validation.
|
You can always start out by using `z.any()` as your schema, and then later on you can add more strict validation. See our [Zod guide](/guides/zod) for more information.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Trigger, customEvent } from "@trigger.dev/sdk";
|
import { Trigger, customEvent } from "@trigger.dev/sdk";
|
||||||
import { slack } from "@trigger.dev/integrations";
|
import { slack } from "@trigger.dev/integrations";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
//this workflow will run when a "user.created" event is sent
|
//this workflow will run when a "user.created" event is sent
|
||||||
new Trigger({
|
new Trigger({
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const trigger = new Trigger({
|
|||||||
name: "My workflow",
|
name: "My workflow",
|
||||||
apiKey: "trigger_dev_zC25mKNn6c0q",
|
apiKey: "trigger_dev_zC25mKNn6c0q",
|
||||||
endpoint: "ws://localhost:8889/ws",
|
endpoint: "ws://localhost:8889/ws",
|
||||||
logLevel: "log",
|
logLevel: "debug",
|
||||||
triggerTTL: 60 * 60 * 24,
|
triggerTTL: 60 * 60 * 24,
|
||||||
on: customEvent({ name: "user.created", schema: userCreatedEvent }),
|
on: customEvent({ name: "user.created", schema: userCreatedEvent }),
|
||||||
run: async (event, ctx) => {
|
run: async (event, ctx) => {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
"ulid": "^2.3.0",
|
"ulid": "^2.3.0",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"ws": "^8.11.0",
|
"ws": "^8.11.0",
|
||||||
"zod": "^3.20.2"
|
"zod": "^3.20.2",
|
||||||
|
"zod-error": "^1.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ import { triggerRunLocalStorage } from "./localStorage";
|
|||||||
import { ContextLogger } from "./logger";
|
import { ContextLogger } from "./logger";
|
||||||
import { Trigger, TriggerOptions } from "./trigger";
|
import { Trigger, TriggerOptions } from "./trigger";
|
||||||
import { TriggerContext, TriggerFetch } from "./types";
|
import { TriggerContext, TriggerFetch } from "./types";
|
||||||
|
import { generateErrorMessage, ErrorMessageOptions } from "zod-error";
|
||||||
|
|
||||||
|
const zodErrorMessageOptions: ErrorMessageOptions = {
|
||||||
|
delimiter: {
|
||||||
|
error: " 🔥 ",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export class TriggerClient<TSchema extends z.ZodTypeAny> {
|
export class TriggerClient<TSchema extends z.ZodTypeAny> {
|
||||||
#trigger: Trigger<TSchema>;
|
#trigger: Trigger<TSchema>;
|
||||||
@@ -292,6 +299,26 @@ export class TriggerClient<TSchema extends z.ZodTypeAny> {
|
|||||||
TRIGGER_WORKFLOW: async (data) => {
|
TRIGGER_WORKFLOW: async (data) => {
|
||||||
this.#logger.debug("Handling TRIGGER_WORKFLOW", data);
|
this.#logger.debug("Handling TRIGGER_WORKFLOW", data);
|
||||||
|
|
||||||
|
const parsedEventData = this.#options.on.schema.safeParse(
|
||||||
|
data.trigger.input
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!parsedEventData.success) {
|
||||||
|
await serverRPC.send("SEND_WORKFLOW_ERROR", {
|
||||||
|
runId: data.id,
|
||||||
|
timestamp: String(highPrecisionTimestamp()),
|
||||||
|
error: {
|
||||||
|
name: "Event validation error",
|
||||||
|
message: generateErrorMessage(
|
||||||
|
parsedEventData.error.issues,
|
||||||
|
zodErrorMessageOptions
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const fetchFunction: TriggerFetch = async (key, url, options) => {
|
const fetchFunction: TriggerFetch = async (key, url, options) => {
|
||||||
const result = new Promise<FetchOutput>((resolve, reject) => {
|
const result = new Promise<FetchOutput>((resolve, reject) => {
|
||||||
this.#fetchCallbacks.set(messageKey(data.id, key), {
|
this.#fetchCallbacks.set(messageKey(data.id, key), {
|
||||||
@@ -399,7 +426,7 @@ export class TriggerClient<TSchema extends z.ZodTypeAny> {
|
|||||||
fetch: fetchFunction,
|
fetch: fetchFunction,
|
||||||
};
|
};
|
||||||
|
|
||||||
const eventData = this.#options.on.schema.parse(data.trigger.input);
|
const eventData = parsedEventData.data;
|
||||||
|
|
||||||
this.#logger.debug("Parsed event data", eventData);
|
this.#logger.debug("Parsed event data", eventData);
|
||||||
|
|
||||||
|
|||||||
Generated
+8
@@ -770,6 +770,7 @@ importers:
|
|||||||
uuid: ^9.0.0
|
uuid: ^9.0.0
|
||||||
ws: ^8.11.0
|
ws: ^8.11.0
|
||||||
zod: ^3.20.2
|
zod: ^3.20.2
|
||||||
|
zod-error: ^1.1.0
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
evt: 2.4.13
|
evt: 2.4.13
|
||||||
@@ -778,6 +779,7 @@ importers:
|
|||||||
uuid: 9.0.0
|
uuid: 9.0.0
|
||||||
ws: 8.12.0
|
ws: 8.12.0
|
||||||
zod: 3.20.2
|
zod: 3.20.2
|
||||||
|
zod-error: 1.1.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@trigger.dev/common-schemas': link:../common-schemas
|
'@trigger.dev/common-schemas': link:../common-schemas
|
||||||
'@trigger.dev/tsconfig': link:../../config-packages/tsconfig
|
'@trigger.dev/tsconfig': link:../../config-packages/tsconfig
|
||||||
@@ -16581,6 +16583,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
/zod-error/1.1.0:
|
||||||
|
resolution: {integrity: sha512-zZ0I9/eFQsaDqglBPOM5Y/kJzbTkoD6hNZGON/kcMe2WIfLse2DIwsZpLMfKwBmcciYaEg+DubtLMnAbZ4/rfA==}
|
||||||
|
dependencies:
|
||||||
|
zod: 3.20.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/zod/3.20.2:
|
/zod/3.20.2:
|
||||||
resolution: {integrity: sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ==}
|
resolution: {integrity: sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ==}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user