{"version":3,"sources":["../src/utils/priority.ts","../src/responses/response-helpers.ts","../src/core/middleware-builder.ts","../src/rules/built-in-rules.ts"],"names":["NextResponse"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Calculate priority based on route specificity.\n * Lower priority means higher precedence (executed first).\n *\n * @param path - The route path pattern\n * @param isExact - Whether this is an exact match\n * @returns Priority number (lower = higher precedence)\n */\nexport function calculatePriority(path: string, isExact: boolean): number {\n  if (isExact) {\n    return path.split('/').length * 10;\n  }\n  const segments = path.replace(/\\/\\*$/, '').split('/').filter(Boolean);\n  return 1000 + (100 - segments.length);\n}\n\n/**\n * Check if a request path matches a route pattern.\n *\n * @param path - The incoming request path\n * @param pattern - The route pattern to match against\n * @param isExact - Whether to perform exact matching\n * @param prefix - Optional prefix for wildcard routes\n * @returns True if the path matches the pattern\n */\nexport function matchRoute(\n  path: string,\n  pattern: string,\n  isExact: boolean,\n  prefix?: string,\n): boolean {\n  if (isExact) {\n    return path === pattern;\n  } else {\n    const routePrefix = prefix || pattern.replace(/\\/\\*$/, '');\n    return path === routePrefix || path.startsWith(routePrefix + '/');\n  }\n}\n\n/**\n * Extract parameters from path matching.\n * Handles dynamic segments like [id] and wildcard parameters.\n *\n * @param path - The incoming request path\n * @param pattern - The route pattern\n * @param isExact - Whether this is exact matching\n * @param prefix - Optional prefix for wildcard routes\n * @returns Object containing extracted parameters\n */\nexport function extractParams(\n  path: string,\n  pattern: string,\n  isExact: boolean,\n  prefix?: string,\n): Record<string, string> {\n  const params: Record<string, string> = {};\n\n  if (!isExact && prefix) {\n    const remaining = path.slice(prefix.length);\n    if (remaining.startsWith('/')) {\n      params['*'] = remaining.slice(1);\n    } else if (remaining === '') {\n      params['*'] = '';\n    }\n  }\n\n  // Handle dynamic segments like [id]\n  if (pattern.includes('[') && pattern.includes(']')) {\n    const patternParts = pattern.split('/');\n    const pathParts = path.split('/');\n\n    patternParts.forEach((part, index) => {\n      if (part.startsWith('[') && part.endsWith(']')) {\n        const paramName = part.slice(1, -1);\n        params[paramName] = pathParts[index] || '';\n      }\n    });\n  }\n\n  return params;\n}\n","import { NextResponse } from 'next/server';\nimport { MiddlewareResponses } from './types';\n\n/**\n * Internal base URL for redirects\n */\nlet currentBaseUrl = 'http://localhost:3000';\n\n/**\n * Collection of helper functions for creating common middleware responses.\n * Provides a consistent API for handling redirects, errors, and other responses.\n */\nexport const Responses: MiddlewareResponses & {\n  setBaseUrl: (url: string) => void;\n} = {\n  /**\n   * Set the base URL for redirects (internal use by MiddlewareBuilder)\n   */\n  setBaseUrl: (url: string) => {\n    currentBaseUrl = url;\n  },\n\n  /**\n   * Creates a response that continues to the next middleware or handler.\n   */\n  next: () => NextResponse.next(),\n\n  /**\n   * Creates a redirect response to the specified URL.\n   */\n  redirect: (url: string) => {\n    return NextResponse.redirect(new URL(url, currentBaseUrl));\n  },\n\n  /**\n   * Creates a JSON response with the specified data and status code.\n   */\n  json: (data: any, status = 200) => {\n    return NextResponse.json(data, { status });\n  },\n\n  /**\n   * Creates an unauthorized (401) response.\n   */\n  unauthorized: (message = 'Unauthorized') => {\n    return NextResponse.json({ error: message }, { status: 401 });\n  },\n\n  /**\n   * Creates a forbidden (403) response.\n   */\n  forbidden: (message = 'Forbidden') => {\n    return NextResponse.json({ error: message }, { status: 403 });\n  },\n\n  /**\n   * Creates a not found (404) response.\n   */\n  notFound: (message = 'Not Found') => {\n    return NextResponse.json({ error: message }, { status: 404 });\n  },\n};\n","import { NextRequest, NextResponse } from 'next/server';\nimport {\n  MiddlewareContext,\n  MiddlewareResult,\n  MiddlewareRule,\n  RouteDefinition,\n  MiddlewareBuilderOptions,\n} from '../types/core';\nimport {\n  calculatePriority,\n  matchRoute,\n  extractParams,\n} from '../utils/priority';\nimport { Responses } from '../responses/response-helpers';\n\n/**\n * Type-safe Next.js middleware builder.\n * Provides a simple, flexible way to build middleware with\n * route protection and built-in rules.\n */\nexport class MiddlewareBuilder<T = any> {\n  private routes: RouteDefinition<T>[] = [];\n  private fetchUserFn: (req: NextRequest) => Promise<T | null>;\n  private baseUrl?: string;\n\n  constructor(options: MiddlewareBuilderOptions<T>) {\n    this.fetchUserFn = options.fetchUser;\n    this.baseUrl = options.baseUrl;\n  }\n\n  /**\n   * Add an exact route match.\n   * The path must match exactly for the rules to execute.\n   */\n  exact(path: string, ...rules: MiddlewareRule<T>[]): MiddlewareBuilder<T> {\n    this.routes.push({\n      pattern: path,\n      rules,\n      priority: calculatePriority(path, true),\n      isExact: true,\n    });\n    return this;\n  }\n\n  /**\n   * Add a prefix route match (wildcard).\n   * Any path starting with the prefix will match.\n   */\n  prefix(\n    pathPrefix: string,\n    ...rules: MiddlewareRule<T>[]\n  ): MiddlewareBuilder<T> {\n    const cleanPrefix = pathPrefix.endsWith('/')\n      ? pathPrefix.slice(0, -1)\n      : pathPrefix;\n    this.routes.push({\n      pattern: pathPrefix,\n      rules,\n      priority: calculatePriority(pathPrefix, false),\n      isExact: false,\n      prefix: cleanPrefix,\n    });\n    return this;\n  }\n\n  /**\n   * Find the best matching route for the given path.\n   * Routes are sorted by priority (lower = higher precedence).\n   */\n  private findMatchingRoute(path: string): RouteDefinition<T> | null {\n    const sortedRoutes = [...this.routes].sort(\n      (a, b) => a.priority - b.priority,\n    );\n\n    for (const route of sortedRoutes) {\n      if (matchRoute(path, route.pattern, route.isExact, route.prefix)) {\n        return route;\n      }\n    }\n\n    return null;\n  }\n\n  /**\n   * Build the final middleware handler.\n   * Returns a function that can be used as Next.js middleware.\n   */\n  build() {\n    const baseUrl = this.baseUrl;\n\n    return async (req: NextRequest): Promise<NextResponse> => {\n      const url = new URL(req.url);\n      const path = url.pathname;\n\n      // Set base URL for Responses if provided\n      if (baseUrl) {\n        Responses.setBaseUrl(baseUrl);\n      } else {\n        Responses.setBaseUrl(url.origin);\n      }\n\n      const matchingRoute = this.findMatchingRoute(path);\n      if (!matchingRoute) {\n        return Responses.next();\n      }\n\n      const context: MiddlewareContext<T> = {\n        data: await this.fetchUserFn(req),\n        req,\n        path,\n        params: extractParams(\n          path,\n          matchingRoute.pattern,\n          matchingRoute.isExact,\n          matchingRoute.prefix,\n        ),\n      };\n\n      for (const rule of matchingRoute.rules) {\n        const result = await rule(context);\n\n        if (result) {\n          return result as NextResponse;\n        }\n      }\n\n      return Responses.next();\n    };\n  }\n}\n","import { MiddlewareRule } from '../types/core';\nimport { RuleFactories } from './types';\nimport { Responses } from '../responses/response-helpers';\n\n/**\n * Collection of built-in rule factories for common middleware patterns.\n * These rules handle authentication, authorization, rate limiting, and more.\n */\nexport const Rules: RuleFactories<any> = {\n  /**\n   * Creates a rule that requires the user to be logged in.\n   * Redirects to /sign-in if user data is not present.\n   */\n  isLoggedIn:\n    () =>\n    ({ data }) => {\n      if (data) {\n        return null;\n      } else {\n        return Responses.redirect('/sign-in');\n      }\n    },\n\n  /**\n   * Creates a rule that requires the user to not be logged in.\n   * Redirects to home if user is already authenticated.\n   */\n  isNotLoggedIn:\n    () =>\n    ({ data }) => {\n      if (!data) {\n        return Responses.next();\n      } else {\n        return Responses.redirect('/');\n      }\n    },\n\n  /**\n   * Creates a rule that requires the user to have a specific role.\n   * Returns forbidden if user doesn't have the required role.\n   */\n  hasRole:\n    (role: string) =>\n    ({ data }) => {\n      if (data?.role === role || data?.roles?.includes(role)) {\n        return null;\n      } else {\n        return Responses.forbidden(`Required role: ${role}`);\n      }\n    },\n\n  /**\n   * Creates a rule that requires the user to have a specific permission.\n   * Returns forbidden if user doesn't have the required permission.\n   */\n  hasPermission:\n    (permission: string) =>\n    ({ data }) => {\n      if (data?.permissions?.includes(permission)) {\n        return null;\n      } else {\n        return Responses.forbidden(`Required permission: ${permission}`);\n      }\n    },\n\n  /**\n   * Creates a rule that always redirects to the specified destination.\n   */\n  redirectTo: (destination: string) => () => {\n    return Responses.redirect(destination);\n  },\n\n  /**\n   * Wraps a custom rule function.\n   */\n  custom: (fn: MiddlewareRule<any>) => fn,\n};\n"]}