next-api-layer 0.1.5 → 0.1.7

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/dist/api.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkOXXKU4OM_cjs=require('./chunk-OXXKU4OM.cjs');require('./chunk-6ENVQMWQ.cjs');Object.defineProperty(exports,"createApiClient",{enumerable:true,get:function(){return chunkOXXKU4OM_cjs.d}});Object.defineProperty(exports,"createSanitizer",{enumerable:true,get:function(){return chunkOXXKU4OM_cjs.a}});Object.defineProperty(exports,"defaultSanitizer",{enumerable:true,get:function(){return chunkOXXKU4OM_cjs.b}});Object.defineProperty(exports,"sanitize",{enumerable:true,get:function(){return chunkOXXKU4OM_cjs.c}});//# sourceMappingURL=api.cjs.map
1
+ 'use strict';var chunkJEEL6S4O_cjs=require('./chunk-JEEL6S4O.cjs');require('./chunk-6ENVQMWQ.cjs');Object.defineProperty(exports,"createApiClient",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.d}});Object.defineProperty(exports,"createSanitizer",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.a}});Object.defineProperty(exports,"defaultSanitizer",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.b}});Object.defineProperty(exports,"sanitize",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.c}});//# sourceMappingURL=api.cjs.map
2
2
  //# sourceMappingURL=api.cjs.map
package/dist/api.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SanitizationConfig } from './createApiClient-CIDYcpNI.cjs';
2
- export { f as ApiClient, g as ApiClientConfig, s as RequestOptions, r as createApiClient } from './createApiClient-CIDYcpNI.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
  /**
@@ -19,20 +19,20 @@ interface SanitizeOptions {
19
19
  * Creates a sanitization function based on config
20
20
  */
21
21
  declare function createSanitizer(config?: SanitizationConfig): {
22
- sanitize: <T>(data: T) => T;
22
+ sanitize: <T>(data: T, perRequestSkipFields?: string[]) => T;
23
23
  sanitizeString: (value: string) => string;
24
24
  sanitizeValue: (value: unknown, path?: string) => unknown;
25
- sanitizeFormData: (formData: FormData) => FormData;
25
+ sanitizeFormData: (formData: FormData, perRequestSkipFields?: string[]) => FormData;
26
26
  };
27
27
  type Sanitizer = ReturnType<typeof createSanitizer>;
28
28
  /**
29
29
  * Default sanitizer with escape mode (enabled by default)
30
30
  */
31
31
  declare const defaultSanitizer: {
32
- sanitize: <T>(data: T) => T;
32
+ sanitize: <T>(data: T, perRequestSkipFields?: string[]) => T;
33
33
  sanitizeString: (value: string) => string;
34
34
  sanitizeValue: (value: unknown, path?: string) => unknown;
35
- sanitizeFormData: (formData: FormData) => FormData;
35
+ sanitizeFormData: (formData: FormData, perRequestSkipFields?: string[]) => FormData;
36
36
  };
37
37
  /**
38
38
  * Quick sanitize function with default config
package/dist/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SanitizationConfig } from './createApiClient-CIDYcpNI.js';
2
- export { f as ApiClient, g as ApiClientConfig, s as RequestOptions, r as createApiClient } from './createApiClient-CIDYcpNI.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
  /**
@@ -19,20 +19,20 @@ interface SanitizeOptions {
19
19
  * Creates a sanitization function based on config
20
20
  */
21
21
  declare function createSanitizer(config?: SanitizationConfig): {
22
- sanitize: <T>(data: T) => T;
22
+ sanitize: <T>(data: T, perRequestSkipFields?: string[]) => T;
23
23
  sanitizeString: (value: string) => string;
24
24
  sanitizeValue: (value: unknown, path?: string) => unknown;
25
- sanitizeFormData: (formData: FormData) => FormData;
25
+ sanitizeFormData: (formData: FormData, perRequestSkipFields?: string[]) => FormData;
26
26
  };
27
27
  type Sanitizer = ReturnType<typeof createSanitizer>;
28
28
  /**
29
29
  * Default sanitizer with escape mode (enabled by default)
30
30
  */
31
31
  declare const defaultSanitizer: {
32
- sanitize: <T>(data: T) => T;
32
+ sanitize: <T>(data: T, perRequestSkipFields?: string[]) => T;
33
33
  sanitizeString: (value: string) => string;
34
34
  sanitizeValue: (value: unknown, path?: string) => unknown;
35
- sanitizeFormData: (formData: FormData) => FormData;
35
+ sanitizeFormData: (formData: FormData, perRequestSkipFields?: string[]) => FormData;
36
36
  };
37
37
  /**
38
38
  * Quick sanitize function with default config
package/dist/api.js CHANGED
@@ -1,2 +1,2 @@
1
- export{d as createApiClient,a as createSanitizer,b as defaultSanitizer,c as sanitize}from'./chunk-NBYI46RO.js';import'./chunk-XBAO7FJN.js';//# sourceMappingURL=api.js.map
1
+ export{d as createApiClient,a as createSanitizer,b as defaultSanitizer,c as sanitize}from'./chunk-NDZA32WH.js';import'./chunk-XBAO7FJN.js';//# sourceMappingURL=api.js.map
2
2
  //# sourceMappingURL=api.js.map
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunk6ENVQMWQ_cjs=require('./chunk-6ENVQMWQ.cjs'),headers=require('next/headers');var j={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"},H=/[&<>"'`=/]/g,P=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,b=/\s*on\w+\s*=\s*["'][^"']*["']/gi,x=/javascript\s*:/gi,D=/data\s*:[^;]*;base64/gi;function O(a){return a.replace(H,c=>j[c]||c)}function M(a){return a.replace(P,"").replace(/<[^>]*>/g,"").replace(b,"").replace(x,"").replace(D,"")}function q(a,c){let g=a.replace(P,"").replace(b,"").replace(x,"").replace(D,"");if(c.length===0)return O(g);let l=c.join("|"),f=new RegExp(`<(?!/?(?:${l})\\b)[^>]*>`,"gi");return g=g.replace(f,""),g}function T(a){let c=a?.mode??"escape",g=a?.allowedTags??[],l=a?.enabled!==false,f=a?.skipFields??[];function u(n){if(!l)return n;switch(c){case "strip":return M(n);case "allowList":return q(n,g);default:return O(n)}}function m(n,s=""){if(f.some(o=>s.endsWith(o))||n==null)return n;if(typeof n=="string")return u(n);if(typeof n=="number"||typeof n=="boolean")return n;if(Array.isArray(n))return n.map((o,t)=>m(o,`${s}[${t}]`));if(typeof n=="object"){let o={};for(let[t,e]of Object.entries(n)){let i=s?`${s}.${t}`:t;o[t]=m(e,i);}return o}return n}function k(n,s){if(!l)return n;let o=s?[...f,...s]:f;return R(n,"",o)}function R(n,s,o){if(o.some(t=>s.endsWith(t)||s===t)||n==null)return n;if(typeof n=="string")return u(n);if(typeof n=="number"||typeof n=="boolean")return n;if(Array.isArray(n))return n.map((t,e)=>R(t,`${s}[${e}]`,o));if(typeof n=="object"){let t={};for(let[e,i]of Object.entries(n)){let r=s?`${s}.${e}`:e;t[e]=R(i,r,o);}return t}return n}function z(n,s){if(!l)return n;let o=s?[...f,...s]:f,t=new FormData;for(let[e,i]of n.entries()){let r=o.some(p=>e===p||e.endsWith(p));i instanceof File?t.append(e,i):typeof i=="string"?t.append(e,r?i:u(i)):t.append(e,i);}return t}return {sanitize:k,sanitizeString:u,sanitizeValue:m,sanitizeFormData:z}}var L=T({enabled:true,mode:"escape",skipFields:[]});function I(a){return L.sanitize(a)}function W(a){let{apiBaseUrl:c,cookies:g,methodSpoofing:l=false,errorMessages:f={},i18n:u}=a,m=c.endsWith("/")?c:`${c}/`,k=T(a.sanitization),R=f.noToken??"Token bulunamad\u0131. L\xFCtfen giri\u015F yap\u0131n.",z=f.connectionError??"Ba\u011Flant\u0131 hatas\u0131 olu\u015Ftu.";async function n(){let i=(await headers.headers()).get(chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN);if(i)return i;let r=await headers.cookies();return r.get(g.user)?.value||r.get(g.guest)?.value||null}function s(e,i=500){return Response.json({success:false,message:e},{status:i})}function o(){return s(R,401)}async function t(e,i,r,p={}){let y=p.skipAuth?null:await n();if(!p.skipAuth&&!y)return o();try{let S={};y&&(S.Authorization=`Bearer ${y}`);let d,E=e;r&&(p.isFormData&&r instanceof FormData?(p.skipSanitize?d=r:d=k.sanitizeFormData(r,p.skipSanitizeFields),(p.methodSpoofing??l)&&(e==="PUT"||e==="PATCH")&&(d.append("_method",e),E="POST")):r instanceof FormData||(S["Content-Type"]="application/json",p.skipSanitize?d=JSON.stringify(r):d=JSON.stringify(k.sanitize(r,p.skipSanitizeFields))));let h=`${m}${i}`;if(u?.enabled){let A=(await headers.headers()).get(chunk6ENVQMWQ_cjs.e.LOCALE);if(A&&(!u.locales||u.locales.includes(A))){let F=new URL(h);F.searchParams.set(u.paramName||"lang",A),h=F.toString();}}let C=await fetch(h,{method:E,headers:S,body:d,cache:"no-store"}),$=await C.json();return Response.json($,{status:C.status})}catch(S){return console.error(`API ${e} Error:`,S),s(z)}}return {get:e=>t("GET",e),post:(e,i,r)=>t("POST",e,i,r),put:(e,i,r)=>t("PUT",e,i,r),patch:(e,i,r)=>t("PATCH",e,i,r),delete:e=>t("DELETE",e)}}exports.a=T;exports.b=L;exports.c=I;exports.d=W;//# sourceMappingURL=chunk-JEEL6S4O.cjs.map
2
+ //# sourceMappingURL=chunk-JEEL6S4O.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/sanitize.ts","../src/api/createApiClient.ts"],"names":["HTML_ENTITIES","HTML_ENTITY_REGEX","SCRIPT_PATTERN","EVENT_HANDLER_PATTERN","JAVASCRIPT_URL_PATTERN","DATA_URL_PATTERN","escapeHtml","str","char","stripHtml","sanitizeWithAllowList","allowedTags","result","allowedPattern","allowedRegex","createSanitizer","config","mode","enabled","skipFields","sanitizeString","value","sanitizeValue","path","field","item","index","sanitized","key","val","newPath","sanitize","data","perRequestSkipFields","allSkipFields","sanitizeValueWithSkip","fieldsToSkip","sanitizeFormData","formData","shouldSkip","defaultSanitizer","createApiClient","apiBaseUrl","cookieNames","globalMethodSpoofing","errorMessages","i18n","baseUrl","sanitizer","noTokenMessage","connectionErrorMessage","getToken","refreshedToken","headers","HEADERS","cookieStore","cookies","errorResponse","message","status","noTokenResponse","makeRequest","method","endpoint","body","options","token","fetchHeaders","fetchBody","actualMethod","url","locale","urlObj","res","error"],"mappings":"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","file":"chunk-JEEL6S4O.cjs","sourcesContent":["/**\r\n * XSS Sanitization utilities\r\n * Zero-dependency, lightweight sanitizer for API responses\r\n * \r\n * Modes:\r\n * - 'escape' (default): Escapes HTML entities (&lt;script&gt;)\r\n * - 'strip': Removes all HTML tags completely\r\n * - 'allowList': Only allows specified tags (advanced)\r\n */\r\n\r\nimport type { SanitizationConfig } from '../shared/types';\r\n\r\nexport interface SanitizeOptions {\r\n config: SanitizationConfig;\r\n}\r\n\r\n// HTML entities to escape\r\nconst HTML_ENTITIES: Record<string, string> = {\r\n '&': '&amp;',\r\n '<': '&lt;',\r\n '>': '&gt;',\r\n '\"': '&quot;',\r\n \"'\": '&#x27;',\r\n '/': '&#x2F;',\r\n '`': '&#x60;',\r\n '=': '&#x3D;',\r\n};\r\n\r\n// Regex patterns\r\nconst HTML_ENTITY_REGEX = /[&<>\"'`=/]/g;\r\nconst SCRIPT_PATTERN = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi;\r\nconst EVENT_HANDLER_PATTERN = /\\s*on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi;\r\nconst JAVASCRIPT_URL_PATTERN = /javascript\\s*:/gi;\r\nconst DATA_URL_PATTERN = /data\\s*:[^;]*;base64/gi;\r\n\r\n/**\r\n * Escapes HTML entities in a string\r\n */\r\nfunction escapeHtml(str: string): string {\r\n return str.replace(HTML_ENTITY_REGEX, (char) => HTML_ENTITIES[char] || char);\r\n}\r\n\r\n/**\r\n * Strips all HTML tags from a string\r\n */\r\nfunction stripHtml(str: string): string {\r\n return str\r\n .replace(SCRIPT_PATTERN, '') // Remove script tags first\r\n .replace(/<[^>]*>/g, '') // Remove all HTML tags\r\n .replace(EVENT_HANDLER_PATTERN, '') // Remove any remaining event handlers\r\n .replace(JAVASCRIPT_URL_PATTERN, '') // Remove javascript: URLs\r\n .replace(DATA_URL_PATTERN, ''); // Remove suspicious data URLs\r\n}\r\n\r\n/**\r\n * Sanitizes HTML while allowing specific tags\r\n */\r\nfunction sanitizeWithAllowList(str: string, allowedTags: string[]): string {\r\n // First, remove dangerous content\r\n let result = str\r\n .replace(SCRIPT_PATTERN, '')\r\n .replace(EVENT_HANDLER_PATTERN, '')\r\n .replace(JAVASCRIPT_URL_PATTERN, '')\r\n .replace(DATA_URL_PATTERN, '');\r\n \r\n // Build regex for allowed tags\r\n if (allowedTags.length === 0) {\r\n return escapeHtml(result);\r\n }\r\n \r\n const allowedPattern = allowedTags.join('|');\r\n const allowedRegex = new RegExp(`<(?!\\/?(?:${allowedPattern})\\\\b)[^>]*>`, 'gi');\r\n \r\n // Remove non-allowed tags\r\n result = result.replace(allowedRegex, '');\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Creates a sanitization function based on config\r\n */\r\nexport function createSanitizer(config?: SanitizationConfig) {\r\n const mode = config?.mode ?? 'escape';\r\n const allowedTags = config?.allowedTags ?? [];\r\n const enabled = config?.enabled !== false; // default: true\r\n const skipFields = config?.skipFields ?? [];\r\n\r\n /**\r\n * Sanitizes a single string value\r\n */\r\n function sanitizeString(value: string): string {\r\n if (!enabled) return value;\r\n \r\n switch (mode) {\r\n case 'strip':\r\n return stripHtml(value);\r\n case 'allowList':\r\n return sanitizeWithAllowList(value, allowedTags);\r\n case 'escape':\r\n default:\r\n return escapeHtml(value);\r\n }\r\n }\r\n\r\n /**\r\n * Recursively sanitizes an object, array, or primitive value\r\n */\r\n function sanitizeValue(value: unknown, path: string = ''): unknown {\r\n // Skip fields in skipFields list\r\n if (skipFields.some(field => path.endsWith(field))) {\r\n return value;\r\n }\r\n\r\n // Null/undefined pass through\r\n if (value === null || value === undefined) {\r\n return value;\r\n }\r\n\r\n // Strings get sanitized\r\n if (typeof value === 'string') {\r\n return sanitizeString(value);\r\n }\r\n\r\n // Numbers, booleans pass through\r\n if (typeof value === 'number' || typeof value === 'boolean') {\r\n return value;\r\n }\r\n\r\n // Arrays - sanitize each element\r\n if (Array.isArray(value)) {\r\n return value.map((item, index) => sanitizeValue(item, `${path}[${index}]`));\r\n }\r\n\r\n // Objects - sanitize each property\r\n if (typeof value === 'object') {\r\n const sanitized: Record<string, unknown> = {};\r\n for (const [key, val] of Object.entries(value)) {\r\n const newPath = path ? `${path}.${key}` : key;\r\n sanitized[key] = sanitizeValue(val, newPath);\r\n }\r\n return sanitized;\r\n }\r\n\r\n // Everything else passes through\r\n return value;\r\n }\r\n\r\n /**\r\n * Main sanitize function\r\n * @param data - Data to sanitize\r\n * @param perRequestSkipFields - Additional fields to skip for this request only\r\n */\r\n function sanitize<T>(data: T, perRequestSkipFields?: string[]): T {\r\n if (!enabled) {\r\n return data;\r\n }\r\n const allSkipFields = perRequestSkipFields \r\n ? [...skipFields, ...perRequestSkipFields]\r\n : skipFields;\r\n return sanitizeValueWithSkip(data, '', allSkipFields) as T;\r\n }\r\n\r\n /**\r\n * Sanitize with custom skip fields\r\n */\r\n function sanitizeValueWithSkip(value: unknown, path: string, fieldsToSkip: string[]): unknown {\r\n // Skip fields in skip list\r\n if (fieldsToSkip.some(field => path.endsWith(field) || path === field)) {\r\n return value;\r\n }\r\n\r\n // Null/undefined pass through\r\n if (value === null || value === undefined) {\r\n return value;\r\n }\r\n\r\n // Strings get sanitized\r\n if (typeof value === 'string') {\r\n return sanitizeString(value);\r\n }\r\n\r\n // Numbers, booleans pass through\r\n if (typeof value === 'number' || typeof value === 'boolean') {\r\n return value;\r\n }\r\n\r\n // Arrays - sanitize each element\r\n if (Array.isArray(value)) {\r\n return value.map((item, index) => sanitizeValueWithSkip(item, `${path}[${index}]`, fieldsToSkip));\r\n }\r\n\r\n // Objects - sanitize each property\r\n if (typeof value === 'object') {\r\n const sanitized: Record<string, unknown> = {};\r\n for (const [key, val] of Object.entries(value)) {\r\n const newPath = path ? `${path}.${key}` : key;\r\n sanitized[key] = sanitizeValueWithSkip(val, newPath, fieldsToSkip);\r\n }\r\n return sanitized;\r\n }\r\n\r\n // Everything else passes through\r\n return value;\r\n }\r\n\r\n /**\r\n * Sanitize FormData values (returns new FormData with sanitized values)\r\n * @param formData - FormData to sanitize\r\n * @param perRequestSkipFields - Additional fields to skip for this request only\r\n */\r\n function sanitizeFormData(formData: FormData, perRequestSkipFields?: string[]): FormData {\r\n if (!enabled) {\r\n return formData;\r\n }\r\n \r\n const allSkipFields = perRequestSkipFields \r\n ? [...skipFields, ...perRequestSkipFields]\r\n : skipFields;\r\n \r\n const sanitized = new FormData();\r\n \r\n for (const [key, value] of formData.entries()) {\r\n // Check if this field should be skipped\r\n const shouldSkip = allSkipFields.some(field => key === field || key.endsWith(field));\r\n \r\n if (value instanceof File) {\r\n // Files pass through unchanged\r\n sanitized.append(key, value);\r\n } else if (typeof value === 'string') {\r\n // Strings get sanitized (unless skipped)\r\n sanitized.append(key, shouldSkip ? value : sanitizeString(value));\r\n } else {\r\n // Everything else passes through\r\n sanitized.append(key, value);\r\n }\r\n }\r\n \r\n return sanitized;\r\n }\r\n\r\n return {\r\n sanitize,\r\n sanitizeString,\r\n sanitizeValue,\r\n sanitizeFormData,\r\n };\r\n}\r\n\r\nexport type Sanitizer = ReturnType<typeof createSanitizer>;\r\n\r\n/**\r\n * Default sanitizer with escape mode (enabled by default)\r\n */\r\nexport const defaultSanitizer = createSanitizer({\r\n enabled: true,\r\n mode: 'escape',\r\n skipFields: [],\r\n});\r\n\r\n/**\r\n * Quick sanitize function with default config\r\n */\r\nexport function sanitize<T>(data: T): T {\r\n return defaultSanitizer.sanitize(data);\r\n}\r\n\r\n/**\r\n * Quick escape function for single strings\r\n */\r\nexport function escapeString(str: string): string {\r\n return escapeHtml(str);\r\n}\r\n\r\n/**\r\n * Quick strip function for single strings\r\n */\r\nexport function stripString(str: string): string {\r\n return stripHtml(str);\r\n}\r\n","/**\r\n * createApiClient\r\n * Server-side API client for Route Handlers\r\n * \r\n * Makes requests directly to backend with auth token from cookies/headers.\r\n * Returns Response objects that can be directly returned from route handlers.\r\n */\r\n\r\nimport { cookies, headers } from 'next/headers';\r\nimport { createSanitizer } from './sanitize';\r\nimport type { SanitizationConfig, I18nConfig } from '../shared/types';\r\nimport { HEADERS } from '../shared/constants';\r\n\r\n// ==================== Types ====================\r\n\r\nexport interface ApiClientConfig {\r\n /** Backend API base URL */\r\n apiBaseUrl: string;\r\n \r\n /** Cookie names for token retrieval */\r\n cookies: {\r\n user: string;\r\n guest: string;\r\n };\r\n \r\n /** Sanitization options */\r\n sanitization?: SanitizationConfig;\r\n \r\n /** Enable Laravel method spoofing for PUT/PATCH */\r\n methodSpoofing?: boolean;\r\n \r\n /** Custom error messages */\r\n errorMessages?: {\r\n noToken?: string;\r\n connectionError?: string;\r\n };\r\n \r\n /** i18n configuration - auto-append locale to API requests */\r\n i18n?: I18nConfig & {\r\n /** Query parameter name (default: 'lang') */\r\n paramName?: string;\r\n };\r\n}\r\n\r\nexport interface RequestOptions {\r\n /** Form data mode (use FormData, skip Content-Type header) */\r\n isFormData?: boolean;\r\n /** Use method spoofing for this request */\r\n methodSpoofing?: boolean;\r\n /** Skip authentication for this request */\r\n skipAuth?: boolean;\r\n /** Skip all sanitization for this request */\r\n skipSanitize?: boolean;\r\n /** Skip sanitization for specific fields only */\r\n skipSanitizeFields?: string[];\r\n}\r\n\r\nexport interface ApiClient {\r\n get: (endpoint: string) => Promise<Response>;\r\n post: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;\r\n put: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;\r\n patch: (endpoint: string, body?: Record<string, unknown>, options?: RequestOptions) => Promise<Response>;\r\n delete: (endpoint: string) => Promise<Response>;\r\n}\r\n\r\n// ==================== Factory ====================\r\n\r\n/**\r\n * Creates a server-side API client for Next.js Route Handlers\r\n * \r\n * @example\r\n * ```ts\r\n * // lib/api.ts\r\n * import { createApiClient } from 'next-api-layer';\r\n * \r\n * export const api = createApiClient({\r\n * apiBaseUrl: process.env.API_BASE_URL!,\r\n * cookies: {\r\n * user: process.env.COOKIE_USER_AUTH_TOKEN_NAME!,\r\n * guest: process.env.COOKIE_PUBLIC_AUTH_TOKEN_NAME!,\r\n * },\r\n * });\r\n * \r\n * // Usage in route handler - direct return!\r\n * export async function GET() {\r\n * return api.get('superadmin/home/list');\r\n * }\r\n * \r\n * export async function POST(request: Request) {\r\n * const body = await request.json();\r\n * return api.post('donations/create', body);\r\n * }\r\n * ```\r\n */\r\nexport function createApiClient(config: ApiClientConfig): ApiClient {\r\n const {\r\n apiBaseUrl,\r\n cookies: cookieNames,\r\n methodSpoofing: globalMethodSpoofing = false,\r\n errorMessages = {},\r\n i18n,\r\n } = config;\r\n \r\n // Ensure baseUrl ends with /\r\n const baseUrl = apiBaseUrl.endsWith('/') ? apiBaseUrl : `${apiBaseUrl}/`;\r\n \r\n // Create sanitizer\r\n const sanitizer = createSanitizer(config.sanitization);\r\n \r\n // Error messages\r\n const noTokenMessage = errorMessages.noToken ?? 'Token bulunamadı. Lütfen giriş yapın.';\r\n const connectionErrorMessage = errorMessages.connectionError ?? 'Bağlantı hatası oluştu.';\r\n\r\n /**\r\n * Get auth token from headers (refreshed) or cookies\r\n */\r\n async function getToken(): Promise<string | null> {\r\n // Check for refreshed token from proxy\r\n const headersList = await headers();\r\n const refreshedToken = headersList.get(HEADERS.REFRESHED_TOKEN);\r\n if (refreshedToken) {\r\n return refreshedToken;\r\n }\r\n \r\n // Get from cookies\r\n const cookieStore = await cookies();\r\n return (\r\n cookieStore.get(cookieNames.user)?.value ||\r\n cookieStore.get(cookieNames.guest)?.value ||\r\n null\r\n );\r\n }\r\n\r\n /**\r\n * Create error response\r\n */\r\n function errorResponse(message: string, status = 500): Response {\r\n return Response.json(\r\n { success: false, message },\r\n { status }\r\n );\r\n }\r\n\r\n /**\r\n * Create no-token response\r\n */\r\n function noTokenResponse(): Response {\r\n return errorResponse(noTokenMessage, 401);\r\n }\r\n\r\n /**\r\n * Make a fetch request to backend\r\n */\r\n async function makeRequest(\r\n method: string,\r\n endpoint: string,\r\n body?: Record<string, unknown> | FormData | null,\r\n options: RequestOptions = {}\r\n ): Promise<Response> {\r\n // Skip auth check if requested\r\n const token = options.skipAuth ? null : await getToken();\r\n \r\n if (!options.skipAuth && !token) {\r\n return noTokenResponse();\r\n }\r\n\r\n try {\r\n const fetchHeaders: HeadersInit = {};\r\n \r\n // Add auth header if we have a token\r\n if (token) {\r\n fetchHeaders['Authorization'] = `Bearer ${token}`;\r\n }\r\n\r\n let fetchBody: string | FormData | undefined;\r\n let actualMethod = method;\r\n\r\n // Handle body\r\n if (body) {\r\n if (options.isFormData && body instanceof FormData) {\r\n // FormData - sanitize (unless skipped) and optionally add method spoofing\r\n if (options.skipSanitize) {\r\n fetchBody = body;\r\n } else {\r\n fetchBody = sanitizer.sanitizeFormData(body, options.skipSanitizeFields);\r\n }\r\n \r\n const useMethodSpoofing = options.methodSpoofing ?? globalMethodSpoofing;\r\n if (useMethodSpoofing && (method === 'PUT' || method === 'PATCH')) {\r\n (fetchBody as FormData).append('_method', method);\r\n actualMethod = 'POST';\r\n }\r\n } else if (!(body instanceof FormData)) {\r\n // JSON body\r\n fetchHeaders['Content-Type'] = 'application/json';\r\n if (options.skipSanitize) {\r\n fetchBody = JSON.stringify(body);\r\n } else {\r\n fetchBody = JSON.stringify(sanitizer.sanitize(body, options.skipSanitizeFields));\r\n }\r\n }\r\n }\r\n\r\n // Build URL with optional locale parameter\r\n let url = `${baseUrl}${endpoint}`;\r\n if (i18n?.enabled) {\r\n const headersList = await headers();\r\n const locale = headersList.get(HEADERS.LOCALE);\r\n if (locale && (!i18n.locales || i18n.locales.includes(locale))) {\r\n const urlObj = new URL(url);\r\n urlObj.searchParams.set(i18n.paramName || 'lang', locale);\r\n url = urlObj.toString();\r\n }\r\n }\r\n\r\n const res = await fetch(url, {\r\n method: actualMethod,\r\n headers: fetchHeaders,\r\n body: fetchBody,\r\n cache: 'no-store',\r\n });\r\n\r\n // Clone response data (stream can only be read once)\r\n const data = await res.json();\r\n return Response.json(data, { status: res.status });\r\n } catch (error) {\r\n console.error(`API ${method} Error:`, error);\r\n return errorResponse(connectionErrorMessage);\r\n }\r\n }\r\n\r\n // Return API client interface\r\n return {\r\n get: (endpoint: string) => makeRequest('GET', endpoint),\r\n \r\n post: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) =>\r\n makeRequest('POST', endpoint, body, options),\r\n \r\n put: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) =>\r\n makeRequest('PUT', endpoint, body, options),\r\n \r\n patch: (endpoint: string, body?: Record<string, unknown>, options?: RequestOptions) =>\r\n makeRequest('PATCH', endpoint, body, options),\r\n \r\n delete: (endpoint: string) => makeRequest('DELETE', endpoint),\r\n };\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ import {e}from'./chunk-XBAO7FJN.js';import {headers,cookies}from'next/headers';var j={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"},H=/[&<>"'`=/]/g,P=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,b=/\s*on\w+\s*=\s*["'][^"']*["']/gi,x=/javascript\s*:/gi,D=/data\s*:[^;]*;base64/gi;function O(a){return a.replace(H,c=>j[c]||c)}function M(a){return a.replace(P,"").replace(/<[^>]*>/g,"").replace(b,"").replace(x,"").replace(D,"")}function q(a,c){let g=a.replace(P,"").replace(b,"").replace(x,"").replace(D,"");if(c.length===0)return O(g);let l=c.join("|"),f=new RegExp(`<(?!/?(?:${l})\\b)[^>]*>`,"gi");return g=g.replace(f,""),g}function T(a){let c=a?.mode??"escape",g=a?.allowedTags??[],l=a?.enabled!==false,f=a?.skipFields??[];function u(n){if(!l)return n;switch(c){case "strip":return M(n);case "allowList":return q(n,g);default:return O(n)}}function m(n,s=""){if(f.some(o=>s.endsWith(o))||n==null)return n;if(typeof n=="string")return u(n);if(typeof n=="number"||typeof n=="boolean")return n;if(Array.isArray(n))return n.map((o,t)=>m(o,`${s}[${t}]`));if(typeof n=="object"){let o={};for(let[t,e]of Object.entries(n)){let i=s?`${s}.${t}`:t;o[t]=m(e,i);}return o}return n}function k(n,s){if(!l)return n;let o=s?[...f,...s]:f;return R(n,"",o)}function R(n,s,o){if(o.some(t=>s.endsWith(t)||s===t)||n==null)return n;if(typeof n=="string")return u(n);if(typeof n=="number"||typeof n=="boolean")return n;if(Array.isArray(n))return n.map((t,e)=>R(t,`${s}[${e}]`,o));if(typeof n=="object"){let t={};for(let[e,i]of Object.entries(n)){let r=s?`${s}.${e}`:e;t[e]=R(i,r,o);}return t}return n}function z(n,s){if(!l)return n;let o=s?[...f,...s]:f,t=new FormData;for(let[e,i]of n.entries()){let r=o.some(p=>e===p||e.endsWith(p));i instanceof File?t.append(e,i):typeof i=="string"?t.append(e,r?i:u(i)):t.append(e,i);}return t}return {sanitize:k,sanitizeString:u,sanitizeValue:m,sanitizeFormData:z}}var L=T({enabled:true,mode:"escape",skipFields:[]});function I(a){return L.sanitize(a)}function W(a){let{apiBaseUrl:c,cookies:g,methodSpoofing:l=false,errorMessages:f={},i18n:u}=a,m=c.endsWith("/")?c:`${c}/`,k=T(a.sanitization),R=f.noToken??"Token bulunamad\u0131. L\xFCtfen giri\u015F yap\u0131n.",z=f.connectionError??"Ba\u011Flant\u0131 hatas\u0131 olu\u015Ftu.";async function n(){let i=(await headers()).get(e.REFRESHED_TOKEN);if(i)return i;let r=await cookies();return r.get(g.user)?.value||r.get(g.guest)?.value||null}function s(e,i=500){return Response.json({success:false,message:e},{status:i})}function o(){return s(R,401)}async function t(e$1,i,r,p={}){let y=p.skipAuth?null:await n();if(!p.skipAuth&&!y)return o();try{let S={};y&&(S.Authorization=`Bearer ${y}`);let d,E=e$1;r&&(p.isFormData&&r instanceof FormData?(p.skipSanitize?d=r:d=k.sanitizeFormData(r,p.skipSanitizeFields),(p.methodSpoofing??l)&&(e$1==="PUT"||e$1==="PATCH")&&(d.append("_method",e$1),E="POST")):r instanceof FormData||(S["Content-Type"]="application/json",p.skipSanitize?d=JSON.stringify(r):d=JSON.stringify(k.sanitize(r,p.skipSanitizeFields))));let h=`${m}${i}`;if(u?.enabled){let A=(await headers()).get(e.LOCALE);if(A&&(!u.locales||u.locales.includes(A))){let F=new URL(h);F.searchParams.set(u.paramName||"lang",A),h=F.toString();}}let C=await fetch(h,{method:E,headers:S,body:d,cache:"no-store"}),$=await C.json();return Response.json($,{status:C.status})}catch(S){return console.error(`API ${e$1} Error:`,S),s(z)}}return {get:e=>t("GET",e),post:(e,i,r)=>t("POST",e,i,r),put:(e,i,r)=>t("PUT",e,i,r),patch:(e,i,r)=>t("PATCH",e,i,r),delete:e=>t("DELETE",e)}}export{T as a,L as b,I as c,W as d};//# sourceMappingURL=chunk-NDZA32WH.js.map
2
+ //# sourceMappingURL=chunk-NDZA32WH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/sanitize.ts","../src/api/createApiClient.ts"],"names":["HTML_ENTITIES","HTML_ENTITY_REGEX","SCRIPT_PATTERN","EVENT_HANDLER_PATTERN","JAVASCRIPT_URL_PATTERN","DATA_URL_PATTERN","escapeHtml","str","char","stripHtml","sanitizeWithAllowList","allowedTags","result","allowedPattern","allowedRegex","createSanitizer","config","mode","enabled","skipFields","sanitizeString","value","sanitizeValue","path","field","item","index","sanitized","key","val","newPath","sanitize","data","perRequestSkipFields","allSkipFields","sanitizeValueWithSkip","fieldsToSkip","sanitizeFormData","formData","shouldSkip","defaultSanitizer","createApiClient","apiBaseUrl","cookieNames","globalMethodSpoofing","errorMessages","i18n","baseUrl","sanitizer","noTokenMessage","connectionErrorMessage","getToken","refreshedToken","headers","HEADERS","cookieStore","cookies","errorResponse","message","status","noTokenResponse","makeRequest","method","endpoint","body","options","token","fetchHeaders","fetchBody","actualMethod","url","locale","urlObj","res","error"],"mappings":"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","file":"chunk-NDZA32WH.js","sourcesContent":["/**\r\n * XSS Sanitization utilities\r\n * Zero-dependency, lightweight sanitizer for API responses\r\n * \r\n * Modes:\r\n * - 'escape' (default): Escapes HTML entities (&lt;script&gt;)\r\n * - 'strip': Removes all HTML tags completely\r\n * - 'allowList': Only allows specified tags (advanced)\r\n */\r\n\r\nimport type { SanitizationConfig } from '../shared/types';\r\n\r\nexport interface SanitizeOptions {\r\n config: SanitizationConfig;\r\n}\r\n\r\n// HTML entities to escape\r\nconst HTML_ENTITIES: Record<string, string> = {\r\n '&': '&amp;',\r\n '<': '&lt;',\r\n '>': '&gt;',\r\n '\"': '&quot;',\r\n \"'\": '&#x27;',\r\n '/': '&#x2F;',\r\n '`': '&#x60;',\r\n '=': '&#x3D;',\r\n};\r\n\r\n// Regex patterns\r\nconst HTML_ENTITY_REGEX = /[&<>\"'`=/]/g;\r\nconst SCRIPT_PATTERN = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi;\r\nconst EVENT_HANDLER_PATTERN = /\\s*on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi;\r\nconst JAVASCRIPT_URL_PATTERN = /javascript\\s*:/gi;\r\nconst DATA_URL_PATTERN = /data\\s*:[^;]*;base64/gi;\r\n\r\n/**\r\n * Escapes HTML entities in a string\r\n */\r\nfunction escapeHtml(str: string): string {\r\n return str.replace(HTML_ENTITY_REGEX, (char) => HTML_ENTITIES[char] || char);\r\n}\r\n\r\n/**\r\n * Strips all HTML tags from a string\r\n */\r\nfunction stripHtml(str: string): string {\r\n return str\r\n .replace(SCRIPT_PATTERN, '') // Remove script tags first\r\n .replace(/<[^>]*>/g, '') // Remove all HTML tags\r\n .replace(EVENT_HANDLER_PATTERN, '') // Remove any remaining event handlers\r\n .replace(JAVASCRIPT_URL_PATTERN, '') // Remove javascript: URLs\r\n .replace(DATA_URL_PATTERN, ''); // Remove suspicious data URLs\r\n}\r\n\r\n/**\r\n * Sanitizes HTML while allowing specific tags\r\n */\r\nfunction sanitizeWithAllowList(str: string, allowedTags: string[]): string {\r\n // First, remove dangerous content\r\n let result = str\r\n .replace(SCRIPT_PATTERN, '')\r\n .replace(EVENT_HANDLER_PATTERN, '')\r\n .replace(JAVASCRIPT_URL_PATTERN, '')\r\n .replace(DATA_URL_PATTERN, '');\r\n \r\n // Build regex for allowed tags\r\n if (allowedTags.length === 0) {\r\n return escapeHtml(result);\r\n }\r\n \r\n const allowedPattern = allowedTags.join('|');\r\n const allowedRegex = new RegExp(`<(?!\\/?(?:${allowedPattern})\\\\b)[^>]*>`, 'gi');\r\n \r\n // Remove non-allowed tags\r\n result = result.replace(allowedRegex, '');\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Creates a sanitization function based on config\r\n */\r\nexport function createSanitizer(config?: SanitizationConfig) {\r\n const mode = config?.mode ?? 'escape';\r\n const allowedTags = config?.allowedTags ?? [];\r\n const enabled = config?.enabled !== false; // default: true\r\n const skipFields = config?.skipFields ?? [];\r\n\r\n /**\r\n * Sanitizes a single string value\r\n */\r\n function sanitizeString(value: string): string {\r\n if (!enabled) return value;\r\n \r\n switch (mode) {\r\n case 'strip':\r\n return stripHtml(value);\r\n case 'allowList':\r\n return sanitizeWithAllowList(value, allowedTags);\r\n case 'escape':\r\n default:\r\n return escapeHtml(value);\r\n }\r\n }\r\n\r\n /**\r\n * Recursively sanitizes an object, array, or primitive value\r\n */\r\n function sanitizeValue(value: unknown, path: string = ''): unknown {\r\n // Skip fields in skipFields list\r\n if (skipFields.some(field => path.endsWith(field))) {\r\n return value;\r\n }\r\n\r\n // Null/undefined pass through\r\n if (value === null || value === undefined) {\r\n return value;\r\n }\r\n\r\n // Strings get sanitized\r\n if (typeof value === 'string') {\r\n return sanitizeString(value);\r\n }\r\n\r\n // Numbers, booleans pass through\r\n if (typeof value === 'number' || typeof value === 'boolean') {\r\n return value;\r\n }\r\n\r\n // Arrays - sanitize each element\r\n if (Array.isArray(value)) {\r\n return value.map((item, index) => sanitizeValue(item, `${path}[${index}]`));\r\n }\r\n\r\n // Objects - sanitize each property\r\n if (typeof value === 'object') {\r\n const sanitized: Record<string, unknown> = {};\r\n for (const [key, val] of Object.entries(value)) {\r\n const newPath = path ? `${path}.${key}` : key;\r\n sanitized[key] = sanitizeValue(val, newPath);\r\n }\r\n return sanitized;\r\n }\r\n\r\n // Everything else passes through\r\n return value;\r\n }\r\n\r\n /**\r\n * Main sanitize function\r\n * @param data - Data to sanitize\r\n * @param perRequestSkipFields - Additional fields to skip for this request only\r\n */\r\n function sanitize<T>(data: T, perRequestSkipFields?: string[]): T {\r\n if (!enabled) {\r\n return data;\r\n }\r\n const allSkipFields = perRequestSkipFields \r\n ? [...skipFields, ...perRequestSkipFields]\r\n : skipFields;\r\n return sanitizeValueWithSkip(data, '', allSkipFields) as T;\r\n }\r\n\r\n /**\r\n * Sanitize with custom skip fields\r\n */\r\n function sanitizeValueWithSkip(value: unknown, path: string, fieldsToSkip: string[]): unknown {\r\n // Skip fields in skip list\r\n if (fieldsToSkip.some(field => path.endsWith(field) || path === field)) {\r\n return value;\r\n }\r\n\r\n // Null/undefined pass through\r\n if (value === null || value === undefined) {\r\n return value;\r\n }\r\n\r\n // Strings get sanitized\r\n if (typeof value === 'string') {\r\n return sanitizeString(value);\r\n }\r\n\r\n // Numbers, booleans pass through\r\n if (typeof value === 'number' || typeof value === 'boolean') {\r\n return value;\r\n }\r\n\r\n // Arrays - sanitize each element\r\n if (Array.isArray(value)) {\r\n return value.map((item, index) => sanitizeValueWithSkip(item, `${path}[${index}]`, fieldsToSkip));\r\n }\r\n\r\n // Objects - sanitize each property\r\n if (typeof value === 'object') {\r\n const sanitized: Record<string, unknown> = {};\r\n for (const [key, val] of Object.entries(value)) {\r\n const newPath = path ? `${path}.${key}` : key;\r\n sanitized[key] = sanitizeValueWithSkip(val, newPath, fieldsToSkip);\r\n }\r\n return sanitized;\r\n }\r\n\r\n // Everything else passes through\r\n return value;\r\n }\r\n\r\n /**\r\n * Sanitize FormData values (returns new FormData with sanitized values)\r\n * @param formData - FormData to sanitize\r\n * @param perRequestSkipFields - Additional fields to skip for this request only\r\n */\r\n function sanitizeFormData(formData: FormData, perRequestSkipFields?: string[]): FormData {\r\n if (!enabled) {\r\n return formData;\r\n }\r\n \r\n const allSkipFields = perRequestSkipFields \r\n ? [...skipFields, ...perRequestSkipFields]\r\n : skipFields;\r\n \r\n const sanitized = new FormData();\r\n \r\n for (const [key, value] of formData.entries()) {\r\n // Check if this field should be skipped\r\n const shouldSkip = allSkipFields.some(field => key === field || key.endsWith(field));\r\n \r\n if (value instanceof File) {\r\n // Files pass through unchanged\r\n sanitized.append(key, value);\r\n } else if (typeof value === 'string') {\r\n // Strings get sanitized (unless skipped)\r\n sanitized.append(key, shouldSkip ? value : sanitizeString(value));\r\n } else {\r\n // Everything else passes through\r\n sanitized.append(key, value);\r\n }\r\n }\r\n \r\n return sanitized;\r\n }\r\n\r\n return {\r\n sanitize,\r\n sanitizeString,\r\n sanitizeValue,\r\n sanitizeFormData,\r\n };\r\n}\r\n\r\nexport type Sanitizer = ReturnType<typeof createSanitizer>;\r\n\r\n/**\r\n * Default sanitizer with escape mode (enabled by default)\r\n */\r\nexport const defaultSanitizer = createSanitizer({\r\n enabled: true,\r\n mode: 'escape',\r\n skipFields: [],\r\n});\r\n\r\n/**\r\n * Quick sanitize function with default config\r\n */\r\nexport function sanitize<T>(data: T): T {\r\n return defaultSanitizer.sanitize(data);\r\n}\r\n\r\n/**\r\n * Quick escape function for single strings\r\n */\r\nexport function escapeString(str: string): string {\r\n return escapeHtml(str);\r\n}\r\n\r\n/**\r\n * Quick strip function for single strings\r\n */\r\nexport function stripString(str: string): string {\r\n return stripHtml(str);\r\n}\r\n","/**\r\n * createApiClient\r\n * Server-side API client for Route Handlers\r\n * \r\n * Makes requests directly to backend with auth token from cookies/headers.\r\n * Returns Response objects that can be directly returned from route handlers.\r\n */\r\n\r\nimport { cookies, headers } from 'next/headers';\r\nimport { createSanitizer } from './sanitize';\r\nimport type { SanitizationConfig, I18nConfig } from '../shared/types';\r\nimport { HEADERS } from '../shared/constants';\r\n\r\n// ==================== Types ====================\r\n\r\nexport interface ApiClientConfig {\r\n /** Backend API base URL */\r\n apiBaseUrl: string;\r\n \r\n /** Cookie names for token retrieval */\r\n cookies: {\r\n user: string;\r\n guest: string;\r\n };\r\n \r\n /** Sanitization options */\r\n sanitization?: SanitizationConfig;\r\n \r\n /** Enable Laravel method spoofing for PUT/PATCH */\r\n methodSpoofing?: boolean;\r\n \r\n /** Custom error messages */\r\n errorMessages?: {\r\n noToken?: string;\r\n connectionError?: string;\r\n };\r\n \r\n /** i18n configuration - auto-append locale to API requests */\r\n i18n?: I18nConfig & {\r\n /** Query parameter name (default: 'lang') */\r\n paramName?: string;\r\n };\r\n}\r\n\r\nexport interface RequestOptions {\r\n /** Form data mode (use FormData, skip Content-Type header) */\r\n isFormData?: boolean;\r\n /** Use method spoofing for this request */\r\n methodSpoofing?: boolean;\r\n /** Skip authentication for this request */\r\n skipAuth?: boolean;\r\n /** Skip all sanitization for this request */\r\n skipSanitize?: boolean;\r\n /** Skip sanitization for specific fields only */\r\n skipSanitizeFields?: string[];\r\n}\r\n\r\nexport interface ApiClient {\r\n get: (endpoint: string) => Promise<Response>;\r\n post: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;\r\n put: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;\r\n patch: (endpoint: string, body?: Record<string, unknown>, options?: RequestOptions) => Promise<Response>;\r\n delete: (endpoint: string) => Promise<Response>;\r\n}\r\n\r\n// ==================== Factory ====================\r\n\r\n/**\r\n * Creates a server-side API client for Next.js Route Handlers\r\n * \r\n * @example\r\n * ```ts\r\n * // lib/api.ts\r\n * import { createApiClient } from 'next-api-layer';\r\n * \r\n * export const api = createApiClient({\r\n * apiBaseUrl: process.env.API_BASE_URL!,\r\n * cookies: {\r\n * user: process.env.COOKIE_USER_AUTH_TOKEN_NAME!,\r\n * guest: process.env.COOKIE_PUBLIC_AUTH_TOKEN_NAME!,\r\n * },\r\n * });\r\n * \r\n * // Usage in route handler - direct return!\r\n * export async function GET() {\r\n * return api.get('superadmin/home/list');\r\n * }\r\n * \r\n * export async function POST(request: Request) {\r\n * const body = await request.json();\r\n * return api.post('donations/create', body);\r\n * }\r\n * ```\r\n */\r\nexport function createApiClient(config: ApiClientConfig): ApiClient {\r\n const {\r\n apiBaseUrl,\r\n cookies: cookieNames,\r\n methodSpoofing: globalMethodSpoofing = false,\r\n errorMessages = {},\r\n i18n,\r\n } = config;\r\n \r\n // Ensure baseUrl ends with /\r\n const baseUrl = apiBaseUrl.endsWith('/') ? apiBaseUrl : `${apiBaseUrl}/`;\r\n \r\n // Create sanitizer\r\n const sanitizer = createSanitizer(config.sanitization);\r\n \r\n // Error messages\r\n const noTokenMessage = errorMessages.noToken ?? 'Token bulunamadı. Lütfen giriş yapın.';\r\n const connectionErrorMessage = errorMessages.connectionError ?? 'Bağlantı hatası oluştu.';\r\n\r\n /**\r\n * Get auth token from headers (refreshed) or cookies\r\n */\r\n async function getToken(): Promise<string | null> {\r\n // Check for refreshed token from proxy\r\n const headersList = await headers();\r\n const refreshedToken = headersList.get(HEADERS.REFRESHED_TOKEN);\r\n if (refreshedToken) {\r\n return refreshedToken;\r\n }\r\n \r\n // Get from cookies\r\n const cookieStore = await cookies();\r\n return (\r\n cookieStore.get(cookieNames.user)?.value ||\r\n cookieStore.get(cookieNames.guest)?.value ||\r\n null\r\n );\r\n }\r\n\r\n /**\r\n * Create error response\r\n */\r\n function errorResponse(message: string, status = 500): Response {\r\n return Response.json(\r\n { success: false, message },\r\n { status }\r\n );\r\n }\r\n\r\n /**\r\n * Create no-token response\r\n */\r\n function noTokenResponse(): Response {\r\n return errorResponse(noTokenMessage, 401);\r\n }\r\n\r\n /**\r\n * Make a fetch request to backend\r\n */\r\n async function makeRequest(\r\n method: string,\r\n endpoint: string,\r\n body?: Record<string, unknown> | FormData | null,\r\n options: RequestOptions = {}\r\n ): Promise<Response> {\r\n // Skip auth check if requested\r\n const token = options.skipAuth ? null : await getToken();\r\n \r\n if (!options.skipAuth && !token) {\r\n return noTokenResponse();\r\n }\r\n\r\n try {\r\n const fetchHeaders: HeadersInit = {};\r\n \r\n // Add auth header if we have a token\r\n if (token) {\r\n fetchHeaders['Authorization'] = `Bearer ${token}`;\r\n }\r\n\r\n let fetchBody: string | FormData | undefined;\r\n let actualMethod = method;\r\n\r\n // Handle body\r\n if (body) {\r\n if (options.isFormData && body instanceof FormData) {\r\n // FormData - sanitize (unless skipped) and optionally add method spoofing\r\n if (options.skipSanitize) {\r\n fetchBody = body;\r\n } else {\r\n fetchBody = sanitizer.sanitizeFormData(body, options.skipSanitizeFields);\r\n }\r\n \r\n const useMethodSpoofing = options.methodSpoofing ?? globalMethodSpoofing;\r\n if (useMethodSpoofing && (method === 'PUT' || method === 'PATCH')) {\r\n (fetchBody as FormData).append('_method', method);\r\n actualMethod = 'POST';\r\n }\r\n } else if (!(body instanceof FormData)) {\r\n // JSON body\r\n fetchHeaders['Content-Type'] = 'application/json';\r\n if (options.skipSanitize) {\r\n fetchBody = JSON.stringify(body);\r\n } else {\r\n fetchBody = JSON.stringify(sanitizer.sanitize(body, options.skipSanitizeFields));\r\n }\r\n }\r\n }\r\n\r\n // Build URL with optional locale parameter\r\n let url = `${baseUrl}${endpoint}`;\r\n if (i18n?.enabled) {\r\n const headersList = await headers();\r\n const locale = headersList.get(HEADERS.LOCALE);\r\n if (locale && (!i18n.locales || i18n.locales.includes(locale))) {\r\n const urlObj = new URL(url);\r\n urlObj.searchParams.set(i18n.paramName || 'lang', locale);\r\n url = urlObj.toString();\r\n }\r\n }\r\n\r\n const res = await fetch(url, {\r\n method: actualMethod,\r\n headers: fetchHeaders,\r\n body: fetchBody,\r\n cache: 'no-store',\r\n });\r\n\r\n // Clone response data (stream can only be read once)\r\n const data = await res.json();\r\n return Response.json(data, { status: res.status });\r\n } catch (error) {\r\n console.error(`API ${method} Error:`, error);\r\n return errorResponse(connectionErrorMessage);\r\n }\r\n }\r\n\r\n // Return API client interface\r\n return {\r\n get: (endpoint: string) => makeRequest('GET', endpoint),\r\n \r\n post: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) =>\r\n makeRequest('POST', endpoint, body, options),\r\n \r\n put: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) =>\r\n makeRequest('PUT', endpoint, body, options),\r\n \r\n patch: (endpoint: string, body?: Record<string, unknown>, options?: RequestOptions) =>\r\n makeRequest('PATCH', endpoint, body, options),\r\n \r\n delete: (endpoint: string) => makeRequest('DELETE', endpoint),\r\n };\r\n}\r\n"]}
@@ -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 */
@@ -343,12 +348,16 @@ interface RequestOptions {
343
348
  methodSpoofing?: boolean;
344
349
  /** Skip authentication for this request */
345
350
  skipAuth?: boolean;
351
+ /** Skip all sanitization for this request */
352
+ skipSanitize?: boolean;
353
+ /** Skip sanitization for specific fields only */
354
+ skipSanitizeFields?: string[];
346
355
  }
347
356
  interface ApiClient {
348
357
  get: (endpoint: string) => Promise<Response>;
349
358
  post: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;
350
359
  put: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;
351
- patch: (endpoint: string, body?: Record<string, unknown>) => Promise<Response>;
360
+ patch: (endpoint: string, body?: Record<string, unknown>, options?: RequestOptions) => Promise<Response>;
352
361
  delete: (endpoint: string) => Promise<Response>;
353
362
  }
354
363
  /**
@@ -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 */
@@ -343,12 +348,16 @@ interface RequestOptions {
343
348
  methodSpoofing?: boolean;
344
349
  /** Skip authentication for this request */
345
350
  skipAuth?: boolean;
351
+ /** Skip all sanitization for this request */
352
+ skipSanitize?: boolean;
353
+ /** Skip sanitization for specific fields only */
354
+ skipSanitizeFields?: string[];
346
355
  }
347
356
  interface ApiClient {
348
357
  get: (endpoint: string) => Promise<Response>;
349
358
  post: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;
350
359
  put: (endpoint: string, body?: Record<string, unknown> | FormData, options?: RequestOptions) => Promise<Response>;
351
- patch: (endpoint: string, body?: Record<string, unknown>) => Promise<Response>;
360
+ patch: (endpoint: string, body?: Record<string, unknown>, options?: RequestOptions) => Promise<Response>;
352
361
  delete: (endpoint: string) => Promise<Response>;
353
362
  }
354
363
  /**
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var chunkOXXKU4OM_cjs=require('./chunk-OXXKU4OM.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 chunkOXXKU4OM_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 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},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 $={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:r}=e,{endpoints:p}=f,R={parseAuthMe:r?.parseAuthMe||$.parseAuthMe,parseRefreshToken:r?.parseRefreshToken||$.parseRefreshToken,parseGuestToken:r?.parseGuestToken||$.parseGuestToken};async function l(i){let u={isValid:false,tokenType:null,exp:null,userData:null};try{let s=await fetch(`${t}${p.validate}`,{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},cache:"no-store"});if(!s.ok)return u;let n=await s.json().catch(()=>null),d=R.parseAuthMe(n);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 s=await u.json().catch(()=>null),n=R.parseRefreshToken(s);return n?{success:!0,newToken:n}:{success:!1,newToken:null}}catch{return {success:false,newToken:null}}}async function a(){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 s=await u.json().catch(()=>null);return R.parseGuestToken(s)}catch{return null}}return {validateToken:l,getTokenInfo:c,refreshToken:m,createGuestToken:a}}function ee(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 z(e,t){let{cookies:f,guestToken:r,access:p,i18n:R,_resolved:l}=e,{cookieOptions:c}=l;function m(o,x,h){o.cookies.get(h)?.value&&x.cookies.delete(h);}function a(o,x){return m(o,x,f.guest),m(o,x,f.user),x}function i(o,x=500){return new server.NextResponse(JSON.stringify({success:false,message:o}),{status:x,headers:{"Content-Type":"application/json"}})}function u(o){return (p?.authRoutes??[]).some(h=>o===h||o.startsWith(`${h}/`))}function s(o){return p?.protectedByDefault?!n(o)&&!u(o):(p?.protectedRoutes??[]).some(h=>o===h||o.startsWith(`${h}/`))}function n(o){return (p?.publicRoutes??[]).some(h=>o===h||o.startsWith(`${h}/`))}function d(o){let x=p?.allowedTokenTypes;return !x||x.length===0?true:o?x.includes(o):false}async function N(o,x){let{origin:h}=o.nextUrl;if(r?.enabled){let y=await t.createGuestToken();if(y){let E;return x?E=server.NextResponse.next():s(o.nextUrl.pathname)?E=server.NextResponse.redirect(new URL("/login",h)):E=server.NextResponse.next(),E.cookies.set(f.guest,y,{...c,maxAge:3600}),E}}return x?i("Token bulunamad\u0131",401):s(o.nextUrl.pathname)?server.NextResponse.redirect(new URL("/login",h)):server.NextResponse.next()}async function L(o,x,h,y,E){let{pathname:k,origin:g}=o.nextUrl,{isValid:S,tokenType:A,userData:w}=x,v=A===chunk6ENVQMWQ_cjs.c.GUEST;if(!S){if(h&&y){let H=await t.refreshToken(y);if(H.success&&H.newToken){let O=await t.getTokenInfo(H.newToken);if(O.isValid){let _=new Headers(o.headers);O.userData&&_.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(O.userData)),_.set(chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN,H.newToken);let Z=ee(k,R);Z&&_.set(chunk6ENVQMWQ_cjs.e.LOCALE,Z);let D;return u(k)?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(o,D,f.guest),D}}}let P=await N(o,E);return P.cookies.get(f.guest)?.value?m(o,P,f.user):a(o,P),P}let U=new Headers(o.headers);w&&U.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(w));let J=ee(k,R);if(J&&U.set(chunk6ENVQMWQ_cjs.e.LOCALE,J),!v&&!d(A)){if(E){let Y=i("Bu i\u015Flem i\xE7in yetkiniz yok",403);return a(o,Y)}let P=server.NextResponse.redirect(new URL("/login",g));return a(o,P)}if(v)return E?server.NextResponse.next({request:{headers:U}}):s(k)?server.NextResponse.redirect(new URL("/login",g)):server.NextResponse.next({request:{headers:U}});if(u(k))return server.NextResponse.redirect(new URL("/",g));let X=server.NextResponse.next({request:{headers:U}});return m(o,X,f.guest),X}return {deleteAllAuthCookies:a,jsonError:i,isAuthPage:u,isProtectedRoute:s,isPublicRoute:n,isTokenTypeAllowed:d,handleNoToken:N,handleValidationResult:L}}function K(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 a=r(l);if(m==="fetch-metadata"||a.valid||a.reason!=="missing-headers")return a}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),a=await crypto.subtle.importKey("raw",c,{name:"HMAC",hash:"SHA-256"},false,["sign"]),i=await crypto.subtle.sign("HMAC",a,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 W(e){let t=new Map,f=setInterval(()=>{let i=Date.now();for(let[u,s]of t)s.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 s=e.keyFn(i),n=Date.now(),d=t.get(s);if(!d||d.resetAt<=n)return d={count:1,resetAt:n+e.windowMs},t.set(s,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 n=e.onRateLimited(i);return R(n,u)}let s=server.NextResponse.json({success:false,message:"Too many requests. Please try again later.",retryAfter:Math.ceil((u.resetAt-Date.now())/1e3)},{status:429});return s.headers.set("Retry-After",Math.ceil((u.resetAt-Date.now())/1e3).toString()),R(s,u)}function c(i){t.delete(i);}function m(){t.clear();}function a(){return t.size}return {check:p,applyHeaders:R,createLimitedResponse:l,shouldSkip:r,reset:c,clear:m,size:a}}function q(e){function t(s){return e.enabled&&e.events.includes(s)}function f(s){return s.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||s.headers.get("x-real-ip")||null}async function r(s,n,d){if(!t(s))return;let N={type:s,timestamp:new Date,ip:f(n),userId:d.userId,path:n.nextUrl.pathname,method:n.method,success:d.success,metadata:d.metadata};if(e.logger)try{await e.logger(N);}catch(L){console.error("[next-api-layer] Audit logger error:",L);}}function p(s,n,d){return r("auth:success",s,{success:true,userId:n,metadata:d})}function R(s,n){return r("auth:fail",s,{success:false,metadata:n})}function l(s,n,d){return r("auth:refresh",s,{success:true,userId:n,metadata:d})}function c(s,n){return r("auth:guest",s,{success:true,metadata:n})}function m(s,n,d){return r("access:denied",s,{success:false,userId:n,metadata:d})}function a(s,n){return r("csrf:fail",s,{success:false,metadata:n})}function i(s,n){return r("rateLimit:exceeded",s,{success:false,metadata:n})}function u(s,n,d){return r("error",s,{success:false,metadata:{...d,error:n.message,stack:n.stack}})}return {emit:r,isEnabled:t,authSuccess:p,authFail:R,authRefresh:l,authGuest:c,accessDenied:m,csrfFail:a,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=Q(e),f=j(t),r=z(t,f),p=K(t._resolved.csrf),R=W(t._resolved.rateLimit),l=q(t._resolved.audit);async function c(a){let{pathname:i,origin:u}=a.nextUrl,s=i.startsWith("/api");if(t._resolved.rateLimit.enabled){let g=R.check(a);if(!g.allowed)return await l.rateLimitExceeded(a,{limit:g.limit,resetAt:g.resetAt}),R.createLimitedResponse(a,g)}if(t._resolved.csrf.enabled){let g=p.validateRequest(a);if(!g.valid)return await l.csrfFail(a,{reason:g.reason}),server.NextResponse.json({success:false,message:"CSRF validation failed"},{status:403})}if(t.blockBrowserApiAccess&&s&&(a.headers.get("accept")||"").includes("text/html"))return server.NextResponse.redirect(new URL("/",u));if(t.beforeAuth){let g=await t.beforeAuth(a);if(g)return g}if((t.excludedPaths??[]).some(g=>i.startsWith(g)))return m(a,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(a,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});let N=a.cookies?.get(t.cookies.user)?.value,L=a.cookies?.get(t.cookies.guest)?.value,o=N||L,x=!!N;if(!o){await l.authFail(a,{reason:"no-token"});let g=await r.handleNoToken(a,s);return m(a,g,{isAuthenticated:false,isGuest:false,tokenType:null,user:null})}let h=await f.getTokenInfo(o),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 l.authGuest(a);else {let g=h.userData?.id?.toString();await l.authSuccess(a,g,{tokenType:h.tokenType});}else await l.authFail(a,{reason:"invalid-token"});let E=await r.handleValidationResult(a,h,x,o,s),k=await m(a,E,y);if(t._resolved.csrf.enabled&&y.isAuthenticated){let g=h.userData?.id?.toString()||o.slice(0,32);k=await p.attachCsrfCookie(k,g);}if(t._resolved.rateLimit.enabled){let g=R.check(a);k=R.applyHeaders(k,g);}return k}async function m(a,i,u){let s=i;if(t.i18n?.middleware){let n=await Promise.resolve(t.i18n.middleware(a));s=te(i,n);}if(t.afterAuth){let n=await t.afterAuth(a,s,u);s=te(s,n);}return s}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:a}=e,i=t.replace(/\/$/,"");function u(n,d){return n.headers.get(chunk6ENVQMWQ_cjs.e.SKIP_AUTH)==="true"||me(d,R)?true:p}async function s(n){try{let d=new URL(n.url),N=d.pathname.replace(/^\/api\/?/,""),L=new URL(`${i}/${N}`);L.search=d.search;let o=new Headers;if(l.forEach(A=>{let w=n.headers.get(A);w&&o.set(A,w);}),n.headers.forEach((A,w)=>{let v=w.toLowerCase();!c.includes(v)&&!o.has(w)&&o.set(w,A);}),!u(n,N)){let A=n.cookies.get(f)?.value,w=n.cookies.get(r)?.value,v=A||w;v&&o.set(chunk6ENVQMWQ_cjs.e.AUTHORIZATION,`Bearer ${v}`);}o.delete(chunk6ENVQMWQ_cjs.e.SKIP_AUTH);let x=m?await m(n,o):o,h=null;if(n.method!=="GET"&&n.method!=="HEAD"){let A=n.headers.get("content-type")||"";A.includes("application/json")?h=await n.text():A.includes("multipart/form-data")?h=await n.formData():h=await n.text();}let y=await fetch(L.toString(),{method:n.method,headers:x,body:h}),E=y.headers.get("content-type")||"",k;E.includes("application/json")?k=await y.text():k=await y.arrayBuffer();let g=new Headers;y.headers.forEach((A,w)=>{let v=w.toLowerCase();["transfer-encoding","connection","keep-alive"].includes(v)||g.set(w,A);});let S=new server.NextResponse(k,{status:y.status,statusText:y.statusText,headers:g});return a&&(S=await a(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 s.config=e,s}
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=se;exports.createCsrfValidator=K;exports.createHandlers=z;exports.createProxyHandler=re;exports.createRateLimiter=W;exports.createTokenValidation=j;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map