{"version":3,"file":"index.js","sources":["../src/fresh.ts","../src/accepts.ts","../src/index.ts"],"sourcesContent":["import { IncomingHttpHeaders, OutgoingHttpHeaders } from 'node:http'\n\nconst CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\\s*?no-cache\\s*?(?:,|$)/\n\nconst compareETags = (etag: string, str: string) => str === etag || str === `W/${etag}` || `W/${str}` === etag\n\nfunction isStale(etag: string, noneMatch: string) {\n let start = 0\n let end = 0\n\n for (let i = 0, len = noneMatch.length; i < len; i++) {\n switch (noneMatch.charCodeAt(i)) {\n case 0x20 /* */:\n if (start === end) start = end = i + 1\n break\n case 0x2c /* , */:\n if (compareETags(etag, noneMatch.substring(start, end))) return false\n start = end = i + 1\n break\n default:\n end = i + 1\n break\n }\n }\n\n if (compareETags(etag, noneMatch.substring(start, end))) return false\n\n return true\n}\n\n/**\n * Check freshness of the response using request and response headers.\n */\nexport function fresh(reqHeaders: IncomingHttpHeaders, resHeaders: OutgoingHttpHeaders) {\n const modifiedSince = reqHeaders['if-modified-since']\n const noneMatch = reqHeaders['if-none-match']\n\n if (!modifiedSince && !noneMatch) return false\n\n const cacheControl = reqHeaders['cache-control']\n if (cacheControl && CACHE_CONTROL_NO_CACHE_REGEXP.test(cacheControl)) return false\n\n // if-none-match\n if (noneMatch !== '*') {\n const etag = resHeaders.etag as string | undefined\n\n if (!etag || isStale(etag, noneMatch)) return false\n }\n\n // if-modified-since\n if (modifiedSince) {\n const lastModified = resHeaders['last-modified'] as string | undefined\n\n if (!lastModified || !(Date.parse(lastModified) <= Date.parse(modifiedSince))) return false\n }\n\n return true\n}\n","import { IncomingMessage } from 'node:http'\nimport { Accepts } from '@tinyhttp/accepts'\n\ntype Request = Pick\n\ntype AcceptReturns = string | boolean | string[]\n\nexport const getAccepts =\n (req: Request) =>\n (...types: string[]): AcceptReturns =>\n new Accepts(req).types(types)\n\nexport const getAcceptsEncodings =\n (req: Request) =>\n (...encodings: string[]): AcceptReturns =>\n new Accepts(req).encodings(encodings)\n\nexport const getAcceptsCharsets =\n (req: Request) =>\n (...charsets: string[]): AcceptReturns =>\n new Accepts(req).charsets(charsets)\n\nexport const getAcceptsLanguages =\n (req: Request) =>\n (...languages: string[]): AcceptReturns =>\n new Accepts(req).languages(languages)\n","import { IncomingMessage as Request, ServerResponse as Response } from 'node:http'\nimport { Options, Ranges, Result, parseRange } from 'header-range-parser'\n\nimport { typeIs } from '@tinyhttp/type-is'\nimport { fresh } from './fresh.js'\n\nexport * from './accepts.js'\n\nexport * from '@tinyhttp/url'\n\nexport const getRequestHeader =\n (req: Pick) =>\n (header: string): string | string[] => {\n const lc = header.toLowerCase()\n\n switch (lc) {\n case 'referer':\n case 'referrer':\n return req.headers.referrer || req.headers.referer\n default:\n return req.headers[lc]\n }\n }\n\nexport const getRangeFromHeader =\n (req: Pick) =>\n (size: number, options?: Options): Result | Ranges => {\n const range = getRequestHeader(req)('Range') as string\n\n if (!range) return\n\n return parseRange(size, range, options)\n }\n\nexport const getFreshOrStale = (\n req: Pick,\n res: Pick\n): boolean => {\n const method = req.method\n const status = res.statusCode\n\n // GET or HEAD for weak freshness validation only\n if (method !== 'GET' && method !== 'HEAD') return false\n\n // 2xx or 304 as per rfc2616 14.26\n if ((status >= 200 && status < 300) || status === 304) {\n return fresh(req.headers, {\n etag: res.getHeader('ETag'),\n 'last-modified': res.getHeader('Last-Modified')\n })\n }\n\n return false\n}\n\nexport const checkIfXMLHttpRequest = (req: Pick): boolean =>\n req.headers['x-requested-with'] === 'XMLHttpRequest'\n\nexport const reqIs =\n (req: Pick) =>\n (...types: string[]) =>\n typeIs(req.headers['content-type'], ...types)\n"],"names":[],"mappings":";;;;AAEA,MAAM,gCAAgC;AAEtC,MAAM,eAAe,CAAC,MAAc,QAAgB,QAAQ,QAAQ,QAAQ,KAAK,IAAI,MAAM,KAAK,GAAG,OAAO;AAE1G,SAAS,QAAQ,MAAc,WAAmB;AAChD,MAAI,QAAQ;AACZ,MAAI,MAAM;AAEV,WAAS,IAAI,GAAG,MAAM,UAAU,QAAQ,IAAI,KAAK,KAAK;AAC5C,YAAA,UAAU,WAAW,CAAC,GAAG;AAAA,MAC/B,KAAK;AACH,YAAI,UAAU;AAAK,kBAAQ,MAAM,IAAI;AACrC;AAAA,MACF,KAAK;AACH,YAAI,aAAa,MAAM,UAAU,UAAU,OAAO,GAAG,CAAC;AAAU,iBAAA;AAChE,gBAAQ,MAAM,IAAI;AAClB;AAAA,MACF;AACE,cAAM,IAAI;AACV;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,aAAa,MAAM,UAAU,UAAU,OAAO,GAAG,CAAC;AAAU,WAAA;AAEzD,SAAA;AACT;AAKgB,SAAA,MAAM,YAAiC,YAAiC;AAChF,QAAA,gBAAgB,WAAW,mBAAmB;AAC9C,QAAA,YAAY,WAAW,eAAe;AAExC,MAAA,CAAC,iBAAiB,CAAC;AAAkB,WAAA;AAEnC,QAAA,eAAe,WAAW,eAAe;AAC3C,MAAA,gBAAgB,8BAA8B,KAAK,YAAY;AAAU,WAAA;AAG7E,MAAI,cAAc,KAAK;AACrB,UAAM,OAAO,WAAW;AAExB,QAAI,CAAC,QAAQ,QAAQ,MAAM,SAAS;AAAU,aAAA;AAAA,EAChD;AAGA,MAAI,eAAe;AACX,UAAA,eAAe,WAAW,eAAe;AAE3C,QAAA,CAAC,gBAAgB,EAAE,KAAK,MAAM,YAAY,KAAK,KAAK,MAAM,aAAa;AAAW,aAAA;AAAA,EACxF;AAEO,SAAA;AACT;AClDa,MAAA,aACX,CAAC,QACD,IAAI,UACF,IAAI,QAAQ,GAAG,EAAE,MAAM,KAAK;AAEnB,MAAA,sBACX,CAAC,QACD,IAAI,cACF,IAAI,QAAQ,GAAG,EAAE,UAAU,SAAS;AAE3B,MAAA,qBACX,CAAC,QACD,IAAI,aACF,IAAI,QAAQ,GAAG,EAAE,SAAS,QAAQ;AAEzB,MAAA,sBACX,CAAC,QACD,IAAI,cACF,IAAI,QAAQ,GAAG,EAAE,UAAU,SAAS;ACfjC,MAAM,mBACX,CAAC,QACD,CAAC,WAAsC;AAC/B,QAAA,KAAK,OAAO;AAElB,UAAQ,IAAI;AAAA,IACV,KAAK;AAAA,IACL,KAAK;AACH,aAAO,IAAI,QAAQ,YAAY,IAAI,QAAQ;AAAA,IAC7C;AACS,aAAA,IAAI,QAAQ,EAAE;AAAA,EACzB;AACF;AAEK,MAAM,qBACX,CAAC,QACD,CAAC,MAAc,YAAuC;AACpD,QAAM,QAAQ,iBAAiB,GAAG,EAAE,OAAO;AAE3C,MAAI,CAAC;AAAO;AAEL,SAAA,WAAW,MAAM,OAAO,OAAO;AACxC;AAEW,MAAA,kBAAkB,CAC7B,KACA,QACY;AACZ,QAAM,SAAS,IAAI;AACnB,QAAM,SAAS,IAAI;AAGf,MAAA,WAAW,SAAS,WAAW;AAAe,WAAA;AAGlD,MAAK,UAAU,OAAO,SAAS,OAAQ,WAAW,KAAK;AAC9C,WAAA,MAAM,IAAI,SAAS;AAAA,MACxB,MAAM,IAAI,UAAU,MAAM;AAAA,MAC1B,iBAAiB,IAAI,UAAU,eAAe;AAAA,IAAA,CAC/C;AAAA,EACH;AAEO,SAAA;AACT;AAEO,MAAM,wBAAwB,CAAC,QACpC,IAAI,QAAQ,kBAAkB,MAAM;AAEzB,MAAA,QACX,CAAC,QACD,IAAI,UACF,OAAO,IAAI,QAAQ,cAAc,GAAG,GAAG,KAAK;"}