@clerk/nextjs
Version:
Clerk SDK for NextJS
1 lines • 18.9 kB
Source Map (JSON)
{"version":3,"sources":["../../../src/server/clerkMiddleware.ts"],"sourcesContent":["import type { AuthObject, ClerkClient } from '@clerk/backend';\nimport type { AuthenticateRequestOptions, ClerkRequest, RedirectFun, RequestState } from '@clerk/backend/internal';\nimport { AuthStatus, constants, createClerkRequest, createRedirect } from '@clerk/backend/internal';\nimport { eventMethodCalled } from '@clerk/shared/telemetry';\nimport { notFound as nextjsNotFound } from 'next/navigation';\nimport type { NextMiddleware, NextRequest } from 'next/server';\nimport { NextResponse } from 'next/server';\n\nimport { isRedirect, serverRedirectWithAuth, setHeader } from '../utils';\nimport { withLogger } from '../utils/debugLogger';\nimport { canUseKeyless } from '../utils/feature-flags';\nimport { clerkClient } from './clerkClient';\nimport { PUBLISHABLE_KEY, SECRET_KEY, SIGN_IN_URL, SIGN_UP_URL } from './constants';\nimport { errorThrower } from './errorThrower';\nimport { getKeylessCookieValue } from './keyless';\nimport { clerkMiddlewareRequestDataStorage, clerkMiddlewareRequestDataStore } from './middleware-storage';\nimport {\n isNextjsNotFoundError,\n isNextjsRedirectError,\n isRedirectToSignInError,\n nextjsRedirectError,\n redirectToSignInError,\n} from './nextErrors';\nimport type { AuthProtect } from './protect';\nimport { createProtect } from './protect';\nimport type { NextMiddlewareEvtParam, NextMiddlewareRequestParam, NextMiddlewareReturn } from './types';\nimport {\n assertKey,\n decorateRequest,\n handleMultiDomainAndProxy,\n redirectAdapter,\n setRequestHeadersOnNextResponse,\n} from './utils';\n\nexport type ClerkMiddlewareAuthObject = AuthObject & {\n redirectToSignIn: RedirectFun<Response>;\n};\n\nexport interface ClerkMiddlewareAuth {\n (): Promise<ClerkMiddlewareAuthObject>;\n\n protect: AuthProtect;\n}\n\ntype ClerkMiddlewareHandler = (\n auth: ClerkMiddlewareAuth,\n request: NextMiddlewareRequestParam,\n event: NextMiddlewareEvtParam,\n) => NextMiddlewareReturn;\n\n/**\n * The `clerkMiddleware()` function accepts an optional object. The following options are available.\n * @interface\n */\nexport type ClerkMiddlewareOptions = AuthenticateRequestOptions & {\n /**\n * If true, additional debug information will be logged to the console.\n */\n debug?: boolean;\n};\n\ntype ClerkMiddlewareOptionsCallback = (req: NextRequest) => ClerkMiddlewareOptions;\n\n/**\n * Middleware for Next.js that handles authentication and authorization with Clerk.\n * For more details, please refer to the docs: https://clerk.com/docs/references/nextjs/clerk-middleware\n */\ninterface ClerkMiddleware {\n /**\n * @example\n * export default clerkMiddleware((auth, request, event) => { ... }, options);\n */\n (handler: ClerkMiddlewareHandler, options?: ClerkMiddlewareOptions): NextMiddleware;\n\n /**\n * @example\n * export default clerkMiddleware((auth, request, event) => { ... }, (req) => options);\n */\n (handler: ClerkMiddlewareHandler, options?: ClerkMiddlewareOptionsCallback): NextMiddleware;\n\n /**\n * @example\n * export default clerkMiddleware(options);\n */\n (options?: ClerkMiddlewareOptions): NextMiddleware;\n\n /**\n * @example\n * export default clerkMiddleware;\n */\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\n}\n\n/**\n * The `clerkMiddleware()` helper integrates Clerk authentication into your Next.js application through Middleware. `clerkMiddleware()` is compatible with both the App and Pages routers.\n */\n// @ts-expect-error TS is not happy here. Will dig into it\nexport const clerkMiddleware: ClerkMiddleware = (...args: unknown[]) => {\n const [request, event] = parseRequestAndEvent(args);\n const [handler, params] = parseHandlerAndOptions(args);\n\n return clerkMiddlewareRequestDataStorage.run(clerkMiddlewareRequestDataStore, () => {\n const baseNextMiddleware: NextMiddleware = withLogger('clerkMiddleware', logger => async (request, event) => {\n // Handles the case where `options` is a callback function to dynamically access `NextRequest`\n const resolvedParams = typeof params === 'function' ? params(request) : params;\n\n const keyless = await getKeylessCookieValue(name => request.cookies.get(name)?.value);\n\n const publishableKey = assertKey(\n resolvedParams.publishableKey || PUBLISHABLE_KEY || keyless?.publishableKey,\n () => errorThrower.throwMissingPublishableKeyError(),\n );\n\n const secretKey = assertKey(resolvedParams.secretKey || SECRET_KEY || keyless?.secretKey, () =>\n errorThrower.throwMissingSecretKeyError(),\n );\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\n\n const options = {\n publishableKey,\n secretKey,\n signInUrl,\n signUpUrl,\n ...resolvedParams,\n };\n\n // Propagates the request data to be accessed on the server application runtime from helpers such as `clerkClient`\n clerkMiddlewareRequestDataStore.set('requestData', options);\n const resolvedClerkClient = await clerkClient();\n\n resolvedClerkClient.telemetry.record(\n eventMethodCalled('clerkMiddleware', {\n handler: Boolean(handler),\n satellite: Boolean(options.isSatellite),\n proxy: Boolean(options.proxyUrl),\n }),\n );\n\n if (options.debug) {\n logger.enable();\n }\n const clerkRequest = createClerkRequest(request);\n logger.debug('options', options);\n logger.debug('url', () => clerkRequest.toJSON());\n\n const requestState = await resolvedClerkClient.authenticateRequest(\n clerkRequest,\n createAuthenticateRequestOptions(clerkRequest, options),\n );\n\n logger.debug('requestState', () => ({\n status: requestState.status,\n // @ts-expect-error : FIXME\n headers: JSON.stringify(Object.fromEntries(requestState.headers)),\n reason: requestState.reason,\n }));\n\n const locationHeader = requestState.headers.get(constants.Headers.Location);\n if (locationHeader) {\n return new Response(null, { status: 307, headers: requestState.headers });\n } else if (requestState.status === AuthStatus.Handshake) {\n throw new Error('Clerk: handshake status without redirect');\n }\n\n const authObject = requestState.toAuth();\n logger.debug('auth', () => ({ auth: authObject, debug: authObject.debug() }));\n\n const redirectToSignIn = createMiddlewareRedirectToSignIn(clerkRequest);\n const protect = await createMiddlewareProtect(clerkRequest, authObject, redirectToSignIn);\n\n const authObjWithMethods: ClerkMiddlewareAuthObject = Object.assign(authObject, { redirectToSignIn });\n const authHandler = () => Promise.resolve(authObjWithMethods);\n authHandler.protect = protect;\n\n let handlerResult: Response = NextResponse.next();\n try {\n const userHandlerResult = await clerkMiddlewareRequestDataStorage.run(\n clerkMiddlewareRequestDataStore,\n async () => handler?.(authHandler, request, event),\n );\n handlerResult = userHandlerResult || handlerResult;\n } catch (e: any) {\n handlerResult = handleControlFlowErrors(e, clerkRequest, request, requestState);\n }\n\n // TODO @nikos: we need to make this more generic\n // and move the logic in clerk/backend\n if (requestState.headers) {\n requestState.headers.forEach((value, key) => {\n handlerResult.headers.append(key, value);\n });\n }\n\n if (isRedirect(handlerResult)) {\n logger.debug('handlerResult is redirect');\n return serverRedirectWithAuth(clerkRequest, handlerResult, options);\n }\n\n if (options.debug) {\n setRequestHeadersOnNextResponse(handlerResult, clerkRequest, { [constants.Headers.EnableDebug]: 'true' });\n }\n\n decorateRequest(clerkRequest, handlerResult, requestState, resolvedParams, {\n publishableKey: keyless?.publishableKey,\n secretKey: keyless?.secretKey,\n });\n\n return handlerResult;\n });\n\n const keylessMiddleware: NextMiddleware = async (request, event) => {\n /**\n * This mechanism replaces a full-page reload. Ensures that middleware will re-run and authenticate the request properly without the secret key or publishable key to be missing.\n */\n if (isKeylessSyncRequest(request)) {\n return returnBackFromKeylessSync(request);\n }\n\n const resolvedParams = typeof params === 'function' ? params(request) : params;\n const keyless = await getKeylessCookieValue(name => request.cookies.get(name)?.value);\n const isMissingPublishableKey = !(resolvedParams.publishableKey || PUBLISHABLE_KEY || keyless?.publishableKey);\n /**\n * In keyless mode, if the publishable key is missing, let the request through, to render `<ClerkProvider/>` that will resume the flow gracefully.\n */\n if (isMissingPublishableKey) {\n const res = NextResponse.next();\n setRequestHeadersOnNextResponse(res, request, {\n [constants.Headers.AuthStatus]: 'signed-out',\n });\n return res;\n }\n\n return baseNextMiddleware(request, event);\n };\n\n const nextMiddleware: NextMiddleware = async (request, event) => {\n if (canUseKeyless) {\n return keylessMiddleware(request, event);\n }\n\n return baseNextMiddleware(request, event);\n };\n\n // If we have a request and event, we're being called as a middleware directly\n // eg, export default clerkMiddleware;\n if (request && event) {\n return nextMiddleware(request, event);\n }\n\n // Otherwise, return a middleware that can be called with a request and event\n // eg, export default clerkMiddleware(auth => { ... });\n return nextMiddleware;\n });\n};\n\nconst parseRequestAndEvent = (args: unknown[]) => {\n return [args[0] instanceof Request ? args[0] : undefined, args[0] instanceof Request ? args[1] : undefined] as [\n NextMiddlewareRequestParam | undefined,\n NextMiddlewareEvtParam | undefined,\n ];\n};\n\nconst parseHandlerAndOptions = (args: unknown[]) => {\n return [\n typeof args[0] === 'function' ? args[0] : undefined,\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\n ] as [ClerkMiddlewareHandler | undefined, ClerkMiddlewareOptions | ClerkMiddlewareOptionsCallback];\n};\n\nconst isKeylessSyncRequest = (request: NextMiddlewareRequestParam) =>\n request.nextUrl.pathname === '/clerk-sync-keyless';\n\nconst returnBackFromKeylessSync = (request: NextMiddlewareRequestParam) => {\n const returnUrl = request.nextUrl.searchParams.get('returnUrl');\n const url = new URL(request.url);\n url.pathname = '';\n\n return NextResponse.redirect(returnUrl || url.toString());\n};\n\ntype AuthenticateRequest = Pick<ClerkClient, 'authenticateRequest'>['authenticateRequest'];\n\nexport const createAuthenticateRequestOptions = (\n clerkRequest: ClerkRequest,\n options: ClerkMiddlewareOptions,\n): Parameters<AuthenticateRequest>[1] => {\n return {\n ...options,\n ...handleMultiDomainAndProxy(clerkRequest, options),\n };\n};\n\nconst createMiddlewareRedirectToSignIn = (\n clerkRequest: ClerkRequest,\n): ClerkMiddlewareAuthObject['redirectToSignIn'] => {\n return (opts = {}) => {\n const url = clerkRequest.clerkUrl.toString();\n redirectToSignInError(url, opts.returnBackUrl);\n };\n};\n\nconst createMiddlewareProtect = (\n clerkRequest: ClerkRequest,\n authObject: AuthObject,\n redirectToSignIn: RedirectFun<Response>,\n) => {\n return (async (params: any, options: any) => {\n const notFound = () => nextjsNotFound();\n\n const redirect = (url: string) =>\n nextjsRedirectError(url, {\n redirectUrl: url,\n });\n\n return createProtect({ request: clerkRequest, redirect, notFound, authObject, redirectToSignIn })(params, options);\n }) as unknown as Promise<AuthProtect>;\n};\n\n// Handle errors thrown by protect() and redirectToSignIn() calls,\n// as we want to align the APIs between middleware, pages and route handlers\n// Normally, middleware requires to explicitly return a response, but we want to\n// avoid discrepancies between the APIs as it's easy to miss the `return` statement\n// especially when copy-pasting code from one place to another.\n// This function handles the known errors thrown by the APIs described above,\n// and returns the appropriate response.\nconst handleControlFlowErrors = (\n e: any,\n clerkRequest: ClerkRequest,\n nextRequest: NextRequest,\n requestState: RequestState,\n): Response => {\n if (isNextjsNotFoundError(e)) {\n // Rewrite to a bogus URL to force not found error\n return setHeader(\n // This is an internal rewrite purely to trigger a not found error. We do not want Next.js to think that the\n // destination URL is a valid page, so we use `nextRequest.url` as the base for the fake URL, which Next.js\n // understands is an internal URL and won't run middleware against the request.\n NextResponse.rewrite(new URL(`/clerk_${Date.now()}`, nextRequest.url)),\n constants.Headers.AuthReason,\n 'protect-rewrite',\n );\n }\n\n if (isRedirectToSignInError(e)) {\n return createRedirect({\n redirectAdapter,\n baseUrl: clerkRequest.clerkUrl,\n signInUrl: requestState.signInUrl,\n signUpUrl: requestState.signUpUrl,\n publishableKey: requestState.publishableKey,\n }).redirectToSignIn({ returnBackUrl: e.returnBackUrl });\n }\n\n if (isNextjsRedirectError(e)) {\n return redirectAdapter(e.redirectUrl);\n }\n\n throw e;\n};\n"],"mappings":";AAEA,SAAS,YAAY,WAAW,oBAAoB,sBAAsB;AAC1E,SAAS,yBAAyB;AAClC,SAAS,YAAY,sBAAsB;AAE3C,SAAS,oBAAoB;AAE7B,SAAS,YAAY,wBAAwB,iBAAiB;AAC9D,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB,YAAY,aAAa,mBAAmB;AACtE,SAAS,oBAAoB;AAC7B,SAAS,6BAA6B;AACtC,SAAS,mCAAmC,uCAAuC;AACnF;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,qBAAqB;AAE9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAiEA,MAAM,kBAAmC,IAAI,SAAoB;AACtE,QAAM,CAAC,SAAS,KAAK,IAAI,qBAAqB,IAAI;AAClD,QAAM,CAAC,SAAS,MAAM,IAAI,uBAAuB,IAAI;AAErD,SAAO,kCAAkC,IAAI,iCAAiC,MAAM;AAClF,UAAM,qBAAqC,WAAW,mBAAmB,YAAU,OAAOA,UAASC,WAAU;AAE3G,YAAM,iBAAiB,OAAO,WAAW,aAAa,OAAOD,QAAO,IAAI;AAExE,YAAM,UAAU,MAAM,sBAAsB,UAAK;AA1GvD;AA0G0D,qBAAAA,SAAQ,QAAQ,IAAI,IAAI,MAAxB,mBAA2B;AAAA,OAAK;AAEpF,YAAM,iBAAiB;AAAA,QACrB,eAAe,kBAAkB,oBAAmB,mCAAS;AAAA,QAC7D,MAAM,aAAa,gCAAgC;AAAA,MACrD;AAEA,YAAM,YAAY;AAAA,QAAU,eAAe,aAAa,eAAc,mCAAS;AAAA,QAAW,MACxF,aAAa,2BAA2B;AAAA,MAC1C;AACA,YAAM,YAAY,eAAe,aAAa;AAC9C,YAAM,YAAY,eAAe,aAAa;AAE9C,YAAM,UAAU;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAG;AAAA,MACL;AAGA,sCAAgC,IAAI,eAAe,OAAO;AAC1D,YAAM,sBAAsB,MAAM,YAAY;AAE9C,0BAAoB,UAAU;AAAA,QAC5B,kBAAkB,mBAAmB;AAAA,UACnC,SAAS,QAAQ,OAAO;AAAA,UACxB,WAAW,QAAQ,QAAQ,WAAW;AAAA,UACtC,OAAO,QAAQ,QAAQ,QAAQ;AAAA,QACjC,CAAC;AAAA,MACH;AAEA,UAAI,QAAQ,OAAO;AACjB,eAAO,OAAO;AAAA,MAChB;AACA,YAAM,eAAe,mBAAmBA,QAAO;AAC/C,aAAO,MAAM,WAAW,OAAO;AAC/B,aAAO,MAAM,OAAO,MAAM,aAAa,OAAO,CAAC;AAE/C,YAAM,eAAe,MAAM,oBAAoB;AAAA,QAC7C;AAAA,QACA,iCAAiC,cAAc,OAAO;AAAA,MACxD;AAEA,aAAO,MAAM,gBAAgB,OAAO;AAAA,QAClC,QAAQ,aAAa;AAAA;AAAA,QAErB,SAAS,KAAK,UAAU,OAAO,YAAY,aAAa,OAAO,CAAC;AAAA,QAChE,QAAQ,aAAa;AAAA,MACvB,EAAE;AAEF,YAAM,iBAAiB,aAAa,QAAQ,IAAI,UAAU,QAAQ,QAAQ;AAC1E,UAAI,gBAAgB;AAClB,eAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,SAAS,aAAa,QAAQ,CAAC;AAAA,MAC1E,WAAW,aAAa,WAAW,WAAW,WAAW;AACvD,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC5D;AAEA,YAAM,aAAa,aAAa,OAAO;AACvC,aAAO,MAAM,QAAQ,OAAO,EAAE,MAAM,YAAY,OAAO,WAAW,MAAM,EAAE,EAAE;AAE5E,YAAM,mBAAmB,iCAAiC,YAAY;AACtE,YAAM,UAAU,MAAM,wBAAwB,cAAc,YAAY,gBAAgB;AAExF,YAAM,qBAAgD,OAAO,OAAO,YAAY,EAAE,iBAAiB,CAAC;AACpG,YAAM,cAAc,MAAM,QAAQ,QAAQ,kBAAkB;AAC5D,kBAAY,UAAU;AAEtB,UAAI,gBAA0B,aAAa,KAAK;AAChD,UAAI;AACF,cAAM,oBAAoB,MAAM,kCAAkC;AAAA,UAChE;AAAA,UACA,YAAY,mCAAU,aAAaA,UAASC;AAAA,QAC9C;AACA,wBAAgB,qBAAqB;AAAA,MACvC,SAAS,GAAQ;AACf,wBAAgB,wBAAwB,GAAG,cAAcD,UAAS,YAAY;AAAA,MAChF;AAIA,UAAI,aAAa,SAAS;AACxB,qBAAa,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC3C,wBAAc,QAAQ,OAAO,KAAK,KAAK;AAAA,QACzC,CAAC;AAAA,MACH;AAEA,UAAI,WAAW,aAAa,GAAG;AAC7B,eAAO,MAAM,2BAA2B;AACxC,eAAO,uBAAuB,cAAc,eAAe,OAAO;AAAA,MACpE;AAEA,UAAI,QAAQ,OAAO;AACjB,wCAAgC,eAAe,cAAc,EAAE,CAAC,UAAU,QAAQ,WAAW,GAAG,OAAO,CAAC;AAAA,MAC1G;AAEA,sBAAgB,cAAc,eAAe,cAAc,gBAAgB;AAAA,QACzE,gBAAgB,mCAAS;AAAA,QACzB,WAAW,mCAAS;AAAA,MACtB,CAAC;AAED,aAAO;AAAA,IACT,CAAC;AAED,UAAM,oBAAoC,OAAOA,UAASC,WAAU;AAIlE,UAAI,qBAAqBD,QAAO,GAAG;AACjC,eAAO,0BAA0BA,QAAO;AAAA,MAC1C;AAEA,YAAM,iBAAiB,OAAO,WAAW,aAAa,OAAOA,QAAO,IAAI;AACxE,YAAM,UAAU,MAAM,sBAAsB,UAAK;AA5NvD;AA4N0D,qBAAAA,SAAQ,QAAQ,IAAI,IAAI,MAAxB,mBAA2B;AAAA,OAAK;AACpF,YAAM,0BAA0B,EAAE,eAAe,kBAAkB,oBAAmB,mCAAS;AAI/F,UAAI,yBAAyB;AAC3B,cAAM,MAAM,aAAa,KAAK;AAC9B,wCAAgC,KAAKA,UAAS;AAAA,UAC5C,CAAC,UAAU,QAAQ,UAAU,GAAG;AAAA,QAClC,CAAC;AACD,eAAO;AAAA,MACT;AAEA,aAAO,mBAAmBA,UAASC,MAAK;AAAA,IAC1C;AAEA,UAAM,iBAAiC,OAAOD,UAASC,WAAU;AAC/D,UAAI,eAAe;AACjB,eAAO,kBAAkBD,UAASC,MAAK;AAAA,MACzC;AAEA,aAAO,mBAAmBD,UAASC,MAAK;AAAA,IAC1C;AAIA,QAAI,WAAW,OAAO;AACpB,aAAO,eAAe,SAAS,KAAK;AAAA,IACtC;AAIA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,MAAM,uBAAuB,CAAC,SAAoB;AAChD,SAAO,CAAC,KAAK,CAAC,aAAa,UAAU,KAAK,CAAC,IAAI,QAAW,KAAK,CAAC,aAAa,UAAU,KAAK,CAAC,IAAI,MAAS;AAI5G;AAEA,MAAM,yBAAyB,CAAC,SAAoB;AAClD,SAAO;AAAA,IACL,OAAO,KAAK,CAAC,MAAM,aAAa,KAAK,CAAC,IAAI;AAAA,KACzC,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC;AAAA,EACnF;AACF;AAEA,MAAM,uBAAuB,CAAC,YAC5B,QAAQ,QAAQ,aAAa;AAE/B,MAAM,4BAA4B,CAAC,YAAwC;AACzE,QAAM,YAAY,QAAQ,QAAQ,aAAa,IAAI,WAAW;AAC9D,QAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,MAAI,WAAW;AAEf,SAAO,aAAa,SAAS,aAAa,IAAI,SAAS,CAAC;AAC1D;AAIO,MAAM,mCAAmC,CAC9C,cACA,YACuC;AACvC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,0BAA0B,cAAc,OAAO;AAAA,EACpD;AACF;AAEA,MAAM,mCAAmC,CACvC,iBACkD;AAClD,SAAO,CAAC,OAAO,CAAC,MAAM;AACpB,UAAM,MAAM,aAAa,SAAS,SAAS;AAC3C,0BAAsB,KAAK,KAAK,aAAa;AAAA,EAC/C;AACF;AAEA,MAAM,0BAA0B,CAC9B,cACA,YACA,qBACG;AACH,SAAQ,OAAO,QAAa,YAAiB;AAC3C,UAAM,WAAW,MAAM,eAAe;AAEtC,UAAM,WAAW,CAAC,QAChB,oBAAoB,KAAK;AAAA,MACvB,aAAa;AAAA,IACf,CAAC;AAEH,WAAO,cAAc,EAAE,SAAS,cAAc,UAAU,UAAU,YAAY,iBAAiB,CAAC,EAAE,QAAQ,OAAO;AAAA,EACnH;AACF;AASA,MAAM,0BAA0B,CAC9B,GACA,cACA,aACA,iBACa;AACb,MAAI,sBAAsB,CAAC,GAAG;AAE5B,WAAO;AAAA;AAAA;AAAA;AAAA,MAIL,aAAa,QAAQ,IAAI,IAAI,UAAU,KAAK,IAAI,CAAC,IAAI,YAAY,GAAG,CAAC;AAAA,MACrE,UAAU,QAAQ;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,wBAAwB,CAAC,GAAG;AAC9B,WAAO,eAAe;AAAA,MACpB;AAAA,MACA,SAAS,aAAa;AAAA,MACtB,WAAW,aAAa;AAAA,MACxB,WAAW,aAAa;AAAA,MACxB,gBAAgB,aAAa;AAAA,IAC/B,CAAC,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,CAAC;AAAA,EACxD;AAEA,MAAI,sBAAsB,CAAC,GAAG;AAC5B,WAAO,gBAAgB,EAAE,WAAW;AAAA,EACtC;AAEA,QAAM;AACR;","names":["request","event"]}