@wopr-network/platform-core 1.50.0 → 1.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/better-auth.js +54 -1
- package/package.json +1 -1
- package/src/auth/better-auth.ts +50 -1
package/dist/auth/better-auth.js
CHANGED
|
@@ -46,13 +46,66 @@ export async function getUserCreator() {
|
|
|
46
46
|
}
|
|
47
47
|
return _userCreatorPromise;
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetch the primary verified email from GitHub's /user/emails API.
|
|
51
|
+
* GitHub returns null for profile.email when the user's email is private.
|
|
52
|
+
* The user:email scope grants access to this endpoint.
|
|
53
|
+
*/
|
|
54
|
+
async function fetchGitHubPrimaryEmail(accessToken) {
|
|
55
|
+
try {
|
|
56
|
+
const res = await fetch("https://api.github.com/user/emails", {
|
|
57
|
+
headers: { Authorization: `Bearer ${accessToken}`, Accept: "application/vnd.github+json" },
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok)
|
|
60
|
+
return null;
|
|
61
|
+
const emails = (await res.json());
|
|
62
|
+
const primary = emails.find((e) => e.primary && e.verified);
|
|
63
|
+
return primary?.email ?? emails.find((e) => e.verified)?.email ?? null;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.error("Failed to fetch GitHub primary email from /user/emails:", error);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
49
70
|
/** Resolve OAuth providers from config or env vars. */
|
|
50
71
|
function resolveSocialProviders(cfg) {
|
|
51
72
|
if (cfg.socialProviders)
|
|
52
73
|
return cfg.socialProviders;
|
|
53
74
|
return {
|
|
54
75
|
...(process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET
|
|
55
|
-
? {
|
|
76
|
+
? {
|
|
77
|
+
github: {
|
|
78
|
+
clientId: process.env.GITHUB_CLIENT_ID,
|
|
79
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
|
80
|
+
getUserInfo: async (token) => {
|
|
81
|
+
const accessToken = token.accessToken;
|
|
82
|
+
if (!accessToken)
|
|
83
|
+
return null;
|
|
84
|
+
const res = await fetch("https://api.github.com/user", {
|
|
85
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
86
|
+
});
|
|
87
|
+
if (!res.ok)
|
|
88
|
+
return null;
|
|
89
|
+
const profile = (await res.json());
|
|
90
|
+
let email = profile.email;
|
|
91
|
+
if (!email) {
|
|
92
|
+
email = await fetchGitHubPrimaryEmail(accessToken);
|
|
93
|
+
}
|
|
94
|
+
if (!email)
|
|
95
|
+
return null;
|
|
96
|
+
return {
|
|
97
|
+
user: {
|
|
98
|
+
id: String(profile.id),
|
|
99
|
+
name: profile.name || profile.login,
|
|
100
|
+
email,
|
|
101
|
+
image: profile.avatar_url,
|
|
102
|
+
emailVerified: true,
|
|
103
|
+
},
|
|
104
|
+
data: profile,
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
}
|
|
56
109
|
: {}),
|
|
57
110
|
...(process.env.DISCORD_CLIENT_ID && process.env.DISCORD_CLIENT_SECRET
|
|
58
111
|
? { discord: { clientId: process.env.DISCORD_CLIENT_ID, clientSecret: process.env.DISCORD_CLIENT_SECRET } }
|
package/package.json
CHANGED
package/src/auth/better-auth.ts
CHANGED
|
@@ -116,12 +116,61 @@ export async function getUserCreator(): Promise<IUserCreator> {
|
|
|
116
116
|
return _userCreatorPromise;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Fetch the primary verified email from GitHub's /user/emails API.
|
|
121
|
+
* GitHub returns null for profile.email when the user's email is private.
|
|
122
|
+
* The user:email scope grants access to this endpoint.
|
|
123
|
+
*/
|
|
124
|
+
async function fetchGitHubPrimaryEmail(accessToken: string): Promise<string | null> {
|
|
125
|
+
try {
|
|
126
|
+
const res = await fetch("https://api.github.com/user/emails", {
|
|
127
|
+
headers: { Authorization: `Bearer ${accessToken}`, Accept: "application/vnd.github+json" },
|
|
128
|
+
});
|
|
129
|
+
if (!res.ok) return null;
|
|
130
|
+
const emails = (await res.json()) as { email: string; primary: boolean; verified: boolean }[];
|
|
131
|
+
const primary = emails.find((e) => e.primary && e.verified);
|
|
132
|
+
return primary?.email ?? emails.find((e) => e.verified)?.email ?? null;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
logger.error("Failed to fetch GitHub primary email from /user/emails:", error);
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
119
139
|
/** Resolve OAuth providers from config or env vars. */
|
|
120
140
|
function resolveSocialProviders(cfg: BetterAuthConfig): BetterAuthOptions["socialProviders"] {
|
|
121
141
|
if (cfg.socialProviders) return cfg.socialProviders;
|
|
122
142
|
return {
|
|
123
143
|
...(process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET
|
|
124
|
-
? {
|
|
144
|
+
? {
|
|
145
|
+
github: {
|
|
146
|
+
clientId: process.env.GITHUB_CLIENT_ID,
|
|
147
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
|
148
|
+
getUserInfo: async (token) => {
|
|
149
|
+
const accessToken = token.accessToken;
|
|
150
|
+
if (!accessToken) return null;
|
|
151
|
+
const res = await fetch("https://api.github.com/user", {
|
|
152
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
153
|
+
});
|
|
154
|
+
if (!res.ok) return null;
|
|
155
|
+
const profile = (await res.json()) as Record<string, unknown>;
|
|
156
|
+
let email = profile.email as string | null;
|
|
157
|
+
if (!email) {
|
|
158
|
+
email = await fetchGitHubPrimaryEmail(accessToken);
|
|
159
|
+
}
|
|
160
|
+
if (!email) return null;
|
|
161
|
+
return {
|
|
162
|
+
user: {
|
|
163
|
+
id: String(profile.id),
|
|
164
|
+
name: (profile.name as string) || (profile.login as string),
|
|
165
|
+
email,
|
|
166
|
+
image: profile.avatar_url as string,
|
|
167
|
+
emailVerified: true,
|
|
168
|
+
},
|
|
169
|
+
data: profile,
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
}
|
|
125
174
|
: {}),
|
|
126
175
|
...(process.env.DISCORD_CLIENT_ID && process.env.DISCORD_CLIENT_SECRET
|
|
127
176
|
? { discord: { clientId: process.env.DISCORD_CLIENT_ID, clientSecret: process.env.DISCORD_CLIENT_SECRET } }
|