better-auth
Version:
The most comprehensive authentication framework for TypeScript.
1 lines • 15.1 kB
Source Map (JSON)
{"version":3,"file":"to-auth-endpoints.mjs","names":["api: Record<\n\t\tstring,\n\t\t((\n\t\t\tcontext: EndpointContext<string, any> & InputContext<string, any>,\n\t\t) => Promise<any>) & {\n\t\t\tpath?: string | undefined;\n\t\t\toptions?: EndpointOptions | undefined;\n\t\t}\n\t>","internalContext: InternalContext","key","modifiedContext: Partial<InternalContext>","beforeHooks: {\n\t\tmatcher: (context: HookEndpointContext) => boolean;\n\t\thandler: AuthMiddleware;\n\t}[]","afterHooks: {\n\t\tmatcher: (context: HookEndpointContext) => boolean;\n\t\thandler: AuthMiddleware;\n\t}[]"],"sources":["../../src/api/to-auth-endpoints.ts"],"sourcesContent":["import type { AuthContext, HookEndpointContext } from \"@better-auth/core\";\nimport type { AuthEndpoint, AuthMiddleware } from \"@better-auth/core/api\";\nimport {\n\thasRequestState,\n\trunWithEndpointContext,\n\trunWithRequestState,\n} from \"@better-auth/core/context\";\nimport { shouldPublishLog } from \"@better-auth/core/env\";\nimport type {\n\tEndpointContext,\n\tEndpointOptions,\n\tInputContext,\n} from \"better-call\";\nimport { APIError, toResponse } from \"better-call\";\nimport { createDefu } from \"defu\";\n\ntype InternalContext = Partial<\n\tInputContext<string, any> & EndpointContext<string, any>\n> & {\n\tpath: string;\n\tasResponse?: boolean | undefined;\n\tcontext: AuthContext & {\n\t\tlogger: AuthContext[\"logger\"];\n\t\treturned?: unknown | undefined;\n\t\tresponseHeaders?: Headers | undefined;\n\t};\n};\n\nconst defuReplaceArrays = createDefu((obj, key, value) => {\n\tif (Array.isArray(obj[key]) && Array.isArray(value)) {\n\t\tobj[key] = value;\n\t\treturn true;\n\t}\n});\n\ntype UserInputContext = Partial<\n\tInputContext<string, any> & EndpointContext<string, any>\n>;\n\nexport function toAuthEndpoints<\n\tconst E extends Record<\n\t\tstring,\n\t\tOmit<AuthEndpoint<string, EndpointOptions, any>, \"wrap\">\n\t>,\n>(endpoints: E, ctx: AuthContext | Promise<AuthContext>): E {\n\tconst api: Record<\n\t\tstring,\n\t\t((\n\t\t\tcontext: EndpointContext<string, any> & InputContext<string, any>,\n\t\t) => Promise<any>) & {\n\t\t\tpath?: string | undefined;\n\t\t\toptions?: EndpointOptions | undefined;\n\t\t}\n\t> = {};\n\n\tfor (const [key, endpoint] of Object.entries(endpoints)) {\n\t\tapi[key] = async (context?: UserInputContext) => {\n\t\t\tconst run = async () => {\n\t\t\t\tconst authContext = await ctx;\n\t\t\t\tlet internalContext: InternalContext = {\n\t\t\t\t\t...context,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\t...authContext,\n\t\t\t\t\t\treturned: undefined,\n\t\t\t\t\t\tresponseHeaders: undefined,\n\t\t\t\t\t\tsession: null,\n\t\t\t\t\t},\n\t\t\t\t\tpath: endpoint.path,\n\t\t\t\t\theaders: context?.headers ? new Headers(context?.headers) : undefined,\n\t\t\t\t};\n\t\t\t\treturn runWithEndpointContext(internalContext, async () => {\n\t\t\t\t\tconst { beforeHooks, afterHooks } = getHooks(authContext);\n\t\t\t\t\tconst before = await runBeforeHooks(internalContext, beforeHooks);\n\t\t\t\t\t/**\n\t\t\t\t\t * If `before.context` is returned, it should\n\t\t\t\t\t * get merged with the original context\n\t\t\t\t\t */\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"context\" in before &&\n\t\t\t\t\t\tbefore.context &&\n\t\t\t\t\t\ttypeof before.context === \"object\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst { headers, ...rest } = before.context as {\n\t\t\t\t\t\t\theaders: Headers;\n\t\t\t\t\t\t};\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Headers should be merged differently\n\t\t\t\t\t\t * so the hook doesn't override the whole\n\t\t\t\t\t\t * header\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (headers) {\n\t\t\t\t\t\t\theaders.forEach((value, key) => {\n\t\t\t\t\t\t\t\t(internalContext.headers as Headers).set(key, value);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinternalContext = defuReplaceArrays(rest, internalContext);\n\t\t\t\t\t} else if (before) {\n\t\t\t\t\t\t/* Return before hook response if it's anything other than a context return */\n\t\t\t\t\t\treturn context?.asResponse\n\t\t\t\t\t\t\t? toResponse(before, {\n\t\t\t\t\t\t\t\t\theaders: context?.headers,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t: context?.returnHeaders\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\theaders: context?.headers,\n\t\t\t\t\t\t\t\t\t\tresponse: before,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: before;\n\t\t\t\t\t}\n\n\t\t\t\t\tinternalContext.asResponse = false;\n\t\t\t\t\tinternalContext.returnHeaders = true;\n\t\t\t\t\tinternalContext.returnStatus = true;\n\t\t\t\t\tconst result = (await runWithEndpointContext(internalContext, () =>\n\t\t\t\t\t\t(endpoint as any)(internalContext as any),\n\t\t\t\t\t).catch((e: any) => {\n\t\t\t\t\t\tif (e instanceof APIError) {\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * API Errors from response are caught\n\t\t\t\t\t\t\t * and returned to hooks\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tresponse: e,\n\t\t\t\t\t\t\t\tstatus: e.statusCode,\n\t\t\t\t\t\t\t\theaders: e.headers ? new Headers(e.headers) : null,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t})) as {\n\t\t\t\t\t\theaders: Headers;\n\t\t\t\t\t\tresponse: any;\n\t\t\t\t\t\tstatus: number;\n\t\t\t\t\t};\n\n\t\t\t\t\t//if response object is returned we skip after hooks and post processing\n\t\t\t\t\tif (result && result instanceof Response) {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\n\t\t\t\t\tinternalContext.context.returned = result.response;\n\t\t\t\t\tinternalContext.context.responseHeaders = result.headers;\n\n\t\t\t\t\tconst after = await runAfterHooks(internalContext, afterHooks);\n\n\t\t\t\t\tif (after.response) {\n\t\t\t\t\t\tresult.response = after.response;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tresult.response instanceof APIError &&\n\t\t\t\t\t\tshouldPublishLog(authContext.logger.level, \"debug\")\n\t\t\t\t\t) {\n\t\t\t\t\t\t// inherit stack from errorStack if debug mode is enabled\n\t\t\t\t\t\tresult.response.stack = result.response.errorStack;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (result.response instanceof APIError && !context?.asResponse) {\n\t\t\t\t\t\tthrow result.response;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst response = context?.asResponse\n\t\t\t\t\t\t? toResponse(result.response, {\n\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\tstatus: result.status,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: context?.returnHeaders\n\t\t\t\t\t\t\t? context?.returnStatus\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\t\t\tresponse: result.response,\n\t\t\t\t\t\t\t\t\t\tstatus: result.status,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\theaders: result.headers,\n\t\t\t\t\t\t\t\t\t\tresponse: result.response,\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: context?.returnStatus\n\t\t\t\t\t\t\t\t? { response: result.response, status: result.status }\n\t\t\t\t\t\t\t\t: result.response;\n\t\t\t\t\treturn response;\n\t\t\t\t});\n\t\t\t};\n\t\t\tif (await hasRequestState()) {\n\t\t\t\treturn run();\n\t\t\t} else {\n\t\t\t\tconst store = new WeakMap();\n\t\t\t\treturn runWithRequestState(store, run);\n\t\t\t}\n\t\t};\n\t\tapi[key].path = endpoint.path;\n\t\tapi[key].options = endpoint.options;\n\t}\n\treturn api as unknown as E;\n}\n\nasync function runBeforeHooks(\n\tcontext: InternalContext,\n\thooks: {\n\t\tmatcher: (context: HookEndpointContext) => boolean;\n\t\thandler: AuthMiddleware;\n\t}[],\n) {\n\tlet modifiedContext: Partial<InternalContext> = {};\n\n\tfor (const hook of hooks) {\n\t\tif (hook.matcher(context)) {\n\t\t\tconst result = await hook\n\t\t\t\t.handler({\n\t\t\t\t\t...context,\n\t\t\t\t\treturnHeaders: false,\n\t\t\t\t})\n\t\t\t\t.catch((e: unknown) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\te instanceof APIError &&\n\t\t\t\t\t\tshouldPublishLog(context.context.logger.level, \"debug\")\n\t\t\t\t\t) {\n\t\t\t\t\t\t// inherit stack from errorStack if debug mode is enabled\n\t\t\t\t\t\te.stack = e.errorStack;\n\t\t\t\t\t}\n\t\t\t\t\tthrow e;\n\t\t\t\t});\n\t\t\tif (result && typeof result === \"object\") {\n\t\t\t\tif (\"context\" in result && typeof result.context === \"object\") {\n\t\t\t\t\tconst { headers, ...rest } =\n\t\t\t\t\t\tresult.context as Partial<InternalContext>;\n\t\t\t\t\tif (headers instanceof Headers) {\n\t\t\t\t\t\tif (modifiedContext.headers) {\n\t\t\t\t\t\t\theaders.forEach((value, key) => {\n\t\t\t\t\t\t\t\tmodifiedContext.headers?.set(key, value);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmodifiedContext.headers = headers;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tmodifiedContext = defuReplaceArrays(rest, modifiedContext);\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t}\n\treturn { context: modifiedContext };\n}\n\nasync function runAfterHooks(\n\tcontext: InternalContext,\n\thooks: {\n\t\tmatcher: (context: HookEndpointContext) => boolean;\n\t\thandler: AuthMiddleware;\n\t}[],\n) {\n\tfor (const hook of hooks) {\n\t\tif (hook.matcher(context)) {\n\t\t\tconst result = (await hook.handler(context).catch((e) => {\n\t\t\t\tif (e instanceof APIError) {\n\t\t\t\t\tif (shouldPublishLog(context.context.logger.level, \"debug\")) {\n\t\t\t\t\t\t// inherit stack from errorStack if debug mode is enabled\n\t\t\t\t\t\te.stack = e.errorStack;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tresponse: e,\n\t\t\t\t\t\theaders: e.headers ? new Headers(e.headers) : null,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t\t})) as {\n\t\t\t\tresponse: any;\n\t\t\t\theaders: Headers;\n\t\t\t};\n\t\t\tif (result.headers) {\n\t\t\t\tresult.headers.forEach((value, key) => {\n\t\t\t\t\tif (!context.context.responseHeaders) {\n\t\t\t\t\t\tcontext.context.responseHeaders = new Headers({\n\t\t\t\t\t\t\t[key]: value,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (key.toLowerCase() === \"set-cookie\") {\n\t\t\t\t\t\t\tcontext.context.responseHeaders.append(key, value);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcontext.context.responseHeaders.set(key, value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (result.response) {\n\t\t\t\tcontext.context.returned = result.response;\n\t\t\t}\n\t\t}\n\t}\n\treturn {\n\t\tresponse: context.context.returned,\n\t\theaders: context.context.responseHeaders,\n\t};\n}\n\nfunction getHooks(authContext: AuthContext) {\n\tconst plugins = authContext.options.plugins || [];\n\tconst beforeHooks: {\n\t\tmatcher: (context: HookEndpointContext) => boolean;\n\t\thandler: AuthMiddleware;\n\t}[] = [];\n\tconst afterHooks: {\n\t\tmatcher: (context: HookEndpointContext) => boolean;\n\t\thandler: AuthMiddleware;\n\t}[] = [];\n\tif (authContext.options.hooks?.before) {\n\t\tbeforeHooks.push({\n\t\t\tmatcher: () => true,\n\t\t\thandler: authContext.options.hooks.before,\n\t\t});\n\t}\n\tif (authContext.options.hooks?.after) {\n\t\tafterHooks.push({\n\t\t\tmatcher: () => true,\n\t\t\thandler: authContext.options.hooks.after,\n\t\t});\n\t}\n\tconst pluginBeforeHooks = plugins\n\t\t.map((plugin) => {\n\t\t\tif (plugin.hooks?.before) {\n\t\t\t\treturn plugin.hooks.before;\n\t\t\t}\n\t\t})\n\t\t.filter((plugin) => plugin !== undefined)\n\t\t.flat();\n\tconst pluginAfterHooks = plugins\n\t\t.map((plugin) => {\n\t\t\tif (plugin.hooks?.after) {\n\t\t\t\treturn plugin.hooks.after;\n\t\t\t}\n\t\t})\n\t\t.filter((plugin) => plugin !== undefined)\n\t\t.flat();\n\n\t/**\n\t * Add plugin added hooks at last\n\t */\n\tif (pluginBeforeHooks.length) beforeHooks.push(...pluginBeforeHooks);\n\tif (pluginAfterHooks.length) afterHooks.push(...pluginAfterHooks);\n\n\treturn {\n\t\tbeforeHooks,\n\t\tafterHooks,\n\t};\n}\n"],"mappings":"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"}