@perkos/util-errors 1.0.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,93 @@
1
+ # @perkos/util-errors
2
+
3
+ Error handling utilities and classes for vendor services with Zod integration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @perkos/util-errors
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import {
15
+ AppError,
16
+ ValidationError,
17
+ PaymentError,
18
+ formatErrorResponse,
19
+ getErrorStatusCode,
20
+ } from "@perkos/util-errors";
21
+ import { z } from "zod";
22
+
23
+ // Throw application errors with context
24
+ throw new AppError("Something went wrong", 500, true, { userId: "123" });
25
+
26
+ // Throw validation errors
27
+ throw new ValidationError("Invalid input", [{ field: "email", message: "Required" }]);
28
+
29
+ // Create from Zod errors
30
+ try {
31
+ schema.parse(data);
32
+ } catch (error) {
33
+ if (error instanceof z.ZodError) {
34
+ throw ValidationError.fromZodError(error);
35
+ }
36
+ }
37
+
38
+ // Payment errors for x402
39
+ throw new PaymentError("Payment failed", "Insufficient funds");
40
+
41
+ // Format errors for API response
42
+ const response = formatErrorResponse(error);
43
+ const statusCode = getErrorStatusCode(error);
44
+ ```
45
+
46
+ ## Error Classes
47
+
48
+ ### `AppError`
49
+ Base error class with HTTP status code and context.
50
+
51
+ ```typescript
52
+ new AppError(message, statusCode?, isOperational?, context?)
53
+ ```
54
+
55
+ ### `ValidationError`
56
+ For request validation failures with Zod integration.
57
+
58
+ ```typescript
59
+ new ValidationError(message?, details?)
60
+ ValidationError.fromZodError(zodError)
61
+ ```
62
+
63
+ ### `PaymentError`
64
+ For x402 payment-related failures.
65
+
66
+ ```typescript
67
+ new PaymentError(message, reason?, transactionHash?, context?)
68
+ ```
69
+
70
+ ### Other Errors
71
+ - `NotFoundError` (404)
72
+ - `UnauthorizedError` (401)
73
+ - `ForbiddenError` (403)
74
+ - `RateLimitError` (429)
75
+ - `ServiceUnavailableError` (503)
76
+
77
+ ## Utilities
78
+
79
+ ### `formatErrorResponse(error)`
80
+ Format any error for API response.
81
+
82
+ ### `getErrorStatusCode(error)`
83
+ Get HTTP status code from any error.
84
+
85
+ ### `isOperationalError(error)`
86
+ Check if error is operational (expected) vs programming error.
87
+
88
+ ### `createErrorHandler(options?)`
89
+ Create error handler middleware.
90
+
91
+ ## License
92
+
93
+ MIT
@@ -0,0 +1,126 @@
1
+ import { ZodError } from 'zod';
2
+
3
+ /**
4
+ * @perkos/error-handling
5
+ * Error handling utilities and classes for vendor services
6
+ */
7
+
8
+ /**
9
+ * Base application error class
10
+ * Extends Error with HTTP status code and context
11
+ */
12
+ declare class AppError extends Error {
13
+ readonly statusCode: number;
14
+ readonly isOperational: boolean;
15
+ readonly context?: Record<string, any>;
16
+ constructor(message: string, statusCode?: number, isOperational?: boolean, context?: Record<string, any>);
17
+ toJSON(): {
18
+ error: string;
19
+ statusCode: number;
20
+ context: Record<string, any> | undefined;
21
+ };
22
+ }
23
+ /**
24
+ * Validation error class
25
+ * For request validation failures with Zod integration
26
+ */
27
+ declare class ValidationError extends AppError {
28
+ readonly details?: any;
29
+ constructor(message?: string, details?: any);
30
+ /**
31
+ * Create ValidationError from ZodError
32
+ */
33
+ static fromZodError(error: ZodError): ValidationError;
34
+ toJSON(): {
35
+ error: string;
36
+ details: any;
37
+ statusCode: number;
38
+ context: Record<string, any> | undefined;
39
+ };
40
+ }
41
+ /**
42
+ * Payment error class
43
+ * For x402 payment-related failures
44
+ */
45
+ declare class PaymentError extends AppError {
46
+ readonly reason?: string;
47
+ readonly transactionHash?: string;
48
+ constructor(message: string, reason?: string, transactionHash?: string, context?: Record<string, any>);
49
+ toJSON(): {
50
+ error: string;
51
+ reason: string | undefined;
52
+ transactionHash: string | undefined;
53
+ statusCode: number;
54
+ context: Record<string, any> | undefined;
55
+ };
56
+ }
57
+ /**
58
+ * Not found error class
59
+ */
60
+ declare class NotFoundError extends AppError {
61
+ constructor(message?: string, context?: Record<string, any>);
62
+ }
63
+ /**
64
+ * Unauthorized error class
65
+ */
66
+ declare class UnauthorizedError extends AppError {
67
+ constructor(message?: string, context?: Record<string, any>);
68
+ }
69
+ /**
70
+ * Forbidden error class
71
+ */
72
+ declare class ForbiddenError extends AppError {
73
+ constructor(message?: string, context?: Record<string, any>);
74
+ }
75
+ /**
76
+ * Rate limit error class
77
+ */
78
+ declare class RateLimitError extends AppError {
79
+ readonly retryAfter?: number;
80
+ constructor(message?: string, retryAfter?: number, context?: Record<string, any>);
81
+ toJSON(): {
82
+ error: string;
83
+ retryAfter: number | undefined;
84
+ statusCode: number;
85
+ context: Record<string, any> | undefined;
86
+ };
87
+ }
88
+ /**
89
+ * Service unavailable error class
90
+ */
91
+ declare class ServiceUnavailableError extends AppError {
92
+ constructor(message?: string, context?: Record<string, any>);
93
+ }
94
+ /**
95
+ * Check if error is operational (expected) or programming error
96
+ */
97
+ declare function isOperationalError(error: Error): boolean;
98
+ /**
99
+ * Error response formatter for API responses
100
+ */
101
+ interface ErrorResponse {
102
+ error: string;
103
+ message?: string;
104
+ details?: any;
105
+ statusCode: number;
106
+ }
107
+ /**
108
+ * Format error for API response
109
+ */
110
+ declare function formatErrorResponse(error: unknown): ErrorResponse;
111
+ /**
112
+ * Get HTTP status code from error
113
+ */
114
+ declare function getErrorStatusCode(error: unknown): number;
115
+ /**
116
+ * Create error handler middleware (framework-agnostic)
117
+ */
118
+ declare function createErrorHandler(options?: {
119
+ logger?: (error: Error, context?: Record<string, any>) => void;
120
+ includeStack?: boolean;
121
+ }): (error: unknown) => {
122
+ response: ErrorResponse;
123
+ statusCode: number;
124
+ };
125
+
126
+ export { AppError, type ErrorResponse, ForbiddenError, NotFoundError, PaymentError, RateLimitError, ServiceUnavailableError, UnauthorizedError, ValidationError, createErrorHandler, formatErrorResponse, getErrorStatusCode, isOperationalError };
@@ -0,0 +1,126 @@
1
+ import { ZodError } from 'zod';
2
+
3
+ /**
4
+ * @perkos/error-handling
5
+ * Error handling utilities and classes for vendor services
6
+ */
7
+
8
+ /**
9
+ * Base application error class
10
+ * Extends Error with HTTP status code and context
11
+ */
12
+ declare class AppError extends Error {
13
+ readonly statusCode: number;
14
+ readonly isOperational: boolean;
15
+ readonly context?: Record<string, any>;
16
+ constructor(message: string, statusCode?: number, isOperational?: boolean, context?: Record<string, any>);
17
+ toJSON(): {
18
+ error: string;
19
+ statusCode: number;
20
+ context: Record<string, any> | undefined;
21
+ };
22
+ }
23
+ /**
24
+ * Validation error class
25
+ * For request validation failures with Zod integration
26
+ */
27
+ declare class ValidationError extends AppError {
28
+ readonly details?: any;
29
+ constructor(message?: string, details?: any);
30
+ /**
31
+ * Create ValidationError from ZodError
32
+ */
33
+ static fromZodError(error: ZodError): ValidationError;
34
+ toJSON(): {
35
+ error: string;
36
+ details: any;
37
+ statusCode: number;
38
+ context: Record<string, any> | undefined;
39
+ };
40
+ }
41
+ /**
42
+ * Payment error class
43
+ * For x402 payment-related failures
44
+ */
45
+ declare class PaymentError extends AppError {
46
+ readonly reason?: string;
47
+ readonly transactionHash?: string;
48
+ constructor(message: string, reason?: string, transactionHash?: string, context?: Record<string, any>);
49
+ toJSON(): {
50
+ error: string;
51
+ reason: string | undefined;
52
+ transactionHash: string | undefined;
53
+ statusCode: number;
54
+ context: Record<string, any> | undefined;
55
+ };
56
+ }
57
+ /**
58
+ * Not found error class
59
+ */
60
+ declare class NotFoundError extends AppError {
61
+ constructor(message?: string, context?: Record<string, any>);
62
+ }
63
+ /**
64
+ * Unauthorized error class
65
+ */
66
+ declare class UnauthorizedError extends AppError {
67
+ constructor(message?: string, context?: Record<string, any>);
68
+ }
69
+ /**
70
+ * Forbidden error class
71
+ */
72
+ declare class ForbiddenError extends AppError {
73
+ constructor(message?: string, context?: Record<string, any>);
74
+ }
75
+ /**
76
+ * Rate limit error class
77
+ */
78
+ declare class RateLimitError extends AppError {
79
+ readonly retryAfter?: number;
80
+ constructor(message?: string, retryAfter?: number, context?: Record<string, any>);
81
+ toJSON(): {
82
+ error: string;
83
+ retryAfter: number | undefined;
84
+ statusCode: number;
85
+ context: Record<string, any> | undefined;
86
+ };
87
+ }
88
+ /**
89
+ * Service unavailable error class
90
+ */
91
+ declare class ServiceUnavailableError extends AppError {
92
+ constructor(message?: string, context?: Record<string, any>);
93
+ }
94
+ /**
95
+ * Check if error is operational (expected) or programming error
96
+ */
97
+ declare function isOperationalError(error: Error): boolean;
98
+ /**
99
+ * Error response formatter for API responses
100
+ */
101
+ interface ErrorResponse {
102
+ error: string;
103
+ message?: string;
104
+ details?: any;
105
+ statusCode: number;
106
+ }
107
+ /**
108
+ * Format error for API response
109
+ */
110
+ declare function formatErrorResponse(error: unknown): ErrorResponse;
111
+ /**
112
+ * Get HTTP status code from error
113
+ */
114
+ declare function getErrorStatusCode(error: unknown): number;
115
+ /**
116
+ * Create error handler middleware (framework-agnostic)
117
+ */
118
+ declare function createErrorHandler(options?: {
119
+ logger?: (error: Error, context?: Record<string, any>) => void;
120
+ includeStack?: boolean;
121
+ }): (error: unknown) => {
122
+ response: ErrorResponse;
123
+ statusCode: number;
124
+ };
125
+
126
+ export { AppError, type ErrorResponse, ForbiddenError, NotFoundError, PaymentError, RateLimitError, ServiceUnavailableError, UnauthorizedError, ValidationError, createErrorHandler, formatErrorResponse, getErrorStatusCode, isOperationalError };
package/dist/index.js ADDED
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AppError: () => AppError,
24
+ ForbiddenError: () => ForbiddenError,
25
+ NotFoundError: () => NotFoundError,
26
+ PaymentError: () => PaymentError,
27
+ RateLimitError: () => RateLimitError,
28
+ ServiceUnavailableError: () => ServiceUnavailableError,
29
+ UnauthorizedError: () => UnauthorizedError,
30
+ ValidationError: () => ValidationError,
31
+ createErrorHandler: () => createErrorHandler,
32
+ formatErrorResponse: () => formatErrorResponse,
33
+ getErrorStatusCode: () => getErrorStatusCode,
34
+ isOperationalError: () => isOperationalError
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_zod = require("zod");
38
+ var AppError = class extends Error {
39
+ constructor(message, statusCode = 500, isOperational = true, context) {
40
+ super(message);
41
+ Object.setPrototypeOf(this, new.target.prototype);
42
+ this.name = this.constructor.name;
43
+ this.statusCode = statusCode;
44
+ this.isOperational = isOperational;
45
+ this.context = context;
46
+ Error.captureStackTrace(this);
47
+ }
48
+ toJSON() {
49
+ return {
50
+ error: this.message,
51
+ statusCode: this.statusCode,
52
+ context: this.context
53
+ };
54
+ }
55
+ };
56
+ var ValidationError = class _ValidationError extends AppError {
57
+ constructor(message = "Validation failed", details) {
58
+ super(message, 400, true, { details });
59
+ this.details = details;
60
+ }
61
+ /**
62
+ * Create ValidationError from ZodError
63
+ */
64
+ static fromZodError(error) {
65
+ const details = error.errors.map((e) => ({
66
+ path: e.path.join("."),
67
+ message: e.message,
68
+ code: e.code
69
+ }));
70
+ return new _ValidationError("Validation error", details);
71
+ }
72
+ toJSON() {
73
+ return {
74
+ error: this.message,
75
+ details: this.details,
76
+ statusCode: this.statusCode,
77
+ context: this.context
78
+ };
79
+ }
80
+ };
81
+ var PaymentError = class extends AppError {
82
+ constructor(message, reason, transactionHash, context) {
83
+ super(message, 402, true, context);
84
+ this.reason = reason;
85
+ this.transactionHash = transactionHash;
86
+ }
87
+ toJSON() {
88
+ return {
89
+ error: this.message,
90
+ reason: this.reason,
91
+ transactionHash: this.transactionHash,
92
+ statusCode: this.statusCode,
93
+ context: this.context
94
+ };
95
+ }
96
+ };
97
+ var NotFoundError = class extends AppError {
98
+ constructor(message = "Resource not found", context) {
99
+ super(message, 404, true, context);
100
+ }
101
+ };
102
+ var UnauthorizedError = class extends AppError {
103
+ constructor(message = "Unauthorized", context) {
104
+ super(message, 401, true, context);
105
+ }
106
+ };
107
+ var ForbiddenError = class extends AppError {
108
+ constructor(message = "Forbidden", context) {
109
+ super(message, 403, true, context);
110
+ }
111
+ };
112
+ var RateLimitError = class extends AppError {
113
+ constructor(message = "Rate limit exceeded", retryAfter, context) {
114
+ super(message, 429, true, context);
115
+ this.retryAfter = retryAfter;
116
+ }
117
+ toJSON() {
118
+ return {
119
+ error: this.message,
120
+ retryAfter: this.retryAfter,
121
+ statusCode: this.statusCode,
122
+ context: this.context
123
+ };
124
+ }
125
+ };
126
+ var ServiceUnavailableError = class extends AppError {
127
+ constructor(message = "Service unavailable", context) {
128
+ super(message, 503, true, context);
129
+ }
130
+ };
131
+ function isOperationalError(error) {
132
+ if (error instanceof AppError) {
133
+ return error.isOperational;
134
+ }
135
+ return false;
136
+ }
137
+ function formatErrorResponse(error) {
138
+ if (error instanceof import_zod.ZodError) {
139
+ const validationError = ValidationError.fromZodError(error);
140
+ return validationError.toJSON();
141
+ }
142
+ if (error instanceof AppError) {
143
+ return error.toJSON();
144
+ }
145
+ if (error instanceof Error) {
146
+ return {
147
+ error: error.message,
148
+ statusCode: 500
149
+ };
150
+ }
151
+ return {
152
+ error: "Unknown error",
153
+ statusCode: 500
154
+ };
155
+ }
156
+ function getErrorStatusCode(error) {
157
+ if (error instanceof AppError) {
158
+ return error.statusCode;
159
+ }
160
+ if (error instanceof import_zod.ZodError) {
161
+ return 400;
162
+ }
163
+ return 500;
164
+ }
165
+ function createErrorHandler(options) {
166
+ return (error) => {
167
+ const response = formatErrorResponse(error);
168
+ const statusCode = getErrorStatusCode(error);
169
+ if (options?.logger && error instanceof Error) {
170
+ options.logger(error, { statusCode });
171
+ }
172
+ if (options?.includeStack && error instanceof Error) {
173
+ response.stack = error.stack;
174
+ }
175
+ return { response, statusCode };
176
+ };
177
+ }
178
+ // Annotate the CommonJS export names for ESM import in node:
179
+ 0 && (module.exports = {
180
+ AppError,
181
+ ForbiddenError,
182
+ NotFoundError,
183
+ PaymentError,
184
+ RateLimitError,
185
+ ServiceUnavailableError,
186
+ UnauthorizedError,
187
+ ValidationError,
188
+ createErrorHandler,
189
+ formatErrorResponse,
190
+ getErrorStatusCode,
191
+ isOperationalError
192
+ });
193
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @perkos/error-handling\n * Error handling utilities and classes for vendor services\n */\n\nimport { ZodError } from \"zod\";\n\n/**\n * Base application error class\n * Extends Error with HTTP status code and context\n */\nexport class AppError extends Error {\n public readonly statusCode: number;\n public readonly isOperational: boolean;\n public readonly context?: Record<string, any>;\n\n constructor(\n message: string,\n statusCode: number = 500,\n isOperational: boolean = true,\n context?: Record<string, any>\n ) {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = this.constructor.name;\n this.statusCode = statusCode;\n this.isOperational = isOperational;\n this.context = context;\n\n Error.captureStackTrace(this);\n }\n\n toJSON() {\n return {\n error: this.message,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Validation error class\n * For request validation failures with Zod integration\n */\nexport class ValidationError extends AppError {\n public readonly details?: any;\n\n constructor(message: string = \"Validation failed\", details?: any) {\n super(message, 400, true, { details });\n this.details = details;\n }\n\n /**\n * Create ValidationError from ZodError\n */\n static fromZodError(error: ZodError): ValidationError {\n const details = error.errors.map((e) => ({\n path: e.path.join(\".\"),\n message: e.message,\n code: e.code,\n }));\n return new ValidationError(\"Validation error\", details);\n }\n\n toJSON() {\n return {\n error: this.message,\n details: this.details,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Payment error class\n * For x402 payment-related failures\n */\nexport class PaymentError extends AppError {\n public readonly reason?: string;\n public readonly transactionHash?: string;\n\n constructor(\n message: string,\n reason?: string,\n transactionHash?: string,\n context?: Record<string, any>\n ) {\n super(message, 402, true, context);\n this.reason = reason;\n this.transactionHash = transactionHash;\n }\n\n toJSON() {\n return {\n error: this.message,\n reason: this.reason,\n transactionHash: this.transactionHash,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Not found error class\n */\nexport class NotFoundError extends AppError {\n constructor(message: string = \"Resource not found\", context?: Record<string, any>) {\n super(message, 404, true, context);\n }\n}\n\n/**\n * Unauthorized error class\n */\nexport class UnauthorizedError extends AppError {\n constructor(message: string = \"Unauthorized\", context?: Record<string, any>) {\n super(message, 401, true, context);\n }\n}\n\n/**\n * Forbidden error class\n */\nexport class ForbiddenError extends AppError {\n constructor(message: string = \"Forbidden\", context?: Record<string, any>) {\n super(message, 403, true, context);\n }\n}\n\n/**\n * Rate limit error class\n */\nexport class RateLimitError extends AppError {\n public readonly retryAfter?: number;\n\n constructor(\n message: string = \"Rate limit exceeded\",\n retryAfter?: number,\n context?: Record<string, any>\n ) {\n super(message, 429, true, context);\n this.retryAfter = retryAfter;\n }\n\n toJSON() {\n return {\n error: this.message,\n retryAfter: this.retryAfter,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Service unavailable error class\n */\nexport class ServiceUnavailableError extends AppError {\n constructor(message: string = \"Service unavailable\", context?: Record<string, any>) {\n super(message, 503, true, context);\n }\n}\n\n/**\n * Check if error is operational (expected) or programming error\n */\nexport function isOperationalError(error: Error): boolean {\n if (error instanceof AppError) {\n return error.isOperational;\n }\n return false;\n}\n\n/**\n * Error response formatter for API responses\n */\nexport interface ErrorResponse {\n error: string;\n message?: string;\n details?: any;\n statusCode: number;\n}\n\n/**\n * Format error for API response\n */\nexport function formatErrorResponse(error: unknown): ErrorResponse {\n if (error instanceof ZodError) {\n const validationError = ValidationError.fromZodError(error);\n return validationError.toJSON() as ErrorResponse;\n }\n\n if (error instanceof AppError) {\n return error.toJSON() as ErrorResponse;\n }\n\n if (error instanceof Error) {\n return {\n error: error.message,\n statusCode: 500,\n };\n }\n\n return {\n error: \"Unknown error\",\n statusCode: 500,\n };\n}\n\n/**\n * Get HTTP status code from error\n */\nexport function getErrorStatusCode(error: unknown): number {\n if (error instanceof AppError) {\n return error.statusCode;\n }\n if (error instanceof ZodError) {\n return 400;\n }\n return 500;\n}\n\n/**\n * Create error handler middleware (framework-agnostic)\n */\nexport function createErrorHandler(options?: {\n logger?: (error: Error, context?: Record<string, any>) => void;\n includeStack?: boolean;\n}) {\n return (error: unknown) => {\n const response = formatErrorResponse(error);\n const statusCode = getErrorStatusCode(error);\n\n if (options?.logger && error instanceof Error) {\n options.logger(error, { statusCode });\n }\n\n if (options?.includeStack && error instanceof Error) {\n (response as any).stack = error.stack;\n }\n\n return { response, statusCode };\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,iBAAyB;AAMlB,IAAM,WAAN,cAAuB,MAAM;AAAA,EAKlC,YACE,SACA,aAAqB,KACrB,gBAAyB,MACzB,SACA;AACA,UAAM,OAAO;AACb,WAAO,eAAe,MAAM,WAAW,SAAS;AAEhD,SAAK,OAAO,KAAK,YAAY;AAC7B,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,UAAU;AAEf,UAAM,kBAAkB,IAAI;AAAA,EAC9B;AAAA,EAEA,SAAS;AACP,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACF;AAMO,IAAM,kBAAN,MAAM,yBAAwB,SAAS;AAAA,EAG5C,YAAY,UAAkB,qBAAqB,SAAe;AAChE,UAAM,SAAS,KAAK,MAAM,EAAE,QAAQ,CAAC;AACrC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,aAAa,OAAkC;AACpD,UAAM,UAAU,MAAM,OAAO,IAAI,CAAC,OAAO;AAAA,MACvC,MAAM,EAAE,KAAK,KAAK,GAAG;AAAA,MACrB,SAAS,EAAE;AAAA,MACX,MAAM,EAAE;AAAA,IACV,EAAE;AACF,WAAO,IAAI,iBAAgB,oBAAoB,OAAO;AAAA,EACxD;AAAA,EAEA,SAAS;AACP,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACF;AAMO,IAAM,eAAN,cAA2B,SAAS;AAAA,EAIzC,YACE,SACA,QACA,iBACA,SACA;AACA,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,SAAK,SAAS;AACd,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,SAAS;AACP,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,iBAAiB,KAAK;AAAA,MACtB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACF;AAKO,IAAM,gBAAN,cAA4B,SAAS;AAAA,EAC1C,YAAY,UAAkB,sBAAsB,SAA+B;AACjF,UAAM,SAAS,KAAK,MAAM,OAAO;AAAA,EACnC;AACF;AAKO,IAAM,oBAAN,cAAgC,SAAS;AAAA,EAC9C,YAAY,UAAkB,gBAAgB,SAA+B;AAC3E,UAAM,SAAS,KAAK,MAAM,OAAO;AAAA,EACnC;AACF;AAKO,IAAM,iBAAN,cAA6B,SAAS;AAAA,EAC3C,YAAY,UAAkB,aAAa,SAA+B;AACxE,UAAM,SAAS,KAAK,MAAM,OAAO;AAAA,EACnC;AACF;AAKO,IAAM,iBAAN,cAA6B,SAAS;AAAA,EAG3C,YACE,UAAkB,uBAClB,YACA,SACA;AACA,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,SAAS;AACP,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACF;AAKO,IAAM,0BAAN,cAAsC,SAAS;AAAA,EACpD,YAAY,UAAkB,uBAAuB,SAA+B;AAClF,UAAM,SAAS,KAAK,MAAM,OAAO;AAAA,EACnC;AACF;AAKO,SAAS,mBAAmB,OAAuB;AACxD,MAAI,iBAAiB,UAAU;AAC7B,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAeO,SAAS,oBAAoB,OAA+B;AACjE,MAAI,iBAAiB,qBAAU;AAC7B,UAAM,kBAAkB,gBAAgB,aAAa,KAAK;AAC1D,WAAO,gBAAgB,OAAO;AAAA,EAChC;AAEA,MAAI,iBAAiB,UAAU;AAC7B,WAAO,MAAM,OAAO;AAAA,EACtB;AAEA,MAAI,iBAAiB,OAAO;AAC1B,WAAO;AAAA,MACL,OAAO,MAAM;AAAA,MACb,YAAY;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,YAAY;AAAA,EACd;AACF;AAKO,SAAS,mBAAmB,OAAwB;AACzD,MAAI,iBAAiB,UAAU;AAC7B,WAAO,MAAM;AAAA,EACf;AACA,MAAI,iBAAiB,qBAAU;AAC7B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,mBAAmB,SAGhC;AACD,SAAO,CAAC,UAAmB;AACzB,UAAM,WAAW,oBAAoB,KAAK;AAC1C,UAAM,aAAa,mBAAmB,KAAK;AAE3C,QAAI,SAAS,UAAU,iBAAiB,OAAO;AAC7C,cAAQ,OAAO,OAAO,EAAE,WAAW,CAAC;AAAA,IACtC;AAEA,QAAI,SAAS,gBAAgB,iBAAiB,OAAO;AACnD,MAAC,SAAiB,QAAQ,MAAM;AAAA,IAClC;AAEA,WAAO,EAAE,UAAU,WAAW;AAAA,EAChC;AACF;","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,157 @@
1
+ // src/index.ts
2
+ import { ZodError } from "zod";
3
+ var AppError = class extends Error {
4
+ constructor(message, statusCode = 500, isOperational = true, context) {
5
+ super(message);
6
+ Object.setPrototypeOf(this, new.target.prototype);
7
+ this.name = this.constructor.name;
8
+ this.statusCode = statusCode;
9
+ this.isOperational = isOperational;
10
+ this.context = context;
11
+ Error.captureStackTrace(this);
12
+ }
13
+ toJSON() {
14
+ return {
15
+ error: this.message,
16
+ statusCode: this.statusCode,
17
+ context: this.context
18
+ };
19
+ }
20
+ };
21
+ var ValidationError = class _ValidationError extends AppError {
22
+ constructor(message = "Validation failed", details) {
23
+ super(message, 400, true, { details });
24
+ this.details = details;
25
+ }
26
+ /**
27
+ * Create ValidationError from ZodError
28
+ */
29
+ static fromZodError(error) {
30
+ const details = error.errors.map((e) => ({
31
+ path: e.path.join("."),
32
+ message: e.message,
33
+ code: e.code
34
+ }));
35
+ return new _ValidationError("Validation error", details);
36
+ }
37
+ toJSON() {
38
+ return {
39
+ error: this.message,
40
+ details: this.details,
41
+ statusCode: this.statusCode,
42
+ context: this.context
43
+ };
44
+ }
45
+ };
46
+ var PaymentError = class extends AppError {
47
+ constructor(message, reason, transactionHash, context) {
48
+ super(message, 402, true, context);
49
+ this.reason = reason;
50
+ this.transactionHash = transactionHash;
51
+ }
52
+ toJSON() {
53
+ return {
54
+ error: this.message,
55
+ reason: this.reason,
56
+ transactionHash: this.transactionHash,
57
+ statusCode: this.statusCode,
58
+ context: this.context
59
+ };
60
+ }
61
+ };
62
+ var NotFoundError = class extends AppError {
63
+ constructor(message = "Resource not found", context) {
64
+ super(message, 404, true, context);
65
+ }
66
+ };
67
+ var UnauthorizedError = class extends AppError {
68
+ constructor(message = "Unauthorized", context) {
69
+ super(message, 401, true, context);
70
+ }
71
+ };
72
+ var ForbiddenError = class extends AppError {
73
+ constructor(message = "Forbidden", context) {
74
+ super(message, 403, true, context);
75
+ }
76
+ };
77
+ var RateLimitError = class extends AppError {
78
+ constructor(message = "Rate limit exceeded", retryAfter, context) {
79
+ super(message, 429, true, context);
80
+ this.retryAfter = retryAfter;
81
+ }
82
+ toJSON() {
83
+ return {
84
+ error: this.message,
85
+ retryAfter: this.retryAfter,
86
+ statusCode: this.statusCode,
87
+ context: this.context
88
+ };
89
+ }
90
+ };
91
+ var ServiceUnavailableError = class extends AppError {
92
+ constructor(message = "Service unavailable", context) {
93
+ super(message, 503, true, context);
94
+ }
95
+ };
96
+ function isOperationalError(error) {
97
+ if (error instanceof AppError) {
98
+ return error.isOperational;
99
+ }
100
+ return false;
101
+ }
102
+ function formatErrorResponse(error) {
103
+ if (error instanceof ZodError) {
104
+ const validationError = ValidationError.fromZodError(error);
105
+ return validationError.toJSON();
106
+ }
107
+ if (error instanceof AppError) {
108
+ return error.toJSON();
109
+ }
110
+ if (error instanceof Error) {
111
+ return {
112
+ error: error.message,
113
+ statusCode: 500
114
+ };
115
+ }
116
+ return {
117
+ error: "Unknown error",
118
+ statusCode: 500
119
+ };
120
+ }
121
+ function getErrorStatusCode(error) {
122
+ if (error instanceof AppError) {
123
+ return error.statusCode;
124
+ }
125
+ if (error instanceof ZodError) {
126
+ return 400;
127
+ }
128
+ return 500;
129
+ }
130
+ function createErrorHandler(options) {
131
+ return (error) => {
132
+ const response = formatErrorResponse(error);
133
+ const statusCode = getErrorStatusCode(error);
134
+ if (options?.logger && error instanceof Error) {
135
+ options.logger(error, { statusCode });
136
+ }
137
+ if (options?.includeStack && error instanceof Error) {
138
+ response.stack = error.stack;
139
+ }
140
+ return { response, statusCode };
141
+ };
142
+ }
143
+ export {
144
+ AppError,
145
+ ForbiddenError,
146
+ NotFoundError,
147
+ PaymentError,
148
+ RateLimitError,
149
+ ServiceUnavailableError,
150
+ UnauthorizedError,
151
+ ValidationError,
152
+ createErrorHandler,
153
+ formatErrorResponse,
154
+ getErrorStatusCode,
155
+ isOperationalError
156
+ };
157
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @perkos/error-handling\n * Error handling utilities and classes for vendor services\n */\n\nimport { ZodError } from \"zod\";\n\n/**\n * Base application error class\n * Extends Error with HTTP status code and context\n */\nexport class AppError extends Error {\n public readonly statusCode: number;\n public readonly isOperational: boolean;\n public readonly context?: Record<string, any>;\n\n constructor(\n message: string,\n statusCode: number = 500,\n isOperational: boolean = true,\n context?: Record<string, any>\n ) {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n\n this.name = this.constructor.name;\n this.statusCode = statusCode;\n this.isOperational = isOperational;\n this.context = context;\n\n Error.captureStackTrace(this);\n }\n\n toJSON() {\n return {\n error: this.message,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Validation error class\n * For request validation failures with Zod integration\n */\nexport class ValidationError extends AppError {\n public readonly details?: any;\n\n constructor(message: string = \"Validation failed\", details?: any) {\n super(message, 400, true, { details });\n this.details = details;\n }\n\n /**\n * Create ValidationError from ZodError\n */\n static fromZodError(error: ZodError): ValidationError {\n const details = error.errors.map((e) => ({\n path: e.path.join(\".\"),\n message: e.message,\n code: e.code,\n }));\n return new ValidationError(\"Validation error\", details);\n }\n\n toJSON() {\n return {\n error: this.message,\n details: this.details,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Payment error class\n * For x402 payment-related failures\n */\nexport class PaymentError extends AppError {\n public readonly reason?: string;\n public readonly transactionHash?: string;\n\n constructor(\n message: string,\n reason?: string,\n transactionHash?: string,\n context?: Record<string, any>\n ) {\n super(message, 402, true, context);\n this.reason = reason;\n this.transactionHash = transactionHash;\n }\n\n toJSON() {\n return {\n error: this.message,\n reason: this.reason,\n transactionHash: this.transactionHash,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Not found error class\n */\nexport class NotFoundError extends AppError {\n constructor(message: string = \"Resource not found\", context?: Record<string, any>) {\n super(message, 404, true, context);\n }\n}\n\n/**\n * Unauthorized error class\n */\nexport class UnauthorizedError extends AppError {\n constructor(message: string = \"Unauthorized\", context?: Record<string, any>) {\n super(message, 401, true, context);\n }\n}\n\n/**\n * Forbidden error class\n */\nexport class ForbiddenError extends AppError {\n constructor(message: string = \"Forbidden\", context?: Record<string, any>) {\n super(message, 403, true, context);\n }\n}\n\n/**\n * Rate limit error class\n */\nexport class RateLimitError extends AppError {\n public readonly retryAfter?: number;\n\n constructor(\n message: string = \"Rate limit exceeded\",\n retryAfter?: number,\n context?: Record<string, any>\n ) {\n super(message, 429, true, context);\n this.retryAfter = retryAfter;\n }\n\n toJSON() {\n return {\n error: this.message,\n retryAfter: this.retryAfter,\n statusCode: this.statusCode,\n context: this.context,\n };\n }\n}\n\n/**\n * Service unavailable error class\n */\nexport class ServiceUnavailableError extends AppError {\n constructor(message: string = \"Service unavailable\", context?: Record<string, any>) {\n super(message, 503, true, context);\n }\n}\n\n/**\n * Check if error is operational (expected) or programming error\n */\nexport function isOperationalError(error: Error): boolean {\n if (error instanceof AppError) {\n return error.isOperational;\n }\n return false;\n}\n\n/**\n * Error response formatter for API responses\n */\nexport interface ErrorResponse {\n error: string;\n message?: string;\n details?: any;\n statusCode: number;\n}\n\n/**\n * Format error for API response\n */\nexport function formatErrorResponse(error: unknown): ErrorResponse {\n if (error instanceof ZodError) {\n const validationError = ValidationError.fromZodError(error);\n return validationError.toJSON() as ErrorResponse;\n }\n\n if (error instanceof AppError) {\n return error.toJSON() as ErrorResponse;\n }\n\n if (error instanceof Error) {\n return {\n error: error.message,\n statusCode: 500,\n };\n }\n\n return {\n error: \"Unknown error\",\n statusCode: 500,\n };\n}\n\n/**\n * Get HTTP status code from error\n */\nexport function getErrorStatusCode(error: unknown): number {\n if (error instanceof AppError) {\n return error.statusCode;\n }\n if (error instanceof ZodError) {\n return 400;\n }\n return 500;\n}\n\n/**\n * Create error handler middleware (framework-agnostic)\n */\nexport function createErrorHandler(options?: {\n logger?: (error: Error, context?: Record<string, any>) => void;\n includeStack?: boolean;\n}) {\n return (error: unknown) => {\n const response = formatErrorResponse(error);\n const statusCode = getErrorStatusCode(error);\n\n if (options?.logger && error instanceof Error) {\n options.logger(error, { statusCode });\n }\n\n if (options?.includeStack && error instanceof Error) {\n (response as any).stack = error.stack;\n }\n\n return { response, statusCode };\n };\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@perkos/util-errors",
3
+ "version": "1.0.0",
4
+ "description": "Error handling utilities and classes for vendor services",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "lint": "tsc --noEmit",
22
+ "test": "vitest run",
23
+ "clean": "rm -rf dist",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "keywords": [
27
+ "error",
28
+ "handling",
29
+ "validation",
30
+ "zod",
31
+ "api",
32
+ "perkos"
33
+ ],
34
+ "author": "PerkOS",
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/PerkOS-xyz/pkg-util-errors.git"
39
+ },
40
+ "dependencies": {
41
+ "zod": "^3.22.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^20.10.0",
45
+ "tsup": "^8.0.1",
46
+ "typescript": "^5.3.3",
47
+ "vitest": "^1.2.0"
48
+ },
49
+ "engines": {
50
+ "node": ">=18.0.0"
51
+ }
52
+ }