{"version":3,"file":"middleware.mjs","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import {\n\tcreateEndpoint,\n\ttype Endpoint,\n\ttype EndpointContext,\n\ttype EndpointOptions,\n} from \"./endpoint\";\nimport {\n\tcreateInternalContext,\n\ttype InferBody,\n\ttype InferBodyInput,\n\ttype InferHeaders,\n\ttype InferHeadersInput,\n\ttype InferMiddlewareBody,\n\ttype InferMiddlewareQuery,\n\ttype InferQuery,\n\ttype InferQueryInput,\n\ttype InferRequest,\n\ttype InferRequestInput,\n\ttype InferUse,\n\ttype InputContext,\n} from \"./context\";\nimport type { Prettify } from \"./helper\";\nimport { isAPIError } from \"./utils\";\nimport { kAPIErrorHeaderSymbol } from \"./error\";\n\nexport interface MiddlewareOptions extends Omit {}\n\nexport type MiddlewareResponse = null | void | undefined | Record;\n\nexport type MiddlewareContext<\n\tOptions extends MiddlewareOptions,\n\tContext = {},\n> = EndpointContext<\n\tstring,\n\tOptions & {\n\t\tmethod: \"*\";\n\t}\n> & {\n\t/**\n\t * Method\n\t *\n\t * The request method\n\t */\n\tmethod: string;\n\t/**\n\t * Path\n\t *\n\t * The path of the endpoint\n\t */\n\tpath: string;\n\t/**\n\t * Body\n\t *\n\t * The body object will be the parsed JSON from the request and validated\n\t * against the body schema if it exists\n\t */\n\tbody: InferMiddlewareBody;\n\t/**\n\t * Query\n\t *\n\t * The query object will be the parsed query string from the request\n\t * and validated against the query schema if it exists\n\t */\n\tquery: InferMiddlewareQuery;\n\t/**\n\t * Params\n\t *\n\t * If the path is `/user/:id` and the request is `/user/1` then the\n\t * params will\n\t * be `{ id: \"1\" }` and if the path includes a wildcard like `/user/*`\n\t * then the\n\t * params will be `{ _: \"1\" }` where `_` is the wildcard key. If the\n\t * wildcard\n\t * is named like `/user/**:name` then the params will be `{ name: string }`\n\t */\n\tparams: string;\n\t/**\n\t * Request object\n\t *\n\t * If `requireRequest` is set to true in the endpoint options this will be\n\t * required\n\t */\n\trequest: InferRequest;\n\t/**\n\t * Headers\n\t *\n\t * If `requireHeaders` is set to true in the endpoint options this will be\n\t * required\n\t */\n\theaders: InferHeaders;\n\t/**\n\t * Set header\n\t *\n\t * If it's called outside of a request it will just be ignored.\n\t */\n\tsetHeader: (key: string, value: string) => void;\n\t/**\n\t * Get header\n\t *\n\t * If it's called outside of a request it will just return null\n\t *\n\t * @param key - The key of the header\n\t * @returns\n\t */\n\tgetHeader: (key: string) => string | null;\n\t/**\n\t * JSON\n\t *\n\t * a helper function to create a JSON response with\n\t * the correct headers\n\t * and status code. If `asResponse` is set to true in\n\t * the context then\n\t * it will return a Response object instead of the\n\t * JSON object.\n\t *\n\t * @param json - The JSON object to return\n\t * @param routerResponse - The response object to\n\t * return if `asResponse` is\n\t * true in the context this will take precedence\n\t */\n\tjson: | null>(\n\t\tjson: R,\n\t\trouterResponse?:\n\t\t\t| {\n\t\t\t\t\tstatus?: number;\n\t\t\t\t\theaders?: Record;\n\t\t\t\t\tresponse?: Response;\n\t\t\t }\n\t\t\t| Response,\n\t) => Promise;\n\t/**\n\t * Middleware context\n\t */\n\tcontext: Prettify;\n};\n\nexport function createMiddleware(\n\toptions: Options,\n\thandler: (context: MiddlewareContext) => Promise,\n): >(\n\tinputContext: InputCtx,\n) => Promise;\nexport function createMiddleware(\n\thandler: (context: MiddlewareContext) => Promise,\n): >(\n\tinputContext: InputCtx,\n) => Promise;\nexport function createMiddleware(optionsOrHandler: any, handler?: any) {\n\tconst internalHandler = async (inputCtx: InputContext) => {\n\t\tconst context = inputCtx as InputContext;\n\t\tconst _handler =\n\t\t\ttypeof optionsOrHandler === \"function\" ? optionsOrHandler : handler;\n\t\tconst options =\n\t\t\ttypeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\t\tconst internalContext = await createInternalContext(context, {\n\t\t\toptions,\n\t\t\tpath: \"/\",\n\t\t});\n\n\t\tif (!_handler) {\n\t\t\tthrow new Error(\"handler must be defined\");\n\t\t}\n\t\ttry {\n\t\t\tconst response = await _handler(internalContext as any);\n\t\t\tconst headers = internalContext.responseHeaders;\n\t\t\treturn context.returnHeaders\n\t\t\t\t? {\n\t\t\t\t\t\theaders,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t}\n\t\t\t\t: response;\n\t\t} catch (e) {\n\t\t\t// fixme(alex): this is workaround that set-cookie headers are not accessible when error is thrown from middleware\n\t\t\tif (isAPIError(e)) {\n\t\t\t\tObject.defineProperty(e, kAPIErrorHeaderSymbol, {\n\t\t\t\t\tenumerable: false,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn internalContext.responseHeaders;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t};\n\tinternalHandler.options =\n\t\ttypeof optionsOrHandler === \"function\" ? {} : optionsOrHandler;\n\treturn internalHandler;\n}\n\nexport type MiddlewareInputContext =\n\tInferBodyInput &\n\t\tInferQueryInput &\n\t\tInferRequestInput &\n\t\tInferHeadersInput & {\n\t\t\tasResponse?: boolean;\n\t\t\treturnHeaders?: boolean;\n\t\t\tuse?: Middleware[];\n\t\t};\n\nexport type Middleware<\n\tOptions extends MiddlewareOptions = MiddlewareOptions,\n\tHandler extends (inputCtx: any) => Promise = any,\n> = Handler & {\n\toptions: Options;\n};\n\ncreateMiddleware.create = <\n\tE extends {\n\t\tuse?: Middleware[];\n\t},\n>(\n\topts?: E,\n) => {\n\ttype InferredContext = InferUse;\n\tfunction fn(\n\t\toptions: Options,\n\t\thandler: (ctx: MiddlewareContext) => Promise,\n\t): (inputContext: MiddlewareInputContext) => Promise;\n\tfunction fn(\n\t\thandler: (ctx: MiddlewareContext) => Promise,\n\t): (inputContext: MiddlewareInputContext) => Promise;\n\tfunction fn(optionsOrHandler: any, handler?: any) {\n\t\tif (typeof optionsOrHandler === \"function\") {\n\t\t\treturn createMiddleware(\n\t\t\t\t{\n\t\t\t\t\tuse: opts?.use,\n\t\t\t\t},\n\t\t\t\toptionsOrHandler,\n\t\t\t);\n\t\t}\n\t\tif (!handler) {\n\t\t\tthrow new Error(\"Middleware handler is required\");\n\t\t}\n\t\tconst middleware = createMiddleware(\n\t\t\t{\n\t\t\t\t...optionsOrHandler,\n\t\t\t\tmethod: \"*\",\n\t\t\t\tuse: [...(opts?.use || []), ...(optionsOrHandler.use || [])],\n\t\t\t},\n\t\t\thandler,\n\t\t);\n\t\treturn middleware as any;\n\t}\n\treturn fn;\n};\n"],"mappings":";;;;;;AAmJA,SAAgB,iBAAiB,kBAAuB,SAAe;CACtE,MAAM,kBAAkB,OAAO,aAAqC;EACnE,MAAM,UAAU;EAChB,MAAM,WACL,OAAO,qBAAqB,aAAa,mBAAmB;EAG7D,MAAM,kBAAkB,MAAM,sBAAsB,SAAS;GAC5D,SAFA,OAAO,qBAAqB,aAAa,EAAE,GAAG;GAG9C,MAAM;GACN,CAAC;AAEF,MAAI,CAAC,SACJ,OAAM,IAAI,MAAM,0BAA0B;AAE3C,MAAI;GACH,MAAM,WAAW,MAAM,SAAS,gBAAuB;GACvD,MAAM,UAAU,gBAAgB;AAChC,UAAO,QAAQ,gBACZ;IACA;IACA;IACA,GACA;WACK,GAAG;AAEX,OAAI,WAAW,EAAE,CAChB,QAAO,eAAe,GAAG,uBAAuB;IAC/C,YAAY;IACZ,cAAc;IACd,MAAM;AACL,YAAO,gBAAgB;;IAExB,CAAC;AAEH,SAAM;;;AAGR,iBAAgB,UACf,OAAO,qBAAqB,aAAa,EAAE,GAAG;AAC/C,QAAO;;AAoBR,iBAAiB,UAKhB,SACI;CASJ,SAAS,GAAG,kBAAuB,SAAe;AACjD,MAAI,OAAO,qBAAqB,WAC/B,QAAO,iBACN,EACC,KAAK,MAAM,KACX,EACD,iBACA;AAEF,MAAI,CAAC,QACJ,OAAM,IAAI,MAAM,iCAAiC;AAUlD,SARmB,iBAClB;GACC,GAAG;GACH,QAAQ;GACR,KAAK,CAAC,GAAI,MAAM,OAAO,EAAE,EAAG,GAAI,iBAAiB,OAAO,EAAE,CAAE;GAC5D,EACD,QACA;;AAGF,QAAO"}