next-api-layer 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -150,9 +150,15 @@ const { data, success } = await api.get('users/profile');
150
150
  // POST with body
151
151
  const result = await api.post('projects', { body: { name: 'New Project' } });
152
152
 
153
- // Per-request skip (overrides global config)
153
+ // Per-request sanitization control
154
154
  const rawHtml = await api.get('editor/content', { skipSanitize: true });
155
155
 
156
+ // Skip specific fields only (sanitize others)
157
+ const post = await api.post('blog/create', formData, {
158
+ isFormData: true,
159
+ skipSanitizeFields: ['content', 'raw_html'],
160
+ });
161
+
156
162
  // With query params
157
163
  const users = await api.get('users', { params: { page: 1, limit: 20 } });
158
164
  ```
@@ -420,6 +426,13 @@ interface AuthProxyConfig {
420
426
  maxSize?: number; // Default: 100 tokens
421
427
  };
422
428
 
429
+ i18n?: {
430
+ enabled?: boolean; // Enable locale detection from URL
431
+ locales?: string[]; // Valid locale codes ['en', 'tr', 'ar']
432
+ defaultLocale?: string; // Fallback locale
433
+ middleware?: (req: NextRequest) => NextResponse; // i18n middleware (e.g., next-intl)
434
+ };
435
+
423
436
  // ======== Composability Hooks ========
424
437
 
425
438
  // Runs BEFORE auth validation. Return NextResponse to bypass auth.
@@ -538,6 +551,13 @@ interface ApiClientConfig {
538
551
 
539
552
  methodSpoofing?: boolean; // Default: false (for Laravel)
540
553
  }
554
+
555
+ // Per-request options
556
+ interface RequestOptions {
557
+ isFormData?: boolean; // Send as FormData
558
+ skipSanitize?: boolean; // Skip all sanitization for this request
559
+ skipSanitizeFields?: string[]; // Skip sanitization for specific fields
560
+ }
541
561
  ```
542
562
 
543
563
  ## i18n Integration
@@ -595,7 +615,36 @@ Backend: GET /api/posts?lang=tr
595
615
 
596
616
  ### With next-intl
597
617
 
598
- When using with next-intl, use `afterAuth` hook to combine both middlewares:
618
+ The easiest way to integrate with next-intl is using the `middleware` option:
619
+
620
+ ```ts
621
+ import { createAuthProxy } from 'next-api-layer';
622
+ import createIntlMiddleware from 'next-intl/middleware';
623
+ import { routing } from './i18n/routing';
624
+
625
+ const intlMiddleware = createIntlMiddleware(routing);
626
+
627
+ export default createAuthProxy({
628
+ apiBaseUrl: process.env.API_URL!,
629
+ cookies: { user: 'userToken', guest: 'guestToken' },
630
+
631
+ i18n: {
632
+ enabled: true,
633
+ locales: ['en', 'tr', 'ar'],
634
+ defaultLocale: 'en',
635
+ middleware: intlMiddleware, // Library handles response merging automatically
636
+ },
637
+ });
638
+ ```
639
+
640
+ The library automatically:
641
+ - Calls your i18n middleware internally
642
+ - Preserves `x-locale`, `x-auth-user`, and `x-refreshed-token` headers
643
+ - Copies all auth cookies to the merged response
644
+
645
+ #### Advanced: Manual Middleware Control
646
+
647
+ If you need more control, use the `afterAuth` hook instead:
599
648
 
600
649
  ```ts
601
650
  import { createAuthProxy } from 'next-api-layer';
package/dist/api.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SanitizationConfig } from './createApiClient-BliWeW4X.cjs';
2
- export { f as ApiClient, g as ApiClientConfig, s as RequestOptions, r as createApiClient } from './createApiClient-BliWeW4X.cjs';
1
+ import { S as SanitizationConfig } from './createApiClient-Brlw1L7n.cjs';
2
+ export { f as ApiClient, g as ApiClientConfig, s as RequestOptions, r as createApiClient } from './createApiClient-Brlw1L7n.cjs';
3
3
  import 'next/server';
4
4
 
5
5
  /**
package/dist/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SanitizationConfig } from './createApiClient-BliWeW4X.js';
2
- export { f as ApiClient, g as ApiClientConfig, s as RequestOptions, r as createApiClient } from './createApiClient-BliWeW4X.js';
1
+ import { S as SanitizationConfig } from './createApiClient-Brlw1L7n.js';
2
+ export { f as ApiClient, g as ApiClientConfig, s as RequestOptions, r as createApiClient } from './createApiClient-Brlw1L7n.js';
3
3
  import 'next/server';
4
4
 
5
5
  /**
@@ -65,6 +65,11 @@ interface I18nConfig {
65
65
  enabled: boolean;
66
66
  locales?: string[];
67
67
  defaultLocale?: string;
68
+ /**
69
+ * next-intl or similar i18n middleware function
70
+ * Library will call this and merge responses to preserve headers
71
+ */
72
+ middleware?: (request: NextRequest) => NextResponse | Promise<NextResponse>;
68
73
  }
69
74
 
70
75
  /** Result of auth validation passed to afterAuth hook */
@@ -65,6 +65,11 @@ interface I18nConfig {
65
65
  enabled: boolean;
66
66
  locales?: string[];
67
67
  defaultLocale?: string;
68
+ /**
69
+ * next-intl or similar i18n middleware function
70
+ * Library will call this and merge responses to preserve headers
71
+ */
72
+ middleware?: (request: NextRequest) => NextResponse | Promise<NextResponse>;
68
73
  }
69
74
 
70
75
  /** Result of auth validation passed to afterAuth hook */
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var chunkJEEL6S4O_cjs=require('./chunk-JEEL6S4O.cjs'),chunk6ENVQMWQ_cjs=require('./chunk-6ENVQMWQ.cjs'),server=require('next/server');function ie(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID()+crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2)}`}function ue(e){return `rl:${e.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||e.headers.get("x-real-ip")||"unknown"}`}function Q(e){if(!e.apiBaseUrl)throw new Error("next-api-layer: apiBaseUrl is required");if(!e.cookies?.user||!e.cookies?.guest)throw new Error("next-api-layer: cookies.user and cookies.guest are required");let t=e.apiBaseUrl.endsWith("/")?e.apiBaseUrl:`${e.apiBaseUrl}/`,f={...chunk6ENVQMWQ_cjs.a,...e.cookies.options},l={...chunk6ENVQMWQ_cjs.b,...e.endpoints},m={enabled:e.csrf?.enabled??false,strategy:e.csrf?.strategy??chunk6ENVQMWQ_cjs.g.strategy,secret:e.csrf?.secret??ie(),cookieName:e.csrf?.cookieName??chunk6ENVQMWQ_cjs.g.cookieName,headerName:e.csrf?.headerName??chunk6ENVQMWQ_cjs.g.headerName,ignoreMethods:e.csrf?.ignoreMethods??chunk6ENVQMWQ_cjs.g.ignoreMethods,trustSameSite:e.csrf?.trustSameSite??chunk6ENVQMWQ_cjs.g.trustSameSite},R={enabled:e.rateLimit?.enabled??false,windowMs:e.rateLimit?.windowMs??chunk6ENVQMWQ_cjs.h.windowMs,maxRequests:e.rateLimit?.maxRequests??chunk6ENVQMWQ_cjs.h.maxRequests,keyFn:e.rateLimit?.keyFn??ue,skipRoutes:e.rateLimit?.skipRoutes??chunk6ENVQMWQ_cjs.h.skipRoutes,onRateLimited:e.rateLimit?.onRateLimited},u={enabled:e.audit?.enabled??false,events:e.audit?.events??[...chunk6ENVQMWQ_cjs.i.events],logger:e.audit?.logger};return {...e,apiBaseUrl:t,_resolved:{cookieOptions:f,endpoints:l,csrf:m,rateLimit:R,audit:u}}}var $={parseAuthMe:e=>{let t=e;return !t?.success||!t?.data?null:{isValid:true,tokenType:t.data.type||"user",exp:t.data.exp||null,userData:t.data}},parseRefreshToken:e=>{let t=e;return t?.success&&t?.data?.accessToken?t.data.accessToken:null},parseGuestToken:e=>e?.data?.accessToken||null};function j(e){let{apiBaseUrl:t,_resolved:f,responseMappers:l}=e,{endpoints:m}=f,R={parseAuthMe:l?.parseAuthMe||$.parseAuthMe,parseRefreshToken:l?.parseRefreshToken||$.parseRefreshToken,parseGuestToken:l?.parseGuestToken||$.parseGuestToken};async function u(a){let i={isValid:false,tokenType:null,exp:null,userData:null};try{let n=await fetch(`${t}${m.validate}`,{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},cache:"no-store"});if(!n.ok)return i;let s=await n.json().catch(()=>null),d=R.parseAuthMe(s);return !d||!d.isValid?i:d}catch{return i}}async function c(a){return u(a)}async function p(a){try{let i=await fetch(`${t}${m.refresh}`,{method:"POST",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},cache:"no-store"});if(!i.ok)return {success:!1,newToken:null};let n=await i.json().catch(()=>null),s=R.parseRefreshToken(n);return s?{success:!0,newToken:s}:{success:!1,newToken:null}}catch{return {success:false,newToken:null}}}async function o(){let a=e.guestToken;if(!a?.enabled||!a.credentials)return null;try{let i=await fetch(`${t}${m.guest}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:a.credentials.username,password:a.credentials.password}),cache:"no-store"});if(!i.ok)return null;let n=await i.json().catch(()=>null);return R.parseGuestToken(n)}catch{return null}}return {validateToken:u,getTokenInfo:c,refreshToken:p,createGuestToken:o}}function ee(e,t){if(!t?.enabled)return null;let f=t.locales??[],l=t.defaultLocale,R=e.split("/").filter(Boolean)[0];return R&&f.includes(R)?R:l??null}function z(e,t){let{cookies:f,guestToken:l,access:m,i18n:R,_resolved:u}=e,{cookieOptions:c}=u;function p(r,x,h){r.cookies.get(h)?.value&&x.cookies.delete(h);}function o(r,x){return p(r,x,f.guest),p(r,x,f.user),x}function a(r,x=500){return new server.NextResponse(JSON.stringify({success:false,message:r}),{status:x,headers:{"Content-Type":"application/json"}})}function i(r){return (m?.authRoutes??[]).some(h=>r===h||r.startsWith(`${h}/`))}function n(r){return m?.protectedByDefault?!s(r)&&!i(r):(m?.protectedRoutes??[]).some(h=>r===h||r.startsWith(`${h}/`))}function s(r){return (m?.publicRoutes??[]).some(h=>r===h||r.startsWith(`${h}/`))}function d(r){let x=m?.allowedTokenTypes;return !x||x.length===0?true:r?x.includes(r):false}async function C(r,x){let{origin:h}=r.nextUrl;if(l?.enabled){let y=await t.createGuestToken();if(y){let N;return x?N=server.NextResponse.next():n(r.nextUrl.pathname)?N=server.NextResponse.redirect(new URL("/login",h)):N=server.NextResponse.next(),N.cookies.set(f.guest,y,{...c,maxAge:3600}),N}}return x?a("Token bulunamad\u0131",401):n(r.nextUrl.pathname)?server.NextResponse.redirect(new URL("/login",h)):server.NextResponse.next()}async function v(r,x,h,y,N){let{pathname:k,origin:g}=r.nextUrl,{isValid:S,tokenType:T,userData:A}=x,E=T===chunk6ENVQMWQ_cjs.c.GUEST;if(!S){if(h&&y){let D=await t.refreshToken(y);if(D.success&&D.newToken){let O=await t.getTokenInfo(D.newToken);if(O.isValid){let _=new Headers(r.headers);O.userData&&_.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(O.userData)),_.set(chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN,D.newToken);let Z=ee(k,R);Z&&_.set(chunk6ENVQMWQ_cjs.e.LOCALE,Z);let I;return i(k)?I=server.NextResponse.redirect(new URL("/",g)):I=server.NextResponse.next({request:{headers:_}}),I.cookies.set(f.user,D.newToken,{...c,maxAge:c.maxAge}),p(r,I,f.guest),I}}}let P=await C(r,N);return P.cookies.get(f.guest)?.value?p(r,P,f.user):o(r,P),P}let U=new Headers(r.headers);A&&U.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(A));let J=ee(k,R);if(J&&U.set(chunk6ENVQMWQ_cjs.e.LOCALE,J),!E&&!d(T)){if(N){let Y=a("Bu i\u015Flem i\xE7in yetkiniz yok",403);return o(r,Y)}let P=server.NextResponse.redirect(new URL("/login",g));return o(r,P)}if(E)return N?server.NextResponse.next({request:{headers:U}}):n(k)?server.NextResponse.redirect(new URL("/login",g)):server.NextResponse.next({request:{headers:U}});if(i(k))return server.NextResponse.redirect(new URL("/",g));let X=server.NextResponse.next({request:{headers:U}});return p(r,X,f.guest),X}return {deleteAllAuthCookies:o,jsonError:a,isAuthPage:i,isProtectedRoute:n,isPublicRoute:s,isTokenTypeAllowed:d,handleNoToken:C,handleValidationResult:v}}function K(e){async function t(u){let c=le();return `${await ce(e.secret,u,c)}.${c}`}function f(u){let c=u.method.toUpperCase();if(e.ignoreMethods.includes(c))return {valid:true};let p=e.strategy;if(p==="fetch-metadata"||p==="both"){let o=l(u);if(p==="fetch-metadata"||o.valid||o.reason!=="missing-headers")return o}return p==="double-submit"||p==="both"?m(u):{valid:true}}function l(u){let c=u.headers.get("sec-fetch-site");if(!c)return {valid:false,reason:"missing-headers"};if(c==="same-origin")return {valid:true};if(c==="none"){let p=u.method.toUpperCase();return e.ignoreMethods.includes(p)?{valid:true}:{valid:false,reason:"direct-navigation-unsafe-method"}}return c==="same-site"?e.trustSameSite?{valid:true}:{valid:false,reason:"same-site-not-trusted"}:c==="cross-site"?{valid:false,reason:"cross-site-request"}:{valid:false,reason:"unknown-sec-fetch-site"}}function m(u){let c=u.cookies.get(e.cookieName)?.value;if(!c)return {valid:false,reason:"missing-cookie-token"};let p=u.headers.get(e.headerName);return p?de(c,p)?c.split(".").length!==2?{valid:false,reason:"invalid-token-format"}:{valid:true}:{valid:false,reason:"token-mismatch"}:{valid:false,reason:"missing-header-token"}}async function R(u,c){let p=await t(c);return u.cookies.set(e.cookieName,p,{httpOnly:false,secure:process.env.NODE_ENV==="production",sameSite:"strict",path:"/"}),u}return {validateRequest:f,generateToken:t,attachCsrfCookie:R}}function le(){if(typeof crypto<"u"&&crypto.getRandomValues){let e=new Uint8Array(32);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}return Math.random().toString(36).substring(2)+Date.now().toString(36)}async function ce(e,t,f){let l=`${t.length}!${t}!${f.length}!${f}`;if(typeof crypto<"u"&&crypto.subtle){let u=new TextEncoder,c=u.encode(e),p=u.encode(l),o=await crypto.subtle.importKey("raw",c,{name:"HMAC",hash:"SHA-256"},false,["sign"]),a=await crypto.subtle.sign("HMAC",o,p);return Array.from(new Uint8Array(a),i=>i.toString(16).padStart(2,"0")).join("")}let m=0,R=e+l;for(let u=0;u<R.length;u++){let c=R.charCodeAt(u);m=(m<<5)-m+c,m=m&m;}return Math.abs(m).toString(16)}function de(e,t){if(e.length!==t.length)return false;let f=0;for(let l=0;l<e.length;l++)f|=e.charCodeAt(l)^t.charCodeAt(l);return f===0}function W(e){let t=new Map,f=setInterval(()=>{let a=Date.now();for(let[i,n]of t)n.resetAt<=a&&t.delete(i);},e.windowMs);typeof process<"u"&&process.on&&process.on("beforeExit",()=>clearInterval(f));function l(a){return e.skipRoutes.some(i=>i.endsWith("*")?a.startsWith(i.slice(0,-1)):i.endsWith("**")?a.startsWith(i.slice(0,-2)):a===i)}function m(a){let i=a.nextUrl.pathname;if(l(i))return {allowed:true,remaining:e.maxRequests,resetAt:0,limit:e.maxRequests};let n=e.keyFn(a),s=Date.now(),d=t.get(n);if(!d||d.resetAt<=s)return d={count:1,resetAt:s+e.windowMs},t.set(n,d),{allowed:true,remaining:e.maxRequests-1,resetAt:d.resetAt,limit:e.maxRequests};d.count++;let C=Math.max(0,e.maxRequests-d.count);return {allowed:d.count<=e.maxRequests,remaining:C,resetAt:d.resetAt,limit:e.maxRequests}}function R(a,i){return a.headers.set("X-RateLimit-Limit",i.limit.toString()),a.headers.set("X-RateLimit-Remaining",i.remaining.toString()),a.headers.set("X-RateLimit-Reset",Math.ceil(i.resetAt/1e3).toString()),a}function u(a,i){if(e.onRateLimited){let s=e.onRateLimited(a);return R(s,i)}let n=server.NextResponse.json({success:false,message:"Too many requests. Please try again later.",retryAfter:Math.ceil((i.resetAt-Date.now())/1e3)},{status:429});return n.headers.set("Retry-After",Math.ceil((i.resetAt-Date.now())/1e3).toString()),R(n,i)}function c(a){t.delete(a);}function p(){t.clear();}function o(){return t.size}return {check:m,applyHeaders:R,createLimitedResponse:u,shouldSkip:l,reset:c,clear:p,size:o}}function q(e){function t(n){return e.enabled&&e.events.includes(n)}function f(n){return n.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||n.headers.get("x-real-ip")||null}async function l(n,s,d){if(!t(n))return;let C={type:n,timestamp:new Date,ip:f(s),userId:d.userId,path:s.nextUrl.pathname,method:s.method,success:d.success,metadata:d.metadata};if(e.logger)try{await e.logger(C);}catch(v){console.error("[next-api-layer] Audit logger error:",v);}}function m(n,s,d){return l("auth:success",n,{success:true,userId:s,metadata:d})}function R(n,s){return l("auth:fail",n,{success:false,metadata:s})}function u(n,s,d){return l("auth:refresh",n,{success:true,userId:s,metadata:d})}function c(n,s){return l("auth:guest",n,{success:true,metadata:s})}function p(n,s,d){return l("access:denied",n,{success:false,userId:s,metadata:d})}function o(n,s){return l("csrf:fail",n,{success:false,metadata:s})}function a(n,s){return l("rateLimit:exceeded",n,{success:false,metadata:s})}function i(n,s,d){return l("error",n,{success:false,metadata:{...d,error:s.message,stack:s.stack}})}return {emit:l,isEnabled:t,authSuccess:m,authFail:R,authRefresh:u,authGuest:c,accessDenied:p,csrfFail:o,rateLimitExceeded:a,error:i}}function te(e){let t=Q(e),f=j(t),l=z(t,f),m=K(t._resolved.csrf),R=W(t._resolved.rateLimit),u=q(t._resolved.audit);async function c(o){let{pathname:a,origin:i}=o.nextUrl,n=a.startsWith("/api");if(t._resolved.rateLimit.enabled){let g=R.check(o);if(!g.allowed)return await u.rateLimitExceeded(o,{limit:g.limit,resetAt:g.resetAt}),R.createLimitedResponse(o,g)}if(t._resolved.csrf.enabled){let g=m.validateRequest(o);if(!g.valid)return await u.csrfFail(o,{reason:g.reason}),server.NextResponse.json({success:false,message:"CSRF validation failed"},{status:403})}if(t.blockBrowserApiAccess&&n&&(o.headers.get("accept")||"").includes("text/html"))return server.NextResponse.redirect(new URL("/",i));if(t.beforeAuth){let g=await t.beforeAuth(o);if(g)return g}if((t.excludedPaths??[]).some(g=>a.startsWith(g)))return p(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});if(["/api/auth/login","/api/auth/logout","/api/auth/me","/api/auth/refresh","/api/auth/register"].includes(a))return p(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});let C=o.cookies?.get(t.cookies.user)?.value,v=o.cookies?.get(t.cookies.guest)?.value,r=C||v,x=!!C;if(!r){await u.authFail(o,{reason:"no-token"});let g=await l.handleNoToken(o,n);return p(o,g,{isAuthenticated:false,isGuest:false,tokenType:null,user:null})}let h=await f.getTokenInfo(r),y={isAuthenticated:h.isValid&&h.tokenType!=="guest",isGuest:h.isValid&&h.tokenType==="guest",tokenType:h.tokenType,user:h.userData};if(h.isValid)if(h.tokenType==="guest")await u.authGuest(o);else {let g=h.userData?.id?.toString();await u.authSuccess(o,g,{tokenType:h.tokenType});}else await u.authFail(o,{reason:"invalid-token"});let N=await l.handleValidationResult(o,h,x,r,n),k=await p(o,N,y);if(t._resolved.csrf.enabled&&y.isAuthenticated){let g=h.userData?.id?.toString()||r.slice(0,32);k=await m.attachCsrfCookie(k,g);}if(t._resolved.rateLimit.enabled){let g=R.check(o);k=R.applyHeaders(k,g);}return k}async function p(o,a,i){return t.afterAuth?t.afterAuth(o,a,i):a}return c.config=t,c.csrf=m,c.rateLimiter=R,c.audit=u,c}function pe(e,t){if(!t||t.length===0)return false;let f=e.replace(/^\/api\//,"").replace(/^\//,"");return t.some(l=>{if(l===f)return true;if(l.includes("*")){let m=l.replace(/\*\*/g,"<<<DOUBLE>>>").replace(/\*/g,"[^/]+").replace(/<<<DOUBLE>>>/g,".+");return new RegExp(`^${m}$`).test(f)}return false})}function ne(e){let{apiBaseUrl:t,userCookieName:f="auth_token",guestCookieName:l="guest_token",skipAuthByDefault:m=false,publicEndpoints:R=[],forwardHeaders:u=["content-type","accept","accept-language","x-requested-with"],excludeHeaders:c=["host","connection","cookie"],transformRequest:p,transformResponse:o}=e,a=t.replace(/\/$/,"");function i(s,d){return s.headers.get(chunk6ENVQMWQ_cjs.e.SKIP_AUTH)==="true"||pe(d,R)?true:m}async function n(s){try{let d=new URL(s.url),C=d.pathname.replace(/^\/api\/?/,""),v=new URL(`${a}/${C}`);v.search=d.search;let r=new Headers;if(u.forEach(T=>{let A=s.headers.get(T);A&&r.set(T,A);}),s.headers.forEach((T,A)=>{let E=A.toLowerCase();!c.includes(E)&&!r.has(A)&&r.set(A,T);}),!i(s,C)){let T=s.cookies.get(f)?.value,A=s.cookies.get(l)?.value,E=T||A;E&&r.set(chunk6ENVQMWQ_cjs.e.AUTHORIZATION,`Bearer ${E}`);}r.delete(chunk6ENVQMWQ_cjs.e.SKIP_AUTH);let x=p?await p(s,r):r,h=null;if(s.method!=="GET"&&s.method!=="HEAD"){let T=s.headers.get("content-type")||"";T.includes("application/json")?h=await s.text():T.includes("multipart/form-data")?h=await s.formData():h=await s.text();}let y=await fetch(v.toString(),{method:s.method,headers:x,body:h}),N=y.headers.get("content-type")||"",k;N.includes("application/json")?k=await y.text():k=await y.arrayBuffer();let g=new Headers;y.headers.forEach((T,A)=>{let E=A.toLowerCase();["transfer-encoding","connection","keep-alive"].includes(E)||g.set(A,T);});let S=new server.NextResponse(k,{status:y.status,statusText:y.statusText,headers:g});return o&&(S=await o(S)),S}catch(d){return console.error("[Proxy Error]",d),server.NextResponse.json({success:false,message:"Proxy error: Unable to connect to backend",error:d instanceof Error?d.message:"Unknown error"},{status:502})}}return n.config=e,n}
2
- Object.defineProperty(exports,"createApiClient",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.d}});Object.defineProperty(exports,"CSRF_SAFE_METHODS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.f}});Object.defineProperty(exports,"DEFAULT_AUDIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.i}});Object.defineProperty(exports,"DEFAULT_COOKIE_OPTIONS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.a}});Object.defineProperty(exports,"DEFAULT_CSRF_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.g}});Object.defineProperty(exports,"DEFAULT_ENDPOINTS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.b}});Object.defineProperty(exports,"DEFAULT_RATE_LIMIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.h}});Object.defineProperty(exports,"ERROR_MESSAGES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.d}});Object.defineProperty(exports,"HEADERS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.e}});Object.defineProperty(exports,"TOKEN_TYPES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.c}});exports.createAuditLogger=q;exports.createAuthProxy=te;exports.createCsrfValidator=K;exports.createHandlers=z;exports.createProxyHandler=ne;exports.createRateLimiter=W;exports.createTokenValidation=j;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var chunkJEEL6S4O_cjs=require('./chunk-JEEL6S4O.cjs'),chunk6ENVQMWQ_cjs=require('./chunk-6ENVQMWQ.cjs'),server=require('next/server');function ue(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID()+crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2)}`}function le(e){return `rl:${e.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||e.headers.get("x-real-ip")||"unknown"}`}function ee(e){if(!e.apiBaseUrl)throw new Error("next-api-layer: apiBaseUrl is required");if(!e.cookies?.user||!e.cookies?.guest)throw new Error("next-api-layer: cookies.user and cookies.guest are required");let t=e.apiBaseUrl.endsWith("/")?e.apiBaseUrl:`${e.apiBaseUrl}/`,f={...chunk6ENVQMWQ_cjs.a,...e.cookies.options},r={...chunk6ENVQMWQ_cjs.b,...e.endpoints},p={enabled:e.csrf?.enabled??false,strategy:e.csrf?.strategy??chunk6ENVQMWQ_cjs.g.strategy,secret:e.csrf?.secret??ue(),cookieName:e.csrf?.cookieName??chunk6ENVQMWQ_cjs.g.cookieName,headerName:e.csrf?.headerName??chunk6ENVQMWQ_cjs.g.headerName,ignoreMethods:e.csrf?.ignoreMethods??chunk6ENVQMWQ_cjs.g.ignoreMethods,trustSameSite:e.csrf?.trustSameSite??chunk6ENVQMWQ_cjs.g.trustSameSite},R={enabled:e.rateLimit?.enabled??false,windowMs:e.rateLimit?.windowMs??chunk6ENVQMWQ_cjs.h.windowMs,maxRequests:e.rateLimit?.maxRequests??chunk6ENVQMWQ_cjs.h.maxRequests,keyFn:e.rateLimit?.keyFn??le,skipRoutes:e.rateLimit?.skipRoutes??chunk6ENVQMWQ_cjs.h.skipRoutes,onRateLimited:e.rateLimit?.onRateLimited},l={enabled:e.audit?.enabled??false,events:e.audit?.events??[...chunk6ENVQMWQ_cjs.i.events],logger:e.audit?.logger};return {...e,apiBaseUrl:t,_resolved:{cookieOptions:f,endpoints:r,csrf:p,rateLimit:R,audit:l}}}var j={parseAuthMe:e=>{let t=e;return !t?.success||!t?.data?null:{isValid:true,tokenType:t.data.type||"user",exp:t.data.exp||null,userData:t.data}},parseRefreshToken:e=>{let t=e;return t?.success&&t?.data?.accessToken?t.data.accessToken:null},parseGuestToken:e=>e?.data?.accessToken||null};function z(e){let{apiBaseUrl:t,_resolved:f,responseMappers:r}=e,{endpoints:p}=f,R={parseAuthMe:r?.parseAuthMe||j.parseAuthMe,parseRefreshToken:r?.parseRefreshToken||j.parseRefreshToken,parseGuestToken:r?.parseGuestToken||j.parseGuestToken};async function l(i){let u={isValid:false,tokenType:null,exp:null,userData:null};try{let n=await fetch(`${t}${p.validate}`,{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},cache:"no-store"});if(!n.ok)return u;let s=await n.json().catch(()=>null),d=R.parseAuthMe(s);return !d||!d.isValid?u:d}catch{return u}}async function c(i){return l(i)}async function m(i){try{let u=await fetch(`${t}${p.refresh}`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},cache:"no-store"});if(!u.ok)return {success:!1,newToken:null};let n=await u.json().catch(()=>null),s=R.parseRefreshToken(n);return s?{success:!0,newToken:s}:{success:!1,newToken:null}}catch{return {success:false,newToken:null}}}async function o(){let i=e.guestToken;if(!i?.enabled||!i.credentials)return null;try{let u=await fetch(`${t}${p.guest}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:i.credentials.username,password:i.credentials.password}),cache:"no-store"});if(!u.ok)return null;let n=await u.json().catch(()=>null);return R.parseGuestToken(n)}catch{return null}}return {validateToken:l,getTokenInfo:c,refreshToken:m,createGuestToken:o}}function O(e,t){if(!t?.enabled)return null;let f=t.locales??[],r=t.defaultLocale,R=e.split("/").filter(Boolean)[0];return R&&f.includes(R)?R:r??null}function K(e,t){let{cookies:f,guestToken:r,access:p,i18n:R,_resolved:l}=e,{cookieOptions:c}=l;function m(a,x,h){a.cookies.get(h)?.value&&x.cookies.delete(h);}function o(a,x){return m(a,x,f.guest),m(a,x,f.user),x}function i(a,x=500){return new server.NextResponse(JSON.stringify({success:false,message:a}),{status:x,headers:{"Content-Type":"application/json"}})}function u(a){return (p?.authRoutes??[]).some(h=>a===h||a.startsWith(`${h}/`))}function n(a){return p?.protectedByDefault?!s(a)&&!u(a):(p?.protectedRoutes??[]).some(h=>a===h||a.startsWith(`${h}/`))}function s(a){return (p?.publicRoutes??[]).some(h=>a===h||a.startsWith(`${h}/`))}function d(a){let x=p?.allowedTokenTypes;return !x||x.length===0?true:a?x.includes(a):false}async function N(a,x){let{origin:h}=a.nextUrl;if(r?.enabled){let k=await t.createGuestToken();if(k){let L;return x?L=server.NextResponse.next():n(a.nextUrl.pathname)?L=server.NextResponse.redirect(new URL("/login",h)):L=server.NextResponse.next(),L.cookies.set(f.guest,k,{...c,maxAge:3600}),L}}return x?i("Token bulunamad\u0131",401):n(a.nextUrl.pathname)?server.NextResponse.redirect(new URL("/login",h)):server.NextResponse.next()}async function E(a,x,h,k,L){let{pathname:T,origin:g}=a.nextUrl,{isValid:S,tokenType:A,userData:w}=x,v=A===chunk6ENVQMWQ_cjs.c.GUEST;if(!S){if(h&&k){let H=await t.refreshToken(k);if(H.success&&H.newToken){let F=await t.getTokenInfo(H.newToken);if(F.isValid){let _=new Headers(a.headers);F.userData&&_.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(F.userData)),_.set(chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN,H.newToken);let Q=O(T,R);Q&&_.set(chunk6ENVQMWQ_cjs.e.LOCALE,Q);let D;return u(T)?D=server.NextResponse.redirect(new URL("/",g)):D=server.NextResponse.next({request:{headers:_}}),D.cookies.set(f.user,H.newToken,{...c,maxAge:c.maxAge}),m(a,D,f.guest),D}}}let P=await N(a,L);return P.cookies.get(f.guest)?.value?m(a,P,f.user):o(a,P),P}let U=new Headers(a.headers);w&&U.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(w));let X=O(T,R);if(X&&U.set(chunk6ENVQMWQ_cjs.e.LOCALE,X),!v&&!d(A)){if(L){let Z=i("Bu i\u015Flem i\xE7in yetkiniz yok",403);return o(a,Z)}let P=server.NextResponse.redirect(new URL("/login",g));return o(a,P)}if(v)return L?server.NextResponse.next({request:{headers:U}}):n(T)?server.NextResponse.redirect(new URL("/login",g)):server.NextResponse.next({request:{headers:U}});if(u(T))return server.NextResponse.redirect(new URL("/",g));let Y=server.NextResponse.next({request:{headers:U}});return m(a,Y,f.guest),Y}return {deleteAllAuthCookies:o,jsonError:i,isAuthPage:u,isProtectedRoute:n,isPublicRoute:s,isTokenTypeAllowed:d,handleNoToken:N,handleValidationResult:E}}function W(e){async function t(l){let c=ce();return `${await de(e.secret,l,c)}.${c}`}function f(l){let c=l.method.toUpperCase();if(e.ignoreMethods.includes(c))return {valid:true};let m=e.strategy;if(m==="fetch-metadata"||m==="both"){let o=r(l);if(m==="fetch-metadata"||o.valid||o.reason!=="missing-headers")return o}return m==="double-submit"||m==="both"?p(l):{valid:true}}function r(l){let c=l.headers.get("sec-fetch-site");if(!c)return {valid:false,reason:"missing-headers"};if(c==="same-origin")return {valid:true};if(c==="none"){let m=l.method.toUpperCase();return e.ignoreMethods.includes(m)?{valid:true}:{valid:false,reason:"direct-navigation-unsafe-method"}}return c==="same-site"?e.trustSameSite?{valid:true}:{valid:false,reason:"same-site-not-trusted"}:c==="cross-site"?{valid:false,reason:"cross-site-request"}:{valid:false,reason:"unknown-sec-fetch-site"}}function p(l){let c=l.cookies.get(e.cookieName)?.value;if(!c)return {valid:false,reason:"missing-cookie-token"};let m=l.headers.get(e.headerName);return m?fe(c,m)?c.split(".").length!==2?{valid:false,reason:"invalid-token-format"}:{valid:true}:{valid:false,reason:"token-mismatch"}:{valid:false,reason:"missing-header-token"}}async function R(l,c){let m=await t(c);return l.cookies.set(e.cookieName,m,{httpOnly:false,secure:process.env.NODE_ENV==="production",sameSite:"strict",path:"/"}),l}return {validateRequest:f,generateToken:t,attachCsrfCookie:R}}function ce(){if(typeof crypto<"u"&&crypto.getRandomValues){let e=new Uint8Array(32);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}return Math.random().toString(36).substring(2)+Date.now().toString(36)}async function de(e,t,f){let r=`${t.length}!${t}!${f.length}!${f}`;if(typeof crypto<"u"&&crypto.subtle){let l=new TextEncoder,c=l.encode(e),m=l.encode(r),o=await crypto.subtle.importKey("raw",c,{name:"HMAC",hash:"SHA-256"},false,["sign"]),i=await crypto.subtle.sign("HMAC",o,m);return Array.from(new Uint8Array(i),u=>u.toString(16).padStart(2,"0")).join("")}let p=0,R=e+r;for(let l=0;l<R.length;l++){let c=R.charCodeAt(l);p=(p<<5)-p+c,p=p&p;}return Math.abs(p).toString(16)}function fe(e,t){if(e.length!==t.length)return false;let f=0;for(let r=0;r<e.length;r++)f|=e.charCodeAt(r)^t.charCodeAt(r);return f===0}function q(e){let t=new Map,f=setInterval(()=>{let i=Date.now();for(let[u,n]of t)n.resetAt<=i&&t.delete(u);},e.windowMs);typeof process<"u"&&process.on&&process.on("beforeExit",()=>clearInterval(f));function r(i){return e.skipRoutes.some(u=>u.endsWith("*")?i.startsWith(u.slice(0,-1)):u.endsWith("**")?i.startsWith(u.slice(0,-2)):i===u)}function p(i){let u=i.nextUrl.pathname;if(r(u))return {allowed:true,remaining:e.maxRequests,resetAt:0,limit:e.maxRequests};let n=e.keyFn(i),s=Date.now(),d=t.get(n);if(!d||d.resetAt<=s)return d={count:1,resetAt:s+e.windowMs},t.set(n,d),{allowed:true,remaining:e.maxRequests-1,resetAt:d.resetAt,limit:e.maxRequests};d.count++;let N=Math.max(0,e.maxRequests-d.count);return {allowed:d.count<=e.maxRequests,remaining:N,resetAt:d.resetAt,limit:e.maxRequests}}function R(i,u){return i.headers.set("X-RateLimit-Limit",u.limit.toString()),i.headers.set("X-RateLimit-Remaining",u.remaining.toString()),i.headers.set("X-RateLimit-Reset",Math.ceil(u.resetAt/1e3).toString()),i}function l(i,u){if(e.onRateLimited){let s=e.onRateLimited(i);return R(s,u)}let n=server.NextResponse.json({success:false,message:"Too many requests. Please try again later.",retryAfter:Math.ceil((u.resetAt-Date.now())/1e3)},{status:429});return n.headers.set("Retry-After",Math.ceil((u.resetAt-Date.now())/1e3).toString()),R(n,u)}function c(i){t.delete(i);}function m(){t.clear();}function o(){return t.size}return {check:p,applyHeaders:R,createLimitedResponse:l,shouldSkip:r,reset:c,clear:m,size:o}}function J(e){function t(n){return e.enabled&&e.events.includes(n)}function f(n){return n.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||n.headers.get("x-real-ip")||null}async function r(n,s,d){if(!t(n))return;let N={type:n,timestamp:new Date,ip:f(s),userId:d.userId,path:s.nextUrl.pathname,method:s.method,success:d.success,metadata:d.metadata};if(e.logger)try{await e.logger(N);}catch(E){console.error("[next-api-layer] Audit logger error:",E);}}function p(n,s,d){return r("auth:success",n,{success:true,userId:s,metadata:d})}function R(n,s){return r("auth:fail",n,{success:false,metadata:s})}function l(n,s,d){return r("auth:refresh",n,{success:true,userId:s,metadata:d})}function c(n,s){return r("auth:guest",n,{success:true,metadata:s})}function m(n,s,d){return r("access:denied",n,{success:false,userId:s,metadata:d})}function o(n,s){return r("csrf:fail",n,{success:false,metadata:s})}function i(n,s){return r("rateLimit:exceeded",n,{success:false,metadata:s})}function u(n,s,d){return r("error",n,{success:false,metadata:{...d,error:s.message,stack:s.stack}})}return {emit:r,isEnabled:t,authSuccess:p,authFail:R,authRefresh:l,authGuest:c,accessDenied:m,csrfFail:o,rateLimitExceeded:i,error:u}}function te(e,t){let f=[chunk6ENVQMWQ_cjs.e.LOCALE,chunk6ENVQMWQ_cjs.e.AUTH_USER,chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN];for(let r of f){let p=e.headers.get(r);p&&!t.headers.has(r)&&t.headers.set(r,p);}return e.cookies.getAll().forEach(r=>{t.cookies.get(r.name)||t.cookies.set(r.name,r.value);}),t}function se(e){let t=ee(e),f=z(t),r=K(t,f),p=W(t._resolved.csrf),R=q(t._resolved.rateLimit),l=J(t._resolved.audit);async function c(o){let{pathname:i,origin:u}=o.nextUrl,n=i.startsWith("/api");if(t._resolved.rateLimit.enabled){let g=R.check(o);if(!g.allowed)return await l.rateLimitExceeded(o,{limit:g.limit,resetAt:g.resetAt}),R.createLimitedResponse(o,g)}if(t._resolved.csrf.enabled){let g=p.validateRequest(o);if(!g.valid)return await l.csrfFail(o,{reason:g.reason}),server.NextResponse.json({success:false,message:"CSRF validation failed"},{status:403})}if(t.blockBrowserApiAccess&&n&&(o.headers.get("accept")||"").includes("text/html"))return server.NextResponse.redirect(new URL("/",u));if(t.beforeAuth){let g=await t.beforeAuth(o);if(g)return g}if((t.excludedPaths??[]).some(g=>i.startsWith(g)))return m(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});if(["/api/auth/login","/api/auth/logout","/api/auth/me","/api/auth/refresh","/api/auth/register"].includes(i))return m(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});let N=o.cookies?.get(t.cookies.user)?.value,E=o.cookies?.get(t.cookies.guest)?.value,a=N||E,x=!!N;if(!a){await l.authFail(o,{reason:"no-token"});let g=await r.handleNoToken(o,n);return m(o,g,{isAuthenticated:false,isGuest:false,tokenType:null,user:null})}let h=await f.getTokenInfo(a),k={isAuthenticated:h.isValid&&h.tokenType!=="guest",isGuest:h.isValid&&h.tokenType==="guest",tokenType:h.tokenType,user:h.userData};if(h.isValid)if(h.tokenType==="guest")await l.authGuest(o);else {let g=h.userData?.id?.toString();await l.authSuccess(o,g,{tokenType:h.tokenType});}else await l.authFail(o,{reason:"invalid-token"});let L=await r.handleValidationResult(o,h,x,a,n),T=await m(o,L,k);if(t._resolved.csrf.enabled&&k.isAuthenticated){let g=h.userData?.id?.toString()||a.slice(0,32);T=await p.attachCsrfCookie(T,g);}if(t._resolved.rateLimit.enabled){let g=R.check(o);T=R.applyHeaders(T,g);}return T}async function m(o,i,u){let n=i;if(t.i18n?.middleware){let s=await Promise.resolve(t.i18n.middleware(o));n=te(i,s);}if(t.i18n?.enabled){let s=O(o.nextUrl.pathname,t.i18n);s&&n.headers.set(chunk6ENVQMWQ_cjs.e.LOCALE,s);}if(t.afterAuth){let s=await t.afterAuth(o,n,u);n=te(n,s);}return n}return c.config=t,c.csrf=p,c.rateLimiter=R,c.audit=l,c}function me(e,t){if(!t||t.length===0)return false;let f=e.replace(/^\/api\//,"").replace(/^\//,"");return t.some(r=>{if(r===f)return true;if(r.includes("*")){let p=r.replace(/\*\*/g,"<<<DOUBLE>>>").replace(/\*/g,"[^/]+").replace(/<<<DOUBLE>>>/g,".+");return new RegExp(`^${p}$`).test(f)}return false})}function re(e){let{apiBaseUrl:t,userCookieName:f="auth_token",guestCookieName:r="guest_token",skipAuthByDefault:p=false,publicEndpoints:R=[],forwardHeaders:l=["content-type","accept","accept-language","x-requested-with"],excludeHeaders:c=["host","connection","cookie"],transformRequest:m,transformResponse:o}=e,i=t.replace(/\/$/,"");function u(s,d){return s.headers.get(chunk6ENVQMWQ_cjs.e.SKIP_AUTH)==="true"||me(d,R)?true:p}async function n(s){try{let d=new URL(s.url),N=d.pathname.replace(/^\/api\/?/,""),E=new URL(`${i}/${N}`);E.search=d.search;let a=new Headers;if(l.forEach(A=>{let w=s.headers.get(A);w&&a.set(A,w);}),s.headers.forEach((A,w)=>{let v=w.toLowerCase();!c.includes(v)&&!a.has(w)&&a.set(w,A);}),!u(s,N)){let A=s.cookies.get(f)?.value,w=s.cookies.get(r)?.value,v=A||w;v&&a.set(chunk6ENVQMWQ_cjs.e.AUTHORIZATION,`Bearer ${v}`);}a.delete(chunk6ENVQMWQ_cjs.e.SKIP_AUTH);let x=m?await m(s,a):a,h=null;if(s.method!=="GET"&&s.method!=="HEAD"){let A=s.headers.get("content-type")||"";A.includes("application/json")?h=await s.text():A.includes("multipart/form-data")?h=await s.formData():h=await s.text();}let k=await fetch(E.toString(),{method:s.method,headers:x,body:h}),L=k.headers.get("content-type")||"",T;L.includes("application/json")?T=await k.text():T=await k.arrayBuffer();let g=new Headers;k.headers.forEach((A,w)=>{let v=w.toLowerCase();["transfer-encoding","connection","keep-alive"].includes(v)||g.set(w,A);});let S=new server.NextResponse(T,{status:k.status,statusText:k.statusText,headers:g});return o&&(S=await o(S)),S}catch(d){return console.error("[Proxy Error]",d),server.NextResponse.json({success:false,message:"Proxy error: Unable to connect to backend",error:d instanceof Error?d.message:"Unknown error"},{status:502})}}return n.config=e,n}
2
+ Object.defineProperty(exports,"createApiClient",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.d}});Object.defineProperty(exports,"CSRF_SAFE_METHODS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.f}});Object.defineProperty(exports,"DEFAULT_AUDIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.i}});Object.defineProperty(exports,"DEFAULT_COOKIE_OPTIONS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.a}});Object.defineProperty(exports,"DEFAULT_CSRF_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.g}});Object.defineProperty(exports,"DEFAULT_ENDPOINTS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.b}});Object.defineProperty(exports,"DEFAULT_RATE_LIMIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.h}});Object.defineProperty(exports,"ERROR_MESSAGES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.d}});Object.defineProperty(exports,"HEADERS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.e}});Object.defineProperty(exports,"TOKEN_TYPES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.c}});exports.createAuditLogger=J;exports.createAuthProxy=se;exports.createCsrfValidator=W;exports.createHandlers=K;exports.createProxyHandler=re;exports.createRateLimiter=q;exports.createTokenValidation=z;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map