@clerk/express
Version:
Clerk server SDK for usage with Express
1 lines • 21.6 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":["defaultClerkClient"],"sources":["../src/clerkClient.ts","../src/errors.ts","../src/authenticateRequest.ts","../src/clerkMiddleware.ts","../src/getAuth.ts","../src/requireAuth.ts"],"sourcesContent":["import type { ClerkClient } from '@clerk/backend';\nimport { createClerkClient } from '@clerk/backend';\n\nimport { loadApiEnv, loadClientEnv } from './utils';\n\nlet clerkClientSingleton = {} as unknown as ClerkClient;\n\nexport const clerkClient = new Proxy(clerkClientSingleton, {\n get(_target, property: keyof ClerkClient) {\n if (property in clerkClientSingleton) {\n return clerkClientSingleton[property];\n }\n\n const env = { ...loadApiEnv(), ...loadClientEnv() };\n const client = createClerkClient({ ...env, userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}` });\n\n // if the client is initialized properly, cache it to a singleton instance variable\n // in the next invocation the guard at the top will be triggered instead of creating another instance\n if (env.secretKey) {\n clerkClientSingleton = client;\n }\n\n return client[property];\n },\n set() {\n return false;\n },\n});\n","const createErrorMessage = (msg: string) => {\n return `🔒 Clerk: ${msg.trim()}\n\n For more info, check out the docs: https://clerk.com/docs,\n or come say hi in our discord server: https://clerk.com/discord\n `;\n};\n\nexport const middlewareRequired = (fnName: string) =>\n createErrorMessage(`The \"clerkMiddleware\" should be registered before using \"${fnName}\".\nExample:\n\nimport express from 'express';\nimport { clerkMiddleware } from '@clerk/express';\n\nconst app = express();\napp.use(clerkMiddleware());\n`);\n\nexport const satelliteAndMissingProxyUrlAndDomain =\n 'Missing domain and proxyUrl. A satellite application needs to specify a domain or a proxyUrl';\nexport const satelliteAndMissingSignInUrl = `\nInvalid signInUrl. A satellite application requires a signInUrl for development instances.\nCheck if signInUrl is missing from your configuration or if it is not an absolute URL.`;\n","import { createClerkClient } from '@clerk/backend';\nimport type { RequestState } from '@clerk/backend/internal';\nimport { AuthStatus, createClerkRequest } from '@clerk/backend/internal';\nimport { clerkFrontendApiProxy, DEFAULT_PROXY_PATH, stripTrailingSlashes } from '@clerk/backend/proxy';\nimport { isDevelopmentFromSecretKey } from '@clerk/shared/keys';\nimport { logger } from '@clerk/shared/logger';\nimport { isHttpOrHttps, isProxyUrlRelative, isValidProxyUrl } from '@clerk/shared/proxy';\nimport { handleValueOrFn } from '@clerk/shared/utils';\nimport type { RequestHandler, Response } from 'express';\nimport { Readable } from 'stream';\n\nimport { clerkClient as defaultClerkClient } from './clerkClient';\nimport { satelliteAndMissingProxyUrlAndDomain, satelliteAndMissingSignInUrl } from './errors';\nimport type { AuthenticateRequestParams, ClerkMiddlewareOptions } from './types';\nimport {\n brandRequestAuth,\n incomingMessageToRequest,\n loadApiEnv,\n loadClientEnv,\n requestHasAuthObject,\n requestToProxyRequest,\n} from './utils';\n\n/**\n * @internal\n * Authenticates an Express request by wrapping clerkClient.authenticateRequest and\n * converts the express request object into a standard web request object\n *\n * @param opts - Configuration options for request authentication\n * @param opts.clerkClient - The Clerk client instance to use for authentication\n * @param opts.request - The Express request object to authenticate\n * @param opts.options - Optional middleware configuration options\n */\nexport const authenticateRequest = (opts: AuthenticateRequestParams) => {\n const { clerkClient, request, options } = opts;\n // Peel off middleware-only keys and the few options that need middleware-side\n // resolution (env fallbacks, URL normalization). Everything else is spread\n // straight through, so new AuthenticateRequestOptions/VerifyTokenOptions\n // fields flow to the backend without another code change here.\n const {\n clerkClient: _clerkClient,\n debug: _debug,\n frontendApiProxy: _frontendApiProxy,\n isSatellite: isSatelliteInput,\n domain: domainInput,\n signInUrl: signInUrlInput,\n proxyUrl: proxyUrlInput,\n secretKey: secretKeyInput,\n machineSecretKey: machineSecretKeyInput,\n publishableKey: publishableKeyInput,\n ...restOptions\n } = options || {};\n\n const clerkRequest = createClerkRequest(incomingMessageToRequest(request));\n const env = { ...loadApiEnv(), ...loadClientEnv() };\n\n const secretKey = secretKeyInput || env.secretKey;\n const machineSecretKey = machineSecretKeyInput || env.machineSecretKey;\n const publishableKey = publishableKeyInput || env.publishableKey;\n\n const isSatellite = handleValueOrFn(isSatelliteInput, clerkRequest.clerkUrl, env.isSatellite);\n const domain = handleValueOrFn(domainInput, clerkRequest.clerkUrl) || env.domain;\n const signInUrl = signInUrlInput || env.signInUrl;\n const proxyUrl = absoluteProxyUrl(\n handleValueOrFn(proxyUrlInput, clerkRequest.clerkUrl, env.proxyUrl),\n clerkRequest.clerkUrl.toString(),\n );\n\n if (isSatellite && !proxyUrl && !domain) {\n throw new Error(satelliteAndMissingProxyUrlAndDomain);\n }\n\n if (isSatellite && !isHttpOrHttps(signInUrl) && isDevelopmentFromSecretKey(secretKey || '')) {\n throw new Error(satelliteAndMissingSignInUrl);\n }\n\n return clerkClient.authenticateRequest(clerkRequest, {\n ...restOptions,\n secretKey,\n machineSecretKey,\n publishableKey,\n proxyUrl,\n isSatellite,\n domain,\n signInUrl,\n });\n};\n\nconst setResponseHeaders = (requestState: RequestState, res: Response): Error | undefined => {\n if (requestState.headers) {\n requestState.headers.forEach((value, key) => res.appendHeader(key, value));\n }\n return setResponseForHandshake(requestState, res);\n};\n\n/**\n * Depending on the auth state of the request, handles applying redirects and validating that a handshake state was properly handled.\n *\n * Returns an error if state is handshake without a redirect, otherwise returns undefined. res.writableEnded should be checked after this method is called.\n */\nconst setResponseForHandshake = (requestState: RequestState, res: Response): Error | undefined => {\n const hasLocationHeader = requestState.headers.get('location');\n if (hasLocationHeader) {\n // triggering a handshake redirect\n res.status(307).end();\n return;\n }\n\n if (requestState.status === AuthStatus.Handshake) {\n return new Error('Clerk: unexpected handshake without redirect');\n }\n\n return;\n};\n\nconst absoluteProxyUrl = (relativeOrAbsoluteUrl: string, baseUrl: string): string => {\n if (!relativeOrAbsoluteUrl || !isValidProxyUrl(relativeOrAbsoluteUrl) || !isProxyUrlRelative(relativeOrAbsoluteUrl)) {\n return relativeOrAbsoluteUrl;\n }\n return new URL(relativeOrAbsoluteUrl, baseUrl).toString();\n};\n\n// `apiUrl` and `apiVersion` are pinned at client construction time inside\n// `@clerk/backend`'s `createAuthenticateRequest` factory (build-time values\n// override runtime ones). The default singleton in `./clerkClient` is built\n// from env only, so passing these via `clerkMiddleware()` would be silently\n// ignored. When the caller hasn't supplied their own `clerkClient` but did\n// pass `apiUrl`/`apiVersion`, build a per-middleware client with those values.\nconst resolveDefaultClerkClient = (options: ClerkMiddlewareOptions) => {\n if (!options.apiUrl && !options.apiVersion) {\n return defaultClerkClient;\n }\n const env = { ...loadApiEnv(), ...loadClientEnv() };\n return createClerkClient({\n ...env,\n ...(options.apiUrl ? { apiUrl: options.apiUrl } : {}),\n ...(options.apiVersion ? { apiVersion: options.apiVersion } : {}),\n userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,\n });\n};\n\nexport const authenticateAndDecorateRequest = (options: ClerkMiddlewareOptions = {}): RequestHandler => {\n const clerkClient = options.clerkClient || resolveDefaultClerkClient(options);\n\n // Extract proxy configuration\n const frontendApiProxy = options.frontendApiProxy;\n const proxyPath = stripTrailingSlashes(frontendApiProxy?.path ?? DEFAULT_PROXY_PATH) || DEFAULT_PROXY_PATH;\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n const middleware: RequestHandler = async (request, response, next) => {\n // Skip authentication only when a Clerk middleware has already processed\n // this request. The brand check matters: a truthy `req.auth` is not proof\n // of that, since express-jwt, passport and other libraries set the same\n // property, and treating their value as ours would silently disable Clerk\n // authentication.\n if (requestHasAuthObject(request)) {\n return next();\n }\n\n if ('auth' in request) {\n logger.warnOnce(\n 'Clerk: another middleware has already set `req.auth` on this request. Clerk authentication will run anyway and overwrite it. To use another auth library alongside Clerk, configure it to store its state on a different request property.',\n );\n }\n\n const env = { ...loadApiEnv(), ...loadClientEnv() };\n const publishableKey = options.publishableKey || env.publishableKey;\n const secretKey = options.secretKey || env.secretKey;\n\n // Handle Frontend API proxy requests early, before authentication\n if (frontendApiProxy) {\n const requestUrl = new URL(request.originalUrl || request.url, `http://${request.headers.host}`);\n const isEnabled =\n typeof frontendApiProxy.enabled === 'function'\n ? frontendApiProxy.enabled(requestUrl)\n : frontendApiProxy.enabled;\n\n if (isEnabled && (requestUrl.pathname === proxyPath || requestUrl.pathname.startsWith(proxyPath + '/'))) {\n // Convert Express request to Fetch API Request\n const proxyRequest = requestToProxyRequest(request);\n\n // Call the core proxy function\n const proxyResponse = await clerkFrontendApiProxy(proxyRequest, {\n proxyPath,\n publishableKey,\n secretKey,\n });\n\n // Send the proxy response back to the client\n response.status(proxyResponse.status);\n proxyResponse.headers.forEach((value, key) => {\n response.setHeader(key, value);\n });\n\n if (proxyResponse.body) {\n const reader = proxyResponse.body.getReader();\n const stream = new Readable({\n async read() {\n try {\n const { done, value } = await reader.read();\n if (done) {\n this.push(null);\n } else {\n this.push(Buffer.from(value));\n }\n } catch (error) {\n this.destroy(error instanceof Error ? error : new Error(String(error)));\n }\n },\n });\n stream.pipe(response);\n } else {\n response.end();\n }\n return;\n }\n }\n\n // Pass the proxy path to authenticateRequest - the backend resolves it\n // against the request's public origin (from x-forwarded-* headers).\n let resolvedOptions = options;\n if (frontendApiProxy && !options.proxyUrl) {\n const requestUrl = new URL(request.originalUrl || request.url, `http://${request.headers.host}`);\n const isProxyEnabled =\n typeof frontendApiProxy.enabled === 'function'\n ? frontendApiProxy.enabled(requestUrl)\n : frontendApiProxy.enabled;\n if (isProxyEnabled) {\n resolvedOptions = { ...options, proxyUrl: proxyPath };\n }\n }\n\n try {\n const requestState = await authenticateRequest({\n clerkClient,\n request,\n options: resolvedOptions,\n });\n\n const err = setResponseHeaders(requestState, response);\n if (err) {\n return next(err);\n }\n if (response.writableEnded) {\n return;\n }\n\n const auth = brandRequestAuth((opts: Parameters<typeof requestState.toAuth>[0]) => requestState.toAuth(opts));\n\n Object.assign(request, { auth });\n\n next();\n } catch (err) {\n next(err);\n }\n };\n\n return middleware;\n};\n","import type { RequestHandler } from 'express';\n\nimport { authenticateAndDecorateRequest } from './authenticateRequest';\nimport type { ClerkMiddlewareOptions, ClerkMiddlewareOptionsCallback } from './types';\n\n/**\n * Middleware that integrates Clerk authentication into your Express application.\n * It checks the request's cookies and headers for a session JWT and, if found,\n * attaches the Auth object to the request object under the `auth` key.\n *\n * Accepts either a static options object or a callback that receives the request\n * and returns options. The callback form is useful for multi-domain setups where\n * the publishable key differs per domain.\n *\n * @example\n * app.use(clerkMiddleware(options));\n *\n * @example\n * const clerkClient = createClerkClient({ ... });\n * app.use(clerkMiddleware({ clerkClient }));\n *\n * @example\n * app.use(clerkMiddleware());\n *\n * @example\n * // Dynamic keys per domain\n * app.use(clerkMiddleware((req) => ({\n * publishableKey: req.hostname === 'example.com' ? PK_A : PK_B,\n * })));\n */\nexport const clerkMiddleware = (\n options: ClerkMiddlewareOptions | ClerkMiddlewareOptionsCallback = {},\n): RequestHandler => {\n if (typeof options !== 'function') {\n const authMiddleware = authenticateAndDecorateRequest({\n ...options,\n acceptsToken: 'any',\n });\n return (request, response, next) => {\n authMiddleware(request, response, next);\n };\n }\n\n return async (request, response, next) => {\n try {\n const resolvedOptions = await options(request);\n const handler = authenticateAndDecorateRequest({\n ...resolvedOptions,\n acceptsToken: 'any',\n });\n handler(request, response, next);\n } catch (err) {\n next(err);\n }\n };\n};\n","import type { AuthOptions, GetAuthFn } from '@clerk/backend/internal';\nimport { getAuthObjectForAcceptedToken } from '@clerk/backend/internal';\nimport type { Request as ExpressRequest } from 'express';\n\nimport { middlewareRequired } from './errors';\nimport { requestHasAuthObject } from './utils';\n\n/**\n * Retrieves the Clerk AuthObject using the current request object.\n *\n * @param {GetAuthOptions} options - Optional configuration for retrieving auth object.\n * @returns {AuthObject} Object with information about the request state and claims.\n * @throws {Error} `clerkMiddleware` or `requireAuth` is required to be set in the middleware chain before this util is used.\n */\nexport const getAuth: GetAuthFn<ExpressRequest> = ((req: ExpressRequest, options?: AuthOptions) => {\n if (!requestHasAuthObject(req)) {\n throw new Error(middlewareRequired('getAuth'));\n }\n\n const authObject = req.auth(options);\n\n return getAuthObjectForAcceptedToken({ authObject, acceptsToken: options?.acceptsToken });\n}) as GetAuthFn<ExpressRequest>;\n","import { deprecated } from '@clerk/shared/deprecated';\nimport type { RequestHandler } from 'express';\n\nimport { authenticateAndDecorateRequest } from './authenticateRequest';\nimport type { ClerkMiddlewareOptions, ExpressRequestWithAuth } from './types';\n\n/**\n * Middleware to require authentication for user requests.\n * Redirects unauthenticated requests to the sign-in url.\n *\n * @deprecated Use `clerkMiddleware()` with `getAuth()` instead.\n * `requireAuth` will be removed in the next major version.\n *\n * @example\n * // Before (deprecated)\n * import { requireAuth } from '@clerk/express'\n * router.get('/path', requireAuth(), getHandler)\n *\n * @example\n * // After (recommended)\n * import { clerkMiddleware, getAuth } from '@clerk/express'\n *\n * app.use(clerkMiddleware())\n *\n * app.get('/api/protected', (req, res) => {\n * const { userId } = getAuth(req);\n * if (!userId) {\n * return res.status(401).json({ error: 'Unauthorized' });\n * }\n * // handle authenticated request\n * })\n */\nexport const requireAuth = (options: ClerkMiddlewareOptions = {}): RequestHandler => {\n const authMiddleware = authenticateAndDecorateRequest({\n ...options,\n acceptsToken: 'any',\n });\n\n return (request, response, next) => {\n deprecated(\n 'requireAuth',\n 'Use `clerkMiddleware()` with `getAuth()` instead. `requireAuth` will be removed in the next major version.',\n );\n\n authMiddleware(request, response, err => {\n if (err) {\n return next(err);\n }\n\n const signInUrl = options.signInUrl || process.env.CLERK_SIGN_IN_URL || '/';\n\n if (!(request as ExpressRequestWithAuth).auth()?.userId) {\n return response.redirect(signInUrl);\n }\n\n next();\n });\n };\n};\n"],"mappings":";;;;;;;;;;;;;;AAKA,IAAI,uBAAuB,CAAC;AAE5B,MAAa,cAAc,IAAI,MAAM,sBAAsB;CACzD,IAAI,SAAS,UAA6B;EACxC,IAAI,YAAY,sBACd,OAAO,qBAAqB;EAG9B,MAAM,MAAM;GAAE,GAAG,WAAW;GAAG,GAAG,cAAc;EAAE;EAClD,MAAM,SAAS,kBAAkB;GAAE,GAAG;GAAK,WAAW;EAAqC,CAAC;EAI5F,IAAI,IAAI,WACN,uBAAuB;EAGzB,OAAO,OAAO;CAChB;CACA,MAAM;EACJ,OAAO;CACT;AACF,CAAC;;;;AC3BD,MAAM,sBAAsB,QAAgB;CAC1C,OAAO,aAAa,IAAI,KAAK,EAAE;;;;;AAKjC;AAEA,MAAa,sBAAsB,WACjC,mBAAmB,4DAA4D,OAAO;;;;;;;;CAQvF;AAED,MAAa,uCACX;AACF,MAAa,+BAA+B;;;;;;;;;;;;;;;;ACY5C,MAAa,uBAAuB,SAAoC;CACtE,MAAM,EAAE,aAAa,SAAS,YAAY;CAK1C,MAAM,EACJ,aAAa,cACb,OAAO,QACP,kBAAkB,mBAClB,aAAa,kBACb,QAAQ,aACR,WAAW,gBACX,UAAU,eACV,WAAW,gBACX,kBAAkB,uBAClB,gBAAgB,qBAChB,GAAG,gBACD,WAAW,CAAC;CAEhB,MAAM,eAAe,mBAAmB,yBAAyB,OAAO,CAAC;CACzE,MAAM,MAAM;EAAE,GAAG,WAAW;EAAG,GAAG,cAAc;CAAE;CAElD,MAAM,YAAY,kBAAkB,IAAI;CACxC,MAAM,mBAAmB,yBAAyB,IAAI;CACtD,MAAM,iBAAiB,uBAAuB,IAAI;CAElD,MAAM,cAAc,gBAAgB,kBAAkB,aAAa,UAAU,IAAI,WAAW;CAC5F,MAAM,SAAS,gBAAgB,aAAa,aAAa,QAAQ,KAAK,IAAI;CAC1E,MAAM,YAAY,kBAAkB,IAAI;CACxC,MAAM,WAAW,iBACf,gBAAgB,eAAe,aAAa,UAAU,IAAI,QAAQ,GAClE,aAAa,SAAS,SAAS,CACjC;CAEA,IAAI,eAAe,CAAC,YAAY,CAAC,QAC/B,MAAM,IAAI,MAAM,oCAAoC;CAGtD,IAAI,eAAe,CAAC,cAAc,SAAS,KAAK,2BAA2B,aAAa,EAAE,GACxF,MAAM,IAAI,MAAM,4BAA4B;CAG9C,OAAO,YAAY,oBAAoB,cAAc;EACnD,GAAG;EACH;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH;AAEA,MAAM,sBAAsB,cAA4B,QAAqC;CAC3F,IAAI,aAAa,SACf,aAAa,QAAQ,SAAS,OAAO,QAAQ,IAAI,aAAa,KAAK,KAAK,CAAC;CAE3E,OAAO,wBAAwB,cAAc,GAAG;AAClD;;;;;;AAOA,MAAM,2BAA2B,cAA4B,QAAqC;CAEhG,IAD0B,aAAa,QAAQ,IAAI,UAC/B,GAAG;EAErB,IAAI,OAAO,GAAG,CAAC,CAAC,IAAI;EACpB;CACF;CAEA,IAAI,aAAa,WAAW,WAAW,WACrC,uBAAO,IAAI,MAAM,8CAA8C;AAInE;AAEA,MAAM,oBAAoB,uBAA+B,YAA4B;CACnF,IAAI,CAAC,yBAAyB,CAAC,gBAAgB,qBAAqB,KAAK,CAAC,mBAAmB,qBAAqB,GAChH,OAAO;CAET,OAAO,IAAI,IAAI,uBAAuB,OAAO,CAAC,CAAC,SAAS;AAC1D;AAQA,MAAM,6BAA6B,YAAoC;CACrE,IAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,YAC9B,OAAOA;CAGT,OAAO,kBAAkB;EADX,GAAG,WAAW;EAAG,GAAG,cAAc;EAG9C,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACnD,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;EAC/D,WAAW;CACb,CAAC;AACH;AAEA,MAAa,kCAAkC,UAAkC,CAAC,MAAsB;CACtG,MAAM,cAAc,QAAQ,eAAe,0BAA0B,OAAO;CAG5E,MAAM,mBAAmB,QAAQ;CACjC,MAAM,YAAY,qBAAqB,kBAAkB,QAAQ,kBAAkB,KAAK;CAGxF,MAAM,aAA6B,OAAO,SAAS,UAAU,SAAS;EAMpE,IAAI,qBAAqB,OAAO,GAC9B,OAAO,KAAK;EAGd,IAAI,UAAU,SACZ,OAAO,SACL,4OACF;EAGF,MAAM,MAAM;GAAE,GAAG,WAAW;GAAG,GAAG,cAAc;EAAE;EAClD,MAAM,iBAAiB,QAAQ,kBAAkB,IAAI;EACrD,MAAM,YAAY,QAAQ,aAAa,IAAI;EAG3C,IAAI,kBAAkB;GACpB,MAAM,aAAa,IAAI,IAAI,QAAQ,eAAe,QAAQ,KAAK,UAAU,QAAQ,QAAQ,MAAM;GAM/F,KAJE,OAAO,iBAAiB,YAAY,aAChC,iBAAiB,QAAQ,UAAU,IACnC,iBAAiB,aAEL,WAAW,aAAa,aAAa,WAAW,SAAS,WAAW,YAAY,GAAG,IAAI;IAKvG,MAAM,gBAAgB,MAAM,sBAHP,sBAAsB,OAGkB,GAAG;KAC9D;KACA;KACA;IACF,CAAC;IAGD,SAAS,OAAO,cAAc,MAAM;IACpC,cAAc,QAAQ,SAAS,OAAO,QAAQ;KAC5C,SAAS,UAAU,KAAK,KAAK;IAC/B,CAAC;IAED,IAAI,cAAc,MAAM;KACtB,MAAM,SAAS,cAAc,KAAK,UAAU;KAe5C,IAdmB,SAAS,EAC1B,MAAM,OAAO;MACX,IAAI;OACF,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;OAC1C,IAAI,MACF,KAAK,KAAK,IAAI;YAEd,KAAK,KAAK,OAAO,KAAK,KAAK,CAAC;MAEhC,SAAS,OAAO;OACd,KAAK,QAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;MACxE;KACF,EACF,CACK,CAAC,CAAC,KAAK,QAAQ;IACtB,OACE,SAAS,IAAI;IAEf;GACF;EACF;EAIA,IAAI,kBAAkB;EACtB,IAAI,oBAAoB,CAAC,QAAQ,UAAU;GACzC,MAAM,aAAa,IAAI,IAAI,QAAQ,eAAe,QAAQ,KAAK,UAAU,QAAQ,QAAQ,MAAM;GAK/F,IAHE,OAAO,iBAAiB,YAAY,aAChC,iBAAiB,QAAQ,UAAU,IACnC,iBAAiB,SAErB,kBAAkB;IAAE,GAAG;IAAS,UAAU;GAAU;EAExD;EAEA,IAAI;GACF,MAAM,eAAe,MAAM,oBAAoB;IAC7C;IACA;IACA,SAAS;GACX,CAAC;GAED,MAAM,MAAM,mBAAmB,cAAc,QAAQ;GACrD,IAAI,KACF,OAAO,KAAK,GAAG;GAEjB,IAAI,SAAS,eACX;GAGF,MAAM,OAAO,kBAAkB,SAAoD,aAAa,OAAO,IAAI,CAAC;GAE5G,OAAO,OAAO,SAAS,EAAE,KAAK,CAAC;GAE/B,KAAK;EACP,SAAS,KAAK;GACZ,KAAK,GAAG;EACV;CACF;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpOA,MAAa,mBACX,UAAmE,CAAC,MACjD;CACnB,IAAI,OAAO,YAAY,YAAY;EACjC,MAAM,iBAAiB,+BAA+B;GACpD,GAAG;GACH,cAAc;EAChB,CAAC;EACD,QAAQ,SAAS,UAAU,SAAS;GAClC,eAAe,SAAS,UAAU,IAAI;EACxC;CACF;CAEA,OAAO,OAAO,SAAS,UAAU,SAAS;EACxC,IAAI;GAMF,AAJgB,+BAA+B;IAC7C,GAAG,MAFyB,QAAQ,OAAO;IAG3C,cAAc;GAChB,CACM,CAAC,CAAC,SAAS,UAAU,IAAI;EACjC,SAAS,KAAK;GACZ,KAAK,GAAG;EACV;CACF;AACF;;;;;;;;;;;ACzCA,MAAa,YAAuC,KAAqB,YAA0B;CACjG,IAAI,CAAC,qBAAqB,GAAG,GAC3B,MAAM,IAAI,MAAM,mBAAmB,SAAS,CAAC;CAK/C,OAAO,8BAA8B;EAAE,YAFpB,IAAI,KAAK,OAEoB;EAAG,cAAc,SAAS;CAAa,CAAC;AAC1F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACUA,MAAa,eAAe,UAAkC,CAAC,MAAsB;CACnF,MAAM,iBAAiB,+BAA+B;EACpD,GAAG;EACH,cAAc;CAChB,CAAC;CAED,QAAQ,SAAS,UAAU,SAAS;EAClC,WACE,eACA,4GACF;EAEA,eAAe,SAAS,WAAU,QAAO;GACvC,IAAI,KACF,OAAO,KAAK,GAAG;GAGjB,MAAM,YAAY,QAAQ,aAAa,QAAQ,IAAI,qBAAqB;GAExE,IAAI,CAAE,QAAmC,KAAK,CAAC,EAAE,QAC/C,OAAO,SAAS,SAAS,SAAS;GAGpC,KAAK;EACP,CAAC;CACH;AACF"}