@abinnovision/nestjs-例外
NestJS例外处理,以实体为重点的例外和GraphQL支持.
安装
yarn add @abinnovision/nestjs-exceptions
特征
- 应用例外: 有输入元数据的运输-不可知基例外类
- Http 软件排除: HTTP 状态代码和信头的 Opt- in接口
- 多选项: 多个例外的折叠器
- 常规例外过滤器: HTTP 和 GraphQL 的统一错误处理
- 以实体为重点的例外情况数字 :
EntityNotFoundException, (中文(简体) ),EntityMutationFailedException可配置实体显示名称
软件包切入点
该套件暴露出两个切入点:
@abinnovision/nestjs-exceptions——基础类,HTTP-意识接口,MultiAppException,以及GenericExceptionFilter。 。 。 .@abinnovision/nestjs-exceptions/entity- 以实体为重点的例外情况EntityRegistry增强点,以及实体名称渲染器辅助器.
快速启动
import { GenericExceptionFilter } from "@abinnovision/nestjs-exceptions";
import {
EntityNotFoundException,
EntityMutationFailedException,
configureEntityNameRenderer,
} from "@abinnovision/nestjs-exceptions/entity";
/**
* Configure entity display names at app startup.
*/
configureEntityNameRenderer({
user: "User",
organization: "Organization",
user_profile: "User profile",
});
throw new EntityNotFoundException({ entity: "user", entityId: "123" });
// Error message: "User with ID '123' not found"
throw new EntityMutationFailedException({
entity: "user",
entityId: "123",
mutationType: "update",
});
// Error message: "Failed to update User with ID '123'"
设置
1. 在应用程序启动时配置全球实体名称渲染器
// main.ts (or app.module.ts constructor)
import { configureEntityNameRenderer } from "@abinnovision/nestjs-exceptions/entity";
configureEntityNameRenderer({
user: "User",
organization: "Organization",
user_profile: "User profile",
});
2. 登记例外过滤器
// main.ts
import { GenericExceptionFilter } from "@abinnovision/nestjs-exceptions";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new GenericExceptionFilter());
await app.listen(3000);
}
滴滴类型增强
对于来自您 Drizzle 方案的安全类型实体名称,请添加
EntityRegistry 界面从 @abinnovision/nestjs-exceptions/entity。 。 。 .
一旦扩大,每个实体的例外 entity 字段自动
缩小——不需要子分类.
1. 衍生物a EntityName 联合从你的德利兹计划
// src/common/exceptions/entity-types.ts
import type { Table } from "drizzle-orm";
import type { db } from "../../database";
type GetTableName<T> = T extends Table<infer C> ? C["name"] : never;
type TableKeys<T> = {
[K in keyof T]: T[K] extends Table ? K : never;
}[keyof T];
/**
* Union of all entity names derived from Drizzle schema.
*/
export type EntityName = GetTableName<(typeof db)[TableKeys<typeof db>]>;
2. 工会登记 EntityRegistry
// src/common/exceptions/entity-registry.ts
import type { EntityName } from "./entity-types";
declare module "@abinnovision/nestjs-exceptions/entity" {
interface EntityRegistry {
entities: EntityName;
}
}
3. 直接使用例外情况 -- -- entity 现在已选中类型
import { EntityNotFoundException } from "@abinnovision/nestjs-exceptions/entity";
throw new EntityNotFoundException({ entity: "user", entityId: id }); // OK
throw new EntityNotFoundException({ entity: "invalid", entityId: id }); // Type error!
API 参考
核心类
AppException<M>
摘要,所有应用例外的运输不可知基等.
abstract class AppException<M = unknown> extends Error {
abstract code: string;
readonly details: string;
readonly meta?: M;
readonly cause?: Error;
readonly sourcePointer?: string;
}
HttpAwareException
由带有HTTP特定信息的例外执行接口.
在 AppException 应影响 HTTP 的子类
响应状态代码和信头.
interface HttpAwareException {
readonly httpStatus: number;
readonly headers?: Record<string, string>;
}
function isHttpAwareException(value: unknown): value is HttpAwareException;
MultiAppException
用于多个例外的包装.
import { MultiAppException } from "@abinnovision/nestjs-exceptions";
import { EntityNotFoundException } from "@abinnovision/nestjs-exceptions/entity";
const errors = new MultiAppException([
new EntityNotFoundException({ entity: "user", entityId: "1" }),
new EntityNotFoundException({ entity: "user", entityId: "2" }),
]);
GenericExceptionFilter
处理 HTTP 和 GraphQL 上下文的例外过滤器 .
实体除外
以下所有符号均从 @abinnovision/nestjs-exceptions/entity。 。 。 .
EntityNotFoundException
未找到实体时抛出 .
throw new EntityNotFoundException({ entity: "user", entityId: "123" });
// Code: COMMON__NOT_FOUND
// HTTP Status: 404
EntityMutationFailedException
当创建/更新/删除操作失败时丢弃 .
throw new EntityMutationFailedException({
entity: "user",
entityId: "123",
mutationType: "update", // 'create' | 'update' | 'delete'
});
// Code: COMMON__MUTATION_FAILED
// HTTP Status: 400
实体名称渲染器
configureEntityNameRenderer(displayNames)
配置全局实体名称渲染器 。 启动时打一次电话.
接受一个 Record<EntityName, string> 绘图要显示名称的实体名称 .
getEntityDisplayName(entity)
获取使用全局渲染器的实体的显示名称 。 倒计时 未配置映射时的原始实体名称.
resetEntityNameRenderer()
重置到默认( 空) 渲染器 。 有用的测试.
创建自定义例外
扩展 AppException 用于海关例外。 选择到 HTTP 语义
执行 HttpAwareException数字 :
import {
AppException,
type HttpAwareException,
} from "@abinnovision/nestjs-exceptions";
interface ValidationMeta {
field: string;
constraint: string;
}
export class ValidationException
extends AppException<ValidationMeta>
implements HttpAwareException
{
public override code = "VALIDATION__FAILED";
public readonly httpStatus = 400;
public constructor(field: string, constraint: string) {
super(`Validation failed for field '${field}': ${constraint}`, {
meta: { field, constraint },
});
}
}
或者延长 EntityFocusedAppException 与实体有关的例外情况:
import { type HttpAwareException } from "@abinnovision/nestjs-exceptions";
import {
EntityFocusedAppException,
type EntityFocusedArgs,
} from "@abinnovision/nestjs-exceptions/entity";
import type { AppExceptionOptsWithoutMeta } from "@abinnovision/nestjs-exceptions";
export class DuplicateEntityException
extends EntityFocusedAppException
implements HttpAwareException
{
public override code = "COMMON__DUPLICATE";
public readonly httpStatus = 409;
public constructor(
args: EntityFocusedArgs,
opts?: AppExceptionOptsWithoutMeta,
) {
super(
args,
(displayName, entityId) =>
`${displayName} with ID '${entityId}' already exists`,
opts,
);
}
}
许可证
阿帕奇 - 2.0