@spfn/core 0.1.0-alpha.64 → 0.1.0-alpha.68
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 +5 -5
- package/dist/{auto-loader-CdsxOceW.d.ts → auto-loader-JFaZ9gON.d.ts} +3 -2
- package/dist/cache/index.d.ts +211 -0
- package/dist/cache/index.js +992 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/codegen/generators/index.d.ts +7 -6
- package/dist/codegen/generators/index.js +208 -27
- package/dist/codegen/generators/index.js.map +1 -1
- package/dist/codegen/index.d.ts +67 -118
- package/dist/codegen/index.js +1419 -1295
- package/dist/codegen/index.js.map +1 -1
- package/dist/database-errors-CoPrcOpq.d.ts +86 -0
- package/dist/db/index.d.ts +316 -9
- package/dist/db/index.js +6 -6
- package/dist/db/index.js.map +1 -1
- package/dist/error-handler-wjLL3v-a.d.ts +44 -0
- package/dist/errors/index.d.ts +119 -0
- package/dist/errors/index.js +160 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index-DHiAqhKv.d.ts +101 -0
- package/dist/index.d.ts +2 -228
- package/dist/index.js +274 -292
- package/dist/index.js.map +1 -1
- package/dist/middleware/index.d.ts +33 -0
- package/dist/middleware/index.js +890 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/route/index.d.ts +172 -7
- package/dist/route/index.js +209 -70
- package/dist/route/index.js.map +1 -1
- package/dist/server/index.js +267 -176
- package/dist/server/index.js.map +1 -1
- package/dist/{types-Bd8YsFSU.d.ts → types-CAON3Mmg.d.ts} +1 -1
- package/package.json +19 -2
- package/dist/bind-CSzshBtm.d.ts +0 -17
- package/dist/contract-generator-CqKsfsNE.d.ts +0 -52
- package/dist/postgres-errors-lw1aRUFe.d.ts +0 -397
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Context } from 'hono';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error Handler Middleware
|
|
5
|
+
*
|
|
6
|
+
* Generic middleware that converts errors with statusCode to HTTP responses
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface ErrorHandlerOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Include stack trace in response
|
|
12
|
+
* @default process.env.NODE_ENV !== 'production'
|
|
13
|
+
*/
|
|
14
|
+
includeStack?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Enable error logging
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
enableLogging?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Standard error response format
|
|
23
|
+
*
|
|
24
|
+
* Used by ErrorHandler middleware for all error responses.
|
|
25
|
+
* Compatible with ApiResponse pattern for consistent API responses.
|
|
26
|
+
*/
|
|
27
|
+
interface ErrorResponse {
|
|
28
|
+
success: false;
|
|
29
|
+
error: {
|
|
30
|
+
message: string;
|
|
31
|
+
type: string;
|
|
32
|
+
statusCode: number;
|
|
33
|
+
stack?: string;
|
|
34
|
+
details?: any;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Error handler middleware
|
|
39
|
+
*
|
|
40
|
+
* Used in Hono's onError hook
|
|
41
|
+
*/
|
|
42
|
+
declare function ErrorHandler(options?: ErrorHandlerOptions): (err: Error, c: Context) => Response | Promise<Response>;
|
|
43
|
+
|
|
44
|
+
export { ErrorHandler as E, type ErrorHandlerOptions as a, type ErrorResponse as b };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { D as DatabaseError } from '../database-errors-CoPrcOpq.js';
|
|
2
|
+
export { C as ConnectionError, a as ConstraintViolationError, b as DeadlockError, c as DuplicateEntryError, N as NotFoundError, Q as QueryError, T as TransactionError } from '../database-errors-CoPrcOpq.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* HTTP Error Classes
|
|
6
|
+
*
|
|
7
|
+
* Standard HTTP error classes for API responses
|
|
8
|
+
* Covers common HTTP status codes beyond database errors
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Base HTTP Error
|
|
12
|
+
*
|
|
13
|
+
* Base class for all HTTP-related errors
|
|
14
|
+
*/
|
|
15
|
+
declare class HttpError<TDetails extends Record<string, unknown> = Record<string, unknown>> extends Error {
|
|
16
|
+
readonly statusCode: number;
|
|
17
|
+
readonly details?: TDetails;
|
|
18
|
+
readonly timestamp: Date;
|
|
19
|
+
constructor(message: string, statusCode: number, details?: TDetails);
|
|
20
|
+
/**
|
|
21
|
+
* Serialize error for API response
|
|
22
|
+
*/
|
|
23
|
+
toJSON(): {
|
|
24
|
+
name: string;
|
|
25
|
+
message: string;
|
|
26
|
+
statusCode: number;
|
|
27
|
+
details: TDetails | undefined;
|
|
28
|
+
timestamp: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Bad Request Error (400)
|
|
33
|
+
*
|
|
34
|
+
* Generic bad request - malformed syntax, invalid parameters, etc.
|
|
35
|
+
*/
|
|
36
|
+
declare class BadRequestError extends HttpError {
|
|
37
|
+
constructor(message?: string, details?: Record<string, any>);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validation Error (400)
|
|
41
|
+
*
|
|
42
|
+
* Input validation failure (request params, query, body)
|
|
43
|
+
* Used by contract-based routing for automatic validation
|
|
44
|
+
*/
|
|
45
|
+
declare class ValidationError extends HttpError {
|
|
46
|
+
constructor(message: string, details?: Record<string, any>);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Unauthorized Error (401)
|
|
50
|
+
*
|
|
51
|
+
* Authentication required or authentication failed
|
|
52
|
+
*/
|
|
53
|
+
declare class UnauthorizedError extends HttpError {
|
|
54
|
+
constructor(message?: string, details?: Record<string, any>);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Forbidden Error (403)
|
|
58
|
+
*
|
|
59
|
+
* Authenticated but lacks permission to access resource
|
|
60
|
+
*/
|
|
61
|
+
declare class ForbiddenError extends HttpError {
|
|
62
|
+
constructor(message?: string, details?: Record<string, any>);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Conflict Error (409)
|
|
66
|
+
*
|
|
67
|
+
* Generic conflict - resource state conflict, concurrent modification, etc.
|
|
68
|
+
* More general than DuplicateEntryError
|
|
69
|
+
*/
|
|
70
|
+
declare class ConflictError extends HttpError {
|
|
71
|
+
constructor(message?: string, details?: Record<string, any>);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Too Many Requests Error (429)
|
|
75
|
+
*
|
|
76
|
+
* Rate limit exceeded
|
|
77
|
+
*/
|
|
78
|
+
declare class TooManyRequestsError extends HttpError {
|
|
79
|
+
constructor(message?: string, retryAfter?: number, details?: Record<string, any>);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Internal Server Error (500)
|
|
83
|
+
*
|
|
84
|
+
* Generic server error when no specific error type applies
|
|
85
|
+
*/
|
|
86
|
+
declare class InternalServerError extends HttpError {
|
|
87
|
+
constructor(message?: string, details?: Record<string, any>);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Service Unavailable Error (503)
|
|
91
|
+
*
|
|
92
|
+
* Service temporarily unavailable (maintenance, overload, etc.)
|
|
93
|
+
*/
|
|
94
|
+
declare class ServiceUnavailableError extends HttpError {
|
|
95
|
+
constructor(message?: string, retryAfter?: number, details?: Record<string, any>);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Error Utility Functions
|
|
100
|
+
*
|
|
101
|
+
* Generic error type checking utilities
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if error is a DatabaseError
|
|
106
|
+
*/
|
|
107
|
+
declare function isDatabaseError(error: unknown): error is DatabaseError;
|
|
108
|
+
/**
|
|
109
|
+
* Check if error is an HttpError
|
|
110
|
+
*/
|
|
111
|
+
declare function isHttpError(error: unknown): error is HttpError;
|
|
112
|
+
/**
|
|
113
|
+
* Check if error has a statusCode property
|
|
114
|
+
*/
|
|
115
|
+
declare function hasStatusCode(error: unknown): error is {
|
|
116
|
+
statusCode: number;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export { BadRequestError, ConflictError, DatabaseError, ForbiddenError, HttpError, InternalServerError, ServiceUnavailableError, TooManyRequestsError, UnauthorizedError, ValidationError, hasStatusCode, isDatabaseError, isHttpError };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// src/errors/database-errors.ts
|
|
2
|
+
var DatabaseError = class extends Error {
|
|
3
|
+
statusCode;
|
|
4
|
+
details;
|
|
5
|
+
timestamp;
|
|
6
|
+
constructor(message, statusCode = 500, details) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "DatabaseError";
|
|
9
|
+
this.statusCode = statusCode;
|
|
10
|
+
this.details = details;
|
|
11
|
+
this.timestamp = /* @__PURE__ */ new Date();
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Serialize error for API response
|
|
16
|
+
*/
|
|
17
|
+
toJSON() {
|
|
18
|
+
return {
|
|
19
|
+
name: this.name,
|
|
20
|
+
message: this.message,
|
|
21
|
+
statusCode: this.statusCode,
|
|
22
|
+
details: this.details,
|
|
23
|
+
timestamp: this.timestamp.toISOString()
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var ConnectionError = class extends DatabaseError {
|
|
28
|
+
constructor(message, details) {
|
|
29
|
+
super(message, 503, details);
|
|
30
|
+
this.name = "ConnectionError";
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var QueryError = class extends DatabaseError {
|
|
34
|
+
constructor(message, statusCode = 500, details) {
|
|
35
|
+
super(message, statusCode, details);
|
|
36
|
+
this.name = "QueryError";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var NotFoundError = class extends QueryError {
|
|
40
|
+
constructor(resource, id) {
|
|
41
|
+
super(`${resource} with id ${id} not found`, 404, { resource, id });
|
|
42
|
+
this.name = "NotFoundError";
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var ConstraintViolationError = class extends QueryError {
|
|
46
|
+
constructor(message, details) {
|
|
47
|
+
super(message, 400, details);
|
|
48
|
+
this.name = "ConstraintViolationError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var TransactionError = class extends DatabaseError {
|
|
52
|
+
constructor(message, statusCode = 500, details) {
|
|
53
|
+
super(message, statusCode, details);
|
|
54
|
+
this.name = "TransactionError";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var DeadlockError = class extends TransactionError {
|
|
58
|
+
constructor(message, details) {
|
|
59
|
+
super(message, 409, details);
|
|
60
|
+
this.name = "DeadlockError";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var DuplicateEntryError = class extends QueryError {
|
|
64
|
+
constructor(field, value) {
|
|
65
|
+
super(`${field} '${value}' already exists`, 409, { field, value });
|
|
66
|
+
this.name = "DuplicateEntryError";
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// src/errors/http-errors.ts
|
|
71
|
+
var HttpError = class extends Error {
|
|
72
|
+
statusCode;
|
|
73
|
+
details;
|
|
74
|
+
timestamp;
|
|
75
|
+
constructor(message, statusCode, details) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.name = "HttpError";
|
|
78
|
+
this.statusCode = statusCode;
|
|
79
|
+
this.details = details;
|
|
80
|
+
this.timestamp = /* @__PURE__ */ new Date();
|
|
81
|
+
Error.captureStackTrace(this, this.constructor);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Serialize error for API response
|
|
85
|
+
*/
|
|
86
|
+
toJSON() {
|
|
87
|
+
return {
|
|
88
|
+
name: this.name,
|
|
89
|
+
message: this.message,
|
|
90
|
+
statusCode: this.statusCode,
|
|
91
|
+
details: this.details,
|
|
92
|
+
timestamp: this.timestamp.toISOString()
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
var BadRequestError = class extends HttpError {
|
|
97
|
+
constructor(message = "Bad request", details) {
|
|
98
|
+
super(message, 400, details);
|
|
99
|
+
this.name = "BadRequestError";
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var ValidationError = class extends HttpError {
|
|
103
|
+
constructor(message, details) {
|
|
104
|
+
super(message, 400, details);
|
|
105
|
+
this.name = "ValidationError";
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
var UnauthorizedError = class extends HttpError {
|
|
109
|
+
constructor(message = "Authentication required", details) {
|
|
110
|
+
super(message, 401, details);
|
|
111
|
+
this.name = "UnauthorizedError";
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var ForbiddenError = class extends HttpError {
|
|
115
|
+
constructor(message = "Access forbidden", details) {
|
|
116
|
+
super(message, 403, details);
|
|
117
|
+
this.name = "ForbiddenError";
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
var ConflictError = class extends HttpError {
|
|
121
|
+
constructor(message = "Resource conflict", details) {
|
|
122
|
+
super(message, 409, details);
|
|
123
|
+
this.name = "ConflictError";
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
var TooManyRequestsError = class extends HttpError {
|
|
127
|
+
constructor(message = "Too many requests", retryAfter, details) {
|
|
128
|
+
const fullDetails = retryAfter ? { ...details, retryAfter } : details;
|
|
129
|
+
super(message, 429, fullDetails);
|
|
130
|
+
this.name = "TooManyRequestsError";
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var InternalServerError = class extends HttpError {
|
|
134
|
+
constructor(message = "Internal server error", details) {
|
|
135
|
+
super(message, 500, details);
|
|
136
|
+
this.name = "InternalServerError";
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
var ServiceUnavailableError = class extends HttpError {
|
|
140
|
+
constructor(message = "Service unavailable", retryAfter, details) {
|
|
141
|
+
const fullDetails = retryAfter ? { ...details, retryAfter } : details;
|
|
142
|
+
super(message, 503, fullDetails);
|
|
143
|
+
this.name = "ServiceUnavailableError";
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// src/errors/error-utils.ts
|
|
148
|
+
function isDatabaseError(error) {
|
|
149
|
+
return error instanceof DatabaseError;
|
|
150
|
+
}
|
|
151
|
+
function isHttpError(error) {
|
|
152
|
+
return error instanceof HttpError;
|
|
153
|
+
}
|
|
154
|
+
function hasStatusCode(error) {
|
|
155
|
+
return typeof error === "object" && error !== null && "statusCode" in error && typeof error.statusCode === "number";
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { BadRequestError, ConflictError, ConnectionError, ConstraintViolationError, DatabaseError, DeadlockError, DuplicateEntryError, ForbiddenError, HttpError, InternalServerError, NotFoundError, QueryError, ServiceUnavailableError, TooManyRequestsError, TransactionError, UnauthorizedError, ValidationError, hasStatusCode, isDatabaseError, isHttpError };
|
|
159
|
+
//# sourceMappingURL=index.js.map
|
|
160
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/errors/database-errors.ts","../../src/errors/http-errors.ts","../../src/errors/error-utils.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Database Error Classes\n *\n * Type-safe error handling with custom error class hierarchy\n * Mapped to HTTP status codes for API responses\n */\n\n/**\n * Base Database Error\n *\n * Base class for all database-related errors\n */\nexport class DatabaseError<TDetails extends Record<string, unknown> = Record<string, unknown>> extends Error\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n public readonly timestamp: Date;\n\n constructor(\n message: string,\n statusCode: number = 500,\n details?: TDetails\n )\n {\n super(message);\n this.name = 'DatabaseError';\n this.statusCode = statusCode;\n this.details = details;\n this.timestamp = new Date();\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Serialize error for API response\n */\n toJSON()\n {\n return {\n name: this.name,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n timestamp: this.timestamp.toISOString()\n };\n }\n}\n\n/**\n * Connection Error (503 Service Unavailable)\n *\n * Database connection failure, connection pool exhaustion, etc.\n */\nexport class ConnectionError extends DatabaseError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 503, details);\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Query Error (500 Internal Server Error)\n *\n * SQL query execution failure, syntax errors, etc.\n */\nexport class QueryError extends DatabaseError\n{\n constructor(message: string, statusCode: number = 500, details?: Record<string, any>)\n {\n super(message, statusCode, details);\n this.name = 'QueryError';\n }\n}\n\n/**\n * Not Found Error (404 Not Found)\n *\n * Requested resource does not exist\n */\nexport class NotFoundError extends QueryError\n{\n constructor(resource: string, id: string | number)\n {\n super(`${resource} with id ${id} not found`, 404, { resource, id });\n this.name = 'NotFoundError';\n }\n}\n\n/**\n * Constraint Violation Error (400 Bad Request)\n *\n * Database constraint violation (NOT NULL, CHECK, FOREIGN KEY, etc.)\n * This is different from HTTP ValidationError which validates request input\n */\nexport class ConstraintViolationError extends QueryError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'ConstraintViolationError';\n }\n}\n\n/**\n * Transaction Error (500 Internal Server Error)\n *\n * Transaction start/commit/rollback failure\n */\nexport class TransactionError extends DatabaseError\n{\n constructor(message: string, statusCode: number = 500, details?: Record<string, any>)\n {\n super(message, statusCode, details);\n this.name = 'TransactionError';\n }\n}\n\n/**\n * Deadlock Error (409 Conflict)\n *\n * Database deadlock detected\n */\nexport class DeadlockError extends TransactionError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 409, details);\n this.name = 'DeadlockError';\n }\n}\n\n/**\n * Duplicate Entry Error (409 Conflict)\n *\n * Unique constraint violation (e.g., duplicate email)\n */\nexport class DuplicateEntryError extends QueryError\n{\n constructor(field: string, value: string | number)\n {\n super(`${field} '${value}' already exists`, 409, { field, value });\n this.name = 'DuplicateEntryError';\n }\n}","/**\n * HTTP Error Classes\n *\n * Standard HTTP error classes for API responses\n * Covers common HTTP status codes beyond database errors\n */\n\n/**\n * Base HTTP Error\n *\n * Base class for all HTTP-related errors\n */\nexport class HttpError<TDetails extends Record<string, unknown> = Record<string, unknown>> extends Error\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n public readonly timestamp: Date;\n\n constructor(\n message: string,\n statusCode: number,\n details?: TDetails\n )\n {\n super(message);\n this.name = 'HttpError';\n this.statusCode = statusCode;\n this.details = details;\n this.timestamp = new Date();\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Serialize error for API response\n */\n toJSON()\n {\n return {\n name: this.name,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n timestamp: this.timestamp.toISOString()\n };\n }\n}\n\n/**\n * Bad Request Error (400)\n *\n * Generic bad request - malformed syntax, invalid parameters, etc.\n */\nexport class BadRequestError extends HttpError\n{\n constructor(message: string = 'Bad request', details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'BadRequestError';\n }\n}\n\n/**\n * Validation Error (400)\n *\n * Input validation failure (request params, query, body)\n * Used by contract-based routing for automatic validation\n */\nexport class ValidationError extends HttpError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Unauthorized Error (401)\n *\n * Authentication required or authentication failed\n */\nexport class UnauthorizedError extends HttpError\n{\n constructor(message: string = 'Authentication required', details?: Record<string, any>)\n {\n super(message, 401, details);\n this.name = 'UnauthorizedError';\n }\n}\n\n/**\n * Forbidden Error (403)\n *\n * Authenticated but lacks permission to access resource\n */\nexport class ForbiddenError extends HttpError\n{\n constructor(message: string = 'Access forbidden', details?: Record<string, any>)\n {\n super(message, 403, details);\n this.name = 'ForbiddenError';\n }\n}\n\n/**\n * Conflict Error (409)\n *\n * Generic conflict - resource state conflict, concurrent modification, etc.\n * More general than DuplicateEntryError\n */\nexport class ConflictError extends HttpError\n{\n constructor(message: string = 'Resource conflict', details?: Record<string, any>)\n {\n super(message, 409, details);\n this.name = 'ConflictError';\n }\n}\n\n/**\n * Too Many Requests Error (429)\n *\n * Rate limit exceeded\n */\nexport class TooManyRequestsError extends HttpError\n{\n constructor(\n message: string = 'Too many requests',\n retryAfter?: number,\n details?: Record<string, any>\n )\n {\n const fullDetails = retryAfter\n ? { ...details, retryAfter }\n : details;\n\n super(message, 429, fullDetails);\n this.name = 'TooManyRequestsError';\n }\n}\n\n/**\n * Internal Server Error (500)\n *\n * Generic server error when no specific error type applies\n */\nexport class InternalServerError extends HttpError\n{\n constructor(message: string = 'Internal server error', details?: Record<string, any>)\n {\n super(message, 500, details);\n this.name = 'InternalServerError';\n }\n}\n\n/**\n * Service Unavailable Error (503)\n *\n * Service temporarily unavailable (maintenance, overload, etc.)\n */\nexport class ServiceUnavailableError extends HttpError\n{\n constructor(\n message: string = 'Service unavailable',\n retryAfter?: number,\n details?: Record<string, any>\n )\n {\n const fullDetails = retryAfter\n ? { ...details, retryAfter }\n : details;\n\n super(message, 503, fullDetails);\n this.name = 'ServiceUnavailableError';\n }\n}","/**\n * Error Utility Functions\n *\n * Generic error type checking utilities\n */\n\nimport { DatabaseError } from './database-errors.js';\nimport { HttpError } from './http-errors.js';\n\n/**\n * Check if error is a DatabaseError\n */\nexport function isDatabaseError(error: unknown): error is DatabaseError\n{\n return error instanceof DatabaseError;\n}\n\n/**\n * Check if error is an HttpError\n */\nexport function isHttpError(error: unknown): error is HttpError\n{\n return error instanceof HttpError;\n}\n\n/**\n * Check if error has a statusCode property\n */\nexport function hasStatusCode(error: unknown): error is { statusCode: number }\n{\n return (\n typeof error === 'object' &&\n error !== null &&\n 'statusCode' in error &&\n typeof (error as any).statusCode === 'number'\n );\n}\n"]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generator Interface
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract for code generators that can be orchestrated by the codegen system.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Generator execution trigger types
|
|
8
|
+
*/
|
|
9
|
+
type GeneratorTrigger = 'watch' | 'manual' | 'build' | 'start';
|
|
10
|
+
interface GeneratorOptions {
|
|
11
|
+
/** Project root directory */
|
|
12
|
+
cwd: string;
|
|
13
|
+
/** Enable debug logging */
|
|
14
|
+
debug?: boolean;
|
|
15
|
+
/** Execution trigger information */
|
|
16
|
+
trigger?: {
|
|
17
|
+
/** How the generator was triggered */
|
|
18
|
+
type: GeneratorTrigger;
|
|
19
|
+
/** Changed file information (only for 'watch' trigger) */
|
|
20
|
+
changedFile?: {
|
|
21
|
+
path: string;
|
|
22
|
+
event: 'add' | 'change' | 'unlink';
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
/** Custom configuration options */
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
}
|
|
28
|
+
interface Generator {
|
|
29
|
+
/** Unique generator name */
|
|
30
|
+
name: string;
|
|
31
|
+
/** File patterns to watch (glob patterns) */
|
|
32
|
+
watchPatterns: string[];
|
|
33
|
+
/**
|
|
34
|
+
* When this generator should run
|
|
35
|
+
*
|
|
36
|
+
* @default ['watch', 'manual', 'build']
|
|
37
|
+
*
|
|
38
|
+
* Examples:
|
|
39
|
+
* - ['watch', 'build']: Run during development and build (e.g., admin-nav-generator)
|
|
40
|
+
* - ['build', 'start']: Run during build and server start (e.g., db-migration)
|
|
41
|
+
* - ['watch', 'manual']: Run during development and manual CLI (e.g., contract-generator)
|
|
42
|
+
* - ['start']: Run only on server start (e.g., runtime config generator)
|
|
43
|
+
*/
|
|
44
|
+
runOn?: GeneratorTrigger[];
|
|
45
|
+
/**
|
|
46
|
+
* Generate code
|
|
47
|
+
*
|
|
48
|
+
* Generator can implement incremental updates by checking `options.trigger.changedFile`.
|
|
49
|
+
* If incremental update is not possible, do full regeneration.
|
|
50
|
+
*
|
|
51
|
+
* @param options - Generator options with trigger context
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* async generate(options: GeneratorOptions): Promise<void>
|
|
56
|
+
* {
|
|
57
|
+
* // Check if incremental update is possible
|
|
58
|
+
* if (options.trigger?.changedFile)
|
|
59
|
+
* {
|
|
60
|
+
* const { path, event } = options.trigger.changedFile;
|
|
61
|
+
*
|
|
62
|
+
* if (canDoIncrementalUpdate(path, event))
|
|
63
|
+
* {
|
|
64
|
+
* await updateSingleFile(path);
|
|
65
|
+
* return;
|
|
66
|
+
* }
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* // Fallback: full regeneration
|
|
70
|
+
* await fullRegenerate();
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
generate(options: GeneratorOptions): Promise<void>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Contract Generator
|
|
79
|
+
*
|
|
80
|
+
* Generates type-safe API client from contract definitions
|
|
81
|
+
*
|
|
82
|
+
* Features:
|
|
83
|
+
* - Automatic scanning of contract files
|
|
84
|
+
* - Type-safe client generation with InferContract
|
|
85
|
+
* - Split output by resource for better code organization
|
|
86
|
+
* - Incremental updates when single files change (smart regeneration)
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
interface ContractGeneratorConfig {
|
|
90
|
+
/** Contracts directory (default: src/lib/contracts) */
|
|
91
|
+
contractsDir?: string;
|
|
92
|
+
/** Output directory (default: src/lib/api) */
|
|
93
|
+
outputPath?: string;
|
|
94
|
+
/** Base URL for API client */
|
|
95
|
+
baseUrl?: string;
|
|
96
|
+
/** When to run this generator (default: ['watch', 'manual', 'build']) */
|
|
97
|
+
runOn?: GeneratorTrigger[];
|
|
98
|
+
}
|
|
99
|
+
declare function createContractGenerator(config?: ContractGeneratorConfig): Generator;
|
|
100
|
+
|
|
101
|
+
export { type ContractGeneratorConfig as C, type Generator as G, type GeneratorTrigger as a, type GeneratorOptions as b, createContractGenerator as c };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,233 +1,7 @@
|
|
|
1
1
|
export { AppFactory, ServerConfig, createServer, startServer } from './server/index.js';
|
|
2
|
-
export {
|
|
3
|
-
|
|
4
|
-
export { d as HttpMethod, I as InferContract, c as RouteContext, R as RouteContract, a as RouteHandler, i as isHttpMethod } from './types-Bd8YsFSU.js';
|
|
5
|
-
import { D as DatabaseError } from './postgres-errors-lw1aRUFe.js';
|
|
6
|
-
export { C as ConnectionError, l as DeadlockError, c as DrizzleConfigOptions, m as DuplicateEntryError, N as NotFoundError, Q as QueryError, h as TransactionContext, k as TransactionError, T as Transactional, j as TransactionalOptions, V as ValidationError, d as detectDialect, f as foreignKey, b as fromPostgresError, a as generateDrizzleConfigFile, g as getDrizzleConfig, e as getTransaction, i as id, o as optionalForeignKey, r as runWithTransaction, t as timestamps } from './postgres-errors-lw1aRUFe.js';
|
|
7
|
-
import { Redis, Cluster } from 'ioredis';
|
|
8
|
-
export { LogLevel, LoggerAdapter, logger } from './logger/index.js';
|
|
9
|
-
import { Context, Next } from 'hono';
|
|
2
|
+
export { H as HttpMethod, I as InferContract, R as RouteContext, a as RouteContract, b as RouteHandler, i as isHttpMethod } from './types-CAON3Mmg.js';
|
|
3
|
+
import 'hono';
|
|
10
4
|
import 'hono/cors';
|
|
11
5
|
import '@hono/node-server';
|
|
12
6
|
import 'hono/utils/http-status';
|
|
13
7
|
import '@sinclair/typebox';
|
|
14
|
-
import 'drizzle-orm';
|
|
15
|
-
import 'drizzle-orm/pg-core';
|
|
16
|
-
import 'drizzle-orm/postgres-js';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Error Utility Functions
|
|
20
|
-
*
|
|
21
|
-
* Generic error type checking utilities
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Check if error is a DatabaseError
|
|
26
|
-
*/
|
|
27
|
-
declare function isDatabaseError(error: unknown): error is DatabaseError;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Redis factory with automatic environment variable detection
|
|
31
|
-
* Supports: Single, Master-Replica, Sentinel, Cluster
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
interface RedisClients {
|
|
35
|
-
/** Primary Redis for writes (or both read/write if no replica) */
|
|
36
|
-
write?: Redis | Cluster;
|
|
37
|
-
/** Replica Redis for reads (optional, falls back to write) */
|
|
38
|
-
read?: Redis | Cluster;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Create Redis client(s) from environment variables
|
|
42
|
-
*
|
|
43
|
-
* Supported patterns (priority order):
|
|
44
|
-
* 1. Single instance: REDIS_URL
|
|
45
|
-
* 2. Master-Replica: REDIS_WRITE_URL + REDIS_READ_URL
|
|
46
|
-
* 3. Sentinel: REDIS_SENTINEL_HOSTS + REDIS_MASTER_NAME
|
|
47
|
-
* 4. Cluster: REDIS_CLUSTER_NODES
|
|
48
|
-
*
|
|
49
|
-
* @returns Redis client(s) or undefined if no configuration found
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```bash
|
|
53
|
-
* # Single (most common)
|
|
54
|
-
* REDIS_URL=redis://localhost:6379
|
|
55
|
-
* REDIS_URL=rediss://secure.redis.com:6380 # TLS
|
|
56
|
-
*
|
|
57
|
-
* # Master-Replica
|
|
58
|
-
* REDIS_WRITE_URL=redis://master:6379
|
|
59
|
-
* REDIS_READ_URL=redis://replica:6379
|
|
60
|
-
*
|
|
61
|
-
* # Sentinel
|
|
62
|
-
* REDIS_SENTINEL_HOSTS=sentinel1:26379,sentinel2:26379
|
|
63
|
-
* REDIS_MASTER_NAME=mymaster
|
|
64
|
-
* REDIS_PASSWORD=secret
|
|
65
|
-
*
|
|
66
|
-
* # Cluster
|
|
67
|
-
* REDIS_CLUSTER_NODES=node1:6379,node2:6379,node3:6379
|
|
68
|
-
* REDIS_PASSWORD=secret
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
declare function createRedisFromEnv(): Promise<RedisClients>;
|
|
72
|
-
/**
|
|
73
|
-
* Create single Redis client (backward compatibility)
|
|
74
|
-
* Only returns write instance
|
|
75
|
-
*/
|
|
76
|
-
declare function createSingleRedisFromEnv(): Promise<Redis | Cluster | undefined>;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Global Redis instance manager
|
|
80
|
-
* Provides singleton access to Redis across all modules
|
|
81
|
-
* Supports Master-Replica pattern with separate read/write instances
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Get global Redis write instance
|
|
86
|
-
*
|
|
87
|
-
* @returns Redis write instance or undefined if not initialized
|
|
88
|
-
*
|
|
89
|
-
* @example
|
|
90
|
-
* ```typescript
|
|
91
|
-
* import { getRedis } from '@spfn/core/cache';
|
|
92
|
-
*
|
|
93
|
-
* const redis = getRedis();
|
|
94
|
-
* if (redis) {
|
|
95
|
-
* await redis.set('key', 'value');
|
|
96
|
-
* }
|
|
97
|
-
* ```
|
|
98
|
-
*/
|
|
99
|
-
declare function getRedis(): Redis | Cluster | undefined;
|
|
100
|
-
/**
|
|
101
|
-
* Get global Redis read instance (falls back to write if no replica)
|
|
102
|
-
*
|
|
103
|
-
* @returns Redis read instance or write instance as fallback
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```typescript
|
|
107
|
-
* import { getRedisRead } from '@spfn/core/cache';
|
|
108
|
-
*
|
|
109
|
-
* const redis = getRedisRead();
|
|
110
|
-
* if (redis) {
|
|
111
|
-
* const value = await redis.get('key');
|
|
112
|
-
* }
|
|
113
|
-
* ```
|
|
114
|
-
*/
|
|
115
|
-
declare function getRedisRead(): Redis | Cluster | undefined;
|
|
116
|
-
/**
|
|
117
|
-
* Set global Redis instances (for testing or manual configuration)
|
|
118
|
-
*
|
|
119
|
-
* @param write - Redis write instance
|
|
120
|
-
* @param read - Redis read instance (optional, defaults to write)
|
|
121
|
-
*
|
|
122
|
-
* @example
|
|
123
|
-
* ```typescript
|
|
124
|
-
* import { setRedis } from '@spfn/core/cache';
|
|
125
|
-
* import Redis from 'ioredis';
|
|
126
|
-
*
|
|
127
|
-
* const write = new Redis('redis://master:6379');
|
|
128
|
-
* const read = new Redis('redis://replica:6379');
|
|
129
|
-
* setRedis(write, read);
|
|
130
|
-
* ```
|
|
131
|
-
*/
|
|
132
|
-
declare function setRedis(write: Redis | Cluster | undefined, read?: Redis | Cluster | undefined): void;
|
|
133
|
-
/**
|
|
134
|
-
* Initialize Redis from environment variables
|
|
135
|
-
* Automatically called by startServer()
|
|
136
|
-
*
|
|
137
|
-
* Supported environment variables:
|
|
138
|
-
* - REDIS_URL (single instance)
|
|
139
|
-
* - REDIS_WRITE_URL + REDIS_READ_URL (master-replica)
|
|
140
|
-
* - REDIS_SENTINEL_HOSTS + REDIS_MASTER_NAME (sentinel)
|
|
141
|
-
* - REDIS_CLUSTER_NODES (cluster)
|
|
142
|
-
* - REDIS_TLS_REJECT_UNAUTHORIZED (TLS config)
|
|
143
|
-
*
|
|
144
|
-
* @returns Object with write and read instances
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* ```typescript
|
|
148
|
-
* import { initRedis } from '@spfn/core/cache';
|
|
149
|
-
*
|
|
150
|
-
* // Manual initialization (not needed if using startServer)
|
|
151
|
-
* const { write, read } = await initRedis();
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
|
-
declare function initRedis(): Promise<{
|
|
155
|
-
write?: Redis | Cluster;
|
|
156
|
-
read?: Redis | Cluster;
|
|
157
|
-
}>;
|
|
158
|
-
/**
|
|
159
|
-
* Close all Redis connections and cleanup
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* ```typescript
|
|
163
|
-
* import { closeRedis } from '@spfn/core/cache';
|
|
164
|
-
*
|
|
165
|
-
* // During graceful shutdown
|
|
166
|
-
* await closeRedis();
|
|
167
|
-
* ```
|
|
168
|
-
*/
|
|
169
|
-
declare function closeRedis(): Promise<void>;
|
|
170
|
-
/**
|
|
171
|
-
* Get Redis connection info (for debugging)
|
|
172
|
-
*/
|
|
173
|
-
declare function getRedisInfo(): {
|
|
174
|
-
hasWrite: boolean;
|
|
175
|
-
hasRead: boolean;
|
|
176
|
-
isReplica: boolean;
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Request Logger Middleware
|
|
181
|
-
*
|
|
182
|
-
* Automatic API request/response logging with performance monitoring
|
|
183
|
-
*/
|
|
184
|
-
|
|
185
|
-
interface RequestLoggerConfig {
|
|
186
|
-
/**
|
|
187
|
-
* Paths to exclude from logging (health checks, etc.)
|
|
188
|
-
*/
|
|
189
|
-
excludePaths?: string[];
|
|
190
|
-
/**
|
|
191
|
-
* Field names to mask for sensitive data
|
|
192
|
-
*/
|
|
193
|
-
sensitiveFields?: string[];
|
|
194
|
-
/**
|
|
195
|
-
* Slow request threshold (ms)
|
|
196
|
-
*/
|
|
197
|
-
slowRequestThreshold?: number;
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Mask sensitive data with circular reference handling
|
|
201
|
-
*/
|
|
202
|
-
declare function maskSensitiveData(obj: any, sensitiveFields: string[], seen?: WeakSet<object>): any;
|
|
203
|
-
/**
|
|
204
|
-
* Request Logger middleware
|
|
205
|
-
*/
|
|
206
|
-
declare function RequestLogger(config?: RequestLoggerConfig): (c: Context, next: Next) => Promise<void>;
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Error Handler Middleware
|
|
210
|
-
*
|
|
211
|
-
* Generic middleware that converts errors with statusCode to HTTP responses
|
|
212
|
-
*/
|
|
213
|
-
|
|
214
|
-
interface ErrorHandlerOptions {
|
|
215
|
-
/**
|
|
216
|
-
* Include stack trace in response
|
|
217
|
-
* @default process.env.NODE_ENV !== 'production'
|
|
218
|
-
*/
|
|
219
|
-
includeStack?: boolean;
|
|
220
|
-
/**
|
|
221
|
-
* Enable error logging
|
|
222
|
-
* @default true
|
|
223
|
-
*/
|
|
224
|
-
enableLogging?: boolean;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Error handler middleware
|
|
228
|
-
*
|
|
229
|
-
* Used in Hono's onError hook
|
|
230
|
-
*/
|
|
231
|
-
declare function ErrorHandler(options?: ErrorHandlerOptions): (err: Error, c: Context) => Response | Promise<Response>;
|
|
232
|
-
|
|
233
|
-
export { DatabaseError, ErrorHandler, type ErrorHandlerOptions, type RedisClients, RequestLogger, type RequestLoggerConfig, closeRedis, createRedisFromEnv, createSingleRedisFromEnv, getRedis, getRedisInfo, getRedisRead, initRedis, isDatabaseError, maskSensitiveData, setRedis };
|