@asapjs/error 1.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # @asapjs/error
2
+
3
+ TypeScript 기반 ASAP.js 프레임워크를 위한 Effect 통합 에러 처리 패키지
4
+
5
+ ## 주요 기능
6
+
7
+ - **TypeIs 기반 에러 정의**: 간단하고 타입 안전한 에러 생성
8
+ - **자동 Swagger 문서화**: TypeIs 스키마로부터 OpenAPI 스펙 자동 생성
9
+ - **Effect 라이브러리 통합**: stack-safe 로깅 및 구조화된 에러 처리
10
+ - **레거시 호환성**: 기존 `HttpException` 지원
11
+
12
+ ## 설치
13
+
14
+ ```bash
15
+ yarn add @asapjs/error effect
16
+ ```
17
+
18
+ ## 기본 사용법
19
+
20
+ ### 1. 에러 정의 (새로운 방식)
21
+
22
+ ```typescript
23
+ import { error, TypeIs } from '@asapjs/error';
24
+
25
+ export class UserErrors {
26
+ static NOT_FOUND = error(404, "USER_NOT_FOUND", "사용자를 찾을 수 없습니다. ID: {userId}", {
27
+ userId: TypeIs.INT({ comment: "사용자 ID" }),
28
+ });
29
+
30
+ static EMAIL_DUPLICATE = error(409, "USER_EMAIL_DUPLICATE", "이미 사용 중인 이메일입니다: {email}", {
31
+ email: TypeIs.STRING({ comment: "중복된 이메일" }),
32
+ existingUserId: TypeIs.INT({ comment: "기존 사용자 ID", optional: true }),
33
+ });
34
+
35
+ static INVALID_DATA = error(400, "USER_INVALID_DATA", "잘못된 사용자 데이터입니다", {
36
+ invalidFields: TypeIs.ARRAY({
37
+ type: () => TypeIs.STRING(),
38
+ comment: "유효하지 않은 필드 목록"
39
+ }),
40
+ details: TypeIs.JSON({
41
+ comment: "상세 오류 정보",
42
+ optional: true
43
+ }),
44
+ });
45
+ }
46
+ ```
47
+
48
+ ### 2. 컨트롤러에서 사용
49
+
50
+ ```typescript
51
+ import { Get, Post, RouterController } from '@asapjs/router';
52
+ import { wrapWithEffect } from '@asapjs/error';
53
+ import { UserErrors } from './errors/UserErrors';
54
+
55
+ export default class UserController extends RouterController {
56
+ @Get('/:id', {
57
+ title: '사용자 조회',
58
+ errors: [UserErrors.NOT_FOUND], // Swagger에 자동으로 문서화
59
+ })
60
+ public getUser = wrapWithEffect(async ({ path }) => {
61
+ const user = await findUser(path.id);
62
+ if (!user) {
63
+ throw UserErrors.NOT_FOUND({ userId: path.id });
64
+ }
65
+ return { result: user };
66
+ });
67
+
68
+ @Post('/', {
69
+ title: '사용자 생성',
70
+ body: CreateUserDto,
71
+ errors: [UserErrors.EMAIL_DUPLICATE, UserErrors.INVALID_DATA],
72
+ })
73
+ public createUser = wrapWithEffect(async ({ body }) => {
74
+ // 이메일 검증
75
+ if (!isValidEmail(body.email)) {
76
+ throw UserErrors.INVALID_DATA({
77
+ invalidFields: ['email'],
78
+ details: { email: 'Invalid email format' }
79
+ });
80
+ }
81
+
82
+ // 중복 체크
83
+ const existing = await findUserByEmail(body.email);
84
+ if (existing) {
85
+ throw UserErrors.EMAIL_DUPLICATE({
86
+ email: body.email,
87
+ existingUserId: existing.id
88
+ });
89
+ }
90
+
91
+ const user = await createUser(body);
92
+ return { result: user };
93
+ });
94
+ }
95
+ ```
96
+
97
+ ### 3. Express 앱에 미들웨어 적용
98
+
99
+ ```typescript
100
+ import { effectErrorHandler } from '@asapjs/error';
101
+
102
+ app.use(effectErrorHandler);
103
+ ```
104
+
105
+ ## HTTP 에러 응답 포맷
106
+
107
+ 모든 에러는 다음과 같은 통일된 포맷으로 응답됩니다:
108
+
109
+ ```json
110
+ {
111
+ "status": 404,
112
+ "errorCode": "USER_NOT_FOUND",
113
+ "message": "사용자를 찾을 수 없습니다. ID: 123",
114
+ "data": {
115
+ "userId": 123
116
+ }
117
+ }
118
+ ```
119
+
120
+ ## 주요 특징
121
+
122
+ ### 1. TypeIs를 활용한 타입 안전성
123
+
124
+ ```typescript
125
+ // 컴파일 타임에 타입 체크
126
+ throw UserErrors.NOT_FOUND({ userId: "123" }); // ❌ Error: userId must be number
127
+ throw UserErrors.NOT_FOUND({ userId: 123 }); // ✅ OK
128
+ ```
129
+
130
+ ### 2. 메시지 템플릿
131
+
132
+ 에러 메시지에 `{fieldName}` 형식으로 데이터를 삽입할 수 있습니다:
133
+
134
+ ```typescript
135
+ static NOT_FOUND = error(404, "USER_NOT_FOUND", "사용자 {userId}를 찾을 수 없습니다", {
136
+ userId: TypeIs.INT(),
137
+ });
138
+
139
+ // 사용 시: "사용자 123를 찾을 수 없습니다"
140
+ throw UserErrors.NOT_FOUND({ userId: 123 });
141
+ ```
142
+
143
+ ### 3. 자동 Swagger 문서화
144
+
145
+ TypeIs 스키마가 자동으로 OpenAPI 스펙으로 변환됩니다:
146
+
147
+ ```yaml
148
+ components:
149
+ schemas:
150
+ USER_NOT_FOUND:
151
+ type: object
152
+ properties:
153
+ status:
154
+ type: number
155
+ example: 404
156
+ errorCode:
157
+ type: string
158
+ example: USER_NOT_FOUND
159
+ message:
160
+ type: string
161
+ data:
162
+ type: object
163
+ properties:
164
+ userId:
165
+ type: integer
166
+ description: 사용자 ID
167
+ ```
168
+
169
+ ## TypeIs 지원 타입
170
+
171
+ ```typescript
172
+ TypeIs.INT() // 정수
173
+ TypeIs.STRING() // 문자열
174
+ TypeIs.BOOLEAN() // 불린
175
+ TypeIs.FLOAT() // 실수
176
+ TypeIs.JSON() // JSON 객체
177
+ TypeIs.ARRAY() // 배열
178
+ TypeIs.DATETIME() // 날짜/시간
179
+ TypeIs.ENUM() // 열거형
180
+ ```
181
+
182
+ 모든 타입은 `optional: true` 옵션을 지원합니다.
183
+
184
+ ## 고급 기능
185
+
186
+ ### Effect 래핑
187
+
188
+ `wrapWithEffect`는 다음 기능을 제공합니다:
189
+
190
+ - 자동 스팬 트레이싱
191
+ - 구조화된 로깅 (요청 ID, 파일, 라인, 함수명 포함)
192
+ - Effect Exit 처리
193
+
194
+ ### 레거시 호환성
195
+
196
+ 기존 `HttpException`을 사용하는 코드도 자동으로 처리됩니다:
197
+
198
+ ```typescript
199
+ throw new HttpException(400, '잘못된 요청입니다');
200
+ // 자동으로 { status: 400, errorCode: 'LEGACY_HTTP_EXCEPTION', message: '...' } 로 변환
201
+ ```
202
+
203
+ ## 마이그레이션 가이드
204
+
205
+ ### 기존 방식
206
+
207
+ ```typescript
208
+ export class UserNotFoundError extends NotFoundError {
209
+ constructor(userId: number) {
210
+ super('USER_NOT_FOUND', `사용자를 찾을 수 없습니다. ID: ${userId}`, { userId });
211
+ }
212
+ }
213
+
214
+ throw new UserNotFoundError(123);
215
+ ```
216
+
217
+ ### 새로운 방식
218
+
219
+ ```typescript
220
+ export class UserErrors {
221
+ static NOT_FOUND = error(404, "USER_NOT_FOUND", "사용자를 찾을 수 없습니다. ID: {userId}", {
222
+ userId: TypeIs.INT(),
223
+ });
224
+ }
225
+
226
+ throw UserErrors.NOT_FOUND({ userId: 123 });
227
+ ```
228
+
229
+ 새로운 방식은 더 간결하고, 타입 안전하며, 자동 문서화를 지원합니다.
@@ -0,0 +1,15 @@
1
+ import { HttpError } from './types';
2
+ export interface ErrorCreator<T = any> {
3
+ (data: T): HttpError;
4
+ _status: number;
5
+ _code: string;
6
+ _message: string;
7
+ _schema: Record<string, any>;
8
+ }
9
+ export declare function error<T extends Record<string, any>>(status: number, code: string, message: string, schema: T): ErrorCreator<InferTypeFromSchema<T>>;
10
+ export declare function setAddSchemeFunction(func: any): void;
11
+ export declare function markSwaggerAsReady(): void;
12
+ type InferTypeFromSchema<T extends Record<string, any>> = {
13
+ [K in keyof T]: any;
14
+ };
15
+ export {};
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.error = error;
4
+ exports.setAddSchemeFunction = setAddSchemeFunction;
5
+ exports.markSwaggerAsReady = markSwaggerAsReady;
6
+ // addScheme will be injected at runtime
7
+ let addSchemeFunc = () => { };
8
+ const types_1 = require("./types");
9
+ const schema_1 = require("./schema");
10
+ // 지연 등록을 위한 큐
11
+ const pendingSchemas = [];
12
+ let isSwaggerReady = false;
13
+ function error(status, code, message, schema) {
14
+ // Swagger 스키마 등록 (지연 실행)
15
+ const registerSchema = () => registerErrorSwaggerSchema(code, status, message, schema);
16
+ if (isSwaggerReady) {
17
+ registerSchema();
18
+ }
19
+ else {
20
+ pendingSchemas.push(registerSchema);
21
+ }
22
+ // 에러 생성 함수
23
+ const creator = ((data) => {
24
+ // 스키마 등록 확인 (첫 사용 시)
25
+ ensureSchemaRegistered(code, status, message, schema);
26
+ // 데이터 유효성 검사
27
+ (0, schema_1.validateDataWithSchema)(data, schema);
28
+ // 메시지 템플릿 처리 (예: "사용자 {userId}를 찾을 수 없습니다")
29
+ const finalMessage = interpolateMessage(message, data);
30
+ return new types_1.HttpError(status, code, finalMessage, data);
31
+ });
32
+ // 메타데이터 저장 (Swagger 문서화용)
33
+ creator._status = status;
34
+ creator._code = code;
35
+ creator._message = message;
36
+ // 원본 schema를 그대로 저장 (함수 호출 결과가 아닌 원본)
37
+ creator._schema = schema;
38
+ return creator;
39
+ }
40
+ // addScheme 함수 주입
41
+ function setAddSchemeFunction(func) {
42
+ addSchemeFunc = func;
43
+ }
44
+ // Swagger가 준비되면 호출
45
+ function markSwaggerAsReady() {
46
+ isSwaggerReady = true;
47
+ // 대기 중인 스키마 모두 등록
48
+ while (pendingSchemas.length > 0) {
49
+ const register = pendingSchemas.shift();
50
+ if (register)
51
+ register();
52
+ }
53
+ }
54
+ // 스키마가 등록되었는지 확인하고 필요시 등록
55
+ const registeredSchemas = new Set();
56
+ function ensureSchemaRegistered(code, status, message, schema) {
57
+ if (!registeredSchemas.has(code)) {
58
+ registerErrorSwaggerSchema(code, status, message, schema);
59
+ registeredSchemas.add(code);
60
+ }
61
+ }
62
+ function registerErrorSwaggerSchema(code, status, message, schema) {
63
+ const swaggerSchema = {
64
+ type: 'object',
65
+ properties: {
66
+ status: { type: 'number', example: status },
67
+ errorCode: { type: 'string', example: code },
68
+ message: { type: 'string', example: message },
69
+ data: {
70
+ type: 'object',
71
+ properties: Object.entries(schema).reduce((acc, [key, typeIs]) => {
72
+ acc[key] = (0, schema_1.typeIsToSwaggerSchema)(typeIs);
73
+ return acc;
74
+ }, {}),
75
+ },
76
+ },
77
+ required: ['status', 'errorCode', 'message'],
78
+ };
79
+ addSchemeFunc({
80
+ name: code,
81
+ data: swaggerSchema,
82
+ });
83
+ }
84
+ function interpolateMessage(template, data) {
85
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
86
+ return data[key] !== undefined ? String(data[key]) : match;
87
+ });
88
+ }
@@ -0,0 +1,7 @@
1
+ import { Effect, Cause } from 'effect';
2
+ import { Response } from 'express';
3
+ import { HttpErrorBody } from './types';
4
+ export declare function makeHttpError(status: number, errorCode: string, message: string, data?: Record<string, any>): HttpErrorBody;
5
+ export declare function errorToResponse(error: unknown, res: Response): void;
6
+ export declare function causeToError(cause: Cause.Cause<unknown>): unknown;
7
+ export declare function runEffectAsPromise<A, E>(effect: Effect.Effect<A, E, never>): Promise<A>;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeHttpError = makeHttpError;
4
+ exports.errorToResponse = errorToResponse;
5
+ exports.causeToError = causeToError;
6
+ exports.runEffectAsPromise = runEffectAsPromise;
7
+ const effect_1 = require("effect");
8
+ const types_1 = require("./types");
9
+ function makeHttpError(status, errorCode, message, data) {
10
+ return {
11
+ status,
12
+ errorCode,
13
+ message,
14
+ data,
15
+ };
16
+ }
17
+ function errorToResponse(error, res) {
18
+ let errorBody;
19
+ if (error instanceof types_1.HttpError) {
20
+ errorBody = error.toJSON();
21
+ }
22
+ else if (error && typeof error === 'object' && 'status' in error && 'message' in error && !('errorCode' in error)) {
23
+ // Legacy HttpException 지원
24
+ errorBody = {
25
+ status: error.status,
26
+ errorCode: 'LEGACY_HTTP_EXCEPTION',
27
+ message: error.message,
28
+ };
29
+ }
30
+ else if (error && typeof error === 'object' && 'status' in error && 'errorCode' in error && 'message' in error) {
31
+ errorBody = error;
32
+ }
33
+ else {
34
+ errorBody = new types_1.HttpError(500, 'INTERNAL_SERVER_ERROR', error instanceof Error ? error.message : '알 수 없는 서버 오류가 발생했습니다.').toJSON();
35
+ }
36
+ res.status(errorBody.status).json(errorBody);
37
+ }
38
+ function causeToError(cause) {
39
+ const failureOption = effect_1.Cause.failureOption(cause);
40
+ const dieOption = effect_1.Cause.dieOption(cause);
41
+ if (failureOption._tag === 'Some') {
42
+ return failureOption.value;
43
+ }
44
+ else if (dieOption._tag === 'Some') {
45
+ return dieOption.value;
46
+ }
47
+ else if (effect_1.Cause.isInterrupted(cause)) {
48
+ return new Error('Operation interrupted');
49
+ }
50
+ else {
51
+ const failures = effect_1.Cause.failures(cause);
52
+ if (effect_1.Chunk.size(failures) > 0) {
53
+ return effect_1.Chunk.unsafeGet(failures, 0);
54
+ }
55
+ return new Error('Unknown error');
56
+ }
57
+ }
58
+ async function runEffectAsPromise(effect) {
59
+ const exit = await effect_1.Effect.runPromiseExit(effect);
60
+ if (effect_1.Exit.isSuccess(exit)) {
61
+ return exit.value;
62
+ }
63
+ else {
64
+ const error = causeToError(exit.cause);
65
+ throw error;
66
+ }
67
+ }
@@ -0,0 +1,5 @@
1
+ export * from './types';
2
+ export * from './helpers';
3
+ export * from './middleware';
4
+ export * from './factory';
5
+ export * from './schema';
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./helpers"), exports);
19
+ __exportStar(require("./middleware"), exports);
20
+ __exportStar(require("./factory"), exports);
21
+ __exportStar(require("./schema"), exports);
22
+ // HttpException은 router 패키지에서 직접 import 해야 함 (순환 의존성 방지)
@@ -0,0 +1,7 @@
1
+ import { NextFunction, Request, Response } from 'express';
2
+ interface RequestWithId extends Request {
3
+ id?: string;
4
+ }
5
+ export declare const effectErrorHandler: (error: unknown, req: RequestWithId, res: Response, next: NextFunction) => void;
6
+ export declare function wrapWithEffect<T extends (...args: any[]) => any>(handler: T): (...args: any[]) => Promise<any>;
7
+ export {};
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.effectErrorHandler = void 0;
4
+ exports.wrapWithEffect = wrapWithEffect;
5
+ const effect_1 = require("effect");
6
+ const common_1 = require("@asapjs/common");
7
+ const helpers_1 = require("./helpers");
8
+ function getStackInfo(error) {
9
+ const stack = error.stack || '';
10
+ const stackLines = stack.split('\n');
11
+ for (const line of stackLines) {
12
+ const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
13
+ if (match) {
14
+ const [, functionName, file, line, column] = match;
15
+ return { functionName, file, line: parseInt(line), column: parseInt(column) };
16
+ }
17
+ const simpleMatch = line.match(/at\s+(.+?):(\d+):(\d+)/);
18
+ if (simpleMatch) {
19
+ const [, file, line, column] = simpleMatch;
20
+ return { functionName: 'anonymous', file, line: parseInt(line), column: parseInt(column) };
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ const effectErrorHandler = (error, req, res, next) => {
26
+ const config = (0, common_1.getConfig)();
27
+ const requestId = req.id || 'unknown';
28
+ const stackInfo = error instanceof Error ? getStackInfo(error) : null;
29
+ const logContext = {
30
+ requestId,
31
+ method: req.method,
32
+ url: req.url,
33
+ ip: req.ip,
34
+ userAgent: req.get('user-agent'),
35
+ ...(stackInfo && {
36
+ file: stackInfo.file,
37
+ line: stackInfo.line,
38
+ function: stackInfo.functionName,
39
+ }),
40
+ };
41
+ if (error instanceof Error) {
42
+ common_1.logger.error(`Error: ${error.message}`, {
43
+ ...logContext,
44
+ stack: error.stack,
45
+ errorName: error.name,
46
+ });
47
+ }
48
+ else {
49
+ common_1.logger.error('Non-Error thrown', {
50
+ ...logContext,
51
+ error: String(error),
52
+ });
53
+ }
54
+ (0, helpers_1.errorToResponse)(error, res);
55
+ };
56
+ exports.effectErrorHandler = effectErrorHandler;
57
+ function wrapWithEffect(handler) {
58
+ return async (...args) => {
59
+ const [req, res, next] = args;
60
+ try {
61
+ const effect = effect_1.Effect.promise(() => handler(...args));
62
+ const traced = effect_1.Effect.withSpan(effect, `${req.method} ${req.path}`, {
63
+ attributes: {
64
+ 'http.method': req.method,
65
+ 'http.path': req.path,
66
+ 'http.request_id': req.id || 'unknown',
67
+ },
68
+ });
69
+ const result = await effect_1.Effect.runPromise(traced);
70
+ return result;
71
+ }
72
+ catch (error) {
73
+ if (next) {
74
+ next(error);
75
+ }
76
+ else {
77
+ throw error;
78
+ }
79
+ }
80
+ };
81
+ }
@@ -0,0 +1,3 @@
1
+ import { SchemaType } from '@asapjs/schema';
2
+ export declare function typeIsToSwaggerSchema(typeIs: SchemaType): any;
3
+ export declare function validateDataWithSchema(data: any, schema: Record<string, any>): void;
package/dist/schema.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.typeIsToSwaggerSchema = typeIsToSwaggerSchema;
4
+ exports.validateDataWithSchema = validateDataWithSchema;
5
+ function typeIsToSwaggerSchema(typeIs) {
6
+ // @asapjs/schema의 toSwagger 메서드 사용
7
+ if (typeIs.toSwagger) {
8
+ return typeIs.toSwagger();
9
+ }
10
+ // fallback
11
+ return { type: 'string' };
12
+ }
13
+ function validateDataWithSchema(data, schema) {
14
+ if (!data || typeof data !== 'object') {
15
+ throw new Error('Invalid data: must be an object');
16
+ }
17
+ for (const [key, typeIs] of Object.entries(schema)) {
18
+ const value = data[key];
19
+ // TypeIs가 함수로 전달된 경우 실행
20
+ const schemaType = typeof typeIs === 'function' ? typeIs() : typeIs;
21
+ // optional 여부 확인
22
+ const isOptional = schemaType.__options.optional || false;
23
+ // 필수 필드 체크
24
+ if (value === undefined && !isOptional) {
25
+ throw new Error(`Missing required field: ${key}`);
26
+ }
27
+ // 값이 있을 때만 타입 체크
28
+ if (value !== undefined) {
29
+ validateFieldType(key, value, schemaType);
30
+ }
31
+ }
32
+ }
33
+ function validateFieldType(fieldName, value, schemaType) {
34
+ // @asapjs/schema의 validate 메서드 사용
35
+ if (!schemaType.validate(value)) {
36
+ throw new Error(`Field '${fieldName}' has invalid type for ${schemaType.__name}`);
37
+ }
38
+ }
@@ -0,0 +1,14 @@
1
+ export interface HttpErrorBody {
2
+ status: number;
3
+ errorCode: string;
4
+ message: string;
5
+ data?: Record<string, any>;
6
+ }
7
+ export declare class HttpError extends Error implements HttpErrorBody {
8
+ readonly status: number;
9
+ readonly errorCode: string;
10
+ readonly message: string;
11
+ readonly data?: Record<string, any>;
12
+ constructor(status: number, errorCode: string, message: string, data?: Record<string, any>);
13
+ toJSON(): HttpErrorBody;
14
+ }
package/dist/types.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpError = void 0;
4
+ class HttpError extends Error {
5
+ constructor(status, errorCode, message, data) {
6
+ super(message);
7
+ this.name = 'HttpError';
8
+ this.status = status;
9
+ this.errorCode = errorCode;
10
+ this.message = message;
11
+ this.data = data;
12
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
13
+ if (Error.captureStackTrace) {
14
+ Error.captureStackTrace(this, HttpError);
15
+ }
16
+ }
17
+ toJSON() {
18
+ return {
19
+ status: this.status,
20
+ errorCode: this.errorCode,
21
+ message: this.message,
22
+ data: this.data,
23
+ };
24
+ }
25
+ }
26
+ exports.HttpError = HttpError;
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@asapjs/error",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "Error handling utilities for ASAP.js with Effect integration",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch"
13
+ },
14
+ "dependencies": {
15
+ "@asapjs/common": "1.0.0-alpha.0",
16
+ "@asapjs/schema": "1.0.0-alpha.0",
17
+ "@asapjs/types": "1.0.0-alpha.0",
18
+ "effect": "^3.11.11",
19
+ "express": "^4.17.3"
20
+ },
21
+ "devDependencies": {
22
+ "@types/express": "^4.17.13",
23
+ "@types/node": "^17.0.21",
24
+ "typescript": "^5.8.3"
25
+ },
26
+ "author": "",
27
+ "license": "ISC",
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "gitHead": "79561e3604dc505813035558d1bfcc6cda0b088a"
32
+ }