better-auth
Version:
The most comprehensive authentication framework for TypeScript.
1 lines • 11.8 kB
Source Map (JSON)
{"version":3,"file":"with-hooks.mjs","names":["entityToDelete: T | null","entitiesToDelete: T[]"],"sources":["../../src/db/with-hooks.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport {\n\tgetCurrentAdapter,\n\tgetCurrentAuthContext,\n} from \"@better-auth/core/context\";\nimport type { BaseModelNames } from \"@better-auth/core/db\";\nimport type { DBAdapter, Where } from \"@better-auth/core/db/adapter\";\n\nexport function getWithHooks(\n\tadapter: DBAdapter<BetterAuthOptions>,\n\tctx: {\n\t\toptions: BetterAuthOptions;\n\t\thooks: Exclude<BetterAuthOptions[\"databaseHooks\"], undefined>[];\n\t},\n) {\n\tconst hooks = ctx.hooks;\n\tasync function createWithHooks<T extends Record<string, any>>(\n\t\tdata: T,\n\t\tmodel: BaseModelNames,\n\t\tcustomCreateFn?:\n\t\t\t| {\n\t\t\t\t\tfn: (data: Record<string, any>) => void | Promise<any>;\n\t\t\t\t\texecuteMainFn?: boolean;\n\t\t\t }\n\t\t\t| undefined,\n\t) {\n\t\tconst context = await getCurrentAuthContext().catch(() => null);\n\t\tlet actualData = data;\n\t\tfor (const hook of hooks || []) {\n\t\t\tconst toRun = hook[model]?.create?.before;\n\t\t\tif (toRun) {\n\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\tconst result = await toRun(actualData as any, context);\n\t\t\t\tif (result === false) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst isObject = typeof result === \"object\" && \"data\" in result;\n\t\t\t\tif (isObject) {\n\t\t\t\t\tactualData = {\n\t\t\t\t\t\t...actualData,\n\t\t\t\t\t\t...result.data,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst customCreated = customCreateFn\n\t\t\t? await customCreateFn.fn(actualData)\n\t\t\t: null;\n\t\tconst created =\n\t\t\t!customCreateFn || customCreateFn.executeMainFn\n\t\t\t\t? await (await getCurrentAdapter(adapter)).create<T>({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tdata: actualData as any,\n\t\t\t\t\t\tforceAllowId: true,\n\t\t\t\t\t})\n\t\t\t\t: customCreated;\n\n\t\tfor (const hook of hooks || []) {\n\t\t\tconst toRun = hook[model]?.create?.after;\n\t\t\tif (toRun) {\n\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\tawait toRun(created as any, context);\n\t\t\t}\n\t\t}\n\n\t\treturn created;\n\t}\n\n\tasync function updateWithHooks<T extends Record<string, any>>(\n\t\tdata: any,\n\t\twhere: Where[],\n\t\tmodel: BaseModelNames,\n\t\tcustomUpdateFn?:\n\t\t\t| {\n\t\t\t\t\tfn: (data: Record<string, any>) => void | Promise<any>;\n\t\t\t\t\texecuteMainFn?: boolean;\n\t\t\t }\n\t\t\t| undefined,\n\t) {\n\t\tconst context = await getCurrentAuthContext().catch(() => null);\n\t\tlet actualData = data;\n\n\t\tfor (const hook of hooks || []) {\n\t\t\tconst toRun = hook[model]?.update?.before;\n\t\t\tif (toRun) {\n\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\tconst result = await toRun(data as any, context);\n\t\t\t\tif (result === false) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst isObject = typeof result === \"object\" && \"data\" in result;\n\t\t\t\tif (isObject) {\n\t\t\t\t\tactualData = {\n\t\t\t\t\t\t...actualData,\n\t\t\t\t\t\t...result.data,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst customUpdated = customUpdateFn\n\t\t\t? await customUpdateFn.fn(actualData)\n\t\t\t: null;\n\n\t\tconst updated =\n\t\t\t!customUpdateFn || customUpdateFn.executeMainFn\n\t\t\t\t? await (await getCurrentAdapter(adapter)).update<T>({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tupdate: actualData,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t})\n\t\t\t\t: customUpdated;\n\n\t\tfor (const hook of hooks || []) {\n\t\t\tconst toRun = hook[model]?.update?.after;\n\t\t\tif (toRun) {\n\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\tawait toRun(updated as any, context);\n\t\t\t}\n\t\t}\n\t\treturn updated;\n\t}\n\n\tasync function updateManyWithHooks<_T extends Record<string, any>>(\n\t\tdata: any,\n\t\twhere: Where[],\n\t\tmodel: BaseModelNames,\n\t\tcustomUpdateFn?:\n\t\t\t| {\n\t\t\t\t\tfn: (data: Record<string, any>) => void | Promise<any>;\n\t\t\t\t\texecuteMainFn?: boolean;\n\t\t\t }\n\t\t\t| undefined,\n\t) {\n\t\tconst context = await getCurrentAuthContext().catch(() => null);\n\t\tlet actualData = data;\n\n\t\tfor (const hook of hooks || []) {\n\t\t\tconst toRun = hook[model]?.update?.before;\n\t\t\tif (toRun) {\n\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\tconst result = await toRun(data as any, context);\n\t\t\t\tif (result === false) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst isObject = typeof result === \"object\" && \"data\" in result;\n\t\t\t\tif (isObject) {\n\t\t\t\t\tactualData = {\n\t\t\t\t\t\t...actualData,\n\t\t\t\t\t\t...result.data,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst customUpdated = customUpdateFn\n\t\t\t? await customUpdateFn.fn(actualData)\n\t\t\t: null;\n\n\t\tconst updated =\n\t\t\t!customUpdateFn || customUpdateFn.executeMainFn\n\t\t\t\t? await (await getCurrentAdapter(adapter)).updateMany({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tupdate: actualData,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t})\n\t\t\t\t: customUpdated;\n\n\t\tfor (const hook of hooks || []) {\n\t\t\tconst toRun = hook[model]?.update?.after;\n\t\t\tif (toRun) {\n\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\tawait toRun(updated as any, context);\n\t\t\t}\n\t\t}\n\n\t\treturn updated;\n\t}\n\n\tasync function deleteWithHooks<T extends Record<string, any>>(\n\t\twhere: Where[],\n\t\tmodel: BaseModelNames,\n\t\tcustomDeleteFn?:\n\t\t\t| {\n\t\t\t\t\tfn: (where: Where[]) => void | Promise<any>;\n\t\t\t\t\texecuteMainFn?: boolean;\n\t\t\t }\n\t\t\t| undefined,\n\t) {\n\t\tconst context = await getCurrentAuthContext().catch(() => null);\n\t\tlet entityToDelete: T | null = null;\n\n\t\ttry {\n\t\t\tconst entities = await (await getCurrentAdapter(adapter)).findMany<T>({\n\t\t\t\tmodel,\n\t\t\t\twhere,\n\t\t\t\tlimit: 1,\n\t\t\t});\n\t\t\tentityToDelete = entities[0] || null;\n\t\t} catch {\n\t\t\t// If we can't find the entity, we'll still proceed with deletion\n\t\t}\n\n\t\tif (entityToDelete) {\n\t\t\tfor (const hook of hooks || []) {\n\t\t\t\tconst toRun = hook[model]?.delete?.before;\n\t\t\t\tif (toRun) {\n\t\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\t\tconst result = await toRun(entityToDelete as any, context);\n\t\t\t\t\tif (result === false) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst customDeleted = customDeleteFn\n\t\t\t? await customDeleteFn.fn(where)\n\t\t\t: null;\n\n\t\tconst deleted =\n\t\t\t!customDeleteFn || customDeleteFn.executeMainFn\n\t\t\t\t? await (await getCurrentAdapter(adapter)).delete({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t})\n\t\t\t\t: customDeleted;\n\n\t\tif (entityToDelete) {\n\t\t\tfor (const hook of hooks || []) {\n\t\t\t\tconst toRun = hook[model]?.delete?.after;\n\t\t\t\tif (toRun) {\n\t\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\t\tawait toRun(entityToDelete as any, context);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn deleted;\n\t}\n\n\tasync function deleteManyWithHooks<T extends Record<string, any>>(\n\t\twhere: Where[],\n\t\tmodel: BaseModelNames,\n\t\tcustomDeleteFn?:\n\t\t\t| {\n\t\t\t\t\tfn: (where: Where[]) => void | Promise<any>;\n\t\t\t\t\texecuteMainFn?: boolean;\n\t\t\t }\n\t\t\t| undefined,\n\t) {\n\t\tconst context = await getCurrentAuthContext().catch(() => null);\n\t\tlet entitiesToDelete: T[] = [];\n\n\t\ttry {\n\t\t\tentitiesToDelete = await (await getCurrentAdapter(adapter)).findMany<T>({\n\t\t\t\tmodel,\n\t\t\t\twhere,\n\t\t\t});\n\t\t} catch {\n\t\t\t// If we can't find the entities, we'll still proceed with deletion\n\t\t}\n\n\t\tfor (const entity of entitiesToDelete) {\n\t\t\tfor (const hook of hooks || []) {\n\t\t\t\tconst toRun = hook[model]?.delete?.before;\n\t\t\t\tif (toRun) {\n\t\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\t\tconst result = await toRun(entity as any, context);\n\t\t\t\t\tif (result === false) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst customDeleted = customDeleteFn\n\t\t\t? await customDeleteFn.fn(where)\n\t\t\t: null;\n\n\t\tconst deleted =\n\t\t\t!customDeleteFn || customDeleteFn.executeMainFn\n\t\t\t\t? await (await getCurrentAdapter(adapter)).deleteMany({\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\twhere,\n\t\t\t\t\t})\n\t\t\t\t: customDeleted;\n\n\t\tfor (const entity of entitiesToDelete) {\n\t\t\tfor (const hook of hooks || []) {\n\t\t\t\tconst toRun = hook[model]?.delete?.after;\n\t\t\t\tif (toRun) {\n\t\t\t\t\t// @ts-expect-error context type mismatch\n\t\t\t\t\tawait toRun(entity as any, context);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn deleted;\n\t}\n\n\treturn {\n\t\tcreateWithHooks,\n\t\tupdateWithHooks,\n\t\tupdateManyWithHooks,\n\t\tdeleteWithHooks,\n\t\tdeleteManyWithHooks,\n\t};\n}\n"],"mappings":"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"}