Skip to content

Commit bd2b9a0

Browse files
committed
schema tasks
1 parent 4a68166 commit bd2b9a0

File tree

13 files changed

+682
-442
lines changed

13 files changed

+682
-442
lines changed

packages/core/src/v3/errors.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ export class AbortTaskRunError extends Error {
1111
}
1212
}
1313

14+
export class TaskPayloadParsedError extends Error {
15+
constructor(cause: unknown) {
16+
const causeMessage = cause instanceof Error ? cause.message : String(cause);
17+
18+
super("Parsing payload with schema failed: " + causeMessage);
19+
this.name = "TaskPayloadParsedError";
20+
this.cause = cause;
21+
}
22+
}
23+
1424
export function parseError(error: unknown): TaskRunError {
1525
if (error instanceof Error) {
1626
return {

packages/core/src/v3/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export {
5858
} from "./utils/ioSerialization.js";
5959

6060
export * from "./config.js";
61+
export { getSchemaParseFn, type AnySchemaParseFn, type SchemaParseFn } from "./types/schemas.js";
6162

6263
import { VERSION } from "../version.js";
6364

packages/core/src/v3/types/index.ts

Lines changed: 0 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,7 @@
1-
import { RetryOptions, TaskMetadata, TaskRunContext } from "../schemas/index.js";
2-
import { Prettify } from "./utils.js";
3-
41
export * from "./utils.js";
52
export * from "./tasks.js";
63
export * from "./idempotencyKeys.js";
74

8-
export type InitOutput = Record<string, any> | void | undefined;
9-
10-
export type RunFnParams<TInitOutput extends InitOutput> = Prettify<{
11-
/** Metadata about the task, run, attempt, queue, environment, organization, project and batch. */
12-
ctx: Context;
13-
/** If you use the `init` function, this will be whatever you returned. */
14-
init?: TInitOutput;
15-
/** Abort signal that is aborted when a task run exceeds it's maxDuration. Can be used to automatically cancel downstream requests */
16-
signal?: AbortSignal;
17-
}>;
18-
19-
export type MiddlewareFnParams = Prettify<{
20-
ctx: Context;
21-
next: () => Promise<void>;
22-
/** Abort signal that is aborted when a task run exceeds it's maxDuration. Can be used to automatically cancel downstream requests */
23-
signal?: AbortSignal;
24-
}>;
25-
26-
export type InitFnParams = Prettify<{
27-
ctx: Context;
28-
/** Abort signal that is aborted when a task run exceeds it's maxDuration. Can be used to automatically cancel downstream requests */
29-
signal?: AbortSignal;
30-
}>;
31-
32-
export type StartFnParams = Prettify<{
33-
ctx: Context;
34-
/** Abort signal that is aborted when a task run exceeds it's maxDuration. Can be used to automatically cancel downstream requests */
35-
signal?: AbortSignal;
36-
}>;
37-
38-
export type Context = TaskRunContext;
39-
40-
export type SuccessFnParams<TInitOutput extends InitOutput> = RunFnParams<TInitOutput>;
41-
42-
export type FailureFnParams<TInitOutput extends InitOutput> = RunFnParams<TInitOutput>;
43-
44-
export type HandleErrorFnParams<TInitOutput extends InitOutput> = RunFnParams<TInitOutput> &
45-
Prettify<{
46-
retry?: RetryOptions;
47-
retryAt?: Date;
48-
retryDelayInMs?: number;
49-
}>;
50-
51-
export type HandleErrorModificationOptions = {
52-
skipRetrying?: boolean | undefined;
53-
retryAt?: Date | undefined;
54-
retryDelayInMs?: number | undefined;
55-
retry?: RetryOptions | undefined;
56-
error?: unknown;
57-
};
58-
59-
export type HandleErrorResult =
60-
| undefined
61-
| void
62-
| HandleErrorModificationOptions
63-
| Promise<undefined | void | HandleErrorModificationOptions>;
64-
65-
export type HandleErrorArgs = {
66-
ctx: Context;
67-
retry?: RetryOptions;
68-
retryAt?: Date;
69-
retryDelayInMs?: number;
70-
/** Abort signal that is aborted when a task run exceeds it's maxDuration. Can be used to automatically cancel downstream requests */
71-
signal?: AbortSignal;
72-
};
73-
74-
export type HandleErrorFunction = (
75-
payload: any,
76-
error: unknown,
77-
params: HandleErrorArgs
78-
) => HandleErrorResult;
79-
805
type ResolveEnvironmentVariablesOptions = {
816
variables: Record<string, string> | Array<{ name: string; value: string }>;
827
override?: boolean;
@@ -97,20 +22,3 @@ export type ResolveEnvironmentVariablesParams = {
9722
export type ResolveEnvironmentVariablesFunction = (
9823
params: ResolveEnvironmentVariablesParams
9924
) => ResolveEnvironmentVariablesResult;
100-
101-
export type TaskMetadataWithFunctions = TaskMetadata & {
102-
fns: {
103-
run: (payload: any, params: RunFnParams<any>) => Promise<any>;
104-
init?: (payload: any, params: InitFnParams) => Promise<InitOutput>;
105-
cleanup?: (payload: any, params: RunFnParams<any>) => Promise<void>;
106-
middleware?: (payload: any, params: MiddlewareFnParams) => Promise<void>;
107-
handleError?: (
108-
payload: any,
109-
error: unknown,
110-
params: HandleErrorFnParams<any>
111-
) => HandleErrorResult;
112-
onSuccess?: (payload: any, output: any, params: SuccessFnParams<any>) => Promise<void>;
113-
onFailure?: (payload: any, error: unknown, params: FailureFnParams<any>) => Promise<void>;
114-
onStart?: (payload: any, params: StartFnParams) => Promise<void>;
115-
};
116-
};

packages/core/src/v3/types/schemas.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
export type SchemaZodEsque<TInput, TParsedInput> = {
2+
_input: TInput;
3+
_output: TParsedInput;
4+
};
5+
6+
export type SchemaValibotEsque<TInput, TParsedInput> = {
7+
schema: {
8+
_types?: {
9+
input: TInput;
10+
output: TParsedInput;
11+
};
12+
};
13+
};
14+
15+
export type SchemaArkTypeEsque<TInput, TParsedInput> = {
16+
inferIn: TInput;
17+
infer: TParsedInput;
18+
};
19+
20+
export type SchemaMyZodEsque<TInput> = {
21+
parse: (input: any) => TInput;
22+
};
23+
24+
export type SchemaSuperstructEsque<TInput> = {
25+
create: (input: unknown) => TInput;
26+
};
27+
28+
export type SchemaCustomValidatorEsque<TInput> = (input: unknown) => Promise<TInput> | TInput;
29+
30+
export type SchemaYupEsque<TInput> = {
31+
validateSync: (input: unknown) => TInput;
32+
};
33+
34+
export type SchemaScaleEsque<TInput> = {
35+
assert(value: unknown): asserts value is TInput;
36+
};
37+
38+
export type SchemaWithoutInput<TInput> =
39+
| SchemaCustomValidatorEsque<TInput>
40+
| SchemaMyZodEsque<TInput>
41+
| SchemaScaleEsque<TInput>
42+
| SchemaSuperstructEsque<TInput>
43+
| SchemaYupEsque<TInput>;
44+
45+
export type SchemaWithInputOutput<TInput, TParsedInput> =
46+
| SchemaZodEsque<TInput, TParsedInput>
47+
| SchemaValibotEsque<TInput, TParsedInput>
48+
| SchemaArkTypeEsque<TInput, TParsedInput>;
49+
50+
export type Schema = SchemaWithInputOutput<any, any> | SchemaWithoutInput<any>;
51+
52+
export type inferSchema<TSchema extends Schema> = TSchema extends SchemaWithInputOutput<
53+
infer $TIn,
54+
infer $TOut
55+
>
56+
? {
57+
in: $TIn;
58+
out: $TOut;
59+
}
60+
: TSchema extends SchemaWithoutInput<infer $InOut>
61+
? {
62+
in: $InOut;
63+
out: $InOut;
64+
}
65+
: never;
66+
67+
export type inferSchemaIn<
68+
TSchema extends Schema | undefined,
69+
TDefault = unknown,
70+
> = TSchema extends Schema ? inferSchema<TSchema>["in"] : TDefault;
71+
72+
export type inferSchemaOut<
73+
TSchema extends Schema | undefined,
74+
TDefault = unknown,
75+
> = TSchema extends Schema ? inferSchema<TSchema>["out"] : TDefault;
76+
77+
export type SchemaParseFn<TType> = (value: unknown) => Promise<TType> | TType;
78+
export type AnySchemaParseFn = SchemaParseFn<any>;
79+
80+
export function getSchemaParseFn<TType>(procedureParser: Schema): SchemaParseFn<TType> {
81+
const parser = procedureParser as any;
82+
83+
if (typeof parser === "function" && typeof parser.assert === "function") {
84+
// ParserArkTypeEsque - arktype schemas shouldn't be called as a function because they return a union type instead of throwing
85+
return parser.assert.bind(parser);
86+
}
87+
88+
if (typeof parser === "function") {
89+
// ParserValibotEsque (>= v0.31.0)
90+
// ParserCustomValidatorEsque
91+
return parser;
92+
}
93+
94+
if (typeof parser.parseAsync === "function") {
95+
// ParserZodEsque
96+
return parser.parseAsync.bind(parser);
97+
}
98+
99+
if (typeof parser.parse === "function") {
100+
// ParserZodEsque
101+
// ParserValibotEsque (< v0.13.0)
102+
return parser.parse.bind(parser);
103+
}
104+
105+
if (typeof parser.validateSync === "function") {
106+
// ParserYupEsque
107+
return parser.validateSync.bind(parser);
108+
}
109+
110+
if (typeof parser.create === "function") {
111+
// ParserSuperstructEsque
112+
return parser.create.bind(parser);
113+
}
114+
115+
if (typeof parser.assert === "function") {
116+
// ParserScaleEsque
117+
return (value) => {
118+
parser.assert(value);
119+
return value as TType;
120+
};
121+
}
122+
123+
throw new Error("Could not find a validator fn");
124+
}

0 commit comments

Comments
 (0)