feat(core-shared): add defineErrorMiddleware factory + export t
Factory takes [[ErrorCtor, TRPC_CODE], ...] tuples and returns a tRPC middleware that translates matching domain errors to TRPCError. Discrim- inates by instanceof; preserves original error as cause; unmapped errors propagate (tRPC then wraps them as INTERNAL_SERVER_ERROR with the original error as .cause — middleware does not interfere). core-shared never enumerates feature errors — each feature passes its own constructors in via integrations/api/procedures.ts (Tasks 3-7). Also exports the `t` instance from trpc/init.ts so feature procedure files can do t.procedure.use(...). Also fixes tsconfig.json: rootDir set to "." and @/* path alias added so test files using @/ resolve correctly under tsc --noEmit. Refactor log: §1, §2, §4 Spec: R13–R17
This commit is contained in:
36
packages/core-shared/src/trpc/define-error-middleware.ts
Normal file
36
packages/core-shared/src/trpc/define-error-middleware.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import type { TRPC_ERROR_CODE_KEY } from "@trpc/server/rpc";
|
||||
import { t } from "./init";
|
||||
|
||||
type ErrorCtor = new (...args: never[]) => Error;
|
||||
|
||||
/**
|
||||
* Build a tRPC middleware that translates domain errors to TRPCError.
|
||||
*
|
||||
* Each tuple pairs a constructor with a TRPC error code. The middleware
|
||||
* runs the procedure body inside a try/catch; on `instanceof Ctor`,
|
||||
* it throws a TRPCError with the configured code and the original error
|
||||
* preserved as `.cause`. Unmapped errors propagate untouched (tRPC's
|
||||
* default INTERNAL_SERVER_ERROR handling applies).
|
||||
*
|
||||
* Owned by features: each feature passes its own constructors in.
|
||||
* core-shared never enumerates feature-specific error classes.
|
||||
*/
|
||||
export function defineErrorMiddleware(
|
||||
map: ReadonlyArray<readonly [ErrorCtor, TRPC_ERROR_CODE_KEY]>,
|
||||
) {
|
||||
return t.middleware(async ({ next }) => {
|
||||
const result = await next();
|
||||
if (!result.ok) {
|
||||
const cause = result.error.cause;
|
||||
if (cause instanceof Error) {
|
||||
for (const [Ctor, code] of map) {
|
||||
if (cause instanceof Ctor) {
|
||||
throw new TRPCError({ code, message: cause.message, cause });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user