@vafast/cors 0.0.2 → 0.0.4

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/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/index.ts
2
+ import { empty } from "vafast";
2
3
  var isBun = typeof new Headers()?.toJSON === "function";
3
4
  var processHeaders = (headers) => {
4
5
  if ("toJSON" in headers && typeof headers.toJSON === "function") {
@@ -109,7 +110,7 @@ var cors = (config) => {
109
110
  response.headers.set("access-control-allow-credentials", "true");
110
111
  };
111
112
  const handlePreflight = async (request) => {
112
- const response = new Response(null, { status: 204 });
113
+ const response = empty(204);
113
114
  handleOrigin(response, request);
114
115
  handleMethod(
115
116
  response,
@@ -133,7 +134,7 @@ var cors = (config) => {
133
134
  };
134
135
  return async (request, next) => {
135
136
  if (preflight && request.method === "OPTIONS") {
136
- const response2 = new Response(null, { status: 204 });
137
+ const response2 = empty(204);
137
138
  handleOrigin(response2, request);
138
139
  handleMethod(
139
140
  response2,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable no-case-declarations */\nimport type { Middleware } from 'vafast'\n\ntype Origin = string | RegExp | ((request: Request) => boolean | void)\n\nexport type HTTPMethod =\n\t| 'ACL'\n\t| 'BIND'\n\t| 'CHECKOUT'\n\t| 'CONNECT'\n\t| 'COPY'\n\t| 'DELETE'\n\t| 'GET'\n\t| 'HEAD'\n\t| 'LINK'\n\t| 'LOCK'\n\t| 'M-SEARCH'\n\t| 'MERGE'\n\t| 'MKACTIVITY'\n\t| 'MKCALENDAR'\n\t| 'MKCOL'\n\t| 'MOVE'\n\t| 'NOTIFY'\n\t| 'OPTIONS'\n\t| 'PATCH'\n\t| 'POST'\n\t| 'PROPFIND'\n\t| 'PROPPATCH'\n\t| 'PURGE'\n\t| 'PUT'\n\t| 'REBIND'\n\t| 'REPORT'\n\t| 'SEARCH'\n\t| 'SOURCE'\n\t| 'SUBSCRIBE'\n\t| 'TRACE'\n\t| 'UNBIND'\n\t| 'UNLINK'\n\t| 'UNLOCK'\n\t| 'UNSUBSCRIBE'\n\ntype MaybeArray<T> = T | T[]\n\ninterface CORSConfig {\n\t/**\n\t * @default `true`\n\t *\n\t * Assign the **Access-Control-Allow-Origin** header.\n\t *\n\t * Value can be one of the following:\n\t * - `string` - String of origin which will be directly assign to `Access-Control-Allow-Origin`\n\t *\n\t * - `boolean` - If set to true, `Access-Control-Allow-Origin` will be set to `*` (accept all origin)\n\t *\n\t * - `RegExp` - Pattern to use to test with request's url, will accept origin if matched.\n\t *\n\t * - `Function` - Custom logic to validate origin acceptance or not. will accept origin if `true` is returned.\n\t * - Function will accepts `Request` as parameter\n\t *\n\t * ```typescript\n\t * // ? Example usage\n\t * const corsMiddleware = cors({\n\t * origin: (request) => true\n\t * })\n\t *\n\t * // Type Definition\n\t * type CORSOriginFn = (request: Request) => boolean | void\n\t * ```\n\t *\n\t * - `Array<string | RegExp | Function>` - Will try to find truthy value of all options above. Will accept request if one is `true`.\n\t */\n\torigin?: Origin | boolean | Origin[]\n\t/**\n\t * @default `*`\n\t *\n\t * Assign **Access-Control-Allow-Methods** header.\n\t *\n\t * Value can be one of the following:\n\t * Accept:\n\t * - `undefined | null | ''` - Ignore all methods.\n\t *\n\t * - `*` - Accept all methods.\n\t *\n\t * - `HTTPMethod` - Will be directly set to **Access-Control-Allow-Methods**.\n\t * - Expects either a single method or a comma-delimited string (eg: 'GET, PUT, POST')\n\t *\n\t * - `HTTPMethod[]` - Allow multiple HTTP methods.\n\t * - eg: ['GET', 'PUT', 'POST']\n\t */\n\tmethods?:\n\t\t| boolean\n\t\t| undefined\n\t\t| null\n\t\t| ''\n\t\t| '*'\n\t\t| MaybeArray<HTTPMethod | (string & {})>\n\t/**\n\t * @default `*`\n\t *\n\t * Assign **Access-Control-Allow-Headers** header.\n\t *\n\t * Allow incoming request with the specified headers.\n\t *\n\t * Value can be one of the following:\n\t * - `string`\n\t * - Expects either a single method or a comma-delimited string (eg: 'Content-Type, Authorization').\n\t *\n\t * - `string[]` - Allow multiple HTTP methods.\n\t * - eg: ['Content-Type', 'Authorization']\n\t */\n\tallowedHeaders?: true | string | string[]\n\t/**\n\t * @default `*`\n\t *\n\t * Assign **Access-Control-Expose-Headers** header.\n\t *\n\t * Return the specified headers to request in CORS mode.\n\t *\n\t * Value can be one of the following:\n\t * - `string`\n\t * - Expects either a single method or a comma-delimited string (eg: 'Content-Type, 'X-Powered-By').\n\t *\n\t * - `string[]` - Allow multiple HTTP methods.\n\t * - eg: ['Content-Type', 'X-Powered-By']\n\t */\n\texposeHeaders?: true | string | string[]\n\t/**\n\t * @default `true`\n\t *\n\t * Assign **Access-Control-Allow-Credentials** header.\n\t *\n\t * Allow incoming requests to send `credentials` header.\n\t *\n\t * - `boolean` - Available if set to `true`.\n\t */\n\tcredentials?: boolean\n\t/**\n\t * @default `5`\n\t *\n\t * Assign **Access-Control-Max-Age** header.\n\t *\n\t * Allow incoming requests to send `credentials` header.\n\t *\n\t * - `number` - Duration in seconds to indicates how long the results of a preflight request can be cached.\n\t */\n\tmaxAge?: number\n\t/**\n\t * @default `true`\n\t *\n\t * Add `[OPTIONS] /*` handler to handle preflight request which response with `HTTP 204` and CORS hints.\n\t *\n\t * - `boolean` - Available if set to `true`.\n\t */\n\tpreflight?: boolean\n}\n\n// @ts-ignore\nconst isBun = typeof new Headers()?.toJSON === 'function'\n\n/**\n * This function is use when headers config is true.\n * Attempts to process headers based on request headers.\n */\nconst processHeaders = (headers: any) => {\n\t// Check if toJSON method exists (Bun specific)\n\tif ('toJSON' in headers && typeof headers.toJSON === 'function') {\n\t\treturn Object.keys(headers.toJSON()).join(', ')\n\t}\n\n\tlet keys = ''\n\n\tlet i = 0\n\theaders.forEach((_: any, key: string) => {\n\t\tif (i) keys = keys + ', ' + key\n\t\telse keys = key\n\n\t\ti++\n\t})\n\n\treturn keys\n}\n\nexport const cors = (config?: CORSConfig): Middleware => {\n\tlet {\n\t\torigin = true,\n\t\tmethods = true,\n\t\tallowedHeaders = true,\n\t\texposeHeaders = true,\n\t\tcredentials = true,\n\t\tmaxAge = 5,\n\t\tpreflight = true\n\t} = config ?? {}\n\n\tif (Array.isArray(allowedHeaders))\n\t\tallowedHeaders = allowedHeaders.join(', ')\n\n\tif (Array.isArray(exposeHeaders)) exposeHeaders = exposeHeaders.join(', ')\n\n\tconst origins =\n\t\ttypeof origin === 'boolean'\n\t\t\t? undefined\n\t\t\t: Array.isArray(origin)\n\t\t\t? origin\n\t\t\t: [origin]\n\n\tconst anyOrigin = origins?.some((o) => o === '*')\n\n\tconst originMap = <Record<string, true>>{}\n\tif (origins)\n\t\tfor (const origin of origins)\n\t\t\tif (typeof origin === 'string') originMap[origin] = true\n\n\tconst processOrigin = (\n\t\torigin: Origin,\n\t\trequest: Request,\n\t\tfrom: string\n\t): boolean => {\n\t\tif (Array.isArray(origin))\n\t\t\treturn origin.some((o) => processOrigin(o, request, from))\n\n\t\tswitch (typeof origin) {\n\t\t\tcase 'string':\n\t\t\t\tif (from in originMap) return true\n\n\t\t\t\tconst fromProtocol = from.indexOf('://')\n\t\t\t\tif (fromProtocol !== -1) from = from.slice(fromProtocol + 3)\n\n\t\t\t\treturn origin === from\n\n\t\t\tcase 'function':\n\t\t\t\treturn origin(request) === true\n\n\t\t\tcase 'object':\n\t\t\t\tif (origin instanceof RegExp) return origin.test(from)\n\t\t}\n\n\t\treturn false\n\t}\n\n\tconst handleOrigin = (response: Response, request: Request) => {\n\t\t// origin === `true` means any origin\n\t\tif (origin === true) {\n\t\t\tresponse.headers.set('vary', '*')\n\t\t\tresponse.headers.set(\n\t\t\t\t'access-control-allow-origin',\n\t\t\t\trequest.headers.get('Origin') || '*'\n\t\t\t)\n\n\t\t\treturn\n\t\t}\n\n\t\tif (anyOrigin) {\n\t\t\tresponse.headers.set('vary', '*')\n\t\t\tresponse.headers.set('access-control-allow-origin', '*')\n\n\t\t\treturn\n\t\t}\n\n\t\tif (!origins?.length) return\n\n\t\tconst headers: string[] = []\n\n\t\tif (origins.length) {\n\t\t\tconst from = request.headers.get('Origin') ?? ''\n\t\t\tfor (let i = 0; i < origins.length; i++) {\n\t\t\t\tconst value = processOrigin(origins[i]!, request, from)\n\t\t\t\tif (value === true) {\n\t\t\t\t\tresponse.headers.set('vary', origin ? 'Origin' : '*')\n\t\t\t\t\tresponse.headers.set(\n\t\t\t\t\t\t'access-control-allow-origin',\n\t\t\t\t\t\tfrom || '*'\n\t\t\t\t\t)\n\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tresponse.headers.set('vary', 'Origin')\n\t\tif (headers.length)\n\t\t\tresponse.headers.set(\n\t\t\t\t'access-control-allow-origin',\n\t\t\t\theaders.join(', ')\n\t\t\t)\n\t}\n\n\tconst handleMethod = (response: Response, method?: string | null) => {\n\t\tif (!method) return\n\n\t\tif (methods === true)\n\t\t\treturn response.headers.set(\n\t\t\t\t'access-control-allow-methods',\n\t\t\t\tmethod ?? '*'\n\t\t\t)\n\n\t\tif (methods === false || !methods?.length) return\n\n\t\tif (methods === '*')\n\t\t\treturn response.headers.set('access-control-allow-methods', '*')\n\n\t\tif (!Array.isArray(methods))\n\t\t\treturn response.headers.set('access-control-allow-methods', methods)\n\n\t\tresponse.headers.set('access-control-allow-methods', methods.join(', '))\n\t}\n\n\tconst setDefaultHeaders = (response: Response) => {\n\t\tif (typeof exposeHeaders === 'string')\n\t\t\tresponse.headers.set('access-control-expose-headers', exposeHeaders)\n\n\t\tif (typeof allowedHeaders === 'string')\n\t\t\tresponse.headers.set('access-control-allow-headers', allowedHeaders)\n\n\t\tif (credentials === true)\n\t\t\tresponse.headers.set('access-control-allow-credentials', 'true')\n\t}\n\n\tconst handlePreflight = async (request: Request): Promise<Response> => {\n\t\tconst response = new Response(null, { status: 204 })\n\n\t\thandleOrigin(response, request)\n\t\thandleMethod(\n\t\t\tresponse,\n\t\t\trequest.headers.get('access-control-request-method')\n\t\t)\n\n\t\tif (allowedHeaders === true || exposeHeaders === true) {\n\t\t\tif (allowedHeaders === true)\n\t\t\t\tresponse.headers.set(\n\t\t\t\t\t'access-control-allow-headers',\n\t\t\t\t\trequest.headers.get('access-control-request-headers') || ''\n\t\t\t\t)\n\n\t\t\tif (exposeHeaders === true)\n\t\t\t\tresponse.headers.set(\n\t\t\t\t\t'access-control-expose-headers',\n\t\t\t\t\tprocessHeaders(request.headers)\n\t\t\t\t)\n\t\t}\n\n\t\tif (maxAge)\n\t\t\tresponse.headers.set('access-control-max-age', maxAge.toString())\n\n\t\treturn response\n\t}\n\n\treturn async (request: Request, next: () => Promise<Response>) => {\n\t\t// Handle preflight requests\n\t\tif (preflight && request.method === 'OPTIONS') {\n\t\t\tconst response = new Response(null, { status: 204 })\n\n\t\t\thandleOrigin(response, request)\n\t\t\thandleMethod(\n\t\t\t\tresponse,\n\t\t\t\trequest.headers.get('access-control-request-method')\n\t\t\t)\n\n\t\t\tif (allowedHeaders === true || exposeHeaders === true) {\n\t\t\t\tif (allowedHeaders === true)\n\t\t\t\t\tresponse.headers.set(\n\t\t\t\t\t\t'access-control-allow-headers',\n\t\t\t\t\t\trequest.headers.get('access-control-request-headers') ||\n\t\t\t\t\t\t\t''\n\t\t\t\t\t)\n\n\t\t\t\tif (exposeHeaders === true)\n\t\t\t\t\tresponse.headers.set(\n\t\t\t\t\t\t'access-control-expose-headers',\n\t\t\t\t\t\tprocessHeaders(request.headers)\n\t\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (maxAge)\n\t\t\t\tresponse.headers.set(\n\t\t\t\t\t'access-control-max-age',\n\t\t\t\t\tmaxAge.toString()\n\t\t\t\t)\n\n\t\t\treturn response\n\t\t}\n\n\t\t// Process CORS for actual requests\n\t\tconst response = await next()\n\n\t\thandleOrigin(response, request)\n\t\thandleMethod(response, request.method)\n\t\tsetDefaultHeaders(response)\n\n\t\tif (allowedHeaders === true || exposeHeaders === true) {\n\t\t\tconst headers = processHeaders(request.headers)\n\n\t\t\tif (allowedHeaders === true)\n\t\t\t\tresponse.headers.set('access-control-allow-headers', headers)\n\n\t\t\tif (exposeHeaders === true)\n\t\t\t\tresponse.headers.set('access-control-expose-headers', headers)\n\t\t}\n\n\t\treturn response\n\t}\n}\n\nexport default cors\n"],"mappings":"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","names":["origin","response"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable no-case-declarations */\nimport type { Middleware } from 'vafast'\nimport { empty } from 'vafast'\n\ntype Origin = string | RegExp | ((request: Request) => boolean | void)\n\nexport type HTTPMethod =\n\t| 'ACL'\n\t| 'BIND'\n\t| 'CHECKOUT'\n\t| 'CONNECT'\n\t| 'COPY'\n\t| 'DELETE'\n\t| 'GET'\n\t| 'HEAD'\n\t| 'LINK'\n\t| 'LOCK'\n\t| 'M-SEARCH'\n\t| 'MERGE'\n\t| 'MKACTIVITY'\n\t| 'MKCALENDAR'\n\t| 'MKCOL'\n\t| 'MOVE'\n\t| 'NOTIFY'\n\t| 'OPTIONS'\n\t| 'PATCH'\n\t| 'POST'\n\t| 'PROPFIND'\n\t| 'PROPPATCH'\n\t| 'PURGE'\n\t| 'PUT'\n\t| 'REBIND'\n\t| 'REPORT'\n\t| 'SEARCH'\n\t| 'SOURCE'\n\t| 'SUBSCRIBE'\n\t| 'TRACE'\n\t| 'UNBIND'\n\t| 'UNLINK'\n\t| 'UNLOCK'\n\t| 'UNSUBSCRIBE'\n\ntype MaybeArray<T> = T | T[]\n\ninterface CORSConfig {\n\t/**\n\t * @default `true`\n\t *\n\t * Assign the **Access-Control-Allow-Origin** header.\n\t *\n\t * Value can be one of the following:\n\t * - `string` - String of origin which will be directly assign to `Access-Control-Allow-Origin`\n\t *\n\t * - `boolean` - If set to true, `Access-Control-Allow-Origin` will be set to `*` (accept all origin)\n\t *\n\t * - `RegExp` - Pattern to use to test with request's url, will accept origin if matched.\n\t *\n\t * - `Function` - Custom logic to validate origin acceptance or not. will accept origin if `true` is returned.\n\t * - Function will accepts `Request` as parameter\n\t *\n\t * ```typescript\n\t * // ? Example usage\n\t * const corsMiddleware = cors({\n\t * origin: (request) => true\n\t * })\n\t *\n\t * // Type Definition\n\t * type CORSOriginFn = (request: Request) => boolean | void\n\t * ```\n\t *\n\t * - `Array<string | RegExp | Function>` - Will try to find truthy value of all options above. Will accept request if one is `true`.\n\t */\n\torigin?: Origin | boolean | Origin[]\n\t/**\n\t * @default `*`\n\t *\n\t * Assign **Access-Control-Allow-Methods** header.\n\t *\n\t * Value can be one of the following:\n\t * Accept:\n\t * - `undefined | null | ''` - Ignore all methods.\n\t *\n\t * - `*` - Accept all methods.\n\t *\n\t * - `HTTPMethod` - Will be directly set to **Access-Control-Allow-Methods**.\n\t * - Expects either a single method or a comma-delimited string (eg: 'GET, PUT, POST')\n\t *\n\t * - `HTTPMethod[]` - Allow multiple HTTP methods.\n\t * - eg: ['GET', 'PUT', 'POST']\n\t */\n\tmethods?:\n\t\t| boolean\n\t\t| undefined\n\t\t| null\n\t\t| ''\n\t\t| '*'\n\t\t| MaybeArray<HTTPMethod | (string & {})>\n\t/**\n\t * @default `*`\n\t *\n\t * Assign **Access-Control-Allow-Headers** header.\n\t *\n\t * Allow incoming request with the specified headers.\n\t *\n\t * Value can be one of the following:\n\t * - `string`\n\t * - Expects either a single method or a comma-delimited string (eg: 'Content-Type, Authorization').\n\t *\n\t * - `string[]` - Allow multiple HTTP methods.\n\t * - eg: ['Content-Type', 'Authorization']\n\t */\n\tallowedHeaders?: true | string | string[]\n\t/**\n\t * @default `*`\n\t *\n\t * Assign **Access-Control-Expose-Headers** header.\n\t *\n\t * Return the specified headers to request in CORS mode.\n\t *\n\t * Value can be one of the following:\n\t * - `string`\n\t * - Expects either a single method or a comma-delimited string (eg: 'Content-Type, 'X-Powered-By').\n\t *\n\t * - `string[]` - Allow multiple HTTP methods.\n\t * - eg: ['Content-Type', 'X-Powered-By']\n\t */\n\texposeHeaders?: true | string | string[]\n\t/**\n\t * @default `true`\n\t *\n\t * Assign **Access-Control-Allow-Credentials** header.\n\t *\n\t * Allow incoming requests to send `credentials` header.\n\t *\n\t * - `boolean` - Available if set to `true`.\n\t */\n\tcredentials?: boolean\n\t/**\n\t * @default `5`\n\t *\n\t * Assign **Access-Control-Max-Age** header.\n\t *\n\t * Allow incoming requests to send `credentials` header.\n\t *\n\t * - `number` - Duration in seconds to indicates how long the results of a preflight request can be cached.\n\t */\n\tmaxAge?: number\n\t/**\n\t * @default `true`\n\t *\n\t * Add `[OPTIONS] /*` handler to handle preflight request which response with `HTTP 204` and CORS hints.\n\t *\n\t * - `boolean` - Available if set to `true`.\n\t */\n\tpreflight?: boolean\n}\n\n// @ts-ignore\nconst isBun = typeof new Headers()?.toJSON === 'function'\n\n/**\n * This function is use when headers config is true.\n * Attempts to process headers based on request headers.\n */\nconst processHeaders = (headers: any) => {\n\t// Check if toJSON method exists (Bun specific)\n\tif ('toJSON' in headers && typeof headers.toJSON === 'function') {\n\t\treturn Object.keys(headers.toJSON()).join(', ')\n\t}\n\n\tlet keys = ''\n\n\tlet i = 0\n\theaders.forEach((_: any, key: string) => {\n\t\tif (i) keys = keys + ', ' + key\n\t\telse keys = key\n\n\t\ti++\n\t})\n\n\treturn keys\n}\n\nexport const cors = (config?: CORSConfig): Middleware => {\n\tlet {\n\t\torigin = true,\n\t\tmethods = true,\n\t\tallowedHeaders = true,\n\t\texposeHeaders = true,\n\t\tcredentials = true,\n\t\tmaxAge = 5,\n\t\tpreflight = true\n\t} = config ?? {}\n\n\tif (Array.isArray(allowedHeaders))\n\t\tallowedHeaders = allowedHeaders.join(', ')\n\n\tif (Array.isArray(exposeHeaders)) exposeHeaders = exposeHeaders.join(', ')\n\n\tconst origins =\n\t\ttypeof origin === 'boolean'\n\t\t\t? undefined\n\t\t\t: Array.isArray(origin)\n\t\t\t? origin\n\t\t\t: [origin]\n\n\tconst anyOrigin = origins?.some((o) => o === '*')\n\n\tconst originMap = <Record<string, true>>{}\n\tif (origins)\n\t\tfor (const origin of origins)\n\t\t\tif (typeof origin === 'string') originMap[origin] = true\n\n\tconst processOrigin = (\n\t\torigin: Origin,\n\t\trequest: Request,\n\t\tfrom: string\n\t): boolean => {\n\t\tif (Array.isArray(origin))\n\t\t\treturn origin.some((o) => processOrigin(o, request, from))\n\n\t\tswitch (typeof origin) {\n\t\t\tcase 'string':\n\t\t\t\tif (from in originMap) return true\n\n\t\t\t\tconst fromProtocol = from.indexOf('://')\n\t\t\t\tif (fromProtocol !== -1) from = from.slice(fromProtocol + 3)\n\n\t\t\t\treturn origin === from\n\n\t\t\tcase 'function':\n\t\t\t\treturn origin(request) === true\n\n\t\t\tcase 'object':\n\t\t\t\tif (origin instanceof RegExp) return origin.test(from)\n\t\t}\n\n\t\treturn false\n\t}\n\n\tconst handleOrigin = (response: Response, request: Request) => {\n\t\t// origin === `true` means any origin\n\t\tif (origin === true) {\n\t\t\tresponse.headers.set('vary', '*')\n\t\t\tresponse.headers.set(\n\t\t\t\t'access-control-allow-origin',\n\t\t\t\trequest.headers.get('Origin') || '*'\n\t\t\t)\n\n\t\t\treturn\n\t\t}\n\n\t\tif (anyOrigin) {\n\t\t\tresponse.headers.set('vary', '*')\n\t\t\tresponse.headers.set('access-control-allow-origin', '*')\n\n\t\t\treturn\n\t\t}\n\n\t\tif (!origins?.length) return\n\n\t\tconst headers: string[] = []\n\n\t\tif (origins.length) {\n\t\t\tconst from = request.headers.get('Origin') ?? ''\n\t\t\tfor (let i = 0; i < origins.length; i++) {\n\t\t\t\tconst value = processOrigin(origins[i]!, request, from)\n\t\t\t\tif (value === true) {\n\t\t\t\t\tresponse.headers.set('vary', origin ? 'Origin' : '*')\n\t\t\t\t\tresponse.headers.set(\n\t\t\t\t\t\t'access-control-allow-origin',\n\t\t\t\t\t\tfrom || '*'\n\t\t\t\t\t)\n\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tresponse.headers.set('vary', 'Origin')\n\t\tif (headers.length)\n\t\t\tresponse.headers.set(\n\t\t\t\t'access-control-allow-origin',\n\t\t\t\theaders.join(', ')\n\t\t\t)\n\t}\n\n\tconst handleMethod = (response: Response, method?: string | null) => {\n\t\tif (!method) return\n\n\t\tif (methods === true)\n\t\t\treturn response.headers.set(\n\t\t\t\t'access-control-allow-methods',\n\t\t\t\tmethod ?? '*'\n\t\t\t)\n\n\t\tif (methods === false || !methods?.length) return\n\n\t\tif (methods === '*')\n\t\t\treturn response.headers.set('access-control-allow-methods', '*')\n\n\t\tif (!Array.isArray(methods))\n\t\t\treturn response.headers.set('access-control-allow-methods', methods)\n\n\t\tresponse.headers.set('access-control-allow-methods', methods.join(', '))\n\t}\n\n\tconst setDefaultHeaders = (response: Response) => {\n\t\tif (typeof exposeHeaders === 'string')\n\t\t\tresponse.headers.set('access-control-expose-headers', exposeHeaders)\n\n\t\tif (typeof allowedHeaders === 'string')\n\t\t\tresponse.headers.set('access-control-allow-headers', allowedHeaders)\n\n\t\tif (credentials === true)\n\t\t\tresponse.headers.set('access-control-allow-credentials', 'true')\n\t}\n\n\tconst handlePreflight = async (request: Request): Promise<Response> => {\n\t\tconst response = empty(204)\n\n\t\thandleOrigin(response, request)\n\t\thandleMethod(\n\t\t\tresponse,\n\t\t\trequest.headers.get('access-control-request-method')\n\t\t)\n\n\t\tif (allowedHeaders === true || exposeHeaders === true) {\n\t\t\tif (allowedHeaders === true)\n\t\t\t\tresponse.headers.set(\n\t\t\t\t\t'access-control-allow-headers',\n\t\t\t\t\trequest.headers.get('access-control-request-headers') || ''\n\t\t\t\t)\n\n\t\t\tif (exposeHeaders === true)\n\t\t\t\tresponse.headers.set(\n\t\t\t\t\t'access-control-expose-headers',\n\t\t\t\t\tprocessHeaders(request.headers)\n\t\t\t\t)\n\t\t}\n\n\t\tif (maxAge)\n\t\t\tresponse.headers.set('access-control-max-age', maxAge.toString())\n\n\t\treturn response\n\t}\n\n\treturn async (request: Request, next: () => Promise<Response>) => {\n\t\t// Handle preflight requests\n\t\tif (preflight && request.method === 'OPTIONS') {\n\t\t\tconst response = empty(204)\n\n\t\t\thandleOrigin(response, request)\n\t\t\thandleMethod(\n\t\t\t\tresponse,\n\t\t\t\trequest.headers.get('access-control-request-method')\n\t\t\t)\n\n\t\t\tif (allowedHeaders === true || exposeHeaders === true) {\n\t\t\t\tif (allowedHeaders === true)\n\t\t\t\t\tresponse.headers.set(\n\t\t\t\t\t\t'access-control-allow-headers',\n\t\t\t\t\t\trequest.headers.get('access-control-request-headers') ||\n\t\t\t\t\t\t\t''\n\t\t\t\t\t)\n\n\t\t\t\tif (exposeHeaders === true)\n\t\t\t\t\tresponse.headers.set(\n\t\t\t\t\t\t'access-control-expose-headers',\n\t\t\t\t\t\tprocessHeaders(request.headers)\n\t\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (maxAge)\n\t\t\t\tresponse.headers.set(\n\t\t\t\t\t'access-control-max-age',\n\t\t\t\t\tmaxAge.toString()\n\t\t\t\t)\n\n\t\t\treturn response\n\t\t}\n\n\t\t// Process CORS for actual requests\n\t\tconst response = await next()\n\n\t\thandleOrigin(response, request)\n\t\thandleMethod(response, request.method)\n\t\tsetDefaultHeaders(response)\n\n\t\tif (allowedHeaders === true || exposeHeaders === true) {\n\t\t\tconst headers = processHeaders(request.headers)\n\n\t\t\tif (allowedHeaders === true)\n\t\t\t\tresponse.headers.set('access-control-allow-headers', headers)\n\n\t\t\tif (exposeHeaders === true)\n\t\t\t\tresponse.headers.set('access-control-expose-headers', headers)\n\t\t}\n\n\t\treturn response\n\t}\n}\n\nexport default cors\n"],"mappings":"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","names":["origin","response"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vafast/cors",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "CORS middleware plugin for Vafast framework",
5
5
  "type": "module",
6
6
  "author": {
@@ -42,18 +42,15 @@
42
42
  "LICENSE"
43
43
  ],
44
44
  "devDependencies": {
45
- "@types/bun": "^1.1.2",
46
45
  "@types/debug": "^4.1.12",
47
46
  "@types/node": "^24.3.0",
48
- "@typescript-eslint/eslint-plugin": "^7.9.0",
49
- "@typescript-eslint/parser": "^7.9.0",
50
- "eslint": "^9.2.0",
51
47
  "rimraf": "^6.0.1",
52
48
  "tsup": "^8.5.1",
53
49
  "typescript": "^5.4.5",
54
- "vafast": "^0.3.4"
50
+ "vafast": ">=0.3.11",
51
+ "vitest": "^4.0.16"
55
52
  },
56
53
  "peerDependencies": {
57
- "vafast": ">= 0.1.12"
54
+ "vafast": ">=0.3.11"
58
55
  }
59
56
  }