better_auth_core/
plugin_runtime.rs1use std::sync::{Arc, OnceLock, Weak};
4
5use crate::request_runtime::RuntimeIdentity;
6use crate::user_fields::UserConfig;
7use crate::{AuthContext, AuthError, AuthResult, AuthSchema};
8
9mod fields;
10pub use fields::ModelFields;
11
12struct Binding<S: AuthSchema> {
13 identity: RuntimeIdentity,
14 context: Weak<AuthContext<S>>,
15}
16
17pub struct PluginRuntime<S: AuthSchema>(Arc<OnceLock<Binding<S>>>);
19
20impl<S: AuthSchema> Clone for PluginRuntime<S> {
21 fn clone(&self) -> Self {
22 Self(self.0.clone())
23 }
24}
25
26impl<S: AuthSchema> Default for PluginRuntime<S> {
27 fn default() -> Self {
28 Self(Arc::default())
29 }
30}
31
32impl<S: AuthSchema> PluginRuntime<S> {
33 pub fn context(&self) -> AuthResult<Arc<AuthContext<S>>> {
35 self.0
36 .get()
37 .and_then(|binding| {
38 binding
39 .identity
40 .current()
41 .or_else(|| binding.context.upgrade())
42 })
43 .ok_or_else(|| {
44 AuthError::config("Plugin runtime is not initialized or has been dropped")
45 })
46 }
47
48 pub fn bind(&self, context: &Arc<AuthContext<S>>) -> AuthResult<()> {
50 self.0
51 .set(Binding {
52 identity: context.runtime_identity(),
53 context: Arc::downgrade(context),
54 })
55 .map_err(|_| AuthError::config("Plugin runtime is already initialized"))
56 }
57}
58
59#[derive(Clone)]
61pub struct AdapterUserFields(pub UserConfig);
62
63pub fn resolve_user_fields(
64 application: &UserConfig,
65 plugins: UserConfig,
66) -> (UserConfig, UserConfig) {
67 let mut adapter = plugins.clone();
68 if let Some(fields) = &application.additional_fields {
69 adapter.fields_mut().extend(fields.clone());
70 }
71 let mut endpoint = application.clone();
72 if let Some(fields) = plugins.additional_fields {
73 endpoint.fields_mut().extend(fields);
74 }
75 (adapter, endpoint)
76}