@spfn/core 0.2.0-beta.22 → 0.2.0-beta.23

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.
@@ -236,6 +236,7 @@ type NamedMiddleware<TName extends string = string> = {
236
236
  name: TName;
237
237
  handler: MiddlewareHandler;
238
238
  _name: TName;
239
+ skips?: string[];
239
240
  };
240
241
  /**
241
242
  * Named middleware factory with type inference
@@ -310,8 +311,27 @@ type NamedMiddlewareFactory<TName extends string = string, TArgs extends any[] =
310
311
  * .handler(async (c) => { ... });
311
312
  * ```
312
313
  */
313
- declare function defineMiddleware<TName extends string>(name: TName, handler: MiddlewareHandler): NamedMiddleware<TName>;
314
- declare function defineMiddleware<TName extends string, TArgs extends any[]>(name: TName, factory: (...args: TArgs) => MiddlewareHandler): NamedMiddlewareFactory<TName, TArgs>;
314
+ /**
315
+ * Options for defineMiddleware
316
+ */
317
+ interface DefineMiddlewareOptions {
318
+ /**
319
+ * Server-level middleware names to auto-skip when this middleware is used at route level.
320
+ *
321
+ * @example
322
+ * ```ts
323
+ * // optionalAuth auto-skips the global 'auth' middleware
324
+ * export const optionalAuth = defineMiddleware('optionalAuth', handler, {
325
+ * skips: ['auth']
326
+ * });
327
+ *
328
+ * // Usage: .use([optionalAuth]) — no need for .skip(['auth'])
329
+ * ```
330
+ */
331
+ skips?: string[];
332
+ }
333
+ declare function defineMiddleware<TName extends string>(name: TName, handler: MiddlewareHandler, options?: DefineMiddlewareOptions): NamedMiddleware<TName>;
334
+ declare function defineMiddleware<TName extends string, TArgs extends any[]>(name: TName, factory: (...args: TArgs) => MiddlewareHandler, options?: DefineMiddlewareOptions): NamedMiddlewareFactory<TName, TArgs>;
315
335
  /**
316
336
  * Define a middleware factory explicitly
317
337
  *
@@ -602,18 +602,28 @@ function registerRoute(app, name, routeDef, namedMiddlewares) {
602
602
  const registeredNames = /* @__PURE__ */ new Set();
603
603
  const registeredHandlers = /* @__PURE__ */ new Set();
604
604
  const skipAll = skipMiddlewares === "*";
605
+ const autoSkips = /* @__PURE__ */ new Set();
606
+ for (const mw of middlewares) {
607
+ if (isNamedMiddleware(mw) && mw.skips) {
608
+ for (const skipName of mw.skips) {
609
+ autoSkips.add(skipName);
610
+ }
611
+ }
612
+ }
605
613
  if (namedMiddlewares && namedMiddlewares.length > 0) {
606
614
  if (skipAll) {
607
615
  logger.debug(`\u23ED\uFE0F Skipping all middlewares (*) for route: ${method} ${path}`, { name });
608
616
  } else {
609
617
  const skipSet = new Set(Array.isArray(skipMiddlewares) ? skipMiddlewares : []);
610
618
  for (const middleware of namedMiddlewares) {
611
- if (!skipSet.has(middleware.name)) {
619
+ if (skipSet.has(middleware.name)) {
620
+ logger.debug(`\u23ED\uFE0F Skipping middleware '${middleware.name}' for route: ${method} ${path}`, { name });
621
+ } else if (autoSkips.has(middleware.name)) {
622
+ logger.debug(`\u23ED\uFE0F Auto-skipping middleware '${middleware.name}' for route: ${method} ${path}`, { name });
623
+ } else {
612
624
  allMiddlewares.push(middleware.handler);
613
625
  registeredNames.add(middleware.name);
614
626
  registeredHandlers.add(middleware.handler);
615
- } else {
616
- logger.debug(`\u23ED\uFE0F Skipping middleware '${middleware.name}' for route: ${method} ${path}`, { name });
617
627
  }
618
628
  }
619
629
  }
@@ -720,14 +730,16 @@ async function createRouteBuilderContext(c, input) {
720
730
  }
721
731
 
722
732
  // src/route/define-middleware.ts
723
- function defineMiddleware(name, handlerOrFactory) {
733
+ function defineMiddleware(name, handlerOrFactory, options) {
734
+ const skips = options?.skips;
724
735
  if (typeof handlerOrFactory === "function") {
725
736
  const paramCount = handlerOrFactory.length;
726
737
  if (paramCount === 2) {
727
738
  return {
728
739
  name,
729
740
  handler: handlerOrFactory,
730
- _name: name
741
+ _name: name,
742
+ ...skips && { skips }
731
743
  };
732
744
  } else {
733
745
  const factory = handlerOrFactory;
@@ -744,13 +756,22 @@ function defineMiddleware(name, handlerOrFactory) {
744
756
  enumerable: false,
745
757
  configurable: true
746
758
  });
759
+ if (skips) {
760
+ Object.defineProperty(wrapper, "skips", {
761
+ value: skips,
762
+ writable: false,
763
+ enumerable: false,
764
+ configurable: true
765
+ });
766
+ }
747
767
  return wrapper;
748
768
  }
749
769
  }
750
770
  return {
751
771
  name,
752
772
  handler: handlerOrFactory,
753
- _name: name
773
+ _name: name,
774
+ ...skips && { skips }
754
775
  };
755
776
  }
756
777
  function defineMiddlewareFactory(name, factory) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/route/route-builder.ts","../../src/route/router.ts","../../src/route/file-schema.ts","../../src/route/validation.ts","../../src/route/register-routes.ts","../../src/route/define-middleware.ts","../../src/route/helpers.ts"],"names":["Type"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Route Builder\n *\n * Provides tRPC-style chainable API for route definition\n */\n\nimport type { MiddlewareHandler } from 'hono';\nimport type { NamedMiddleware } from './define-middleware';\nimport type { RouteInput } from './route-input';\nimport type { RouteBuilderContext } from './context';\nimport type { HttpMethod } from './types';\n\n/**\n * Route handler function\n */\nexport type RouteHandlerFn<\n TInput extends RouteInput = RouteInput,\n TInterceptor extends RouteInput = {},\n TResponse = unknown\n> = (c: RouteBuilderContext<TInput, TInterceptor>) => Response | Promise<Response> | TResponse | Promise<TResponse>;\n\n/**\n * Route definition result\n *\n * Contains all information needed for type inference and registration\n */\nexport type RouteDef<\n TInput extends RouteInput = RouteInput,\n TInterceptor extends RouteInput = {},\n TResponse = unknown\n> = {\n method?: HttpMethod;\n path?: string;\n input?: TInput;\n interceptor?: TInterceptor;\n middlewares?: (MiddlewareHandler | NamedMiddleware<string>)[];\n skipMiddlewares?: string[] | '*';\n handler: RouteHandlerFn<TInput, TInterceptor, TResponse>;\n\n // Type inference helpers\n _input: TInput;\n _interceptor: TInterceptor;\n _response: TResponse;\n};\n\n/**\n * Route builder with chainable API (tRPC-style)\n */\nexport class RouteBuilder<\n TInput extends RouteInput = {},\n TInterceptor extends RouteInput = {},\n TResponse = never\n>\n{\n public _method?: HttpMethod;\n public _path?: string;\n public _input?: TInput;\n public _interceptor?: TInterceptor;\n public _middlewares?: (MiddlewareHandler | NamedMiddleware<string>)[];\n public _skipMiddlewares?: string[] | '*';\n\n /**\n * Create a new RouteBuilder with copied properties and optional overrides\n */\n private clone<\n TNewInput extends RouteInput = TInput,\n TNewInterceptor extends RouteInput = TInterceptor\n >(\n overrides?: Partial<{\n input: TNewInput;\n interceptor: TNewInterceptor;\n middlewares: (MiddlewareHandler | NamedMiddleware<string>)[];\n skipMiddlewares: string[] | '*';\n }>\n ): RouteBuilder<TNewInput, TNewInterceptor, TResponse>\n {\n const builder = new RouteBuilder<TNewInput, TNewInterceptor, TResponse>();\n builder._method = this._method;\n builder._path = this._path;\n builder._input = (overrides?.input ?? this._input) as TNewInput | undefined;\n builder._interceptor = (overrides?.interceptor ?? this._interceptor) as TNewInterceptor | undefined;\n builder._middlewares = overrides?.middlewares ?? this._middlewares;\n builder._skipMiddlewares = overrides?.skipMiddlewares ?? this._skipMiddlewares;\n return builder;\n }\n\n /**\n * Define input schemas\n *\n * @example\n * ```ts\n * route.get('/users/:id')\n * .input({\n * params: Type.Object({ id: Type.String() }),\n * query: Type.Object({ page: Type.Number() }),\n * headers: Type.Object({ authorization: Type.String() })\n * })\n * .handler(async (c) => {\n * const { params, query, headers } = await c.data();\n * // params = { id: string }\n * // query = { page: number }\n * // headers = { authorization: string }\n * })\n * ```\n */\n input<TNewInput extends RouteInput>(input: TNewInput): RouteBuilder<TNewInput, TInterceptor, TResponse>\n {\n return this.clone({ input });\n }\n\n /**\n * Define fields injected by interceptors\n *\n * These fields are:\n * - Available in the handler (merged with input)\n * - Excluded from client types (codegen uses only input)\n * - Not validated by route input schema (injected by middleware)\n *\n * Use this when middleware/interceptors add fields to the request\n * before it reaches the handler.\n *\n * @example\n * ```ts\n * // Auth interceptor injects crypto key fields\n * route.post('/_auth/login')\n * .input({\n * body: Type.Object({\n * email: Type.String(),\n * password: Type.String()\n * })\n * })\n * .interceptor({\n * body: Type.Object({\n * publicKey: Type.String(),\n * keyId: Type.String(),\n * fingerprint: Type.String()\n * })\n * })\n * .handler(async (c) => {\n * const { body } = await c.data();\n * // body type: { email, password, publicKey, keyId, fingerprint }\n * // Client only sees: { email, password }\n * return loginService(body);\n * });\n * ```\n */\n interceptor<TNewInterceptor extends RouteInput>(\n interceptor: TNewInterceptor\n ): RouteBuilder<TInput, TNewInterceptor, TResponse>\n {\n return this.clone({ interceptor });\n }\n\n /**\n * Add middlewares to the route\n *\n * Accepts both regular middleware handlers and named middlewares (NamedMiddleware).\n * Named middlewares that are already registered globally will be automatically\n * deduplicated to prevent double execution.\n *\n * @example\n * ```ts\n * import { authenticate } from '@spfn/auth/server/middleware';\n *\n * // With NamedMiddleware (auto-deduped if registered globally)\n * route.get('/users')\n * .use([authenticate, RateLimitMiddleware()])\n *\n * // With regular middleware handlers\n * route.get('/users')\n * .use([AuthMiddleware(), RateLimitMiddleware()])\n * ```\n */\n middleware(middlewares: (MiddlewareHandler | NamedMiddleware<string>)[]): RouteBuilder<TInput, TInterceptor, TResponse>\n {\n return this.clone({ middlewares });\n }\n\n /**\n * Add middlewares to the route (alias for `.middleware()`)\n *\n * Accepts both regular middleware handlers and named middlewares (NamedMiddleware).\n * Named middlewares that are already registered globally will be automatically\n * deduplicated to prevent double execution.\n *\n * @example\n * ```ts\n * import { authenticate } from '@spfn/auth/server/middleware';\n *\n * // With NamedMiddleware (auto-deduped if registered globally)\n * route.get('/users')\n * .use([authenticate, RateLimitMiddleware()])\n *\n * // With regular middleware handlers\n * route.get('/users')\n * .use([AuthMiddleware(), RateLimitMiddleware()])\n * ```\n */\n use(middlewares: (MiddlewareHandler | NamedMiddleware<string>)[]): RouteBuilder<TInput, TInterceptor, TResponse>\n {\n return this.middleware(middlewares);\n }\n\n /**\n * Skip server-level named middlewares\n *\n * Useful for public endpoints that should bypass auth or rate limiting\n *\n * @param middlewareNames - Array of middleware names to skip, or '*' to skip all\n *\n * @example\n * ```ts\n * // Skip specific middlewares\n * route.get('/health')\n * .skip(['auth', 'rateLimit'])\n * .handler(async (c) => c.json({ status: 'ok' }));\n *\n * // Skip only auth (still apply rate limiting)\n * route.get('/public-data')\n * .skip(['auth'])\n * .handler(async (c) => { ... });\n *\n * // Skip all middlewares\n * route.get('/public-health')\n * .skip('*')\n * .handler(async (c) => c.json({ status: 'ok' }));\n * ```\n */\n skip(middlewareNames: string[] | '*'): RouteBuilder<TInput, TInterceptor, TResponse>\n {\n return this.clone({ skipMiddlewares: middlewareNames });\n }\n\n /**\n * Define handler function\n *\n * Response type is automatically inferred from the return value.\n * Use helper methods like `c.created()`, `c.paginated()` for proper type inference.\n *\n * @example\n * ```ts\n * // Direct return - type inferred from data\n * route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => {\n * const { params } = await c.data();\n * return await getUser(params.id); // Type: User\n * })\n *\n * // Using c.created() - returns data with 201 status, type preserved\n * route.post('/users')\n * .input({ body: Type.Object({ name: Type.String() }) })\n * .handler(async (c) => {\n * const { body } = await c.data();\n * return c.created(await createUser(body)); // Type: User\n * })\n *\n * // Using c.paginated() - returns PaginatedResult<T>\n * route.get('/users')\n * .handler(async (c) => {\n * const users = await getUsers();\n * return c.paginated(users, 1, 20, 100); // Type: PaginatedResult<User>\n * })\n *\n * // Using c.noContent() - returns void\n * route.delete('/users/:id')\n * .handler(async (c) => {\n * await deleteUser(params.id);\n * return c.noContent(); // Type: void\n * })\n *\n * // Using c.json() - returns Response (type inference lost)\n * // Use only when you need custom status codes not covered by helpers\n * route.get('/custom')\n * .handler(async (c) => {\n * return c.json({ data }, 418); // Type: Response\n * })\n * ```\n */\n handler<THandlerResponse>(\n fn: RouteHandlerFn<TInput, TInterceptor, THandlerResponse>\n ): RouteDef<TInput, TInterceptor, THandlerResponse>\n {\n return {\n method: this._method,\n path: this._path,\n input: this._input,\n interceptor: this._interceptor,\n middlewares: this._middlewares,\n skipMiddlewares: this._skipMiddlewares,\n handler: fn,\n _input: {} as TInput,\n _interceptor: {} as TInterceptor,\n _response: {} as THandlerResponse,\n };\n }\n}\n\n/**\n * Create a route definition with HTTP method shortcuts\n */\nfunction createMethodRoute(method: HttpMethod): (path: string) => RouteBuilder\n{\n return (path: string) =>\n {\n const builder = new RouteBuilder();\n builder._method = method;\n builder._path = path;\n return builder;\n };\n}\n\n/**\n * Route builder entry point\n *\n * @example\n * ```ts\n * // GET request\n * export const getUser = route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => {\n * const { params } = await c.data();\n * return await db.user.findUnique({ where: { id: params.id } });\n * });\n *\n * // POST request\n * export const createUser = route.post('/users')\n * .input({ body: Type.Object({ name: Type.String(), email: Type.String() }) })\n * .handler(async (c) => {\n * const { body } = await c.data();\n * return c.created(await db.user.create({ data: body }));\n * });\n * ```\n */\nexport const route = {\n get: createMethodRoute('GET'),\n post: createMethodRoute('POST'),\n put: createMethodRoute('PUT'),\n patch: createMethodRoute('PATCH'),\n delete: createMethodRoute('DELETE'),\n};","/**\n * Router Definition\n *\n * Provides router composition and middleware management\n */\n\nimport type { NamedMiddleware } from './define-middleware';\nimport type { RouteDef } from './route-builder';\n\n/**\n * Router definition - holds all routes\n */\nexport interface Router<TRoutes extends Record<string, RouteDef<any, any, any> | Router<any>>> {\n routes: TRoutes;\n _routes: TRoutes;\n _packageRouters: Router<any>[];\n _globalMiddlewares: NamedMiddleware<string>[];\n\n /**\n * Register package routers (type-hidden)\n *\n * Package routes are:\n * - Recognized by RPC proxy and backend\n * - NOT exposed in client types (use package's own API like authApi, cmsApi)\n *\n * @example\n * ```ts\n * import { authRouter } from '@spfn/auth/server';\n * import { cmsAppRouter } from '@spfn/cms/server';\n *\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter, cmsAppRouter]);\n *\n * // Client usage:\n * // api.getRoot.call({}) - app routes\n * // authApi.login.call({}) - package API\n * ```\n */\n packages(routers: Router<any>[]): Router<TRoutes>;\n\n /**\n * Register global middlewares\n *\n * Applied to all routes unless explicitly skipped via .skip()\n *\n * @example\n * ```ts\n * import { authMiddleware, loggingMiddleware } from './middlewares';\n *\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter])\n * .use([authMiddleware, loggingMiddleware]);\n * ```\n */\n use(middlewares: NamedMiddleware<string>[]): Router<TRoutes>;\n}\n\n/**\n * Create a Router instance with chainable methods\n */\nfunction createRouterInstance<TRoutes extends Record<string, RouteDef<any, any, any> | Router<any>>>(\n routes: TRoutes,\n packageRouters: Router<any>[] = [],\n globalMiddlewares: NamedMiddleware<string>[] = []\n): Router<TRoutes>\n{\n return {\n routes,\n _routes: routes,\n _packageRouters: packageRouters,\n _globalMiddlewares: globalMiddlewares,\n\n packages(routers: Router<any>[]): Router<TRoutes>\n {\n const newPackageRouters = [...this._packageRouters, ...routers];\n\n // Also include nested package routers if any\n for (const pkgRouter of routers)\n {\n if (pkgRouter._packageRouters?.length > 0)\n {\n newPackageRouters.push(...pkgRouter._packageRouters);\n }\n }\n\n return createRouterInstance(this.routes, newPackageRouters, this._globalMiddlewares);\n },\n\n use(middlewares: NamedMiddleware<string>[]): Router<TRoutes>\n {\n return createRouterInstance(this.routes, this._packageRouters, [...this._globalMiddlewares, ...middlewares]);\n },\n };\n}\n\n/**\n * Define a router with multiple routes (tRPC-style)\n *\n * Supports chainable API for packages and middlewares:\n *\n * @example\n * ```ts\n * // Basic usage\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * listExamples,\n * });\n *\n * // With package routers (type-hidden)\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter, cmsAppRouter]);\n *\n * // With global middlewares\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter])\n * .use([authMiddleware, loggingMiddleware]);\n *\n * export type AppRouter = typeof appRouter;\n * ```\n *\n * Package routes:\n * - Recognized by RPC proxy and backend for routing\n * - NOT included in AppRouter type (use authApi, cmsApi instead)\n * - Prevents confusion between app API and package APIs\n */\nexport function defineRouter<TRoutes extends Record<string, RouteDef<any, any, any> | Router<any>>>(\n routes: TRoutes\n): Router<TRoutes>\n{\n return createRouterInstance(routes);\n}","/**\n * File Schema Helpers for TypeBox\n *\n * Provides TypeBox schema definitions for file upload handling\n * with optional validation constraints.\n */\n\nimport { Kind, Type, type TSchema } from '@sinclair/typebox';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * File validation options\n */\nexport interface FileSchemaOptions\n{\n /**\n * Maximum file size in bytes\n *\n * @example 5 * 1024 * 1024 // 5MB\n */\n maxSize?: number;\n\n /**\n * Allowed MIME types\n *\n * @example ['image/jpeg', 'image/png', 'image/webp']\n */\n allowedTypes?: string[];\n\n /**\n * Minimum file size in bytes (optional)\n *\n * @example 1024 // 1KB minimum\n */\n minSize?: number;\n}\n\n/**\n * File array validation options\n */\nexport interface FileArraySchemaOptions extends FileSchemaOptions\n{\n /**\n * Maximum number of files\n *\n * @example 5\n */\n maxFiles?: number;\n\n /**\n * Minimum number of files (optional)\n *\n * @example 1\n */\n minFiles?: number;\n}\n\n/**\n * Internal schema type with file validation metadata\n */\nexport interface FileSchemaType extends TSchema\n{\n [Kind]: 'File';\n fileOptions?: FileSchemaOptions;\n}\n\nexport interface FileArraySchemaType extends TSchema\n{\n [Kind]: 'FileArray';\n fileOptions?: FileArraySchemaOptions;\n}\n\n// ============================================================================\n// Schema Creators\n// ============================================================================\n\n/**\n * Create a File schema with optional validation\n *\n * @example\n * ```ts\n * // Basic usage (no validation)\n * formData: Type.Object({\n * file: FileSchema()\n * })\n *\n * // With validation\n * formData: Type.Object({\n * avatar: FileSchema({\n * maxSize: 5 * 1024 * 1024, // 5MB\n * allowedTypes: ['image/jpeg', 'image/png', 'image/webp']\n * })\n * })\n * ```\n */\nexport function FileSchema(options?: FileSchemaOptions): FileSchemaType\n{\n return Type.Unsafe<File>({\n [Kind]: 'File',\n type: 'object',\n fileOptions: options,\n }) as FileSchemaType;\n}\n\n/**\n * Create a File array schema with optional validation\n *\n * @example\n * ```ts\n * // Basic usage (no validation)\n * formData: Type.Object({\n * files: FileArraySchema()\n * })\n *\n * // With validation\n * formData: Type.Object({\n * documents: FileArraySchema({\n * maxSize: 10 * 1024 * 1024, // 10MB per file\n * maxFiles: 5,\n * allowedTypes: ['application/pdf', 'application/msword']\n * })\n * })\n * ```\n */\nexport function FileArraySchema(options?: FileArraySchemaOptions): FileArraySchemaType\n{\n return Type.Unsafe<File[]>({\n [Kind]: 'FileArray',\n type: 'array',\n items: { [Kind]: 'File', type: 'object' },\n fileOptions: options,\n }) as FileArraySchemaType;\n}\n\n/**\n * Create an optional File schema with validation\n *\n * @example\n * ```ts\n * formData: Type.Object({\n * name: Type.String(),\n * avatar: OptionalFileSchema({\n * maxSize: 2 * 1024 * 1024,\n * allowedTypes: ['image/jpeg', 'image/png']\n * })\n * })\n * ```\n */\nexport function OptionalFileSchema(options?: FileSchemaOptions): TSchema\n{\n return Type.Optional(FileSchema(options));\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Check if a schema is a File schema\n */\nexport function isFileSchema(schema: TSchema): schema is FileSchemaType\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'File';\n}\n\n/**\n * Check if a schema is a FileArray schema\n */\nexport function isFileArraySchema(schema: TSchema): schema is FileArraySchemaType\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'FileArray';\n}\n\n/**\n * Get file options from schema\n */\nexport function getFileOptions(schema: TSchema): FileSchemaOptions | FileArraySchemaOptions | undefined\n{\n return (schema as any).fileOptions;\n}\n\n/**\n * Format file size for error messages\n */\nexport function formatFileSize(bytes: number): string\n{\n if (bytes >= 1024 * 1024 * 1024)\n {\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}GB`;\n }\n if (bytes >= 1024 * 1024)\n {\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n }\n if (bytes >= 1024)\n {\n return `${(bytes / 1024).toFixed(1)}KB`;\n }\n return `${bytes}B`;\n}\n","/**\n * Route Input Validation\n *\n * Provides unified validation logic for route input fields\n */\n\nimport type { TSchema } from '@sinclair/typebox';\nimport { FormatRegistry } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport type { Context } from 'hono';\nimport { ValidationError } from '@spfn/core/errors';\nimport { formatFileSize } from './file-schema';\n\n// ============================================\n// Format Registry\n// ============================================\n\nFormatRegistry.Set('email', (value: string) =>\n /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n);\n\nFormatRegistry.Set('uri', (value: string) =>\n /^https?:\\/\\/.+/.test(value)\n);\n\nFormatRegistry.Set('uuid', (value: string) =>\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)\n);\n\nFormatRegistry.Set('date', (value: string) =>\n /^\\d{4}-\\d{2}-\\d{2}$/.test(value)\n);\n\nFormatRegistry.Set('date-time', (value: string) =>\n !isNaN(Date.parse(value))\n);\n\n/**\n * Validation error field info\n */\ninterface ValidationFieldError\n{\n path: string;\n message: string;\n value: unknown;\n}\n\n/**\n * Check if a value is a File object\n */\nfunction isFile(value: unknown): value is File\n{\n return value instanceof File ||\n (typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'size' in value &&\n 'type' in value &&\n typeof (value as any).arrayBuffer === 'function');\n}\n\n/**\n * Check if a TypeBox schema represents a File type\n */\nfunction isFileSchemaDef(schema: TSchema): boolean\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'File';\n}\n\n/**\n * Check if a TypeBox schema represents a FileArray type\n */\nfunction isFileArraySchemaDef(schema: TSchema): boolean\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'FileArray';\n}\n\n/**\n * Get file options from schema\n */\nfunction getSchemaFileOptions(schema: TSchema): any | undefined\n{\n return (schema as any).fileOptions;\n}\n\n\n/**\n * Validate a single file against schema options\n */\nfunction validateSingleFile(\n file: File,\n fieldPath: string,\n options: { maxSize?: number; minSize?: number; allowedTypes?: string[] } | undefined,\n errors: ValidationFieldError[]\n): void\n{\n if (!options) return;\n\n const { maxSize, minSize, allowedTypes } = options;\n\n if (maxSize !== undefined && file.size > maxSize)\n {\n errors.push({\n path: fieldPath,\n message: `File size ${formatFileSize(file.size)} exceeds maximum ${formatFileSize(maxSize)}`,\n value: file.size,\n });\n }\n\n if (minSize !== undefined && file.size < minSize)\n {\n errors.push({\n path: fieldPath,\n message: `File size ${formatFileSize(file.size)} is below minimum ${formatFileSize(minSize)}`,\n value: file.size,\n });\n }\n\n if (allowedTypes && allowedTypes.length > 0 && !allowedTypes.includes(file.type))\n {\n errors.push({\n path: fieldPath,\n message: `File type \"${file.type}\" is not allowed. Allowed: ${allowedTypes.join(', ')}`,\n value: file.type,\n });\n }\n}\n\n/**\n * Validate a value against a TypeBox schema\n *\n * @param schema - TypeBox schema to validate against\n * @param rawValue - Raw value to validate\n * @param fieldName - Field name for error messages\n * @returns Validated and converted value\n * @throws ValidationError if validation fails\n */\nexport function validateField<T extends Record<string, unknown>>(\n schema: TSchema | undefined,\n rawValue: Record<string, unknown>,\n fieldName: string\n): T\n{\n if (!schema)\n {\n return {} as T;\n }\n\n const converted = Value.Convert(schema, rawValue);\n const errors = [...Value.Errors(schema, converted)];\n\n if (errors.length > 0)\n {\n throw new ValidationError({\n message: `Invalid ${fieldName}`,\n fields: errors.map((e): ValidationFieldError => ({\n path: e.path,\n message: e.message,\n value: e.value,\n })),\n });\n }\n\n return converted as T;\n}\n\n/**\n * Validate form data against a TypeBox schema\n *\n * Handles File fields specially:\n * - File/FileArray schemas are validated using fileOptions (maxSize, allowedTypes, etc.)\n * - Non-file fields are validated using TypeBox\n *\n * @param schema - TypeBox schema to validate against\n * @param rawValue - Raw form data to validate\n * @param fieldName - Field name for error messages\n * @returns Validated form data\n * @throws ValidationError if validation fails\n */\nexport function validateFormData<T extends Record<string, unknown>>(\n schema: TSchema | undefined,\n rawValue: Record<string, unknown>,\n fieldName: string\n): T\n{\n if (!schema)\n {\n return {} as T;\n }\n\n // For Object schemas, validate non-File fields and validate File fields with fileOptions\n const schemaProps = (schema as any).properties;\n if (!schemaProps)\n {\n // Not an object schema, just return raw value\n return rawValue as T;\n }\n\n const result: Record<string, unknown> = {};\n const nonFileData: Record<string, unknown> = {};\n const nonFileSchema: Record<string, TSchema> = {};\n const fileErrors: ValidationFieldError[] = [];\n\n // Process each field\n for (const [key, value] of Object.entries(rawValue))\n {\n const propSchema = schemaProps[key];\n\n if (propSchema && isFileSchemaDef(propSchema))\n {\n // Single File field\n result[key] = value;\n\n if (isFile(value))\n {\n const fileOptions = getSchemaFileOptions(propSchema);\n validateSingleFile(value, `/${key}`, fileOptions, fileErrors);\n }\n }\n else if (propSchema && isFileArraySchemaDef(propSchema))\n {\n // File array field\n result[key] = value;\n\n const fileOptions = getSchemaFileOptions(propSchema);\n const files = Array.isArray(value) ? value : [value];\n const fileArray = files.filter(isFile);\n\n // Validate file count\n if (fileOptions?.maxFiles !== undefined && fileArray.length > fileOptions.maxFiles)\n {\n fileErrors.push({\n path: `/${key}`,\n message: `Too many files. Maximum: ${fileOptions.maxFiles}, received: ${fileArray.length}`,\n value: fileArray.length,\n });\n }\n\n if (fileOptions?.minFiles !== undefined && fileArray.length < fileOptions.minFiles)\n {\n fileErrors.push({\n path: `/${key}`,\n message: `Too few files. Minimum: ${fileOptions.minFiles}, received: ${fileArray.length}`,\n value: fileArray.length,\n });\n }\n\n // Validate each file\n fileArray.forEach((file, index) =>\n {\n validateSingleFile(file, `/${key}/${index}`, fileOptions, fileErrors);\n });\n }\n else if (isFile(value) || (Array.isArray(value) && value.some(isFile)))\n {\n // Value is a File but schema doesn't indicate it - pass through without validation\n result[key] = value;\n }\n else\n {\n // Non-file field - collect for TypeBox validation\n nonFileData[key] = value;\n if (propSchema)\n {\n nonFileSchema[key] = propSchema;\n }\n }\n }\n\n // Throw file validation errors if any\n if (fileErrors.length > 0)\n {\n throw new ValidationError({\n message: `Invalid ${fieldName}`,\n fields: fileErrors,\n });\n }\n\n // Validate non-file fields if any\n if (Object.keys(nonFileSchema).length > 0)\n {\n const tempSchema = {\n ...schema,\n properties: nonFileSchema,\n required: (schema as any).required?.filter((r: string) => r in nonFileSchema) ?? [],\n };\n\n const converted = Value.Convert(tempSchema, nonFileData);\n const errors = [...Value.Errors(tempSchema, converted)];\n\n if (errors.length > 0)\n {\n throw new ValidationError({\n message: `Invalid ${fieldName}`,\n fields: errors.map((e): ValidationFieldError => ({\n path: e.path,\n message: e.message,\n value: e.value,\n })),\n });\n }\n\n // Merge validated non-file fields with file fields\n Object.assign(result, converted);\n }\n else\n {\n // No non-file fields to validate\n Object.assign(result, nonFileData);\n }\n\n return result as T;\n}\n\n/**\n * Extract query parameters from request URL\n *\n * Handles array values (multiple params with same key)\n */\nexport function extractQueryParams(c: Context): Record<string, string | string[]>\n{\n const url = new URL(c.req.url);\n const queryObj: Record<string, string | string[]> = {};\n\n url.searchParams.forEach((v, k) =>\n {\n const existing = queryObj[k];\n if (existing)\n {\n queryObj[k] = Array.isArray(existing) ? [...existing, v] : [existing, v];\n }\n else\n {\n queryObj[k] = v;\n }\n });\n\n return queryObj;\n}\n\n/**\n * Extract headers from request (lowercase keys)\n */\nexport function extractHeaders(c: Context): Record<string, string>\n{\n const rawHeaders: Record<string, string> = {};\n\n c.req.raw.headers.forEach((value, key) =>\n {\n rawHeaders[key.toLowerCase()] = value;\n });\n\n return rawHeaders;\n}\n\n/**\n * Extract and parse cookies from request\n */\nexport function extractCookies(c: Context): Record<string, string>\n{\n const cookieHeader = c.req.header('cookie');\n const rawCookies: Record<string, string> = {};\n\n if (cookieHeader)\n {\n cookieHeader.split(';').forEach(cookie =>\n {\n const [key, value] = cookie.trim().split('=');\n if (key && value)\n {\n rawCookies[key] = decodeURIComponent(value);\n }\n });\n }\n\n return rawCookies;\n}\n\n/**\n * Parse JSON body from request\n *\n * @throws ValidationError if JSON parsing fails\n */\nexport async function parseJsonBody(c: Context): Promise<Record<string, unknown>>\n{\n try\n {\n return await c.req.json();\n }\n catch (error)\n {\n throw new ValidationError({\n message: 'Invalid JSON body',\n fields: [{\n path: '/',\n message: 'Failed to parse JSON',\n value: error instanceof Error ? error.message : 'Unknown error',\n }],\n });\n }\n}\n\n/**\n * Parse multipart/form-data from request\n *\n * Handles file uploads and form fields.\n * Multiple files with same key are collected into arrays.\n *\n * @throws ValidationError if form data parsing fails\n */\nexport async function parseFormData(c: Context): Promise<Record<string, unknown>>\n{\n try\n {\n const formData = await c.req.formData();\n const result: Record<string, unknown> = {};\n\n formData.forEach((value, key) =>\n {\n const existing = result[key];\n\n if (existing !== undefined)\n {\n // Multiple values with same key - convert to array\n if (Array.isArray(existing))\n {\n existing.push(value);\n }\n else\n {\n result[key] = [existing, value];\n }\n }\n else\n {\n result[key] = value;\n }\n });\n\n return result;\n }\n catch (error)\n {\n throw new ValidationError({\n message: 'Invalid form data',\n fields: [{\n path: '/',\n message: 'Failed to parse form data',\n value: error instanceof Error ? error.message : 'Unknown error',\n }],\n });\n }\n}","/**\n * Route Registration for define-route style routing\n *\n * Registers routes defined with route.get()...handler() to Hono app\n */\n\nimport type { Context, Hono, MiddlewareHandler } from 'hono';\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status';\nimport { logger } from '@spfn/core/logger';\nimport type { NamedMiddleware } from './define-middleware';\nimport type { RouteInput } from './route-input';\nimport type { RouteBuilderContext } from './context';\nimport type { RouteDef } from './route-builder';\nimport type { Router } from './router';\nimport type { HttpMethod } from './types';\nimport {\n validateField,\n validateFormData,\n extractQueryParams,\n extractHeaders,\n extractCookies,\n parseJsonBody,\n parseFormData,\n} from './validation';\n\n/**\n * Registered route information for logging\n */\nexport interface RegisteredRoute\n{\n method: HttpMethod;\n path: string;\n name: string;\n}\n\n/**\n * Type guard to check if value is a Router\n */\nfunction isRouter(value: unknown): value is Router<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'routes' in value &&\n '_routes' in value;\n}\n\n/**\n * Type guard to check if value is a RouteDef\n */\nfunction isRouteDef(value: unknown): value is RouteDef<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'handler' in value;\n}\n\n/**\n * Type guard to check if value is a NamedMiddleware\n */\nfunction isNamedMiddleware(value: unknown): value is NamedMiddleware<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'name' in value &&\n 'handler' in value &&\n '_name' in value;\n}\n\n/**\n * Register routes from defineRouter() to Hono app\n *\n * @param app - Hono app instance\n * @param router - Router definition\n * @param namedMiddlewares - Optional server-level named middlewares\n *\n * @param collectedRoutes\n * @example\n * ```ts\n * const appRouter = defineRouter({\n * getUser: route.get('/users/:id')...\n * createUser: route.post('/users')...\n * });\n *\n * const app = new Hono();\n * const namedMiddlewares = [\n * { name: 'auth', handler: AuthMiddleware() },\n * { name: 'rateLimit', handler: RateLimitMiddleware() },\n * ];\n * registerRoutes(app, appRouter, namedMiddlewares);\n * ```\n */\nexport function registerRoutes<TRoutes extends Record<string, RouteDef<any> | Router<any>>>(\n app: Hono,\n router: Router<TRoutes>,\n namedMiddlewares?: ReadonlyArray<{ name: string; handler: MiddlewareHandler }>,\n collectedRoutes?: RegisteredRoute[]\n): RegisteredRoute[]\n{\n // Use provided array or create new one (top-level call)\n const routes = collectedRoutes ?? [];\n\n // Merge router's global middlewares with provided named middlewares\n const allNamedMiddlewares = [\n ...(namedMiddlewares ?? []),\n ...router._globalMiddlewares.map(mw => ({ name: mw.name, handler: mw.handler })),\n ];\n\n // 1. Register routes from router.routes\n for (const [name, routeOrRouter] of Object.entries(router.routes))\n {\n if (isRouter(routeOrRouter))\n {\n // Nested router - recursively register\n registerRoutes(app, routeOrRouter, allNamedMiddlewares, routes);\n }\n else if (isRouteDef(routeOrRouter))\n {\n // Single route - register\n const registered = registerRoute(app, name, routeOrRouter, allNamedMiddlewares);\n if (registered)\n {\n routes.push(registered);\n }\n }\n else\n {\n logger.warn(`Unknown route type for \"${name}\" - skipping`, {\n type: typeof routeOrRouter,\n });\n }\n }\n\n // 2. Register routes from package routers (_packageRouters)\n if (router._packageRouters && router._packageRouters.length > 0)\n {\n for (const pkgRouter of router._packageRouters)\n {\n registerRoutes(app, pkgRouter, allNamedMiddlewares, routes);\n }\n }\n\n return routes;\n}\n\n/**\n * Register a single route\n */\nfunction registerRoute(\n app: Hono,\n name: string,\n routeDef: RouteDef<any>,\n namedMiddlewares?: ReadonlyArray<{ name: string; handler: MiddlewareHandler }>\n): RegisteredRoute | null\n{\n const { method, path, input, middlewares = [], skipMiddlewares, handler } = routeDef;\n\n if (!method || !path)\n {\n logger.warn(`Route \"${name}\" is missing method or path - skipping`, {\n method,\n path,\n });\n\n return null;\n }\n\n // Create wrapped handler with validation\n const wrappedHandler = async (c: Context) =>\n {\n // Create RouteBuilderContext with validation\n const { context, responseMeta } = await createRouteBuilderContext(c, input || {});\n\n // Call user handler\n const result = await handler(context);\n\n // If handler returns Response, use it directly (e.g., c.json(), c.redirect())\n if (result instanceof Response)\n {\n return result;\n }\n\n // Handle empty responses (noContent, notModified, accepted without data)\n if (responseMeta.isEmpty)\n {\n return c.body(null, responseMeta.status);\n }\n\n // Return data as JSON with status and headers from helper methods\n const hasCustomHeaders = Object.keys(responseMeta.headers).length > 0;\n\n if (hasCustomHeaders)\n {\n return c.json(result, responseMeta.status, responseMeta.headers);\n }\n\n return c.json(result, responseMeta.status);\n };\n\n // Collect all middlewares: server-level (filtered) + route-level\n const allMiddlewares: MiddlewareHandler[] = [];\n\n // Track registered middlewares for deduplication\n const registeredNames = new Set<string>();\n const registeredHandlers = new Set<MiddlewareHandler>();\n\n // Check if skipping all middlewares\n const skipAll = skipMiddlewares === '*';\n\n // Add server-level named middlewares (skip those in skipMiddlewares or if '*')\n if (namedMiddlewares && namedMiddlewares.length > 0)\n {\n if (skipAll)\n {\n logger.debug(`⏭️ Skipping all middlewares (*) for route: ${method} ${path}`, { name });\n }\n else\n {\n const skipSet = new Set(Array.isArray(skipMiddlewares) ? skipMiddlewares : []);\n for (const middleware of namedMiddlewares)\n {\n if (!skipSet.has(middleware.name))\n {\n allMiddlewares.push(middleware.handler);\n registeredNames.add(middleware.name);\n registeredHandlers.add(middleware.handler);\n }\n else\n {\n logger.debug(`⏭️ Skipping middleware '${middleware.name}' for route: ${method} ${path}`, { name });\n }\n }\n }\n }\n\n // Add route-level middlewares (with deduplication by name or handler reference)\n for (const mw of middlewares)\n {\n if (isNamedMiddleware(mw))\n {\n // Named middleware: deduplicate by name\n if (registeredNames.has(mw.name))\n {\n logger.debug(`🔄 Skipping duplicate middleware '${mw.name}' for route: ${method} ${path}`, { name });\n continue;\n }\n registeredNames.add(mw.name);\n allMiddlewares.push(mw.handler);\n }\n else\n {\n // Regular middleware: deduplicate by handler reference\n if (registeredHandlers.has(mw))\n {\n logger.debug(`🔄 Skipping duplicate middleware handler for route: ${method} ${path}`, { name });\n continue;\n }\n registeredHandlers.add(mw);\n allMiddlewares.push(mw);\n }\n }\n\n // Register to Hono with correct HTTP method\n const methodLower = method.toLowerCase() as Lowercase<HttpMethod>;\n\n if (allMiddlewares.length > 0)\n {\n // Register with middlewares\n app[methodLower](path, ...allMiddlewares, wrappedHandler);\n }\n else\n {\n // Register without middlewares\n app[methodLower](path, wrappedHandler);\n }\n\n logger.debug(`Registered route: ${method} ${path}`, { name });\n\n return { method, path, name };\n}\n\n/**\n * Response metadata set by helper methods\n */\ninterface ResponseMeta\n{\n status: ContentfulStatusCode;\n headers: Record<string, string>;\n isEmpty: boolean;\n}\n\n/**\n * Create RouteBuilderContext from Hono Context\n *\n * Validates params, query, body, headers, cookies and returns structured input.\n * Helper methods (created, accepted, etc.) return data directly for type inference,\n * while storing response metadata internally for later use.\n */\nasync function createRouteBuilderContext<TInput extends RouteInput>(\n c: Context,\n input: TInput\n): Promise<{ context: RouteBuilderContext<TInput>; responseMeta: ResponseMeta }>\n{\n // Validate and extract all input fields\n const params = validateField(input.params, c.req.param(), 'path parameters');\n const query = validateField(input.query, extractQueryParams(c), 'query parameters');\n const headers = validateField(input.headers, extractHeaders(c), 'headers');\n const cookies = validateField(input.cookies, extractCookies(c), 'cookies');\n\n // Body/FormData requires async parsing - determine by Content-Type\n let body: Record<string, unknown> = {};\n let formData: Record<string, unknown> = {};\n\n if (input.body || input.formData)\n {\n const contentType = c.req.header('content-type') || '';\n\n if (contentType.includes('multipart/form-data') && input.formData)\n {\n const rawFormData = await parseFormData(c);\n formData = validateFormData(input.formData, rawFormData, 'form data');\n }\n else if (input.body)\n {\n const rawBody = await parseJsonBody(c);\n body = validateField(input.body, rawBody, 'request body');\n }\n }\n\n // Cache for data() - avoid creating new object on each call\n let cachedData: any = null;\n\n // Response metadata - set by helper methods, used when building final Response\n const responseMeta: ResponseMeta = {\n status: 200 as ContentfulStatusCode,\n headers: {},\n isEmpty: false,\n };\n\n // Create context with structured data()\n const context: RouteBuilderContext<TInput> = {\n data: async () =>\n {\n if (!cachedData)\n {\n cachedData = { params, query, body, formData, headers, cookies };\n }\n return cachedData;\n },\n\n json: (data, status, resHeaders) =>\n {\n return c.json(data, status, resHeaders);\n },\n\n created: <T>(data: T, location?: string): T =>\n {\n responseMeta.status = 201 as ContentfulStatusCode;\n if (location)\n {\n responseMeta.headers['Location'] = location;\n }\n return data;\n },\n\n accepted: <T>(data?: T): any =>\n {\n responseMeta.status = 202 as ContentfulStatusCode;\n if (data === undefined)\n {\n responseMeta.isEmpty = true;\n return undefined;\n }\n return data;\n },\n\n noContent: (): void =>\n {\n responseMeta.status = 204 as ContentfulStatusCode;\n responseMeta.isEmpty = true;\n },\n\n notModified: (): void =>\n {\n responseMeta.status = 304 as ContentfulStatusCode;\n responseMeta.isEmpty = true;\n },\n\n paginated: <T>(data: T[], page: number, limit: number, total: number) =>\n {\n return {\n items: data,\n pagination: {\n page,\n limit,\n total,\n totalPages: Math.ceil(total / limit),\n },\n };\n },\n\n redirect: (url, status) =>\n {\n return c.redirect(url, status as RedirectStatusCode);\n },\n\n raw: c,\n };\n\n return { context, responseMeta };\n}","/**\n * Middleware Definition Helper\n *\n * Provides type-safe middleware definition with name inference\n */\n\nimport type { MiddlewareHandler } from 'hono';\n\n/**\n * Named middleware with type inference\n *\n * @example\n * ```ts\n * export const authMiddleware = defineMiddleware('auth', async (c, next) => {\n * // auth logic\n * c.set('user', { id: 1 });\n * await next();\n * });\n *\n * export const rateLimitMiddleware = defineMiddleware('rateLimit', async (c, next) => {\n * // rate limit logic\n * await next();\n * });\n * ```\n */\nexport type NamedMiddleware<TName extends string = string> = {\n name: TName;\n handler: MiddlewareHandler;\n _name: TName; // Type inference helper\n};\n\n/**\n * Named middleware factory with type inference\n *\n * Factory function that creates middleware instances with parameters\n *\n * @example\n * ```ts\n * export const requirePermissions = defineMiddleware('permission',\n * (...permissions: string[]) => async (c, next) => {\n * // permission check logic\n * await next();\n * }\n * );\n * ```\n */\nexport type NamedMiddlewareFactory<TName extends string = string, TArgs extends any[] = any[]> = {\n name: TName;\n _name: TName; // Type inference helper\n} & ((...args: TArgs) => MiddlewareHandler);\n\n/**\n * Define a named middleware\n *\n * Creates a middleware with a unique name that can be referenced\n * in route-level skip() calls with full type safety.\n *\n * Supports two patterns:\n * 1. Regular middleware: Direct middleware handler\n * 2. Factory middleware: Function that creates middleware with parameters\n *\n * @param name - Unique middleware name\n * @param handler - Middleware handler function\n * @returns Named middleware with type inference\n *\n * @example\n * ```ts\n * // Regular middleware\n * export const authMiddleware = defineMiddleware('auth', async (c, next) => {\n * const token = c.req.header('authorization');\n * if (!token) {\n * return c.json({ error: 'Unauthorized' }, 401);\n * }\n * c.set('user', await verifyToken(token));\n * await next();\n * });\n *\n * // Factory middleware\n * export const requirePermissions = defineMiddleware('permission',\n * (...permissions: string[]) => async (c, next) => {\n * const user = c.get('user');\n * if (!hasPermissions(user, permissions)) {\n * return c.json({ error: 'Forbidden' }, 403);\n * }\n * await next();\n * }\n * );\n *\n * // server.config.ts\n * export default defineServerConfig()\n * .middlewares([authMiddleware])\n * .routes(appRouter)\n * .build();\n *\n * // routes.ts - skip by name\n * export const publicRoute = route.get('/health')\n * .skip(['auth']) // ✅ Type-safe! Autocomplete!\n * .handler(async (c) => c.success({ status: 'ok' }));\n *\n * // Use factory middleware inline\n * export const protectedRoute = route.get('/admin')\n * .use([requirePermissions('admin:write')])\n * .handler(async (c) => { ... });\n * ```\n */\nexport function defineMiddleware<TName extends string>(\n name: TName,\n handler: MiddlewareHandler\n): NamedMiddleware<TName>;\n\nexport function defineMiddleware<TName extends string, TArgs extends any[]>(\n name: TName,\n factory: (...args: TArgs) => MiddlewareHandler\n): NamedMiddlewareFactory<TName, TArgs>;\n\nexport function defineMiddleware<TName extends string, TArgs extends any[] = []>(\n name: TName,\n handlerOrFactory: MiddlewareHandler | ((...args: TArgs) => MiddlewareHandler)\n): NamedMiddleware<TName> | NamedMiddlewareFactory<TName, TArgs>\n{\n // Distinguish between regular middleware and factory by parameter count\n // MiddlewareHandler always has exactly 2 parameters: (c, next)\n // Factory has any other number of parameters\n if (typeof handlerOrFactory === 'function')\n {\n const paramCount = handlerOrFactory.length;\n\n // Regular middleware handler (c, next) => ...\n if (paramCount === 2)\n {\n return {\n name,\n handler: handlerOrFactory as MiddlewareHandler,\n _name: name as TName,\n };\n }\n // Factory (...args) => (c, next) => ...\n else\n {\n // Create a new wrapper function to avoid \"Cannot assign to read only property 'name'\" error\n const factory = handlerOrFactory as (...args: TArgs) => MiddlewareHandler;\n const wrapper = (...args: TArgs) => factory(...args);\n\n // Use Object.defineProperty to set name property (which is read-only by default)\n Object.defineProperty(wrapper, 'name', {\n value: name,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n Object.defineProperty(wrapper, '_name', {\n value: name as TName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n return wrapper as NamedMiddlewareFactory<TName, TArgs>;\n }\n }\n\n // Fallback: treat as regular middleware\n return {\n name,\n handler: handlerOrFactory as MiddlewareHandler,\n _name: name as TName,\n };\n}\n\n/**\n * Define a middleware factory explicitly\n *\n * Use this when your factory function has exactly 2 parameters,\n * which would be incorrectly detected as a regular middleware handler.\n *\n * @param name - Unique middleware name\n * @param factory - Factory function that returns a middleware handler\n * @returns Named middleware factory with type inference\n *\n * @example\n * ```ts\n * // Factory with 2 params (would be misdetected by defineMiddleware)\n * export const rateLimiter = defineMiddlewareFactory('rateLimit',\n * (limit: number, window: number) => async (c, next) => {\n * // rate limit logic using limit and window\n * await next();\n * }\n * );\n *\n * // Usage\n * route.get('/api')\n * .use([rateLimiter(100, 60000)]) // 100 requests per minute\n * .handler(...)\n * ```\n */\nexport function defineMiddlewareFactory<TName extends string, TArgs extends unknown[]>(\n name: TName,\n factory: (...args: TArgs) => MiddlewareHandler\n): NamedMiddlewareFactory<TName, TArgs>\n{\n const wrapper = (...args: TArgs) => factory(...args);\n\n Object.defineProperty(wrapper, 'name', {\n value: name,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n Object.defineProperty(wrapper, '_name', {\n value: name as TName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n return wrapper as NamedMiddlewareFactory<TName, TArgs>;\n}\n\n/**\n * Extract middleware names from an array of named middlewares\n *\n * @example\n * ```ts\n * type Middlewares = [\n * NamedMiddleware<'auth'>,\n * NamedMiddleware<'rateLimit'>\n * ];\n * type Names = ExtractMiddlewareNames<Middlewares>; // 'auth' | 'rateLimit'\n * ```\n */\nexport type ExtractMiddlewareNames<T extends readonly NamedMiddleware<string>[]> =\n T[number]['_name'];","/**\n * Route Helper Functions\n *\n * Type guards and TypeBox utilities\n */\n\nimport type { TSchema } from '@sinclair/typebox';\nimport { Type } from '@sinclair/typebox';\nimport type { HttpMethod } from './types';\n\n/**\n * Type guard for HttpMethod\n */\nexport function isHttpMethod(value: unknown): value is HttpMethod\n{\n return (\n typeof value === 'string' &&\n ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(value)\n );\n}\n\n/**\n * Nullable - Creates a union of T | null\n *\n * @example\n * ```typescript\n * // string | null\n * firstName: Nullable(Type.String())\n * ```\n */\nexport const Nullable = <T extends TSchema>(schema: T) =>\n Type.Union([schema, Type.Null()]);\n\n/**\n * OptionalNullable - Creates a union of T | null | undefined\n *\n * @example\n * ```typescript\n * // string | null | undefined\n * lastName: OptionalNullable(Type.String())\n * ```\n */\nexport const OptionalNullable = <T extends TSchema>(schema: T) =>\n Type.Optional(Type.Union([schema, Type.Null()]));"]}
1
+ {"version":3,"sources":["../../src/route/route-builder.ts","../../src/route/router.ts","../../src/route/file-schema.ts","../../src/route/validation.ts","../../src/route/register-routes.ts","../../src/route/define-middleware.ts","../../src/route/helpers.ts"],"names":["Type"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Route Builder\n *\n * Provides tRPC-style chainable API for route definition\n */\n\nimport type { MiddlewareHandler } from 'hono';\nimport type { NamedMiddleware } from './define-middleware';\nimport type { RouteInput } from './route-input';\nimport type { RouteBuilderContext } from './context';\nimport type { HttpMethod } from './types';\n\n/**\n * Route handler function\n */\nexport type RouteHandlerFn<\n TInput extends RouteInput = RouteInput,\n TInterceptor extends RouteInput = {},\n TResponse = unknown\n> = (c: RouteBuilderContext<TInput, TInterceptor>) => Response | Promise<Response> | TResponse | Promise<TResponse>;\n\n/**\n * Route definition result\n *\n * Contains all information needed for type inference and registration\n */\nexport type RouteDef<\n TInput extends RouteInput = RouteInput,\n TInterceptor extends RouteInput = {},\n TResponse = unknown\n> = {\n method?: HttpMethod;\n path?: string;\n input?: TInput;\n interceptor?: TInterceptor;\n middlewares?: (MiddlewareHandler | NamedMiddleware<string>)[];\n skipMiddlewares?: string[] | '*';\n handler: RouteHandlerFn<TInput, TInterceptor, TResponse>;\n\n // Type inference helpers\n _input: TInput;\n _interceptor: TInterceptor;\n _response: TResponse;\n};\n\n/**\n * Route builder with chainable API (tRPC-style)\n */\nexport class RouteBuilder<\n TInput extends RouteInput = {},\n TInterceptor extends RouteInput = {},\n TResponse = never\n>\n{\n public _method?: HttpMethod;\n public _path?: string;\n public _input?: TInput;\n public _interceptor?: TInterceptor;\n public _middlewares?: (MiddlewareHandler | NamedMiddleware<string>)[];\n public _skipMiddlewares?: string[] | '*';\n\n /**\n * Create a new RouteBuilder with copied properties and optional overrides\n */\n private clone<\n TNewInput extends RouteInput = TInput,\n TNewInterceptor extends RouteInput = TInterceptor\n >(\n overrides?: Partial<{\n input: TNewInput;\n interceptor: TNewInterceptor;\n middlewares: (MiddlewareHandler | NamedMiddleware<string>)[];\n skipMiddlewares: string[] | '*';\n }>\n ): RouteBuilder<TNewInput, TNewInterceptor, TResponse>\n {\n const builder = new RouteBuilder<TNewInput, TNewInterceptor, TResponse>();\n builder._method = this._method;\n builder._path = this._path;\n builder._input = (overrides?.input ?? this._input) as TNewInput | undefined;\n builder._interceptor = (overrides?.interceptor ?? this._interceptor) as TNewInterceptor | undefined;\n builder._middlewares = overrides?.middlewares ?? this._middlewares;\n builder._skipMiddlewares = overrides?.skipMiddlewares ?? this._skipMiddlewares;\n return builder;\n }\n\n /**\n * Define input schemas\n *\n * @example\n * ```ts\n * route.get('/users/:id')\n * .input({\n * params: Type.Object({ id: Type.String() }),\n * query: Type.Object({ page: Type.Number() }),\n * headers: Type.Object({ authorization: Type.String() })\n * })\n * .handler(async (c) => {\n * const { params, query, headers } = await c.data();\n * // params = { id: string }\n * // query = { page: number }\n * // headers = { authorization: string }\n * })\n * ```\n */\n input<TNewInput extends RouteInput>(input: TNewInput): RouteBuilder<TNewInput, TInterceptor, TResponse>\n {\n return this.clone({ input });\n }\n\n /**\n * Define fields injected by interceptors\n *\n * These fields are:\n * - Available in the handler (merged with input)\n * - Excluded from client types (codegen uses only input)\n * - Not validated by route input schema (injected by middleware)\n *\n * Use this when middleware/interceptors add fields to the request\n * before it reaches the handler.\n *\n * @example\n * ```ts\n * // Auth interceptor injects crypto key fields\n * route.post('/_auth/login')\n * .input({\n * body: Type.Object({\n * email: Type.String(),\n * password: Type.String()\n * })\n * })\n * .interceptor({\n * body: Type.Object({\n * publicKey: Type.String(),\n * keyId: Type.String(),\n * fingerprint: Type.String()\n * })\n * })\n * .handler(async (c) => {\n * const { body } = await c.data();\n * // body type: { email, password, publicKey, keyId, fingerprint }\n * // Client only sees: { email, password }\n * return loginService(body);\n * });\n * ```\n */\n interceptor<TNewInterceptor extends RouteInput>(\n interceptor: TNewInterceptor\n ): RouteBuilder<TInput, TNewInterceptor, TResponse>\n {\n return this.clone({ interceptor });\n }\n\n /**\n * Add middlewares to the route\n *\n * Accepts both regular middleware handlers and named middlewares (NamedMiddleware).\n * Named middlewares that are already registered globally will be automatically\n * deduplicated to prevent double execution.\n *\n * @example\n * ```ts\n * import { authenticate } from '@spfn/auth/server/middleware';\n *\n * // With NamedMiddleware (auto-deduped if registered globally)\n * route.get('/users')\n * .use([authenticate, RateLimitMiddleware()])\n *\n * // With regular middleware handlers\n * route.get('/users')\n * .use([AuthMiddleware(), RateLimitMiddleware()])\n * ```\n */\n middleware(middlewares: (MiddlewareHandler | NamedMiddleware<string>)[]): RouteBuilder<TInput, TInterceptor, TResponse>\n {\n return this.clone({ middlewares });\n }\n\n /**\n * Add middlewares to the route (alias for `.middleware()`)\n *\n * Accepts both regular middleware handlers and named middlewares (NamedMiddleware).\n * Named middlewares that are already registered globally will be automatically\n * deduplicated to prevent double execution.\n *\n * @example\n * ```ts\n * import { authenticate } from '@spfn/auth/server/middleware';\n *\n * // With NamedMiddleware (auto-deduped if registered globally)\n * route.get('/users')\n * .use([authenticate, RateLimitMiddleware()])\n *\n * // With regular middleware handlers\n * route.get('/users')\n * .use([AuthMiddleware(), RateLimitMiddleware()])\n * ```\n */\n use(middlewares: (MiddlewareHandler | NamedMiddleware<string>)[]): RouteBuilder<TInput, TInterceptor, TResponse>\n {\n return this.middleware(middlewares);\n }\n\n /**\n * Skip server-level named middlewares\n *\n * Useful for public endpoints that should bypass auth or rate limiting\n *\n * @param middlewareNames - Array of middleware names to skip, or '*' to skip all\n *\n * @example\n * ```ts\n * // Skip specific middlewares\n * route.get('/health')\n * .skip(['auth', 'rateLimit'])\n * .handler(async (c) => c.json({ status: 'ok' }));\n *\n * // Skip only auth (still apply rate limiting)\n * route.get('/public-data')\n * .skip(['auth'])\n * .handler(async (c) => { ... });\n *\n * // Skip all middlewares\n * route.get('/public-health')\n * .skip('*')\n * .handler(async (c) => c.json({ status: 'ok' }));\n * ```\n */\n skip(middlewareNames: string[] | '*'): RouteBuilder<TInput, TInterceptor, TResponse>\n {\n return this.clone({ skipMiddlewares: middlewareNames });\n }\n\n /**\n * Define handler function\n *\n * Response type is automatically inferred from the return value.\n * Use helper methods like `c.created()`, `c.paginated()` for proper type inference.\n *\n * @example\n * ```ts\n * // Direct return - type inferred from data\n * route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => {\n * const { params } = await c.data();\n * return await getUser(params.id); // Type: User\n * })\n *\n * // Using c.created() - returns data with 201 status, type preserved\n * route.post('/users')\n * .input({ body: Type.Object({ name: Type.String() }) })\n * .handler(async (c) => {\n * const { body } = await c.data();\n * return c.created(await createUser(body)); // Type: User\n * })\n *\n * // Using c.paginated() - returns PaginatedResult<T>\n * route.get('/users')\n * .handler(async (c) => {\n * const users = await getUsers();\n * return c.paginated(users, 1, 20, 100); // Type: PaginatedResult<User>\n * })\n *\n * // Using c.noContent() - returns void\n * route.delete('/users/:id')\n * .handler(async (c) => {\n * await deleteUser(params.id);\n * return c.noContent(); // Type: void\n * })\n *\n * // Using c.json() - returns Response (type inference lost)\n * // Use only when you need custom status codes not covered by helpers\n * route.get('/custom')\n * .handler(async (c) => {\n * return c.json({ data }, 418); // Type: Response\n * })\n * ```\n */\n handler<THandlerResponse>(\n fn: RouteHandlerFn<TInput, TInterceptor, THandlerResponse>\n ): RouteDef<TInput, TInterceptor, THandlerResponse>\n {\n return {\n method: this._method,\n path: this._path,\n input: this._input,\n interceptor: this._interceptor,\n middlewares: this._middlewares,\n skipMiddlewares: this._skipMiddlewares,\n handler: fn,\n _input: {} as TInput,\n _interceptor: {} as TInterceptor,\n _response: {} as THandlerResponse,\n };\n }\n}\n\n/**\n * Create a route definition with HTTP method shortcuts\n */\nfunction createMethodRoute(method: HttpMethod): (path: string) => RouteBuilder\n{\n return (path: string) =>\n {\n const builder = new RouteBuilder();\n builder._method = method;\n builder._path = path;\n return builder;\n };\n}\n\n/**\n * Route builder entry point\n *\n * @example\n * ```ts\n * // GET request\n * export const getUser = route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => {\n * const { params } = await c.data();\n * return await db.user.findUnique({ where: { id: params.id } });\n * });\n *\n * // POST request\n * export const createUser = route.post('/users')\n * .input({ body: Type.Object({ name: Type.String(), email: Type.String() }) })\n * .handler(async (c) => {\n * const { body } = await c.data();\n * return c.created(await db.user.create({ data: body }));\n * });\n * ```\n */\nexport const route = {\n get: createMethodRoute('GET'),\n post: createMethodRoute('POST'),\n put: createMethodRoute('PUT'),\n patch: createMethodRoute('PATCH'),\n delete: createMethodRoute('DELETE'),\n};","/**\n * Router Definition\n *\n * Provides router composition and middleware management\n */\n\nimport type { NamedMiddleware } from './define-middleware';\nimport type { RouteDef } from './route-builder';\n\n/**\n * Router definition - holds all routes\n */\nexport interface Router<TRoutes extends Record<string, RouteDef<any, any, any> | Router<any>>> {\n routes: TRoutes;\n _routes: TRoutes;\n _packageRouters: Router<any>[];\n _globalMiddlewares: NamedMiddleware<string>[];\n\n /**\n * Register package routers (type-hidden)\n *\n * Package routes are:\n * - Recognized by RPC proxy and backend\n * - NOT exposed in client types (use package's own API like authApi, cmsApi)\n *\n * @example\n * ```ts\n * import { authRouter } from '@spfn/auth/server';\n * import { cmsAppRouter } from '@spfn/cms/server';\n *\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter, cmsAppRouter]);\n *\n * // Client usage:\n * // api.getRoot.call({}) - app routes\n * // authApi.login.call({}) - package API\n * ```\n */\n packages(routers: Router<any>[]): Router<TRoutes>;\n\n /**\n * Register global middlewares\n *\n * Applied to all routes unless explicitly skipped via .skip()\n *\n * @example\n * ```ts\n * import { authMiddleware, loggingMiddleware } from './middlewares';\n *\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter])\n * .use([authMiddleware, loggingMiddleware]);\n * ```\n */\n use(middlewares: NamedMiddleware<string>[]): Router<TRoutes>;\n}\n\n/**\n * Create a Router instance with chainable methods\n */\nfunction createRouterInstance<TRoutes extends Record<string, RouteDef<any, any, any> | Router<any>>>(\n routes: TRoutes,\n packageRouters: Router<any>[] = [],\n globalMiddlewares: NamedMiddleware<string>[] = []\n): Router<TRoutes>\n{\n return {\n routes,\n _routes: routes,\n _packageRouters: packageRouters,\n _globalMiddlewares: globalMiddlewares,\n\n packages(routers: Router<any>[]): Router<TRoutes>\n {\n const newPackageRouters = [...this._packageRouters, ...routers];\n\n // Also include nested package routers if any\n for (const pkgRouter of routers)\n {\n if (pkgRouter._packageRouters?.length > 0)\n {\n newPackageRouters.push(...pkgRouter._packageRouters);\n }\n }\n\n return createRouterInstance(this.routes, newPackageRouters, this._globalMiddlewares);\n },\n\n use(middlewares: NamedMiddleware<string>[]): Router<TRoutes>\n {\n return createRouterInstance(this.routes, this._packageRouters, [...this._globalMiddlewares, ...middlewares]);\n },\n };\n}\n\n/**\n * Define a router with multiple routes (tRPC-style)\n *\n * Supports chainable API for packages and middlewares:\n *\n * @example\n * ```ts\n * // Basic usage\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * listExamples,\n * });\n *\n * // With package routers (type-hidden)\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter, cmsAppRouter]);\n *\n * // With global middlewares\n * export const appRouter = defineRouter({\n * getRoot,\n * getHealth,\n * })\n * .packages([authRouter])\n * .use([authMiddleware, loggingMiddleware]);\n *\n * export type AppRouter = typeof appRouter;\n * ```\n *\n * Package routes:\n * - Recognized by RPC proxy and backend for routing\n * - NOT included in AppRouter type (use authApi, cmsApi instead)\n * - Prevents confusion between app API and package APIs\n */\nexport function defineRouter<TRoutes extends Record<string, RouteDef<any, any, any> | Router<any>>>(\n routes: TRoutes\n): Router<TRoutes>\n{\n return createRouterInstance(routes);\n}","/**\n * File Schema Helpers for TypeBox\n *\n * Provides TypeBox schema definitions for file upload handling\n * with optional validation constraints.\n */\n\nimport { Kind, Type, type TSchema } from '@sinclair/typebox';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * File validation options\n */\nexport interface FileSchemaOptions\n{\n /**\n * Maximum file size in bytes\n *\n * @example 5 * 1024 * 1024 // 5MB\n */\n maxSize?: number;\n\n /**\n * Allowed MIME types\n *\n * @example ['image/jpeg', 'image/png', 'image/webp']\n */\n allowedTypes?: string[];\n\n /**\n * Minimum file size in bytes (optional)\n *\n * @example 1024 // 1KB minimum\n */\n minSize?: number;\n}\n\n/**\n * File array validation options\n */\nexport interface FileArraySchemaOptions extends FileSchemaOptions\n{\n /**\n * Maximum number of files\n *\n * @example 5\n */\n maxFiles?: number;\n\n /**\n * Minimum number of files (optional)\n *\n * @example 1\n */\n minFiles?: number;\n}\n\n/**\n * Internal schema type with file validation metadata\n */\nexport interface FileSchemaType extends TSchema\n{\n [Kind]: 'File';\n fileOptions?: FileSchemaOptions;\n}\n\nexport interface FileArraySchemaType extends TSchema\n{\n [Kind]: 'FileArray';\n fileOptions?: FileArraySchemaOptions;\n}\n\n// ============================================================================\n// Schema Creators\n// ============================================================================\n\n/**\n * Create a File schema with optional validation\n *\n * @example\n * ```ts\n * // Basic usage (no validation)\n * formData: Type.Object({\n * file: FileSchema()\n * })\n *\n * // With validation\n * formData: Type.Object({\n * avatar: FileSchema({\n * maxSize: 5 * 1024 * 1024, // 5MB\n * allowedTypes: ['image/jpeg', 'image/png', 'image/webp']\n * })\n * })\n * ```\n */\nexport function FileSchema(options?: FileSchemaOptions): FileSchemaType\n{\n return Type.Unsafe<File>({\n [Kind]: 'File',\n type: 'object',\n fileOptions: options,\n }) as FileSchemaType;\n}\n\n/**\n * Create a File array schema with optional validation\n *\n * @example\n * ```ts\n * // Basic usage (no validation)\n * formData: Type.Object({\n * files: FileArraySchema()\n * })\n *\n * // With validation\n * formData: Type.Object({\n * documents: FileArraySchema({\n * maxSize: 10 * 1024 * 1024, // 10MB per file\n * maxFiles: 5,\n * allowedTypes: ['application/pdf', 'application/msword']\n * })\n * })\n * ```\n */\nexport function FileArraySchema(options?: FileArraySchemaOptions): FileArraySchemaType\n{\n return Type.Unsafe<File[]>({\n [Kind]: 'FileArray',\n type: 'array',\n items: { [Kind]: 'File', type: 'object' },\n fileOptions: options,\n }) as FileArraySchemaType;\n}\n\n/**\n * Create an optional File schema with validation\n *\n * @example\n * ```ts\n * formData: Type.Object({\n * name: Type.String(),\n * avatar: OptionalFileSchema({\n * maxSize: 2 * 1024 * 1024,\n * allowedTypes: ['image/jpeg', 'image/png']\n * })\n * })\n * ```\n */\nexport function OptionalFileSchema(options?: FileSchemaOptions): TSchema\n{\n return Type.Optional(FileSchema(options));\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Check if a schema is a File schema\n */\nexport function isFileSchema(schema: TSchema): schema is FileSchemaType\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'File';\n}\n\n/**\n * Check if a schema is a FileArray schema\n */\nexport function isFileArraySchema(schema: TSchema): schema is FileArraySchemaType\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'FileArray';\n}\n\n/**\n * Get file options from schema\n */\nexport function getFileOptions(schema: TSchema): FileSchemaOptions | FileArraySchemaOptions | undefined\n{\n return (schema as any).fileOptions;\n}\n\n/**\n * Format file size for error messages\n */\nexport function formatFileSize(bytes: number): string\n{\n if (bytes >= 1024 * 1024 * 1024)\n {\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}GB`;\n }\n if (bytes >= 1024 * 1024)\n {\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n }\n if (bytes >= 1024)\n {\n return `${(bytes / 1024).toFixed(1)}KB`;\n }\n return `${bytes}B`;\n}\n","/**\n * Route Input Validation\n *\n * Provides unified validation logic for route input fields\n */\n\nimport type { TSchema } from '@sinclair/typebox';\nimport { FormatRegistry } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport type { Context } from 'hono';\nimport { ValidationError } from '@spfn/core/errors';\nimport { formatFileSize } from './file-schema';\n\n// ============================================\n// Format Registry\n// ============================================\n\nFormatRegistry.Set('email', (value: string) =>\n /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n);\n\nFormatRegistry.Set('uri', (value: string) =>\n /^https?:\\/\\/.+/.test(value)\n);\n\nFormatRegistry.Set('uuid', (value: string) =>\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)\n);\n\nFormatRegistry.Set('date', (value: string) =>\n /^\\d{4}-\\d{2}-\\d{2}$/.test(value)\n);\n\nFormatRegistry.Set('date-time', (value: string) =>\n !isNaN(Date.parse(value))\n);\n\n/**\n * Validation error field info\n */\ninterface ValidationFieldError\n{\n path: string;\n message: string;\n value: unknown;\n}\n\n/**\n * Check if a value is a File object\n */\nfunction isFile(value: unknown): value is File\n{\n return value instanceof File ||\n (typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'size' in value &&\n 'type' in value &&\n typeof (value as any).arrayBuffer === 'function');\n}\n\n/**\n * Check if a TypeBox schema represents a File type\n */\nfunction isFileSchemaDef(schema: TSchema): boolean\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'File';\n}\n\n/**\n * Check if a TypeBox schema represents a FileArray type\n */\nfunction isFileArraySchemaDef(schema: TSchema): boolean\n{\n const kind = (schema as any)[Symbol.for('TypeBox.Kind')];\n return kind === 'FileArray';\n}\n\n/**\n * Get file options from schema\n */\nfunction getSchemaFileOptions(schema: TSchema): any | undefined\n{\n return (schema as any).fileOptions;\n}\n\n\n/**\n * Validate a single file against schema options\n */\nfunction validateSingleFile(\n file: File,\n fieldPath: string,\n options: { maxSize?: number; minSize?: number; allowedTypes?: string[] } | undefined,\n errors: ValidationFieldError[]\n): void\n{\n if (!options) return;\n\n const { maxSize, minSize, allowedTypes } = options;\n\n if (maxSize !== undefined && file.size > maxSize)\n {\n errors.push({\n path: fieldPath,\n message: `File size ${formatFileSize(file.size)} exceeds maximum ${formatFileSize(maxSize)}`,\n value: file.size,\n });\n }\n\n if (minSize !== undefined && file.size < minSize)\n {\n errors.push({\n path: fieldPath,\n message: `File size ${formatFileSize(file.size)} is below minimum ${formatFileSize(minSize)}`,\n value: file.size,\n });\n }\n\n if (allowedTypes && allowedTypes.length > 0 && !allowedTypes.includes(file.type))\n {\n errors.push({\n path: fieldPath,\n message: `File type \"${file.type}\" is not allowed. Allowed: ${allowedTypes.join(', ')}`,\n value: file.type,\n });\n }\n}\n\n/**\n * Validate a value against a TypeBox schema\n *\n * @param schema - TypeBox schema to validate against\n * @param rawValue - Raw value to validate\n * @param fieldName - Field name for error messages\n * @returns Validated and converted value\n * @throws ValidationError if validation fails\n */\nexport function validateField<T extends Record<string, unknown>>(\n schema: TSchema | undefined,\n rawValue: Record<string, unknown>,\n fieldName: string\n): T\n{\n if (!schema)\n {\n return {} as T;\n }\n\n const converted = Value.Convert(schema, rawValue);\n const errors = [...Value.Errors(schema, converted)];\n\n if (errors.length > 0)\n {\n throw new ValidationError({\n message: `Invalid ${fieldName}`,\n fields: errors.map((e): ValidationFieldError => ({\n path: e.path,\n message: e.message,\n value: e.value,\n })),\n });\n }\n\n return converted as T;\n}\n\n/**\n * Validate form data against a TypeBox schema\n *\n * Handles File fields specially:\n * - File/FileArray schemas are validated using fileOptions (maxSize, allowedTypes, etc.)\n * - Non-file fields are validated using TypeBox\n *\n * @param schema - TypeBox schema to validate against\n * @param rawValue - Raw form data to validate\n * @param fieldName - Field name for error messages\n * @returns Validated form data\n * @throws ValidationError if validation fails\n */\nexport function validateFormData<T extends Record<string, unknown>>(\n schema: TSchema | undefined,\n rawValue: Record<string, unknown>,\n fieldName: string\n): T\n{\n if (!schema)\n {\n return {} as T;\n }\n\n // For Object schemas, validate non-File fields and validate File fields with fileOptions\n const schemaProps = (schema as any).properties;\n if (!schemaProps)\n {\n // Not an object schema, just return raw value\n return rawValue as T;\n }\n\n const result: Record<string, unknown> = {};\n const nonFileData: Record<string, unknown> = {};\n const nonFileSchema: Record<string, TSchema> = {};\n const fileErrors: ValidationFieldError[] = [];\n\n // Process each field\n for (const [key, value] of Object.entries(rawValue))\n {\n const propSchema = schemaProps[key];\n\n if (propSchema && isFileSchemaDef(propSchema))\n {\n // Single File field\n result[key] = value;\n\n if (isFile(value))\n {\n const fileOptions = getSchemaFileOptions(propSchema);\n validateSingleFile(value, `/${key}`, fileOptions, fileErrors);\n }\n }\n else if (propSchema && isFileArraySchemaDef(propSchema))\n {\n // File array field\n result[key] = value;\n\n const fileOptions = getSchemaFileOptions(propSchema);\n const files = Array.isArray(value) ? value : [value];\n const fileArray = files.filter(isFile);\n\n // Validate file count\n if (fileOptions?.maxFiles !== undefined && fileArray.length > fileOptions.maxFiles)\n {\n fileErrors.push({\n path: `/${key}`,\n message: `Too many files. Maximum: ${fileOptions.maxFiles}, received: ${fileArray.length}`,\n value: fileArray.length,\n });\n }\n\n if (fileOptions?.minFiles !== undefined && fileArray.length < fileOptions.minFiles)\n {\n fileErrors.push({\n path: `/${key}`,\n message: `Too few files. Minimum: ${fileOptions.minFiles}, received: ${fileArray.length}`,\n value: fileArray.length,\n });\n }\n\n // Validate each file\n fileArray.forEach((file, index) =>\n {\n validateSingleFile(file, `/${key}/${index}`, fileOptions, fileErrors);\n });\n }\n else if (isFile(value) || (Array.isArray(value) && value.some(isFile)))\n {\n // Value is a File but schema doesn't indicate it - pass through without validation\n result[key] = value;\n }\n else\n {\n // Non-file field - collect for TypeBox validation\n nonFileData[key] = value;\n if (propSchema)\n {\n nonFileSchema[key] = propSchema;\n }\n }\n }\n\n // Throw file validation errors if any\n if (fileErrors.length > 0)\n {\n throw new ValidationError({\n message: `Invalid ${fieldName}`,\n fields: fileErrors,\n });\n }\n\n // Validate non-file fields if any\n if (Object.keys(nonFileSchema).length > 0)\n {\n const tempSchema = {\n ...schema,\n properties: nonFileSchema,\n required: (schema as any).required?.filter((r: string) => r in nonFileSchema) ?? [],\n };\n\n const converted = Value.Convert(tempSchema, nonFileData);\n const errors = [...Value.Errors(tempSchema, converted)];\n\n if (errors.length > 0)\n {\n throw new ValidationError({\n message: `Invalid ${fieldName}`,\n fields: errors.map((e): ValidationFieldError => ({\n path: e.path,\n message: e.message,\n value: e.value,\n })),\n });\n }\n\n // Merge validated non-file fields with file fields\n Object.assign(result, converted);\n }\n else\n {\n // No non-file fields to validate\n Object.assign(result, nonFileData);\n }\n\n return result as T;\n}\n\n/**\n * Extract query parameters from request URL\n *\n * Handles array values (multiple params with same key)\n */\nexport function extractQueryParams(c: Context): Record<string, string | string[]>\n{\n const url = new URL(c.req.url);\n const queryObj: Record<string, string | string[]> = {};\n\n url.searchParams.forEach((v, k) =>\n {\n const existing = queryObj[k];\n if (existing)\n {\n queryObj[k] = Array.isArray(existing) ? [...existing, v] : [existing, v];\n }\n else\n {\n queryObj[k] = v;\n }\n });\n\n return queryObj;\n}\n\n/**\n * Extract headers from request (lowercase keys)\n */\nexport function extractHeaders(c: Context): Record<string, string>\n{\n const rawHeaders: Record<string, string> = {};\n\n c.req.raw.headers.forEach((value, key) =>\n {\n rawHeaders[key.toLowerCase()] = value;\n });\n\n return rawHeaders;\n}\n\n/**\n * Extract and parse cookies from request\n */\nexport function extractCookies(c: Context): Record<string, string>\n{\n const cookieHeader = c.req.header('cookie');\n const rawCookies: Record<string, string> = {};\n\n if (cookieHeader)\n {\n cookieHeader.split(';').forEach(cookie =>\n {\n const [key, value] = cookie.trim().split('=');\n if (key && value)\n {\n rawCookies[key] = decodeURIComponent(value);\n }\n });\n }\n\n return rawCookies;\n}\n\n/**\n * Parse JSON body from request\n *\n * @throws ValidationError if JSON parsing fails\n */\nexport async function parseJsonBody(c: Context): Promise<Record<string, unknown>>\n{\n try\n {\n return await c.req.json();\n }\n catch (error)\n {\n throw new ValidationError({\n message: 'Invalid JSON body',\n fields: [{\n path: '/',\n message: 'Failed to parse JSON',\n value: error instanceof Error ? error.message : 'Unknown error',\n }],\n });\n }\n}\n\n/**\n * Parse multipart/form-data from request\n *\n * Handles file uploads and form fields.\n * Multiple files with same key are collected into arrays.\n *\n * @throws ValidationError if form data parsing fails\n */\nexport async function parseFormData(c: Context): Promise<Record<string, unknown>>\n{\n try\n {\n const formData = await c.req.formData();\n const result: Record<string, unknown> = {};\n\n formData.forEach((value, key) =>\n {\n const existing = result[key];\n\n if (existing !== undefined)\n {\n // Multiple values with same key - convert to array\n if (Array.isArray(existing))\n {\n existing.push(value);\n }\n else\n {\n result[key] = [existing, value];\n }\n }\n else\n {\n result[key] = value;\n }\n });\n\n return result;\n }\n catch (error)\n {\n throw new ValidationError({\n message: 'Invalid form data',\n fields: [{\n path: '/',\n message: 'Failed to parse form data',\n value: error instanceof Error ? error.message : 'Unknown error',\n }],\n });\n }\n}","/**\n * Route Registration for define-route style routing\n *\n * Registers routes defined with route.get()...handler() to Hono app\n */\n\nimport type { Context, Hono, MiddlewareHandler } from 'hono';\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status';\nimport { logger } from '@spfn/core/logger';\nimport type { NamedMiddleware } from './define-middleware';\nimport type { RouteInput } from './route-input';\nimport type { RouteBuilderContext } from './context';\nimport type { RouteDef } from './route-builder';\nimport type { Router } from './router';\nimport type { HttpMethod } from './types';\nimport {\n validateField,\n validateFormData,\n extractQueryParams,\n extractHeaders,\n extractCookies,\n parseJsonBody,\n parseFormData,\n} from './validation';\n\n/**\n * Registered route information for logging\n */\nexport interface RegisteredRoute\n{\n method: HttpMethod;\n path: string;\n name: string;\n}\n\n/**\n * Type guard to check if value is a Router\n */\nfunction isRouter(value: unknown): value is Router<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'routes' in value &&\n '_routes' in value;\n}\n\n/**\n * Type guard to check if value is a RouteDef\n */\nfunction isRouteDef(value: unknown): value is RouteDef<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'handler' in value;\n}\n\n/**\n * Type guard to check if value is a NamedMiddleware\n */\nfunction isNamedMiddleware(value: unknown): value is NamedMiddleware<any>\n{\n return value !== null &&\n typeof value === 'object' &&\n 'name' in value &&\n 'handler' in value &&\n '_name' in value;\n}\n\n/**\n * Register routes from defineRouter() to Hono app\n *\n * @param app - Hono app instance\n * @param router - Router definition\n * @param namedMiddlewares - Optional server-level named middlewares\n *\n * @param collectedRoutes\n * @example\n * ```ts\n * const appRouter = defineRouter({\n * getUser: route.get('/users/:id')...\n * createUser: route.post('/users')...\n * });\n *\n * const app = new Hono();\n * const namedMiddlewares = [\n * { name: 'auth', handler: AuthMiddleware() },\n * { name: 'rateLimit', handler: RateLimitMiddleware() },\n * ];\n * registerRoutes(app, appRouter, namedMiddlewares);\n * ```\n */\nexport function registerRoutes<TRoutes extends Record<string, RouteDef<any> | Router<any>>>(\n app: Hono,\n router: Router<TRoutes>,\n namedMiddlewares?: ReadonlyArray<{ name: string; handler: MiddlewareHandler }>,\n collectedRoutes?: RegisteredRoute[]\n): RegisteredRoute[]\n{\n // Use provided array or create new one (top-level call)\n const routes = collectedRoutes ?? [];\n\n // Merge router's global middlewares with provided named middlewares\n const allNamedMiddlewares = [\n ...(namedMiddlewares ?? []),\n ...router._globalMiddlewares.map(mw => ({ name: mw.name, handler: mw.handler })),\n ];\n\n // 1. Register routes from router.routes\n for (const [name, routeOrRouter] of Object.entries(router.routes))\n {\n if (isRouter(routeOrRouter))\n {\n // Nested router - recursively register\n registerRoutes(app, routeOrRouter, allNamedMiddlewares, routes);\n }\n else if (isRouteDef(routeOrRouter))\n {\n // Single route - register\n const registered = registerRoute(app, name, routeOrRouter, allNamedMiddlewares);\n if (registered)\n {\n routes.push(registered);\n }\n }\n else\n {\n logger.warn(`Unknown route type for \"${name}\" - skipping`, {\n type: typeof routeOrRouter,\n });\n }\n }\n\n // 2. Register routes from package routers (_packageRouters)\n if (router._packageRouters && router._packageRouters.length > 0)\n {\n for (const pkgRouter of router._packageRouters)\n {\n registerRoutes(app, pkgRouter, allNamedMiddlewares, routes);\n }\n }\n\n return routes;\n}\n\n/**\n * Register a single route\n */\nfunction registerRoute(\n app: Hono,\n name: string,\n routeDef: RouteDef<any>,\n namedMiddlewares?: ReadonlyArray<{ name: string; handler: MiddlewareHandler }>\n): RegisteredRoute | null\n{\n const { method, path, input, middlewares = [], skipMiddlewares, handler } = routeDef;\n\n if (!method || !path)\n {\n logger.warn(`Route \"${name}\" is missing method or path - skipping`, {\n method,\n path,\n });\n\n return null;\n }\n\n // Create wrapped handler with validation\n const wrappedHandler = async (c: Context) =>\n {\n // Create RouteBuilderContext with validation\n const { context, responseMeta } = await createRouteBuilderContext(c, input || {});\n\n // Call user handler\n const result = await handler(context);\n\n // If handler returns Response, use it directly (e.g., c.json(), c.redirect())\n if (result instanceof Response)\n {\n return result;\n }\n\n // Handle empty responses (noContent, notModified, accepted without data)\n if (responseMeta.isEmpty)\n {\n return c.body(null, responseMeta.status);\n }\n\n // Return data as JSON with status and headers from helper methods\n const hasCustomHeaders = Object.keys(responseMeta.headers).length > 0;\n\n if (hasCustomHeaders)\n {\n return c.json(result, responseMeta.status, responseMeta.headers);\n }\n\n return c.json(result, responseMeta.status);\n };\n\n // Collect all middlewares: server-level (filtered) + route-level\n const allMiddlewares: MiddlewareHandler[] = [];\n\n // Track registered middlewares for deduplication\n const registeredNames = new Set<string>();\n const registeredHandlers = new Set<MiddlewareHandler>();\n\n // Check if skipping all middlewares\n const skipAll = skipMiddlewares === '*';\n\n // Collect auto-skips from route-level middlewares (e.g., optionalAuth skips 'auth')\n const autoSkips = new Set<string>();\n for (const mw of middlewares)\n {\n if (isNamedMiddleware(mw) && mw.skips)\n {\n for (const skipName of mw.skips)\n {\n autoSkips.add(skipName);\n }\n }\n }\n\n // Add server-level named middlewares (skip those in skipMiddlewares, autoSkips, or if '*')\n if (namedMiddlewares && namedMiddlewares.length > 0)\n {\n if (skipAll)\n {\n logger.debug(`⏭️ Skipping all middlewares (*) for route: ${method} ${path}`, { name });\n }\n else\n {\n const skipSet = new Set(Array.isArray(skipMiddlewares) ? skipMiddlewares : []);\n for (const middleware of namedMiddlewares)\n {\n if (skipSet.has(middleware.name))\n {\n logger.debug(`⏭️ Skipping middleware '${middleware.name}' for route: ${method} ${path}`, { name });\n }\n else if (autoSkips.has(middleware.name))\n {\n logger.debug(`⏭️ Auto-skipping middleware '${middleware.name}' for route: ${method} ${path}`, { name });\n }\n else\n {\n allMiddlewares.push(middleware.handler);\n registeredNames.add(middleware.name);\n registeredHandlers.add(middleware.handler);\n }\n }\n }\n }\n\n // Add route-level middlewares (with deduplication by name or handler reference)\n for (const mw of middlewares)\n {\n if (isNamedMiddleware(mw))\n {\n // Named middleware: deduplicate by name\n if (registeredNames.has(mw.name))\n {\n logger.debug(`🔄 Skipping duplicate middleware '${mw.name}' for route: ${method} ${path}`, { name });\n continue;\n }\n registeredNames.add(mw.name);\n allMiddlewares.push(mw.handler);\n }\n else\n {\n // Regular middleware: deduplicate by handler reference\n if (registeredHandlers.has(mw))\n {\n logger.debug(`🔄 Skipping duplicate middleware handler for route: ${method} ${path}`, { name });\n continue;\n }\n registeredHandlers.add(mw);\n allMiddlewares.push(mw);\n }\n }\n\n // Register to Hono with correct HTTP method\n const methodLower = method.toLowerCase() as Lowercase<HttpMethod>;\n\n if (allMiddlewares.length > 0)\n {\n // Register with middlewares\n app[methodLower](path, ...allMiddlewares, wrappedHandler);\n }\n else\n {\n // Register without middlewares\n app[methodLower](path, wrappedHandler);\n }\n\n logger.debug(`Registered route: ${method} ${path}`, { name });\n\n return { method, path, name };\n}\n\n/**\n * Response metadata set by helper methods\n */\ninterface ResponseMeta\n{\n status: ContentfulStatusCode;\n headers: Record<string, string>;\n isEmpty: boolean;\n}\n\n/**\n * Create RouteBuilderContext from Hono Context\n *\n * Validates params, query, body, headers, cookies and returns structured input.\n * Helper methods (created, accepted, etc.) return data directly for type inference,\n * while storing response metadata internally for later use.\n */\nasync function createRouteBuilderContext<TInput extends RouteInput>(\n c: Context,\n input: TInput\n): Promise<{ context: RouteBuilderContext<TInput>; responseMeta: ResponseMeta }>\n{\n // Validate and extract all input fields\n const params = validateField(input.params, c.req.param(), 'path parameters');\n const query = validateField(input.query, extractQueryParams(c), 'query parameters');\n const headers = validateField(input.headers, extractHeaders(c), 'headers');\n const cookies = validateField(input.cookies, extractCookies(c), 'cookies');\n\n // Body/FormData requires async parsing - determine by Content-Type\n let body: Record<string, unknown> = {};\n let formData: Record<string, unknown> = {};\n\n if (input.body || input.formData)\n {\n const contentType = c.req.header('content-type') || '';\n\n if (contentType.includes('multipart/form-data') && input.formData)\n {\n const rawFormData = await parseFormData(c);\n formData = validateFormData(input.formData, rawFormData, 'form data');\n }\n else if (input.body)\n {\n const rawBody = await parseJsonBody(c);\n body = validateField(input.body, rawBody, 'request body');\n }\n }\n\n // Cache for data() - avoid creating new object on each call\n let cachedData: any = null;\n\n // Response metadata - set by helper methods, used when building final Response\n const responseMeta: ResponseMeta = {\n status: 200 as ContentfulStatusCode,\n headers: {},\n isEmpty: false,\n };\n\n // Create context with structured data()\n const context: RouteBuilderContext<TInput> = {\n data: async () =>\n {\n if (!cachedData)\n {\n cachedData = { params, query, body, formData, headers, cookies };\n }\n return cachedData;\n },\n\n json: (data, status, resHeaders) =>\n {\n return c.json(data, status, resHeaders);\n },\n\n created: <T>(data: T, location?: string): T =>\n {\n responseMeta.status = 201 as ContentfulStatusCode;\n if (location)\n {\n responseMeta.headers['Location'] = location;\n }\n return data;\n },\n\n accepted: <T>(data?: T): any =>\n {\n responseMeta.status = 202 as ContentfulStatusCode;\n if (data === undefined)\n {\n responseMeta.isEmpty = true;\n return undefined;\n }\n return data;\n },\n\n noContent: (): void =>\n {\n responseMeta.status = 204 as ContentfulStatusCode;\n responseMeta.isEmpty = true;\n },\n\n notModified: (): void =>\n {\n responseMeta.status = 304 as ContentfulStatusCode;\n responseMeta.isEmpty = true;\n },\n\n paginated: <T>(data: T[], page: number, limit: number, total: number) =>\n {\n return {\n items: data,\n pagination: {\n page,\n limit,\n total,\n totalPages: Math.ceil(total / limit),\n },\n };\n },\n\n redirect: (url, status) =>\n {\n return c.redirect(url, status as RedirectStatusCode);\n },\n\n raw: c,\n };\n\n return { context, responseMeta };\n}","/**\n * Middleware Definition Helper\n *\n * Provides type-safe middleware definition with name inference\n */\n\nimport type { MiddlewareHandler } from 'hono';\n\n/**\n * Named middleware with type inference\n *\n * @example\n * ```ts\n * export const authMiddleware = defineMiddleware('auth', async (c, next) => {\n * // auth logic\n * c.set('user', { id: 1 });\n * await next();\n * });\n *\n * export const rateLimitMiddleware = defineMiddleware('rateLimit', async (c, next) => {\n * // rate limit logic\n * await next();\n * });\n * ```\n */\nexport type NamedMiddleware<TName extends string = string> = {\n name: TName;\n handler: MiddlewareHandler;\n _name: TName; // Type inference helper\n skips?: string[]; // Server-level middlewares to auto-skip when this middleware is used\n};\n\n/**\n * Named middleware factory with type inference\n *\n * Factory function that creates middleware instances with parameters\n *\n * @example\n * ```ts\n * export const requirePermissions = defineMiddleware('permission',\n * (...permissions: string[]) => async (c, next) => {\n * // permission check logic\n * await next();\n * }\n * );\n * ```\n */\nexport type NamedMiddlewareFactory<TName extends string = string, TArgs extends any[] = any[]> = {\n name: TName;\n _name: TName; // Type inference helper\n} & ((...args: TArgs) => MiddlewareHandler);\n\n/**\n * Define a named middleware\n *\n * Creates a middleware with a unique name that can be referenced\n * in route-level skip() calls with full type safety.\n *\n * Supports two patterns:\n * 1. Regular middleware: Direct middleware handler\n * 2. Factory middleware: Function that creates middleware with parameters\n *\n * @param name - Unique middleware name\n * @param handler - Middleware handler function\n * @returns Named middleware with type inference\n *\n * @example\n * ```ts\n * // Regular middleware\n * export const authMiddleware = defineMiddleware('auth', async (c, next) => {\n * const token = c.req.header('authorization');\n * if (!token) {\n * return c.json({ error: 'Unauthorized' }, 401);\n * }\n * c.set('user', await verifyToken(token));\n * await next();\n * });\n *\n * // Factory middleware\n * export const requirePermissions = defineMiddleware('permission',\n * (...permissions: string[]) => async (c, next) => {\n * const user = c.get('user');\n * if (!hasPermissions(user, permissions)) {\n * return c.json({ error: 'Forbidden' }, 403);\n * }\n * await next();\n * }\n * );\n *\n * // server.config.ts\n * export default defineServerConfig()\n * .middlewares([authMiddleware])\n * .routes(appRouter)\n * .build();\n *\n * // routes.ts - skip by name\n * export const publicRoute = route.get('/health')\n * .skip(['auth']) // ✅ Type-safe! Autocomplete!\n * .handler(async (c) => c.success({ status: 'ok' }));\n *\n * // Use factory middleware inline\n * export const protectedRoute = route.get('/admin')\n * .use([requirePermissions('admin:write')])\n * .handler(async (c) => { ... });\n * ```\n */\n/**\n * Options for defineMiddleware\n */\nexport interface DefineMiddlewareOptions\n{\n /**\n * Server-level middleware names to auto-skip when this middleware is used at route level.\n *\n * @example\n * ```ts\n * // optionalAuth auto-skips the global 'auth' middleware\n * export const optionalAuth = defineMiddleware('optionalAuth', handler, {\n * skips: ['auth']\n * });\n *\n * // Usage: .use([optionalAuth]) — no need for .skip(['auth'])\n * ```\n */\n skips?: string[];\n}\n\nexport function defineMiddleware<TName extends string>(\n name: TName,\n handler: MiddlewareHandler,\n options?: DefineMiddlewareOptions\n): NamedMiddleware<TName>;\n\nexport function defineMiddleware<TName extends string, TArgs extends any[]>(\n name: TName,\n factory: (...args: TArgs) => MiddlewareHandler,\n options?: DefineMiddlewareOptions\n): NamedMiddlewareFactory<TName, TArgs>;\n\nexport function defineMiddleware<TName extends string, TArgs extends any[] = []>(\n name: TName,\n handlerOrFactory: MiddlewareHandler | ((...args: TArgs) => MiddlewareHandler),\n options?: DefineMiddlewareOptions\n): NamedMiddleware<TName> | NamedMiddlewareFactory<TName, TArgs>\n{\n const skips = options?.skips;\n\n // Distinguish between regular middleware and factory by parameter count\n // MiddlewareHandler always has exactly 2 parameters: (c, next)\n // Factory has any other number of parameters\n if (typeof handlerOrFactory === 'function')\n {\n const paramCount = handlerOrFactory.length;\n\n // Regular middleware handler (c, next) => ...\n if (paramCount === 2)\n {\n return {\n name,\n handler: handlerOrFactory as MiddlewareHandler,\n _name: name as TName,\n ...(skips && { skips }),\n };\n }\n // Factory (...args) => (c, next) => ...\n else\n {\n // Create a new wrapper function to avoid \"Cannot assign to read only property 'name'\" error\n const factory = handlerOrFactory as (...args: TArgs) => MiddlewareHandler;\n const wrapper = (...args: TArgs) => factory(...args);\n\n // Use Object.defineProperty to set name property (which is read-only by default)\n Object.defineProperty(wrapper, 'name', {\n value: name,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n Object.defineProperty(wrapper, '_name', {\n value: name as TName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n if (skips)\n {\n Object.defineProperty(wrapper, 'skips', {\n value: skips,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n }\n\n return wrapper as NamedMiddlewareFactory<TName, TArgs>;\n }\n }\n\n // Fallback: treat as regular middleware\n return {\n name,\n handler: handlerOrFactory as MiddlewareHandler,\n _name: name as TName,\n ...(skips && { skips }),\n };\n}\n\n/**\n * Define a middleware factory explicitly\n *\n * Use this when your factory function has exactly 2 parameters,\n * which would be incorrectly detected as a regular middleware handler.\n *\n * @param name - Unique middleware name\n * @param factory - Factory function that returns a middleware handler\n * @returns Named middleware factory with type inference\n *\n * @example\n * ```ts\n * // Factory with 2 params (would be misdetected by defineMiddleware)\n * export const rateLimiter = defineMiddlewareFactory('rateLimit',\n * (limit: number, window: number) => async (c, next) => {\n * // rate limit logic using limit and window\n * await next();\n * }\n * );\n *\n * // Usage\n * route.get('/api')\n * .use([rateLimiter(100, 60000)]) // 100 requests per minute\n * .handler(...)\n * ```\n */\nexport function defineMiddlewareFactory<TName extends string, TArgs extends unknown[]>(\n name: TName,\n factory: (...args: TArgs) => MiddlewareHandler\n): NamedMiddlewareFactory<TName, TArgs>\n{\n const wrapper = (...args: TArgs) => factory(...args);\n\n Object.defineProperty(wrapper, 'name', {\n value: name,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n Object.defineProperty(wrapper, '_name', {\n value: name as TName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n\n return wrapper as NamedMiddlewareFactory<TName, TArgs>;\n}\n\n/**\n * Extract middleware names from an array of named middlewares\n *\n * @example\n * ```ts\n * type Middlewares = [\n * NamedMiddleware<'auth'>,\n * NamedMiddleware<'rateLimit'>\n * ];\n * type Names = ExtractMiddlewareNames<Middlewares>; // 'auth' | 'rateLimit'\n * ```\n */\nexport type ExtractMiddlewareNames<T extends readonly NamedMiddleware<string>[]> =\n T[number]['_name'];","/**\n * Route Helper Functions\n *\n * Type guards and TypeBox utilities\n */\n\nimport type { TSchema } from '@sinclair/typebox';\nimport { Type } from '@sinclair/typebox';\nimport type { HttpMethod } from './types';\n\n/**\n * Type guard for HttpMethod\n */\nexport function isHttpMethod(value: unknown): value is HttpMethod\n{\n return (\n typeof value === 'string' &&\n ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(value)\n );\n}\n\n/**\n * Nullable - Creates a union of T | null\n *\n * @example\n * ```typescript\n * // string | null\n * firstName: Nullable(Type.String())\n * ```\n */\nexport const Nullable = <T extends TSchema>(schema: T) =>\n Type.Union([schema, Type.Null()]);\n\n/**\n * OptionalNullable - Creates a union of T | null | undefined\n *\n * @example\n * ```typescript\n * // string | null | undefined\n * lastName: OptionalNullable(Type.String())\n * ```\n */\nexport const OptionalNullable = <T extends TSchema>(schema: T) =>\n Type.Optional(Type.Union([schema, Type.Null()]));"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spfn/core",
3
- "version": "0.2.0-beta.22",
3
+ "version": "0.2.0-beta.23",
4
4
  "description": "SPFN Framework Core - File-based routing, transactions, repository pattern",
5
5
  "type": "module",
6
6
  "exports": {