Skip to content

Commit 5e673a1

Browse files
committed
fix: add edge cases testing for errors when no input/output schemas defined
Signed-off-by: tunnckoCore <5038030+tunnckoCore@users.noreply.github.com>
1 parent 8edfc19 commit 5e673a1

File tree

6 files changed

+94
-32
lines changed

6 files changed

+94
-32
lines changed

bun.lock

Lines changed: 4 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

new-src/index.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import {
77
import type {
88
AnySchema,
99
InferSchemaInput,
10+
InferSchemaInputSafe,
1011
InferSchemaOutput,
12+
InferSchemaOutputSafe,
1113
IsPromise,
1214
Prettify,
1315
ProcedureOptions,
@@ -31,8 +33,8 @@ export class Zagora<
3133
TIsHandlerAsync,
3234
THandlerFn,
3335
TContext extends any | undefined = undefined,
34-
TInputSchema extends AnySchema = AnySchema,
35-
TOutputSchema extends AnySchema = AnySchema,
36+
TInputSchema extends AnySchema | undefined = undefined,
37+
TOutputSchema extends AnySchema | undefined = undefined,
3638
TErrorsMap extends Record<string, AnySchema> | undefined = undefined,
3739
> {
3840
constructor(
@@ -106,18 +108,20 @@ export class Zagora<
106108
}
107109

108110
handler<
109-
TFn extends InferSchemaOutput<TInputSchema> extends readonly any[]
110-
? SpreadTuple<
111-
[
112-
Prettify<ProcedureOptions<TContext, TErrorsMap>>,
113-
...InferSchemaOutput<TInputSchema>,
114-
],
115-
any
116-
>
117-
: (
118-
options: Prettify<ProcedureOptions<TContext, TErrorsMap>>,
119-
arg: InferSchemaOutput<TInputSchema>,
120-
) => any,
111+
TFn extends TInputSchema extends AnySchema
112+
? InferSchemaOutput<TInputSchema> extends readonly any[]
113+
? SpreadTuple<
114+
[
115+
Prettify<ProcedureOptions<TContext, TErrorsMap>>,
116+
...InferSchemaOutput<TInputSchema>,
117+
],
118+
any
119+
>
120+
: (
121+
options: Prettify<ProcedureOptions<TContext, TErrorsMap>>,
122+
arg: InferSchemaOutput<TInputSchema>,
123+
) => any
124+
: (options: Prettify<ProcedureOptions<TContext, TErrorsMap>>) => any,
121125
TReturn = ReturnType<TFn>,
122126
TIsAsync extends boolean = IsPromise<TReturn>,
123127
>(
@@ -167,19 +171,21 @@ export class Zagora<
167171
type TResult = TIsHandlerAsync extends true
168172
? Promise<
169173
ZagoraResult<
170-
InferSchemaOutput<TOutputSchema>,
174+
InferSchemaOutputSafe<TOutputSchema>,
171175
ErrorsMapResolved<TErrorsMap>,
172176
TResolvedResult
173177
>
174178
>
175179
: ZagoraResult<
176-
InferSchemaOutput<TOutputSchema>,
180+
InferSchemaOutputSafe<TOutputSchema>,
177181
ErrorsMapResolved<TErrorsMap>,
178182
TResolvedResult
179183
>;
180184

181-
return procedure as InferSchemaInput<TInputSchema> extends readonly any[]
182-
? SpreadTuple<InferSchemaInput<TInputSchema>, TResult>
183-
: (arg: InferSchemaOutput<TInputSchema>) => TResult;
185+
return procedure as TInputSchema extends AnySchema
186+
? InferSchemaInput<TInputSchema> extends readonly any[]
187+
? SpreadTuple<InferSchemaInput<TInputSchema>, TResult>
188+
: (arg: InferSchemaOutput<TInputSchema>) => TResult
189+
: () => TResult;
184190
}
185191
}

new-src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ export type InferSchemaInput<T extends AnySchema> = T extends StandardSchemaV1<
2727
? UInput
2828
: never;
2929

30+
export type InferSchemaOutputSafe<T> = T extends AnySchema
31+
? InferSchemaOutput<T>
32+
: any;
33+
34+
export type InferSchemaInputSafe<T> = T extends AnySchema
35+
? InferSchemaInput<T>
36+
: any;
37+
3038
export type UppercaseKeys<T> = {
3139
[K in keyof T as Uppercase<string & K>]: T[K];
3240
};

new-test/edge-cases.test.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from "../new-src/errors";
1010
import { zagora } from "../new-src/index";
1111

12-
test("typed errors should be in options", () => {
12+
test("typed errors should be in options - when input schema is defined", () => {
1313
const errorSchemas = {
1414
BAR_ERR: z.object({
1515
msg: z.string(),
@@ -18,7 +18,7 @@ test("typed errors should be in options", () => {
1818
};
1919

2020
const func = zagora()
21-
// .input(z.string())
21+
.input(z.string())
2222
// .output(z.string())
2323
.errors(errorSchemas)
2424
// .errors({ FOO: z.object({ msg: z.string() }) })
@@ -310,3 +310,53 @@ test("Zod Tuple without defaults - missing required arg should fail", async () =
310310
expect(res.ok).toBe(false);
311311
expect(res.error?.message).toContain("Input validation failed");
312312
});
313+
314+
test("Handler without input schema should work", () => {
315+
const errorSchemas = {
316+
BARRY_ERR: z.object({
317+
msg: z.string(),
318+
foo: z.number().min(100).max(999).default(500),
319+
}),
320+
};
321+
322+
const func = zagora()
323+
// no .input() call
324+
.errors(errorSchemas)
325+
.handler(({ errors }) => {
326+
throw errors.BARRY_ERR({ msg: "Some custom error" });
327+
// biome-ignore lint/correctness/noUnreachable: bruh
328+
return "foo";
329+
})
330+
.callable();
331+
332+
const res = func();
333+
expect(res.ok).toBe(false);
334+
335+
if (res.error) {
336+
expect(Object.keys(errorSchemas)[0]).toBe(res.error.kind);
337+
expect(res.error.kind).toBe("BARRY_ERR");
338+
if (res.error.kind === "BARRY_ERR") {
339+
expect(res.error.msg).toBe("Some custom error");
340+
expect(res.error.foo).toBe(500);
341+
}
342+
} else {
343+
throw new Error(
344+
"Expected BARRY_ERR, but got: " + JSON.stringify(res.error),
345+
);
346+
}
347+
});
348+
349+
test("Handler without input schema and no errors should work", () => {
350+
const func = zagora()
351+
// no .input() call
352+
.handler(({ context }) => {
353+
return { result: "success", ctx: context };
354+
})
355+
.callable();
356+
357+
const res = func();
358+
expect(res.ok).toBe(true);
359+
if (res.ok) {
360+
expect(res.data).toEqual({ result: "success", ctx: undefined });
361+
}
362+
});

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@
4747
},
4848
"devDependencies": {
4949
"@biomejs/biome": "^2",
50-
"@types/bun": "latest",
50+
"@types/bun": "^1.3.3",
5151
"arktype": "2.1.23",
5252
"biome-config-xaxa": "^0.2.1",
53+
"bun-types": "^1.3.3",
5354
"expect-type": "^0.20.0",
5455
"tsdown": "^0.16.6",
5556
"tsgo-dev": "^2025.11.22",

tsconfig.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
"noUnusedParameters": false,
2424
"noPropertyAccessFromIndexSignature": false,
2525
"strictNullChecks": true,
26-
"types": []
26+
"types": ["bun-types"]
2727
},
28-
"include": ["new-src"],
29-
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
28+
"include": ["new-src", "new-test"],
29+
"exclude": ["node_modules", "dist"]
3030
}

0 commit comments

Comments
 (0)