@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.
@@ -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-CAON3Mmg.js';
4
- export { c as HeaderRecord, H as HttpMethod, I as InferContract, d as RouteMeta, i as isHttpMethod } from '../types-CAON3Mmg.js';
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 };
@@ -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(error2) {
122
+ function formatError(error) {
123
123
  const lines = [];
124
- lines.push(`${error2.name}: ${error2.message}`);
125
- if (error2.stack) {
126
- const stackLines = error2.stack.split("\n").slice(1);
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, error2, context) {
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: error2,
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((error2) => {
333
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
345
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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", (error2) => {
436
- if (error2) {
437
- process.stderr.write(`[FileTransport] Failed to write log: ${error2.message}
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(error2);
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", (error2) => {
462
- process.stderr.write(`[FileTransport] Stream error: ${error2.message}
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((error2) => {
477
- if (error2) {
478
- reject(error2);
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 (error2) {
504
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
531
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
544
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
572
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
579
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
639
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
653
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
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 (error2) {
731
- if (error2 instanceof Error) {
732
- throw new Error(`[Logger] Configuration validation failed: ${error2.message}`);
730
+ } catch (error) {
731
+ if (error instanceof Error) {
732
+ throw new Error(`[Logger] Configuration validation failed: ${error.message}`);
733
733
  }
734
- throw error2;
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 (error2) {
888
+ } catch (error) {
889
889
  }
890
890
  }
891
- } catch (error2) {
891
+ } catch (error) {
892
892
  routeLogger.warn("Failed to discover function routes", {
893
- error: error2 instanceof Error ? error2.message : "Unknown 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 success2 = await this.loadRoute(app, file);
928
- if (success2) ; else {
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 success2 = await this.loadRoute(app, file, prefix);
966
- if (success2) {
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 (error2) {
1065
- this.categorizeAndLogError(error2, relativePath);
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(error2, relativePath) {
1122
- const message = error2.message;
1123
- const stack = error2.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 (error2) {
1186
+ } catch (error) {
1187
1187
  routeLogger2.error("Failed to load function routes", {
1188
1188
  package: func.packageName,
1189
- error: error2 instanceof Error ? error2.message : "Unknown 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, error, isHttpMethod, loadRoutes, paginated, success };
1455
+ export { ApiErrorSchema, ApiResponseSchema, ApiSuccessSchema, AutoRouteLoader, bind, createApp, isHttpMethod, loadRoutes };
1466
1456
  //# sourceMappingURL=index.js.map
1467
1457
  //# sourceMappingURL=index.js.map