diff --git a/.changeset/nine-snails-beam.md b/.changeset/nine-snails-beam.md new file mode 100644 index 00000000000..fb90ac903fc --- /dev/null +++ b/.changeset/nine-snails-beam.md @@ -0,0 +1,17 @@ +--- +"@trigger.dev/core": major +--- +Why +Allow usage of validation libraries that implement standard schema for schemaTask + +What +support standard schema for schemaTask + +How +Pass schema definition via schemaTask.schema +Usage: +schemaTask({ + schema : `any compatable schema` +}) + + diff --git a/packages/core/package.json b/packages/core/package.json index d73b425f7d4..9d35ff1368b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -199,7 +199,8 @@ "uncrypto": "^0.1.3", "zod": "3.25.76", "zod-error": "1.5.0", - "zod-validation-error": "^1.5.0" + "zod-validation-error": "^1.5.0", + "@standard-schema/spec": "^1.1.0" }, "devDependencies": { "@ai-sdk/provider-utils": "^1.0.22", diff --git a/packages/core/src/v3/index.ts b/packages/core/src/v3/index.ts index f4c114c5f9d..898b9374d64 100644 --- a/packages/core/src/v3/index.ts +++ b/packages/core/src/v3/index.ts @@ -79,6 +79,7 @@ export { type SchemaParseFn, isSchemaZodEsque, isSchemaValibotEsque, + isSchemaStandardSchemaV1, isSchemaArkTypeEsque, } from "./types/schemas.js"; diff --git a/packages/core/src/v3/types/schemas.ts b/packages/core/src/v3/types/schemas.ts index e5ae9c3d88e..08c13ab5548 100644 --- a/packages/core/src/v3/types/schemas.ts +++ b/packages/core/src/v3/types/schemas.ts @@ -1,3 +1,5 @@ +import { StandardSchemaV1 } from "@standard-schema/spec"; + export type SchemaZodEsque = { _input: TInput; _output: TParsedInput; @@ -41,6 +43,12 @@ export function isSchemaArkTypeEsque( return typeof schema === "object" && "_inferIn" in schema && "_infer" in schema; } +export function isSchemaStandardSchemaV1( + schema: Schema +): schema is StandardSchemaV1 { + return typeof schema === "object" && "~standard" in schema && schema["~standard"].version === 1; +} + export type SchemaMyZodEsque = { parse: (input: any) => TInput; }; @@ -64,12 +72,14 @@ export type SchemaWithoutInput = | SchemaMyZodEsque | SchemaScaleEsque | SchemaSuperstructEsque - | SchemaYupEsque; + | SchemaYupEsque + | StandardSchemaV1; export type SchemaWithInputOutput = | SchemaZodEsque | SchemaValibotEsque - | SchemaArkTypeEsque; + | SchemaArkTypeEsque + | StandardSchemaV1; export type Schema = SchemaWithInputOutput | SchemaWithoutInput; @@ -98,11 +108,26 @@ export type inferSchemaOut< TDefault = unknown, > = TSchema extends Schema ? inferSchema["out"] : TDefault; +function issueToString(issue: StandardSchemaV1.Issue) : string { + return `{ message : ${issue.message} , path : ${issue.path}}` +} + +class StandardSchemaV1ValidateError extends Error { + constructor(result : StandardSchemaV1.FailureResult){ + let message = `StandardSchemaV1 Validate Error [` + result.issues.forEach((issue) => { + message += ` ${issueToString(issue)}` + }) + message += ' ]' + super(message) + } +} + export type SchemaParseFn = (value: unknown) => Promise | TType; export type AnySchemaParseFn = SchemaParseFn; export function getSchemaParseFn(procedureParser: Schema): SchemaParseFn { - const parser = procedureParser as any; + const parser = procedureParser as any; if (typeof parser === "function" && typeof parser.assert === "function") { // ParserArkTypeEsque - arktype schemas shouldn't be called as a function because they return a union type instead of throwing @@ -144,5 +169,16 @@ export function getSchemaParseFn(procedureParser: Schema): SchemaParseFn< }; } + if (parser["~standard"] && typeof parser["~standard"].validate === "function") { + return (value) => { + let response = parser["~standard"].validate(value); + if ("value" in response) { + return response["value"] as TType; + } + //FailureResult type + throw new StandardSchemaV1ValidateError(response); + }; + } + throw new Error("Could not find a validator fn"); }