@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
package/dist/route/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { join, dirname, relative } from 'path';
|
|
|
4
4
|
import { readdir, stat } from 'fs/promises';
|
|
5
5
|
import { Value } from '@sinclair/typebox/value';
|
|
6
6
|
import { Hono } from 'hono';
|
|
7
|
+
import { Type } from '@sinclair/typebox';
|
|
7
8
|
|
|
8
9
|
var __defProp = Object.defineProperty;
|
|
9
10
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -118,11 +119,11 @@ function formatTimestampHuman(date) {
|
|
|
118
119
|
const ms = String(date.getMilliseconds()).padStart(3, "0");
|
|
119
120
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;
|
|
120
121
|
}
|
|
121
|
-
function formatError(
|
|
122
|
+
function formatError(error2) {
|
|
122
123
|
const lines = [];
|
|
123
|
-
lines.push(`${
|
|
124
|
-
if (
|
|
125
|
-
const stackLines =
|
|
124
|
+
lines.push(`${error2.name}: ${error2.message}`);
|
|
125
|
+
if (error2.stack) {
|
|
126
|
+
const stackLines = error2.stack.split("\n").slice(1);
|
|
126
127
|
lines.push(...stackLines);
|
|
127
128
|
}
|
|
128
129
|
return lines.join("\n");
|
|
@@ -308,7 +309,7 @@ var init_logger = __esm({
|
|
|
308
309
|
/**
|
|
309
310
|
* Log processing (internal)
|
|
310
311
|
*/
|
|
311
|
-
log(level, message,
|
|
312
|
+
log(level, message, error2, context) {
|
|
312
313
|
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level]) {
|
|
313
314
|
return;
|
|
314
315
|
}
|
|
@@ -317,7 +318,7 @@ var init_logger = __esm({
|
|
|
317
318
|
level,
|
|
318
319
|
message,
|
|
319
320
|
module: this.module,
|
|
320
|
-
error,
|
|
321
|
+
error: error2,
|
|
321
322
|
// Mask sensitive information in context to prevent credential leaks
|
|
322
323
|
context: context ? maskSensitiveData(context) : void 0
|
|
323
324
|
};
|
|
@@ -328,8 +329,8 @@ var init_logger = __esm({
|
|
|
328
329
|
*/
|
|
329
330
|
processTransports(metadata) {
|
|
330
331
|
const promises = this.config.transports.filter((transport) => transport.enabled).map((transport) => this.safeTransportLog(transport, metadata));
|
|
331
|
-
Promise.all(promises).catch((
|
|
332
|
-
const errorMessage =
|
|
332
|
+
Promise.all(promises).catch((error2) => {
|
|
333
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
333
334
|
process.stderr.write(`[Logger] Transport error: ${errorMessage}
|
|
334
335
|
`);
|
|
335
336
|
});
|
|
@@ -340,8 +341,8 @@ var init_logger = __esm({
|
|
|
340
341
|
async safeTransportLog(transport, metadata) {
|
|
341
342
|
try {
|
|
342
343
|
await transport.log(metadata);
|
|
343
|
-
} catch (
|
|
344
|
-
const errorMessage =
|
|
344
|
+
} catch (error2) {
|
|
345
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
345
346
|
process.stderr.write(`[Logger] Transport "${transport.name}" failed: ${errorMessage}
|
|
346
347
|
`);
|
|
347
348
|
}
|
|
@@ -431,11 +432,11 @@ var init_file = __esm({
|
|
|
431
432
|
}
|
|
432
433
|
if (this.currentStream) {
|
|
433
434
|
return new Promise((resolve, reject) => {
|
|
434
|
-
this.currentStream.write(message + "\n", "utf-8", (
|
|
435
|
-
if (
|
|
436
|
-
process.stderr.write(`[FileTransport] Failed to write log: ${
|
|
435
|
+
this.currentStream.write(message + "\n", "utf-8", (error2) => {
|
|
436
|
+
if (error2) {
|
|
437
|
+
process.stderr.write(`[FileTransport] Failed to write log: ${error2.message}
|
|
437
438
|
`);
|
|
438
|
-
reject(
|
|
439
|
+
reject(error2);
|
|
439
440
|
} else {
|
|
440
441
|
resolve();
|
|
441
442
|
}
|
|
@@ -457,8 +458,8 @@ var init_file = __esm({
|
|
|
457
458
|
encoding: "utf-8"
|
|
458
459
|
});
|
|
459
460
|
this.currentFilename = filename;
|
|
460
|
-
this.currentStream.on("error", (
|
|
461
|
-
process.stderr.write(`[FileTransport] Stream error: ${
|
|
461
|
+
this.currentStream.on("error", (error2) => {
|
|
462
|
+
process.stderr.write(`[FileTransport] Stream error: ${error2.message}
|
|
462
463
|
`);
|
|
463
464
|
this.currentStream = null;
|
|
464
465
|
this.currentFilename = null;
|
|
@@ -472,9 +473,9 @@ var init_file = __esm({
|
|
|
472
473
|
return;
|
|
473
474
|
}
|
|
474
475
|
return new Promise((resolve, reject) => {
|
|
475
|
-
this.currentStream.end((
|
|
476
|
-
if (
|
|
477
|
-
reject(
|
|
476
|
+
this.currentStream.end((error2) => {
|
|
477
|
+
if (error2) {
|
|
478
|
+
reject(error2);
|
|
478
479
|
} else {
|
|
479
480
|
this.currentStream = null;
|
|
480
481
|
this.currentFilename = null;
|
|
@@ -499,8 +500,8 @@ var init_file = __esm({
|
|
|
499
500
|
if (stats.size >= this.maxFileSize) {
|
|
500
501
|
await this.rotateBySize();
|
|
501
502
|
}
|
|
502
|
-
} catch (
|
|
503
|
-
const errorMessage =
|
|
503
|
+
} catch (error2) {
|
|
504
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
504
505
|
process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}
|
|
505
506
|
`);
|
|
506
507
|
}
|
|
@@ -526,8 +527,8 @@ var init_file = __esm({
|
|
|
526
527
|
const newPath2 = join(this.logDir, `${baseName}.${newNum}.log`);
|
|
527
528
|
try {
|
|
528
529
|
renameSync(oldPath, newPath2);
|
|
529
|
-
} catch (
|
|
530
|
-
const errorMessage =
|
|
530
|
+
} catch (error2) {
|
|
531
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
531
532
|
process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}
|
|
532
533
|
`);
|
|
533
534
|
}
|
|
@@ -539,8 +540,8 @@ var init_file = __esm({
|
|
|
539
540
|
if (existsSync(currentPath)) {
|
|
540
541
|
renameSync(currentPath, newPath);
|
|
541
542
|
}
|
|
542
|
-
} catch (
|
|
543
|
-
const errorMessage =
|
|
543
|
+
} catch (error2) {
|
|
544
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
544
545
|
process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}
|
|
545
546
|
`);
|
|
546
547
|
}
|
|
@@ -567,15 +568,15 @@ var init_file = __esm({
|
|
|
567
568
|
const filepath = join(this.logDir, file);
|
|
568
569
|
try {
|
|
569
570
|
unlinkSync(filepath);
|
|
570
|
-
} catch (
|
|
571
|
-
const errorMessage =
|
|
571
|
+
} catch (error2) {
|
|
572
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
572
573
|
process.stderr.write(`[FileTransport] Failed to delete old file "${file}": ${errorMessage}
|
|
573
574
|
`);
|
|
574
575
|
}
|
|
575
576
|
}
|
|
576
577
|
}
|
|
577
|
-
} catch (
|
|
578
|
-
const errorMessage =
|
|
578
|
+
} catch (error2) {
|
|
579
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
579
580
|
process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}
|
|
580
581
|
`);
|
|
581
582
|
}
|
|
@@ -634,8 +635,8 @@ function validateDirectoryWritable(dirPath) {
|
|
|
634
635
|
if (!existsSync(dirPath)) {
|
|
635
636
|
try {
|
|
636
637
|
mkdirSync(dirPath, { recursive: true });
|
|
637
|
-
} catch (
|
|
638
|
-
const errorMessage =
|
|
638
|
+
} catch (error2) {
|
|
639
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
639
640
|
throw new Error(`Failed to create log directory "${dirPath}": ${errorMessage}`);
|
|
640
641
|
}
|
|
641
642
|
}
|
|
@@ -648,8 +649,8 @@ function validateDirectoryWritable(dirPath) {
|
|
|
648
649
|
try {
|
|
649
650
|
writeFileSync(testFile, "test", "utf-8");
|
|
650
651
|
unlinkSync(testFile);
|
|
651
|
-
} catch (
|
|
652
|
-
const errorMessage =
|
|
652
|
+
} catch (error2) {
|
|
653
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
653
654
|
throw new Error(`Cannot write to log directory "${dirPath}": ${errorMessage}`);
|
|
654
655
|
}
|
|
655
656
|
}
|
|
@@ -726,11 +727,11 @@ function validateConfig() {
|
|
|
726
727
|
validateFileConfig();
|
|
727
728
|
validateSlackConfig();
|
|
728
729
|
validateEmailConfig();
|
|
729
|
-
} catch (
|
|
730
|
-
if (
|
|
731
|
-
throw new Error(`[Logger] Configuration validation failed: ${
|
|
730
|
+
} catch (error2) {
|
|
731
|
+
if (error2 instanceof Error) {
|
|
732
|
+
throw new Error(`[Logger] Configuration validation failed: ${error2.message}`);
|
|
732
733
|
}
|
|
733
|
-
throw
|
|
734
|
+
throw error2;
|
|
734
735
|
}
|
|
735
736
|
}
|
|
736
737
|
var init_config = __esm({
|
|
@@ -868,24 +869,28 @@ function discoverFunctionRoutes(cwd = process.cwd()) {
|
|
|
868
869
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
869
870
|
if (pkg.spfn?.routes?.dir) {
|
|
870
871
|
const { dir } = pkg.spfn.routes;
|
|
872
|
+
const prefix = pkg.spfn.prefix;
|
|
871
873
|
const packagePath = dirname(pkgPath);
|
|
872
874
|
const routesDir = join(packagePath, dir);
|
|
873
875
|
functions.push({
|
|
874
876
|
packageName,
|
|
875
877
|
routesDir,
|
|
876
|
-
packagePath
|
|
878
|
+
packagePath,
|
|
879
|
+
prefix
|
|
880
|
+
// Include prefix in function info
|
|
877
881
|
});
|
|
878
882
|
routeLogger.debug("Discovered function routes", {
|
|
879
883
|
package: packageName,
|
|
880
|
-
dir
|
|
884
|
+
dir,
|
|
885
|
+
prefix: prefix || "(none)"
|
|
881
886
|
});
|
|
882
887
|
}
|
|
883
|
-
} catch (
|
|
888
|
+
} catch (error2) {
|
|
884
889
|
}
|
|
885
890
|
}
|
|
886
|
-
} catch (
|
|
891
|
+
} catch (error2) {
|
|
887
892
|
routeLogger.warn("Failed to discover function routes", {
|
|
888
|
-
error:
|
|
893
|
+
error: error2 instanceof Error ? error2.message : "Unknown error"
|
|
889
894
|
});
|
|
890
895
|
}
|
|
891
896
|
return functions;
|
|
@@ -919,8 +924,8 @@ var AutoRouteLoader = class {
|
|
|
919
924
|
}
|
|
920
925
|
let failureCount = 0;
|
|
921
926
|
for (const file of files) {
|
|
922
|
-
const
|
|
923
|
-
if (
|
|
927
|
+
const success2 = await this.loadRoute(app, file);
|
|
928
|
+
if (success2) ; else {
|
|
924
929
|
failureCount++;
|
|
925
930
|
}
|
|
926
931
|
}
|
|
@@ -936,14 +941,15 @@ var AutoRouteLoader = class {
|
|
|
936
941
|
}
|
|
937
942
|
/**
|
|
938
943
|
* Load routes from an external directory (e.g., from SPFN function packages)
|
|
939
|
-
*
|
|
944
|
+
* Reads package.json spfn.prefix and mounts routes under that prefix
|
|
940
945
|
*
|
|
941
946
|
* @param app - Hono app instance
|
|
942
947
|
* @param routesDir - Directory containing route handlers
|
|
943
948
|
* @param packageName - Name of the package (for logging)
|
|
949
|
+
* @param prefix - Optional prefix to mount routes under (from package.json spfn.prefix)
|
|
944
950
|
* @returns Route statistics
|
|
945
951
|
*/
|
|
946
|
-
async loadExternalRoutes(app, routesDir, packageName) {
|
|
952
|
+
async loadExternalRoutes(app, routesDir, packageName, prefix) {
|
|
947
953
|
const startTime = Date.now();
|
|
948
954
|
const tempRoutesDir = this.routesDir;
|
|
949
955
|
this.routesDir = routesDir;
|
|
@@ -956,8 +962,8 @@ var AutoRouteLoader = class {
|
|
|
956
962
|
let successCount = 0;
|
|
957
963
|
let failureCount = 0;
|
|
958
964
|
for (const file of files) {
|
|
959
|
-
const
|
|
960
|
-
if (
|
|
965
|
+
const success2 = await this.loadRoute(app, file, prefix);
|
|
966
|
+
if (success2) {
|
|
961
967
|
successCount++;
|
|
962
968
|
} else {
|
|
963
969
|
failureCount++;
|
|
@@ -967,6 +973,7 @@ var AutoRouteLoader = class {
|
|
|
967
973
|
if (this.debug) {
|
|
968
974
|
routeLogger2.info("External routes loaded", {
|
|
969
975
|
package: packageName,
|
|
976
|
+
prefix: prefix || "/",
|
|
970
977
|
total: successCount,
|
|
971
978
|
failed: failureCount,
|
|
972
979
|
elapsed: `${elapsed}ms`
|
|
@@ -1010,7 +1017,7 @@ var AutoRouteLoader = class {
|
|
|
1010
1017
|
isValidRouteFile(fileName) {
|
|
1011
1018
|
return fileName === "index.ts" || fileName === "index.js" || fileName === "index.mjs";
|
|
1012
1019
|
}
|
|
1013
|
-
async loadRoute(app, absolutePath) {
|
|
1020
|
+
async loadRoute(app, absolutePath, prefix) {
|
|
1014
1021
|
const relativePath = relative(this.routesDir, absolutePath);
|
|
1015
1022
|
try {
|
|
1016
1023
|
const module = await import(absolutePath);
|
|
@@ -1026,11 +1033,24 @@ var AutoRouteLoader = class {
|
|
|
1026
1033
|
return false;
|
|
1027
1034
|
}
|
|
1028
1035
|
const contractPaths = this.extractContractPaths(module);
|
|
1036
|
+
if (prefix) {
|
|
1037
|
+
const invalidPaths = contractPaths.filter((path) => !path.startsWith(prefix));
|
|
1038
|
+
if (invalidPaths.length > 0) {
|
|
1039
|
+
routeLogger2.error("Contract paths must include the package prefix", {
|
|
1040
|
+
file: relativePath,
|
|
1041
|
+
prefix,
|
|
1042
|
+
invalidPaths,
|
|
1043
|
+
hint: `Contract paths should start with "${prefix}". Example: path: "${prefix}/labels"`
|
|
1044
|
+
});
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1029
1048
|
this.registerContractBasedMiddlewares(app, contractPaths, module);
|
|
1030
1049
|
app.route("/", module.default);
|
|
1031
1050
|
contractPaths.forEach((path) => {
|
|
1032
1051
|
this.routes.push({
|
|
1033
1052
|
path,
|
|
1053
|
+
// Use contract path as-is (already includes prefix)
|
|
1034
1054
|
file: relativePath,
|
|
1035
1055
|
meta: module.meta,
|
|
1036
1056
|
priority: this.calculateContractPriority(path)
|
|
@@ -1041,8 +1061,8 @@ var AutoRouteLoader = class {
|
|
|
1041
1061
|
}
|
|
1042
1062
|
});
|
|
1043
1063
|
return true;
|
|
1044
|
-
} catch (
|
|
1045
|
-
this.categorizeAndLogError(
|
|
1064
|
+
} catch (error2) {
|
|
1065
|
+
this.categorizeAndLogError(error2, relativePath);
|
|
1046
1066
|
return false;
|
|
1047
1067
|
}
|
|
1048
1068
|
}
|
|
@@ -1098,9 +1118,9 @@ var AutoRouteLoader = class {
|
|
|
1098
1118
|
}
|
|
1099
1119
|
}
|
|
1100
1120
|
}
|
|
1101
|
-
categorizeAndLogError(
|
|
1102
|
-
const message =
|
|
1103
|
-
const stack =
|
|
1121
|
+
categorizeAndLogError(error2, relativePath) {
|
|
1122
|
+
const message = error2.message;
|
|
1123
|
+
const stack = error2.stack;
|
|
1104
1124
|
if (message.includes("Cannot find module") || message.includes("MODULE_NOT_FOUND")) {
|
|
1105
1125
|
routeLogger2.error("Missing dependency", {
|
|
1106
1126
|
file: relativePath,
|
|
@@ -1157,15 +1177,16 @@ async function loadRoutes(app, options) {
|
|
|
1157
1177
|
routeLogger2.info("Loading function routes", { count: functionRoutes.length });
|
|
1158
1178
|
for (const func of functionRoutes) {
|
|
1159
1179
|
try {
|
|
1160
|
-
await loader.loadExternalRoutes(app, func.routesDir, func.packageName);
|
|
1180
|
+
await loader.loadExternalRoutes(app, func.routesDir, func.packageName, func.prefix);
|
|
1161
1181
|
routeLogger2.info("Function routes loaded", {
|
|
1162
1182
|
package: func.packageName,
|
|
1163
|
-
routesDir: func.routesDir
|
|
1183
|
+
routesDir: func.routesDir,
|
|
1184
|
+
prefix: func.prefix || "/"
|
|
1164
1185
|
});
|
|
1165
|
-
} catch (
|
|
1186
|
+
} catch (error2) {
|
|
1166
1187
|
routeLogger2.error("Failed to load function routes", {
|
|
1167
1188
|
package: func.packageName,
|
|
1168
|
-
error:
|
|
1189
|
+
error: error2 instanceof Error ? error2.message : "Unknown error"
|
|
1169
1190
|
});
|
|
1170
1191
|
}
|
|
1171
1192
|
}
|
|
@@ -1174,14 +1195,14 @@ async function loadRoutes(app, options) {
|
|
|
1174
1195
|
return stats;
|
|
1175
1196
|
}
|
|
1176
1197
|
|
|
1177
|
-
// src/errors/
|
|
1178
|
-
var
|
|
1198
|
+
// src/errors/http-errors.ts
|
|
1199
|
+
var HttpError = class extends Error {
|
|
1179
1200
|
statusCode;
|
|
1180
1201
|
details;
|
|
1181
1202
|
timestamp;
|
|
1182
|
-
constructor(message, statusCode
|
|
1203
|
+
constructor(message, statusCode, details) {
|
|
1183
1204
|
super(message);
|
|
1184
|
-
this.name = "
|
|
1205
|
+
this.name = "HttpError";
|
|
1185
1206
|
this.statusCode = statusCode;
|
|
1186
1207
|
this.details = details;
|
|
1187
1208
|
this.timestamp = /* @__PURE__ */ new Date();
|
|
@@ -1200,13 +1221,7 @@ var DatabaseError = class extends Error {
|
|
|
1200
1221
|
};
|
|
1201
1222
|
}
|
|
1202
1223
|
};
|
|
1203
|
-
var
|
|
1204
|
-
constructor(message, statusCode = 500, details) {
|
|
1205
|
-
super(message, statusCode, details);
|
|
1206
|
-
this.name = "QueryError";
|
|
1207
|
-
}
|
|
1208
|
-
};
|
|
1209
|
-
var ValidationError = class extends QueryError {
|
|
1224
|
+
var ValidationError = class extends HttpError {
|
|
1210
1225
|
constructor(message, details) {
|
|
1211
1226
|
super(message, 400, details);
|
|
1212
1227
|
this.name = "ValidationError";
|
|
@@ -1290,10 +1305,56 @@ function bind(contract, handler) {
|
|
|
1290
1305
|
return handler(routeContext);
|
|
1291
1306
|
};
|
|
1292
1307
|
}
|
|
1308
|
+
|
|
1309
|
+
// src/middleware/error-handler.ts
|
|
1310
|
+
init_logger2();
|
|
1311
|
+
var errorLogger = logger.child("error-handler");
|
|
1312
|
+
function ErrorHandler(options = {}) {
|
|
1313
|
+
const {
|
|
1314
|
+
includeStack = process.env.NODE_ENV !== "production",
|
|
1315
|
+
enableLogging = true
|
|
1316
|
+
} = options;
|
|
1317
|
+
return (err, c) => {
|
|
1318
|
+
const errorWithCode = err;
|
|
1319
|
+
const statusCode = errorWithCode.statusCode || 500;
|
|
1320
|
+
const errorType = err.name || "Error";
|
|
1321
|
+
if (enableLogging) {
|
|
1322
|
+
const logLevel = statusCode >= 500 ? "error" : "warn";
|
|
1323
|
+
errorLogger[logLevel]("Error occurred", {
|
|
1324
|
+
type: errorType,
|
|
1325
|
+
message: err.message,
|
|
1326
|
+
statusCode,
|
|
1327
|
+
path: c.req.path,
|
|
1328
|
+
method: c.req.method
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
const response = {
|
|
1332
|
+
success: false,
|
|
1333
|
+
error: {
|
|
1334
|
+
message: err.message || "Internal Server Error",
|
|
1335
|
+
type: errorType,
|
|
1336
|
+
statusCode
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
if (errorWithCode.details) {
|
|
1340
|
+
response.error.details = errorWithCode.details;
|
|
1341
|
+
}
|
|
1342
|
+
if (includeStack) {
|
|
1343
|
+
response.error.stack = err.stack;
|
|
1344
|
+
}
|
|
1345
|
+
return c.json(response, statusCode);
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
// src/middleware/request-logger.ts
|
|
1350
|
+
init_logger2();
|
|
1351
|
+
|
|
1352
|
+
// src/route/create-app.ts
|
|
1293
1353
|
function createApp() {
|
|
1294
1354
|
const hono = new Hono();
|
|
1295
1355
|
const app = hono;
|
|
1296
1356
|
app._contractMetas = /* @__PURE__ */ new Map();
|
|
1357
|
+
app.onError(ErrorHandler());
|
|
1297
1358
|
const methodMap = /* @__PURE__ */ new Map([
|
|
1298
1359
|
["get", (path, handlers) => hono.get(path, ...handlers)],
|
|
1299
1360
|
["post", (path, handlers) => hono.post(path, ...handlers)],
|
|
@@ -1317,12 +1378,90 @@ function createApp() {
|
|
|
1317
1378
|
};
|
|
1318
1379
|
return app;
|
|
1319
1380
|
}
|
|
1381
|
+
function ApiSuccessSchema(dataSchema) {
|
|
1382
|
+
return Type.Object({
|
|
1383
|
+
success: Type.Literal(true),
|
|
1384
|
+
data: dataSchema,
|
|
1385
|
+
meta: Type.Optional(Type.Object({
|
|
1386
|
+
timestamp: Type.Optional(Type.String()),
|
|
1387
|
+
requestId: Type.Optional(Type.String()),
|
|
1388
|
+
pagination: Type.Optional(Type.Object({
|
|
1389
|
+
page: Type.Number(),
|
|
1390
|
+
limit: Type.Number(),
|
|
1391
|
+
total: Type.Number(),
|
|
1392
|
+
totalPages: Type.Number()
|
|
1393
|
+
}))
|
|
1394
|
+
}))
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
function ApiErrorSchema() {
|
|
1398
|
+
return Type.Object({
|
|
1399
|
+
success: Type.Literal(false),
|
|
1400
|
+
error: Type.Object({
|
|
1401
|
+
message: Type.String(),
|
|
1402
|
+
type: Type.String(),
|
|
1403
|
+
statusCode: Type.Number(),
|
|
1404
|
+
stack: Type.Optional(Type.String()),
|
|
1405
|
+
details: Type.Optional(Type.Any())
|
|
1406
|
+
})
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
function ApiResponseSchema(dataSchema) {
|
|
1410
|
+
return Type.Union([
|
|
1411
|
+
ApiSuccessSchema(dataSchema),
|
|
1412
|
+
ApiErrorSchema()
|
|
1413
|
+
]);
|
|
1414
|
+
}
|
|
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
|
+
}
|
|
1320
1459
|
|
|
1321
1460
|
// src/route/types.ts
|
|
1322
1461
|
function isHttpMethod(value) {
|
|
1323
1462
|
return typeof value === "string" && ["GET", "POST", "PUT", "PATCH", "DELETE"].includes(value);
|
|
1324
1463
|
}
|
|
1325
1464
|
|
|
1326
|
-
export { AutoRouteLoader, bind, createApp, isHttpMethod, loadRoutes };
|
|
1465
|
+
export { ApiErrorSchema, ApiResponseSchema, ApiSuccessSchema, AutoRouteLoader, bind, createApp, error, isHttpMethod, loadRoutes, paginated, success };
|
|
1327
1466
|
//# sourceMappingURL=index.js.map
|
|
1328
1467
|
//# sourceMappingURL=index.js.map
|