@spfn/core 0.1.0-alpha.68 → 0.1.0-alpha.72
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/dist/client/index.d.ts +2 -1
- package/dist/codegen/generators/index.js +59 -57
- package/dist/codegen/generators/index.js.map +1 -1
- package/dist/codegen/index.d.ts +2 -1
- package/dist/codegen/index.js +59 -57
- package/dist/codegen/index.js.map +1 -1
- package/dist/{database-errors-CoPrcOpq.d.ts → database-errors-BNNmLTJE.d.ts} +4 -4
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/errors/index.d.ts +20 -3
- package/dist/errors/index.js +15 -3
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +115 -109
- package/dist/index.js.map +1 -1
- package/dist/route/index.d.ts +5 -157
- package/dist/route/index.js +86 -96
- package/dist/route/index.js.map +1 -1
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +115 -109
- package/dist/server/index.js.map +1 -1
- package/dist/types-Dzggq1Yb.d.ts +170 -0
- package/package.json +1 -1
- package/dist/types-CAON3Mmg.d.ts +0 -57
package/dist/route/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export { A as AutoRouteLoader, R as RouteInfo, a as RouteStats, l as loadRoutes } from '../auto-loader-JFaZ9gON.js';
|
|
2
2
|
import { Context, Hono, MiddlewareHandler } from 'hono';
|
|
3
|
-
import { a as RouteContract, R as RouteContext, b as RouteHandler } from '../types-
|
|
4
|
-
export { c as HeaderRecord, H as HttpMethod, I as InferContract,
|
|
5
|
-
import * as _sinclair_typebox from '@sinclair/typebox';
|
|
6
|
-
import { TSchema } from '@sinclair/typebox';
|
|
7
|
-
import { b as ErrorResponse } from '../error-handler-wjLL3v-a.js';
|
|
3
|
+
import { a as RouteContract, R as RouteContext, b as RouteHandler } from '../types-Dzggq1Yb.js';
|
|
4
|
+
export { f as ApiErrorResponse, c as ApiErrorSchema, g as ApiResponse, d as ApiResponseSchema, e as ApiSuccessResponse, A as ApiSuccessSchema, h as HeaderRecord, H as HttpMethod, I as InferContract, j as RouteMeta, i as isHttpMethod } from '../types-Dzggq1Yb.js';
|
|
8
5
|
import 'hono/utils/http-status';
|
|
6
|
+
import '@sinclair/typebox';
|
|
7
|
+
import '../error-handler-wjLL3v-a.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Contract-based Route Handler Wrapper
|
|
@@ -38,155 +37,4 @@ type SPFNApp = Hono & {
|
|
|
38
37
|
*/
|
|
39
38
|
declare function createApp(): SPFNApp;
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
* Success response wrapper
|
|
43
|
-
*/
|
|
44
|
-
interface ApiSuccessResponse<T = any> {
|
|
45
|
-
success: true;
|
|
46
|
-
data: T;
|
|
47
|
-
meta?: {
|
|
48
|
-
timestamp?: string;
|
|
49
|
-
requestId?: string;
|
|
50
|
-
pagination?: {
|
|
51
|
-
page: number;
|
|
52
|
-
limit: number;
|
|
53
|
-
total: number;
|
|
54
|
-
totalPages: number;
|
|
55
|
-
};
|
|
56
|
-
[key: string]: any;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Error response type (re-exported from ErrorHandler for consistency)
|
|
61
|
-
*/
|
|
62
|
-
type ApiErrorResponse = ErrorResponse;
|
|
63
|
-
/**
|
|
64
|
-
* Unified API response type
|
|
65
|
-
*/
|
|
66
|
-
type ApiResponse<T = any> = ApiSuccessResponse<T> | ApiErrorResponse;
|
|
67
|
-
/**
|
|
68
|
-
* Creates a TypeBox schema for ApiSuccessResponse<T>
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* ```ts
|
|
72
|
-
* const UserSchema = Type.Object({
|
|
73
|
-
* id: Type.String(),
|
|
74
|
-
* name: Type.String(),
|
|
75
|
-
* });
|
|
76
|
-
*
|
|
77
|
-
* const contract = {
|
|
78
|
-
* response: ApiSuccessSchema(UserSchema),
|
|
79
|
-
* };
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
declare function ApiSuccessSchema<T extends TSchema>(dataSchema: T): _sinclair_typebox.TObject<{
|
|
83
|
-
success: _sinclair_typebox.TLiteral<true>;
|
|
84
|
-
data: T;
|
|
85
|
-
meta: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
|
|
86
|
-
timestamp: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
87
|
-
requestId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
88
|
-
pagination: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
|
|
89
|
-
page: _sinclair_typebox.TNumber;
|
|
90
|
-
limit: _sinclair_typebox.TNumber;
|
|
91
|
-
total: _sinclair_typebox.TNumber;
|
|
92
|
-
totalPages: _sinclair_typebox.TNumber;
|
|
93
|
-
}>>;
|
|
94
|
-
}>>;
|
|
95
|
-
}>;
|
|
96
|
-
/**
|
|
97
|
-
* Creates a TypeBox schema for ApiErrorResponse
|
|
98
|
-
*/
|
|
99
|
-
declare function ApiErrorSchema(): _sinclair_typebox.TObject<{
|
|
100
|
-
success: _sinclair_typebox.TLiteral<false>;
|
|
101
|
-
error: _sinclair_typebox.TObject<{
|
|
102
|
-
message: _sinclair_typebox.TString;
|
|
103
|
-
type: _sinclair_typebox.TString;
|
|
104
|
-
statusCode: _sinclair_typebox.TNumber;
|
|
105
|
-
stack: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
106
|
-
details: _sinclair_typebox.TOptional<_sinclair_typebox.TAny>;
|
|
107
|
-
}>;
|
|
108
|
-
}>;
|
|
109
|
-
/**
|
|
110
|
-
* Creates a TypeBox union schema for ApiResponse<T>
|
|
111
|
-
*
|
|
112
|
-
* Use this in your route contract's response field for standardized responses.
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* ```ts
|
|
116
|
-
* const contract = {
|
|
117
|
-
* method: 'GET',
|
|
118
|
-
* path: '/users/:id',
|
|
119
|
-
* response: ApiResponseSchema(Type.Object({
|
|
120
|
-
* id: Type.String(),
|
|
121
|
-
* name: Type.String(),
|
|
122
|
-
* })),
|
|
123
|
-
* };
|
|
124
|
-
* ```
|
|
125
|
-
*/
|
|
126
|
-
declare function ApiResponseSchema<T extends TSchema>(dataSchema: T): _sinclair_typebox.TUnion<[_sinclair_typebox.TObject<{
|
|
127
|
-
success: _sinclair_typebox.TLiteral<true>;
|
|
128
|
-
data: T;
|
|
129
|
-
meta: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
|
|
130
|
-
timestamp: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
131
|
-
requestId: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
132
|
-
pagination: _sinclair_typebox.TOptional<_sinclair_typebox.TObject<{
|
|
133
|
-
page: _sinclair_typebox.TNumber;
|
|
134
|
-
limit: _sinclair_typebox.TNumber;
|
|
135
|
-
total: _sinclair_typebox.TNumber;
|
|
136
|
-
totalPages: _sinclair_typebox.TNumber;
|
|
137
|
-
}>>;
|
|
138
|
-
}>>;
|
|
139
|
-
}>, _sinclair_typebox.TObject<{
|
|
140
|
-
success: _sinclair_typebox.TLiteral<false>;
|
|
141
|
-
error: _sinclair_typebox.TObject<{
|
|
142
|
-
message: _sinclair_typebox.TString;
|
|
143
|
-
type: _sinclair_typebox.TString;
|
|
144
|
-
statusCode: _sinclair_typebox.TNumber;
|
|
145
|
-
stack: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
|
|
146
|
-
details: _sinclair_typebox.TOptional<_sinclair_typebox.TAny>;
|
|
147
|
-
}>;
|
|
148
|
-
}>]>;
|
|
149
|
-
/**
|
|
150
|
-
* Creates a success response
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```ts
|
|
154
|
-
* // Simple success
|
|
155
|
-
* return success(c, { id: '123', name: 'John' });
|
|
156
|
-
*
|
|
157
|
-
* // With metadata
|
|
158
|
-
* return success(c, user, { timestamp: new Date().toISOString() });
|
|
159
|
-
*
|
|
160
|
-
* // With custom status
|
|
161
|
-
* return success(c, newUser, undefined, 201);
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
|
-
declare function success<T, TContract extends RouteContract = any>(c: RouteContext<TContract>, data: T, meta?: ApiSuccessResponse<T>['meta'], status?: number): Response;
|
|
165
|
-
/**
|
|
166
|
-
* Creates an error response
|
|
167
|
-
*
|
|
168
|
-
* Note: This is a convenience wrapper. ValidationErrors thrown by bind()
|
|
169
|
-
* are automatically handled by ErrorHandler middleware.
|
|
170
|
-
*
|
|
171
|
-
* @example
|
|
172
|
-
* ```ts
|
|
173
|
-
* // Not found
|
|
174
|
-
* return error(c, 'User not found', 404);
|
|
175
|
-
*
|
|
176
|
-
* // Validation error with details
|
|
177
|
-
* return error(c, 'Invalid input', 400, { fields: ['email', 'password'] });
|
|
178
|
-
* ```
|
|
179
|
-
*/
|
|
180
|
-
declare function error<TContract extends RouteContract = any>(c: RouteContext<TContract>, message: string, statusCode?: number, details?: any): Response;
|
|
181
|
-
/**
|
|
182
|
-
* Creates a paginated success response
|
|
183
|
-
*
|
|
184
|
-
* @example
|
|
185
|
-
* ```ts
|
|
186
|
-
* const { users, total } = await db.listUsers(page, limit);
|
|
187
|
-
* return paginated(c, users, page, limit, total);
|
|
188
|
-
* ```
|
|
189
|
-
*/
|
|
190
|
-
declare function paginated<T, TContract extends RouteContract = any>(c: RouteContext<TContract>, data: T[], page: number, limit: number, total: number): Response;
|
|
191
|
-
|
|
192
|
-
export { type ApiErrorResponse, ApiErrorSchema, type ApiResponse, ApiResponseSchema, type ApiSuccessResponse, ApiSuccessSchema, RouteContext, RouteContract, RouteHandler, type SPFNApp, bind, createApp, error, paginated, success };
|
|
40
|
+
export { RouteContext, RouteContract, RouteHandler, type SPFNApp, bind, createApp };
|
package/dist/route/index.js
CHANGED
|
@@ -119,11 +119,11 @@ function formatTimestampHuman(date) {
|
|
|
119
119
|
const ms = String(date.getMilliseconds()).padStart(3, "0");
|
|
120
120
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;
|
|
121
121
|
}
|
|
122
|
-
function formatError(
|
|
122
|
+
function formatError(error) {
|
|
123
123
|
const lines = [];
|
|
124
|
-
lines.push(`${
|
|
125
|
-
if (
|
|
126
|
-
const stackLines =
|
|
124
|
+
lines.push(`${error.name}: ${error.message}`);
|
|
125
|
+
if (error.stack) {
|
|
126
|
+
const stackLines = error.stack.split("\n").slice(1);
|
|
127
127
|
lines.push(...stackLines);
|
|
128
128
|
}
|
|
129
129
|
return lines.join("\n");
|
|
@@ -309,7 +309,7 @@ var init_logger = __esm({
|
|
|
309
309
|
/**
|
|
310
310
|
* Log processing (internal)
|
|
311
311
|
*/
|
|
312
|
-
log(level, message,
|
|
312
|
+
log(level, message, error, context) {
|
|
313
313
|
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level]) {
|
|
314
314
|
return;
|
|
315
315
|
}
|
|
@@ -318,7 +318,7 @@ var init_logger = __esm({
|
|
|
318
318
|
level,
|
|
319
319
|
message,
|
|
320
320
|
module: this.module,
|
|
321
|
-
error
|
|
321
|
+
error,
|
|
322
322
|
// Mask sensitive information in context to prevent credential leaks
|
|
323
323
|
context: context ? maskSensitiveData(context) : void 0
|
|
324
324
|
};
|
|
@@ -329,8 +329,8 @@ var init_logger = __esm({
|
|
|
329
329
|
*/
|
|
330
330
|
processTransports(metadata) {
|
|
331
331
|
const promises = this.config.transports.filter((transport) => transport.enabled).map((transport) => this.safeTransportLog(transport, metadata));
|
|
332
|
-
Promise.all(promises).catch((
|
|
333
|
-
const errorMessage =
|
|
332
|
+
Promise.all(promises).catch((error) => {
|
|
333
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
334
334
|
process.stderr.write(`[Logger] Transport error: ${errorMessage}
|
|
335
335
|
`);
|
|
336
336
|
});
|
|
@@ -341,8 +341,8 @@ var init_logger = __esm({
|
|
|
341
341
|
async safeTransportLog(transport, metadata) {
|
|
342
342
|
try {
|
|
343
343
|
await transport.log(metadata);
|
|
344
|
-
} catch (
|
|
345
|
-
const errorMessage =
|
|
344
|
+
} catch (error) {
|
|
345
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
346
346
|
process.stderr.write(`[Logger] Transport "${transport.name}" failed: ${errorMessage}
|
|
347
347
|
`);
|
|
348
348
|
}
|
|
@@ -432,11 +432,11 @@ var init_file = __esm({
|
|
|
432
432
|
}
|
|
433
433
|
if (this.currentStream) {
|
|
434
434
|
return new Promise((resolve, reject) => {
|
|
435
|
-
this.currentStream.write(message + "\n", "utf-8", (
|
|
436
|
-
if (
|
|
437
|
-
process.stderr.write(`[FileTransport] Failed to write log: ${
|
|
435
|
+
this.currentStream.write(message + "\n", "utf-8", (error) => {
|
|
436
|
+
if (error) {
|
|
437
|
+
process.stderr.write(`[FileTransport] Failed to write log: ${error.message}
|
|
438
438
|
`);
|
|
439
|
-
reject(
|
|
439
|
+
reject(error);
|
|
440
440
|
} else {
|
|
441
441
|
resolve();
|
|
442
442
|
}
|
|
@@ -458,8 +458,8 @@ var init_file = __esm({
|
|
|
458
458
|
encoding: "utf-8"
|
|
459
459
|
});
|
|
460
460
|
this.currentFilename = filename;
|
|
461
|
-
this.currentStream.on("error", (
|
|
462
|
-
process.stderr.write(`[FileTransport] Stream error: ${
|
|
461
|
+
this.currentStream.on("error", (error) => {
|
|
462
|
+
process.stderr.write(`[FileTransport] Stream error: ${error.message}
|
|
463
463
|
`);
|
|
464
464
|
this.currentStream = null;
|
|
465
465
|
this.currentFilename = null;
|
|
@@ -473,9 +473,9 @@ var init_file = __esm({
|
|
|
473
473
|
return;
|
|
474
474
|
}
|
|
475
475
|
return new Promise((resolve, reject) => {
|
|
476
|
-
this.currentStream.end((
|
|
477
|
-
if (
|
|
478
|
-
reject(
|
|
476
|
+
this.currentStream.end((error) => {
|
|
477
|
+
if (error) {
|
|
478
|
+
reject(error);
|
|
479
479
|
} else {
|
|
480
480
|
this.currentStream = null;
|
|
481
481
|
this.currentFilename = null;
|
|
@@ -500,8 +500,8 @@ var init_file = __esm({
|
|
|
500
500
|
if (stats.size >= this.maxFileSize) {
|
|
501
501
|
await this.rotateBySize();
|
|
502
502
|
}
|
|
503
|
-
} catch (
|
|
504
|
-
const errorMessage =
|
|
503
|
+
} catch (error) {
|
|
504
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
505
505
|
process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}
|
|
506
506
|
`);
|
|
507
507
|
}
|
|
@@ -527,8 +527,8 @@ var init_file = __esm({
|
|
|
527
527
|
const newPath2 = join(this.logDir, `${baseName}.${newNum}.log`);
|
|
528
528
|
try {
|
|
529
529
|
renameSync(oldPath, newPath2);
|
|
530
|
-
} catch (
|
|
531
|
-
const errorMessage =
|
|
530
|
+
} catch (error) {
|
|
531
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
532
532
|
process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}
|
|
533
533
|
`);
|
|
534
534
|
}
|
|
@@ -540,8 +540,8 @@ var init_file = __esm({
|
|
|
540
540
|
if (existsSync(currentPath)) {
|
|
541
541
|
renameSync(currentPath, newPath);
|
|
542
542
|
}
|
|
543
|
-
} catch (
|
|
544
|
-
const errorMessage =
|
|
543
|
+
} catch (error) {
|
|
544
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
545
545
|
process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}
|
|
546
546
|
`);
|
|
547
547
|
}
|
|
@@ -568,15 +568,15 @@ var init_file = __esm({
|
|
|
568
568
|
const filepath = join(this.logDir, file);
|
|
569
569
|
try {
|
|
570
570
|
unlinkSync(filepath);
|
|
571
|
-
} catch (
|
|
572
|
-
const errorMessage =
|
|
571
|
+
} catch (error) {
|
|
572
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
573
573
|
process.stderr.write(`[FileTransport] Failed to delete old file "${file}": ${errorMessage}
|
|
574
574
|
`);
|
|
575
575
|
}
|
|
576
576
|
}
|
|
577
577
|
}
|
|
578
|
-
} catch (
|
|
579
|
-
const errorMessage =
|
|
578
|
+
} catch (error) {
|
|
579
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
580
580
|
process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}
|
|
581
581
|
`);
|
|
582
582
|
}
|
|
@@ -635,8 +635,8 @@ function validateDirectoryWritable(dirPath) {
|
|
|
635
635
|
if (!existsSync(dirPath)) {
|
|
636
636
|
try {
|
|
637
637
|
mkdirSync(dirPath, { recursive: true });
|
|
638
|
-
} catch (
|
|
639
|
-
const errorMessage =
|
|
638
|
+
} catch (error) {
|
|
639
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
640
640
|
throw new Error(`Failed to create log directory "${dirPath}": ${errorMessage}`);
|
|
641
641
|
}
|
|
642
642
|
}
|
|
@@ -649,8 +649,8 @@ function validateDirectoryWritable(dirPath) {
|
|
|
649
649
|
try {
|
|
650
650
|
writeFileSync(testFile, "test", "utf-8");
|
|
651
651
|
unlinkSync(testFile);
|
|
652
|
-
} catch (
|
|
653
|
-
const errorMessage =
|
|
652
|
+
} catch (error) {
|
|
653
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
654
654
|
throw new Error(`Cannot write to log directory "${dirPath}": ${errorMessage}`);
|
|
655
655
|
}
|
|
656
656
|
}
|
|
@@ -727,11 +727,11 @@ function validateConfig() {
|
|
|
727
727
|
validateFileConfig();
|
|
728
728
|
validateSlackConfig();
|
|
729
729
|
validateEmailConfig();
|
|
730
|
-
} catch (
|
|
731
|
-
if (
|
|
732
|
-
throw new Error(`[Logger] Configuration validation failed: ${
|
|
730
|
+
} catch (error) {
|
|
731
|
+
if (error instanceof Error) {
|
|
732
|
+
throw new Error(`[Logger] Configuration validation failed: ${error.message}`);
|
|
733
733
|
}
|
|
734
|
-
throw
|
|
734
|
+
throw error;
|
|
735
735
|
}
|
|
736
736
|
}
|
|
737
737
|
var init_config = __esm({
|
|
@@ -885,12 +885,12 @@ function discoverFunctionRoutes(cwd = process.cwd()) {
|
|
|
885
885
|
prefix: prefix || "(none)"
|
|
886
886
|
});
|
|
887
887
|
}
|
|
888
|
-
} catch (
|
|
888
|
+
} catch (error) {
|
|
889
889
|
}
|
|
890
890
|
}
|
|
891
|
-
} catch (
|
|
891
|
+
} catch (error) {
|
|
892
892
|
routeLogger.warn("Failed to discover function routes", {
|
|
893
|
-
error:
|
|
893
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
894
894
|
});
|
|
895
895
|
}
|
|
896
896
|
return functions;
|
|
@@ -924,8 +924,8 @@ var AutoRouteLoader = class {
|
|
|
924
924
|
}
|
|
925
925
|
let failureCount = 0;
|
|
926
926
|
for (const file of files) {
|
|
927
|
-
const
|
|
928
|
-
if (
|
|
927
|
+
const success = await this.loadRoute(app, file);
|
|
928
|
+
if (success) ; else {
|
|
929
929
|
failureCount++;
|
|
930
930
|
}
|
|
931
931
|
}
|
|
@@ -962,8 +962,8 @@ var AutoRouteLoader = class {
|
|
|
962
962
|
let successCount = 0;
|
|
963
963
|
let failureCount = 0;
|
|
964
964
|
for (const file of files) {
|
|
965
|
-
const
|
|
966
|
-
if (
|
|
965
|
+
const success = await this.loadRoute(app, file, prefix);
|
|
966
|
+
if (success) {
|
|
967
967
|
successCount++;
|
|
968
968
|
} else {
|
|
969
969
|
failureCount++;
|
|
@@ -1061,8 +1061,8 @@ var AutoRouteLoader = class {
|
|
|
1061
1061
|
}
|
|
1062
1062
|
});
|
|
1063
1063
|
return true;
|
|
1064
|
-
} catch (
|
|
1065
|
-
this.categorizeAndLogError(
|
|
1064
|
+
} catch (error) {
|
|
1065
|
+
this.categorizeAndLogError(error, relativePath);
|
|
1066
1066
|
return false;
|
|
1067
1067
|
}
|
|
1068
1068
|
}
|
|
@@ -1118,9 +1118,9 @@ var AutoRouteLoader = class {
|
|
|
1118
1118
|
}
|
|
1119
1119
|
}
|
|
1120
1120
|
}
|
|
1121
|
-
categorizeAndLogError(
|
|
1122
|
-
const message =
|
|
1123
|
-
const stack =
|
|
1121
|
+
categorizeAndLogError(error, relativePath) {
|
|
1122
|
+
const message = error.message;
|
|
1123
|
+
const stack = error.stack;
|
|
1124
1124
|
if (message.includes("Cannot find module") || message.includes("MODULE_NOT_FOUND")) {
|
|
1125
1125
|
routeLogger2.error("Missing dependency", {
|
|
1126
1126
|
file: relativePath,
|
|
@@ -1183,10 +1183,10 @@ async function loadRoutes(app, options) {
|
|
|
1183
1183
|
routesDir: func.routesDir,
|
|
1184
1184
|
prefix: func.prefix || "/"
|
|
1185
1185
|
});
|
|
1186
|
-
} catch (
|
|
1186
|
+
} catch (error) {
|
|
1187
1187
|
routeLogger2.error("Failed to load function routes", {
|
|
1188
1188
|
package: func.packageName,
|
|
1189
|
-
error:
|
|
1189
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1190
1190
|
});
|
|
1191
1191
|
}
|
|
1192
1192
|
}
|
|
@@ -1298,8 +1298,42 @@ function bind(contract, handler) {
|
|
|
1298
1298
|
return body;
|
|
1299
1299
|
},
|
|
1300
1300
|
json: (data, status, headers) => {
|
|
1301
|
+
const errorHandlerEnabled = rawContext.get("errorHandlerEnabled");
|
|
1302
|
+
if (errorHandlerEnabled && process.env.NODE_ENV !== "production") {
|
|
1303
|
+
const hasSuccessField = data && typeof data === "object" && "success" in data;
|
|
1304
|
+
if (!hasSuccessField) {
|
|
1305
|
+
console.warn(
|
|
1306
|
+
"[SPFN] Warning: ErrorHandler is enabled but c.json() is being used with non-standard response format.\nConsider using c.success() for consistent API responses, or disable ErrorHandler if you prefer custom formats."
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1301
1310
|
return rawContext.json(data, status, headers);
|
|
1302
1311
|
},
|
|
1312
|
+
success: (data, meta, status = 200) => {
|
|
1313
|
+
const response = {
|
|
1314
|
+
success: true,
|
|
1315
|
+
data
|
|
1316
|
+
};
|
|
1317
|
+
if (meta) {
|
|
1318
|
+
response.meta = meta;
|
|
1319
|
+
}
|
|
1320
|
+
return rawContext.json(response, status);
|
|
1321
|
+
},
|
|
1322
|
+
paginated: (data, page, limit, total) => {
|
|
1323
|
+
const response = {
|
|
1324
|
+
success: true,
|
|
1325
|
+
data,
|
|
1326
|
+
meta: {
|
|
1327
|
+
pagination: {
|
|
1328
|
+
page,
|
|
1329
|
+
limit,
|
|
1330
|
+
total,
|
|
1331
|
+
totalPages: Math.ceil(total / limit)
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
return rawContext.json(response, 200);
|
|
1336
|
+
},
|
|
1303
1337
|
raw: rawContext
|
|
1304
1338
|
};
|
|
1305
1339
|
return handler(routeContext);
|
|
@@ -1412,56 +1446,12 @@ function ApiResponseSchema(dataSchema) {
|
|
|
1412
1446
|
ApiErrorSchema()
|
|
1413
1447
|
]);
|
|
1414
1448
|
}
|
|
1415
|
-
function success(c, data, meta, status = 200) {
|
|
1416
|
-
const response = {
|
|
1417
|
-
success: true,
|
|
1418
|
-
data
|
|
1419
|
-
};
|
|
1420
|
-
if (meta) {
|
|
1421
|
-
response.meta = meta;
|
|
1422
|
-
}
|
|
1423
|
-
return c.json(response, status);
|
|
1424
|
-
}
|
|
1425
|
-
function error(c, message, statusCode = 400, details) {
|
|
1426
|
-
const response = {
|
|
1427
|
-
success: false,
|
|
1428
|
-
error: {
|
|
1429
|
-
message,
|
|
1430
|
-
type: getErrorType(statusCode),
|
|
1431
|
-
statusCode
|
|
1432
|
-
}
|
|
1433
|
-
};
|
|
1434
|
-
if (details) {
|
|
1435
|
-
response.error.details = details;
|
|
1436
|
-
}
|
|
1437
|
-
return c.json(response, statusCode);
|
|
1438
|
-
}
|
|
1439
|
-
function paginated(c, data, page, limit, total) {
|
|
1440
|
-
return success(c, data, {
|
|
1441
|
-
pagination: {
|
|
1442
|
-
page,
|
|
1443
|
-
limit,
|
|
1444
|
-
total,
|
|
1445
|
-
totalPages: Math.ceil(total / limit)
|
|
1446
|
-
}
|
|
1447
|
-
});
|
|
1448
|
-
}
|
|
1449
|
-
function getErrorType(statusCode) {
|
|
1450
|
-
if (statusCode >= 500) return "InternalServerError";
|
|
1451
|
-
if (statusCode === 404) return "NotFoundError";
|
|
1452
|
-
if (statusCode === 401) return "UnauthorizedError";
|
|
1453
|
-
if (statusCode === 403) return "ForbiddenError";
|
|
1454
|
-
if (statusCode === 400) return "ValidationError";
|
|
1455
|
-
if (statusCode === 409) return "ConflictError";
|
|
1456
|
-
if (statusCode === 422) return "UnprocessableEntityError";
|
|
1457
|
-
return "ClientError";
|
|
1458
|
-
}
|
|
1459
1449
|
|
|
1460
1450
|
// src/route/types.ts
|
|
1461
1451
|
function isHttpMethod(value) {
|
|
1462
1452
|
return typeof value === "string" && ["GET", "POST", "PUT", "PATCH", "DELETE"].includes(value);
|
|
1463
1453
|
}
|
|
1464
1454
|
|
|
1465
|
-
export { ApiErrorSchema, ApiResponseSchema, ApiSuccessSchema, AutoRouteLoader, bind, createApp,
|
|
1455
|
+
export { ApiErrorSchema, ApiResponseSchema, ApiSuccessSchema, AutoRouteLoader, bind, createApp, isHttpMethod, loadRoutes };
|
|
1466
1456
|
//# sourceMappingURL=index.js.map
|
|
1467
1457
|
//# sourceMappingURL=index.js.map
|