@rttnd/gau 1.4.3 → 1.4.4
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/chunk-6HKZAQHT.js +1 -0
- package/dist/chunk-6HKZAQHT.js.map +1 -0
- package/dist/chunk-MXZ363UZ.js +1 -0
- package/dist/chunk-MXZ363UZ.js.map +1 -0
- package/dist/chunk-NHENQLYI.js +1 -0
- package/dist/chunk-NHENQLYI.js.map +1 -0
- package/dist/chunk-V6AIGB33.js +1 -0
- package/dist/chunk-V6AIGB33.js.map +1 -0
- package/dist/chunk-VXWI4D7H.js +1 -0
- package/dist/chunk-VXWI4D7H.js.map +1 -0
- package/dist/src/adapters/drizzle/index.d.ts +1 -1
- package/dist/src/adapters/drizzle/index.js +1 -1
- package/dist/src/adapters/drizzle/pg.d.ts +3 -26
- package/dist/src/adapters/drizzle/pg.d.ts.map +1 -1
- package/dist/src/adapters/drizzle/shared.d.ts +49 -0
- package/dist/src/adapters/drizzle/shared.d.ts.map +1 -0
- package/dist/src/adapters/drizzle/sqlite.d.ts +3 -26
- package/dist/src/adapters/drizzle/sqlite.d.ts.map +1 -1
- package/dist/src/adapters/index.js +1 -1
- package/dist/src/client/shared/clientAuth.d.ts +57 -0
- package/dist/src/client/shared/clientAuth.d.ts.map +1 -0
- package/dist/src/client/solid/index.d.ts +3 -14
- package/dist/src/client/solid/index.d.ts.map +1 -1
- package/dist/src/client/solid/index.jsx +160 -216
- package/dist/src/client/solid2/Protected.d.ts +5 -0
- package/dist/src/client/solid2/Protected.d.ts.map +1 -0
- package/dist/src/client/solid2/index.d.ts +36 -0
- package/dist/src/client/solid2/index.d.ts.map +1 -0
- package/dist/src/client/solid2/index.jsx +708 -0
- package/dist/src/client/svelte/index.svelte.d.ts +3 -14
- package/dist/src/client/svelte/index.svelte.d.ts.map +1 -1
- package/dist/src/client/svelte/index.svelte.js +1 -1
- package/dist/src/client/svelte/index.svelte.js.map +1 -1
- package/dist/src/client/vanilla/index.js +1 -1
- package/dist/src/client/vanilla/index.js.map +1 -1
- package/dist/src/core/handlers/callback.d.ts.map +1 -1
- package/dist/src/core/handlers/index.js +1 -1
- package/dist/src/core/index.js +1 -1
- package/dist/src/core/serverSession.d.ts +13 -0
- package/dist/src/core/serverSession.d.ts.map +1 -0
- package/dist/src/index.js +1 -1
- package/dist/src/jwt/index.js +1 -1
- package/dist/src/oauth/index.d.ts +13 -11
- package/dist/src/oauth/index.d.ts.map +1 -1
- package/dist/src/oauth/index.js +1 -1
- package/dist/src/oauth/index.js.map +1 -1
- package/dist/src/oauth/providers/discord.d.ts.map +1 -1
- package/dist/src/oauth/providers/facebook.d.ts.map +1 -1
- package/dist/src/oauth/providers/github.d.ts.map +1 -1
- package/dist/src/oauth/providers/google.d.ts.map +1 -1
- package/dist/src/oauth/providers/microsoft.d.ts.map +1 -1
- package/dist/src/oauth/utils.d.ts +26 -0
- package/dist/src/oauth/utils.d.ts.map +1 -1
- package/dist/src/runtimes/index.js +1 -1
- package/dist/src/runtimes/tauri/index.d.ts.map +1 -1
- package/dist/src/runtimes/tauri/index.js +1 -1
- package/dist/src/solidstart/index.d.ts +4 -4
- package/dist/src/solidstart/index.d.ts.map +1 -1
- package/dist/src/solidstart/index.js +1 -1
- package/dist/src/solidstart/index.js.map +1 -1
- package/dist/src/sveltekit/index.d.ts +2 -2
- package/dist/src/sveltekit/index.d.ts.map +1 -1
- package/dist/src/sveltekit/index.js +1 -1
- package/dist/src/sveltekit/index.js.map +1 -1
- package/package.json +14 -4
- package/dist/chunk-DVVL3GFT.js +0 -1
- package/dist/chunk-DVVL3GFT.js.map +0 -1
- package/dist/chunk-MRKRGLUT.js +0 -1
- package/dist/chunk-MRKRGLUT.js.map +0 -1
- package/dist/chunk-PL7MV7OC.js +0 -1
- package/dist/chunk-PL7MV7OC.js.map +0 -1
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/client/token.ts
|
|
12
|
+
import { BROWSER } from "esm-env";
|
|
13
|
+
function storeSessionToken(token) {
|
|
14
|
+
if (!BROWSER)
|
|
15
|
+
return;
|
|
16
|
+
try {
|
|
17
|
+
localStorage.setItem(SESSION_TOKEN_KEY, token);
|
|
18
|
+
} catch {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function getSessionToken() {
|
|
22
|
+
if (!BROWSER)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
return localStorage.getItem(SESSION_TOKEN_KEY);
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function clearSessionToken() {
|
|
31
|
+
if (!BROWSER)
|
|
32
|
+
return;
|
|
33
|
+
try {
|
|
34
|
+
localStorage.removeItem(SESSION_TOKEN_KEY);
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function handleRefreshedToken(response) {
|
|
39
|
+
if (!BROWSER)
|
|
40
|
+
return;
|
|
41
|
+
const refreshed = response.headers.get(REFRESHED_TOKEN_HEADER);
|
|
42
|
+
if (refreshed)
|
|
43
|
+
storeSessionToken(refreshed);
|
|
44
|
+
}
|
|
45
|
+
async function generatePKCE() {
|
|
46
|
+
if (!BROWSER || !window.crypto || !window.crypto.subtle)
|
|
47
|
+
throw new Error("PKCE relies on window.crypto, which is not available in this environment.");
|
|
48
|
+
function base64UrlEncode(array) {
|
|
49
|
+
return btoa(String.fromCharCode(...array)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
50
|
+
}
|
|
51
|
+
const verifierLength = 43;
|
|
52
|
+
const randomValues = new Uint8Array(verifierLength);
|
|
53
|
+
window.crypto.getRandomValues(randomValues);
|
|
54
|
+
const codeVerifier = base64UrlEncode(randomValues);
|
|
55
|
+
const encoder = new TextEncoder();
|
|
56
|
+
const data = encoder.encode(codeVerifier);
|
|
57
|
+
const hash = await window.crypto.subtle.digest("SHA-256", data);
|
|
58
|
+
const codeChallenge = base64UrlEncode(new Uint8Array(hash));
|
|
59
|
+
return { codeVerifier, codeChallenge };
|
|
60
|
+
}
|
|
61
|
+
var SESSION_TOKEN_KEY, REFRESHED_TOKEN_HEADER;
|
|
62
|
+
var init_token = __esm({
|
|
63
|
+
"src/client/token.ts"() {
|
|
64
|
+
"use strict";
|
|
65
|
+
SESSION_TOKEN_KEY = "__gau-session-token";
|
|
66
|
+
REFRESHED_TOKEN_HEADER = "X-Refreshed-Token";
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// src/runtimes/tauri/index.ts
|
|
71
|
+
var tauri_exports = {};
|
|
72
|
+
__export(tauri_exports, {
|
|
73
|
+
handleTauriDeepLink: () => handleTauriDeepLink,
|
|
74
|
+
isTauri: () => isTauri,
|
|
75
|
+
linkAccountWithTauri: () => linkAccountWithTauri,
|
|
76
|
+
setupTauriListener: () => setupTauriListener,
|
|
77
|
+
signInWithTauri: () => signInWithTauri,
|
|
78
|
+
startAuthBridge: () => startAuthBridge
|
|
79
|
+
});
|
|
80
|
+
import { BROWSER as BROWSER2 } from "esm-env";
|
|
81
|
+
function isTauri() {
|
|
82
|
+
return BROWSER2 && "__TAURI_INTERNALS__" in globalThis;
|
|
83
|
+
}
|
|
84
|
+
function resolveOrigin(baseUrl) {
|
|
85
|
+
try {
|
|
86
|
+
return new URL(baseUrl).origin;
|
|
87
|
+
} catch {
|
|
88
|
+
if (BROWSER2 && typeof window !== "undefined") {
|
|
89
|
+
try {
|
|
90
|
+
return new URL(baseUrl, window.location.origin).origin;
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function resolveAbsoluteBase(baseUrl) {
|
|
99
|
+
try {
|
|
100
|
+
return new URL(baseUrl).toString().replace(/\/$/, "");
|
|
101
|
+
} catch {
|
|
102
|
+
if (BROWSER2 && typeof window !== "undefined") {
|
|
103
|
+
try {
|
|
104
|
+
return new URL(baseUrl, window.location.origin).toString().replace(/\/$/, "");
|
|
105
|
+
} catch {
|
|
106
|
+
return baseUrl;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return baseUrl;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function resolveTauriRedirect(redirectOverride, scheme) {
|
|
113
|
+
return redirectOverride ?? `${scheme}://oauth/callback`;
|
|
114
|
+
}
|
|
115
|
+
async function signInWithTauri(provider, baseUrl, scheme = "gau", redirectOverride, profile) {
|
|
116
|
+
if (!isTauri())
|
|
117
|
+
return;
|
|
118
|
+
const { openUrl } = await import("@tauri-apps/plugin-opener");
|
|
119
|
+
const redirectTo = resolveTauriRedirect(redirectOverride, scheme);
|
|
120
|
+
const { codeVerifier, codeChallenge } = await generatePKCE();
|
|
121
|
+
localStorage.setItem("gau-pkce-verifier", codeVerifier);
|
|
122
|
+
const params = new URLSearchParams();
|
|
123
|
+
params.set("redirectTo", redirectTo);
|
|
124
|
+
if (profile)
|
|
125
|
+
params.set("profile", String(profile));
|
|
126
|
+
params.set("code_challenge", codeChallenge);
|
|
127
|
+
const authUrl = `${resolveAbsoluteBase(baseUrl)}/${provider}?${params.toString()}`;
|
|
128
|
+
await openUrl(authUrl);
|
|
129
|
+
}
|
|
130
|
+
async function setupTauriListener(handler) {
|
|
131
|
+
if (!isTauri())
|
|
132
|
+
return;
|
|
133
|
+
const { listen } = await import("@tauri-apps/api/event");
|
|
134
|
+
try {
|
|
135
|
+
const unlisten = await listen("deep-link", async (event) => {
|
|
136
|
+
await handler(event.payload);
|
|
137
|
+
});
|
|
138
|
+
return unlisten;
|
|
139
|
+
} catch (err) {
|
|
140
|
+
console.error(err);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function handleTauriDeepLink(url, baseUrl, scheme, onToken) {
|
|
144
|
+
const parsed = new URL(url);
|
|
145
|
+
const baseOrigin = resolveOrigin(baseUrl);
|
|
146
|
+
if (parsed.protocol !== `${scheme}:` && (!baseOrigin || parsed.origin !== baseOrigin))
|
|
147
|
+
return;
|
|
148
|
+
const queryParams = new URLSearchParams(parsed.search);
|
|
149
|
+
const code = queryParams.get("code");
|
|
150
|
+
if (code) {
|
|
151
|
+
const verifier = localStorage.getItem("gau-pkce-verifier");
|
|
152
|
+
if (!verifier) {
|
|
153
|
+
console.error("No PKCE verifier found");
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
localStorage.removeItem("gau-pkce-verifier");
|
|
157
|
+
try {
|
|
158
|
+
const res = await fetch(`${baseUrl}/token`, {
|
|
159
|
+
method: "POST",
|
|
160
|
+
headers: { "Content-Type": "application/json" },
|
|
161
|
+
body: JSON.stringify({ code, codeVerifier: verifier })
|
|
162
|
+
});
|
|
163
|
+
if (res.ok) {
|
|
164
|
+
const data = await res.json();
|
|
165
|
+
if (data.token)
|
|
166
|
+
onToken(data.token);
|
|
167
|
+
} else {
|
|
168
|
+
console.error("Failed to exchange code for token");
|
|
169
|
+
}
|
|
170
|
+
} catch (e) {
|
|
171
|
+
console.error("Error exchanging code for token:", e);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function linkAccountWithTauri(provider, baseUrl, scheme = "gau", redirectOverride, profile) {
|
|
176
|
+
if (!isTauri())
|
|
177
|
+
return;
|
|
178
|
+
const { openUrl } = await import("@tauri-apps/plugin-opener");
|
|
179
|
+
const redirectTo = resolveTauriRedirect(redirectOverride, scheme);
|
|
180
|
+
const token = getSessionToken();
|
|
181
|
+
if (!token) {
|
|
182
|
+
console.error("No session token found, cannot link account.");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const params = new URLSearchParams();
|
|
186
|
+
params.set("redirectTo", redirectTo);
|
|
187
|
+
params.set("token", token);
|
|
188
|
+
if (profile)
|
|
189
|
+
params.set("profile", String(profile));
|
|
190
|
+
const linkUrl = `${resolveAbsoluteBase(baseUrl)}/link/${provider}?${params.toString()}`;
|
|
191
|
+
await openUrl(linkUrl);
|
|
192
|
+
}
|
|
193
|
+
async function startAuthBridge(baseUrl, scheme, onToken) {
|
|
194
|
+
if (!isTauri())
|
|
195
|
+
return;
|
|
196
|
+
const unlisten = await setupTauriListener(async (url) => {
|
|
197
|
+
handleTauriDeepLink(url, baseUrl, scheme, onToken);
|
|
198
|
+
});
|
|
199
|
+
return unlisten;
|
|
200
|
+
}
|
|
201
|
+
var init_tauri = __esm({
|
|
202
|
+
"src/runtimes/tauri/index.ts"() {
|
|
203
|
+
"use strict";
|
|
204
|
+
init_token();
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// src/client/solid2/index.tsx
|
|
209
|
+
init_tauri();
|
|
210
|
+
import { isServer as isServer2 } from "@solidjs/web";
|
|
211
|
+
import { createContext, createMemo, onSettled as onSettled2, untrack, useContext } from "solid-js";
|
|
212
|
+
import { createStore } from "solid-js/store";
|
|
213
|
+
|
|
214
|
+
// src/client/shared/clientAuth.ts
|
|
215
|
+
init_tauri();
|
|
216
|
+
var EMPTY_CLIENT_SESSION = {
|
|
217
|
+
user: null,
|
|
218
|
+
session: null,
|
|
219
|
+
accounts: null
|
|
220
|
+
};
|
|
221
|
+
function createEmptyClientSession() {
|
|
222
|
+
return { ...EMPTY_CLIENT_SESSION, providers: [] };
|
|
223
|
+
}
|
|
224
|
+
function isBrowser() {
|
|
225
|
+
return typeof window !== "undefined";
|
|
226
|
+
}
|
|
227
|
+
function createBrowserEnvironment(env = {}) {
|
|
228
|
+
return {
|
|
229
|
+
isBrowser,
|
|
230
|
+
isTauri: () => isBrowser() && isTauri(),
|
|
231
|
+
origin: () => window.location.origin,
|
|
232
|
+
href: () => window.location.href,
|
|
233
|
+
navigate: (url) => {
|
|
234
|
+
window.location.href = url;
|
|
235
|
+
},
|
|
236
|
+
...env
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function createClientAuth({
|
|
240
|
+
client,
|
|
241
|
+
redirectTo: defaultRedirectTo,
|
|
242
|
+
setSession,
|
|
243
|
+
onReady,
|
|
244
|
+
onRefreshing,
|
|
245
|
+
replaceUrl,
|
|
246
|
+
logger = console,
|
|
247
|
+
env
|
|
248
|
+
}) {
|
|
249
|
+
const browser = createBrowserEnvironment(env);
|
|
250
|
+
function resolveRedirectTo(type, redirectTo) {
|
|
251
|
+
let next = redirectTo ?? defaultRedirectTo;
|
|
252
|
+
if (!next && browser.isBrowser())
|
|
253
|
+
next = type === "signIn" ? browser.origin() : browser.href();
|
|
254
|
+
return next;
|
|
255
|
+
}
|
|
256
|
+
function navigateTo(url) {
|
|
257
|
+
if (browser.isBrowser() && !browser.isTauri())
|
|
258
|
+
browser.navigate(url);
|
|
259
|
+
}
|
|
260
|
+
async function refresh() {
|
|
261
|
+
onRefreshing?.(true);
|
|
262
|
+
try {
|
|
263
|
+
setSession(browser.isBrowser() ? await client.refreshSession() : createEmptyClientSession());
|
|
264
|
+
} finally {
|
|
265
|
+
onRefreshing?.(false);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
async function signIn(provider, options = {}) {
|
|
269
|
+
const profile = options.profile;
|
|
270
|
+
const url = await client.signIn(provider, { redirectTo: resolveRedirectTo("signIn", options.redirectTo), profile });
|
|
271
|
+
navigateTo(url);
|
|
272
|
+
}
|
|
273
|
+
async function linkAccount(provider, options = {}) {
|
|
274
|
+
const profile = options.profile;
|
|
275
|
+
const url = await client.linkAccount(provider, { redirectTo: resolveRedirectTo("linkAccount", options.redirectTo), profile });
|
|
276
|
+
navigateTo(url);
|
|
277
|
+
}
|
|
278
|
+
async function unlinkAccount(provider) {
|
|
279
|
+
const ok = await client.unlinkAccount(provider);
|
|
280
|
+
if (!ok)
|
|
281
|
+
logger.error("Failed to unlink account");
|
|
282
|
+
}
|
|
283
|
+
function mount() {
|
|
284
|
+
if (!browser.isBrowser())
|
|
285
|
+
return () => {
|
|
286
|
+
};
|
|
287
|
+
const unsubscribe = client.onSessionChange(setSession);
|
|
288
|
+
let disposed = false;
|
|
289
|
+
let cleanup;
|
|
290
|
+
void (async () => {
|
|
291
|
+
try {
|
|
292
|
+
const handled = await client.handleRedirectCallback(replaceUrl);
|
|
293
|
+
if (!handled)
|
|
294
|
+
await refresh();
|
|
295
|
+
} finally {
|
|
296
|
+
if (!disposed)
|
|
297
|
+
onReady?.();
|
|
298
|
+
}
|
|
299
|
+
})();
|
|
300
|
+
if (browser.isTauri()) {
|
|
301
|
+
void (async () => {
|
|
302
|
+
const unlisten = await client.startTauriBridge();
|
|
303
|
+
if (disposed)
|
|
304
|
+
unlisten?.();
|
|
305
|
+
else
|
|
306
|
+
cleanup = unlisten ?? void 0;
|
|
307
|
+
})();
|
|
308
|
+
}
|
|
309
|
+
return () => {
|
|
310
|
+
disposed = true;
|
|
311
|
+
cleanup?.();
|
|
312
|
+
cleanup = void 0;
|
|
313
|
+
unsubscribe();
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
mount,
|
|
318
|
+
controls: {
|
|
319
|
+
signIn,
|
|
320
|
+
linkAccount,
|
|
321
|
+
unlinkAccount,
|
|
322
|
+
signOut: client.signOut,
|
|
323
|
+
refresh,
|
|
324
|
+
fetch: client.fetch
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/client/solid/solidStartFetchBridge.ts
|
|
330
|
+
init_token();
|
|
331
|
+
import { BROWSER as BROWSER3 } from "esm-env";
|
|
332
|
+
function installSolidStartFetchBridge(options = {}) {
|
|
333
|
+
if (!BROWSER3 || typeof window === "undefined")
|
|
334
|
+
return;
|
|
335
|
+
if (window.__GAU_SOLIDSTART_FETCH_BRIDGE_INSTALLED__)
|
|
336
|
+
return;
|
|
337
|
+
window.__GAU_SOLIDSTART_FETCH_BRIDGE_INSTALLED__ = true;
|
|
338
|
+
const originalFetch = globalThis.fetch.bind(globalThis);
|
|
339
|
+
const serverFunctionTarget = resolveServerFunctionTarget(options.serverBaseUrl);
|
|
340
|
+
const wrappedFetch = async (input, init = {}) => {
|
|
341
|
+
const requestUrl = resolveRequestUrl(input);
|
|
342
|
+
if (!requestUrl || !isSolidStartServerFunctionRequest(requestUrl, serverFunctionTarget))
|
|
343
|
+
return originalFetch(input, init);
|
|
344
|
+
const headers = mergeHeaders(input, init);
|
|
345
|
+
if (!headers.has("Authorization")) {
|
|
346
|
+
const token = getSessionToken();
|
|
347
|
+
if (token)
|
|
348
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
349
|
+
}
|
|
350
|
+
const response = await originalFetch(input, {
|
|
351
|
+
...init,
|
|
352
|
+
headers
|
|
353
|
+
});
|
|
354
|
+
handleRefreshedToken(response);
|
|
355
|
+
return response;
|
|
356
|
+
};
|
|
357
|
+
const wrappedFetchWithBunCompat = wrappedFetch;
|
|
358
|
+
wrappedFetchWithBunCompat.preconnect = originalFetch.preconnect?.bind(originalFetch);
|
|
359
|
+
globalThis.fetch = wrappedFetchWithBunCompat;
|
|
360
|
+
window.fetch = wrappedFetchWithBunCompat;
|
|
361
|
+
}
|
|
362
|
+
function resolveServerFunctionTarget(serverBaseUrl) {
|
|
363
|
+
const envBase = serverBaseUrl ?? (import.meta?.env?.SERVER_BASE_URL ?? "");
|
|
364
|
+
const trimmed = envBase.trim();
|
|
365
|
+
if (!trimmed || trimmed === "/") {
|
|
366
|
+
return {
|
|
367
|
+
origin: window.location.origin,
|
|
368
|
+
path: "/_server"
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
const baseUrl = new URL(trimmed, window.location.origin);
|
|
373
|
+
const basePath = normalizePath(baseUrl.pathname);
|
|
374
|
+
const serverPath = basePath === "/" ? "/_server" : `${basePath}/_server`;
|
|
375
|
+
return {
|
|
376
|
+
origin: baseUrl.origin,
|
|
377
|
+
path: normalizePath(serverPath)
|
|
378
|
+
};
|
|
379
|
+
} catch {
|
|
380
|
+
return {
|
|
381
|
+
origin: window.location.origin,
|
|
382
|
+
path: "/_server"
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function resolveRequestUrl(input) {
|
|
387
|
+
try {
|
|
388
|
+
if (input instanceof URL)
|
|
389
|
+
return input;
|
|
390
|
+
if (typeof input === "string")
|
|
391
|
+
return new URL(input, window.location.href);
|
|
392
|
+
return new URL(input.url, window.location.href);
|
|
393
|
+
} catch {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function mergeHeaders(input, init) {
|
|
398
|
+
const headers = new Headers();
|
|
399
|
+
if (input instanceof Request) {
|
|
400
|
+
input.headers.forEach((value, key) => {
|
|
401
|
+
headers.set(key, value);
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
if (init.headers) {
|
|
405
|
+
new Headers(init.headers).forEach((value, key) => {
|
|
406
|
+
headers.set(key, value);
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
return headers;
|
|
410
|
+
}
|
|
411
|
+
function isSolidStartServerFunctionRequest(requestUrl, target) {
|
|
412
|
+
if (requestUrl.origin !== target.origin)
|
|
413
|
+
return false;
|
|
414
|
+
return normalizePath(requestUrl.pathname) === target.path;
|
|
415
|
+
}
|
|
416
|
+
function normalizePath(pathname) {
|
|
417
|
+
if (!pathname)
|
|
418
|
+
return "/";
|
|
419
|
+
const normalized = pathname.replace(/\/{2,}/g, "/").replace(/\/+$/, "");
|
|
420
|
+
return normalized || "/";
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// src/client/vanilla/index.ts
|
|
424
|
+
init_tauri();
|
|
425
|
+
init_token();
|
|
426
|
+
init_token();
|
|
427
|
+
function buildQuery(params) {
|
|
428
|
+
const q = new URLSearchParams();
|
|
429
|
+
for (const [k, v] of Object.entries(params)) {
|
|
430
|
+
if (v != null && v !== "")
|
|
431
|
+
q.set(k, String(v));
|
|
432
|
+
}
|
|
433
|
+
const s = q.toString();
|
|
434
|
+
return s ? `?${s}` : "";
|
|
435
|
+
}
|
|
436
|
+
function createAuthClient({ baseUrl, scheme = "gau" }) {
|
|
437
|
+
let currentSession = { user: null, session: null, accounts: null, providers: [] };
|
|
438
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
439
|
+
const notify = () => {
|
|
440
|
+
for (const l of listeners)
|
|
441
|
+
l(currentSession);
|
|
442
|
+
};
|
|
443
|
+
async function fetchSession() {
|
|
444
|
+
const token = getSessionToken();
|
|
445
|
+
const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
|
|
446
|
+
const res = await fetch(`${baseUrl}/session`, token ? { headers } : { credentials: "include" });
|
|
447
|
+
const contentType = res.headers.get("content-type");
|
|
448
|
+
if (contentType?.includes("application/json"))
|
|
449
|
+
return await res.json();
|
|
450
|
+
return { user: null, session: null, accounts: null, providers: [] };
|
|
451
|
+
}
|
|
452
|
+
async function refreshSession() {
|
|
453
|
+
const next = await fetchSession();
|
|
454
|
+
currentSession = next;
|
|
455
|
+
notify();
|
|
456
|
+
return next;
|
|
457
|
+
}
|
|
458
|
+
async function applySessionToken(token) {
|
|
459
|
+
try {
|
|
460
|
+
storeSessionToken(token);
|
|
461
|
+
} finally {
|
|
462
|
+
await refreshSession();
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function onSessionChange(listener) {
|
|
466
|
+
listeners.add(listener);
|
|
467
|
+
return () => listeners.delete(listener);
|
|
468
|
+
}
|
|
469
|
+
async function handleRedirectCallback(replaceUrl) {
|
|
470
|
+
if (typeof window === "undefined")
|
|
471
|
+
return false;
|
|
472
|
+
if (window.location.hash === "#_=_") {
|
|
473
|
+
const cleanUrl2 = window.location.pathname + window.location.search;
|
|
474
|
+
if (replaceUrl)
|
|
475
|
+
replaceUrl(cleanUrl2);
|
|
476
|
+
else
|
|
477
|
+
window.history.replaceState(null, "", cleanUrl2);
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
const hash = window.location.hash?.substring(1) ?? "";
|
|
481
|
+
if (!hash)
|
|
482
|
+
return false;
|
|
483
|
+
const params = new URLSearchParams(hash);
|
|
484
|
+
const token = params.get("token");
|
|
485
|
+
if (!token)
|
|
486
|
+
return false;
|
|
487
|
+
await applySessionToken(token);
|
|
488
|
+
const cleanUrl = window.location.pathname + window.location.search;
|
|
489
|
+
if (replaceUrl)
|
|
490
|
+
replaceUrl(cleanUrl);
|
|
491
|
+
else
|
|
492
|
+
window.history.replaceState(null, "", cleanUrl);
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
495
|
+
function makeProviderUrl(provider, params) {
|
|
496
|
+
const q = buildQuery({
|
|
497
|
+
redirectTo: params?.redirectTo,
|
|
498
|
+
profile: params?.profile != null ? String(params.profile) : void 0
|
|
499
|
+
});
|
|
500
|
+
return `${baseUrl}/${provider}${q}`;
|
|
501
|
+
}
|
|
502
|
+
function makeLinkUrl(provider, params) {
|
|
503
|
+
const q = buildQuery({
|
|
504
|
+
redirectTo: params.redirectTo,
|
|
505
|
+
profile: params.profile != null ? String(params.profile) : void 0,
|
|
506
|
+
redirect: params.redirect
|
|
507
|
+
});
|
|
508
|
+
return `${baseUrl}/link/${provider}${q}`;
|
|
509
|
+
}
|
|
510
|
+
async function signIn(provider, options) {
|
|
511
|
+
const url = makeProviderUrl(provider, options);
|
|
512
|
+
if (isTauri()) {
|
|
513
|
+
const { signInWithTauri: signInWithTauri2 } = await Promise.resolve().then(() => (init_tauri(), tauri_exports));
|
|
514
|
+
await signInWithTauri2(provider, baseUrl, scheme, options?.redirectTo, options?.profile);
|
|
515
|
+
}
|
|
516
|
+
return url;
|
|
517
|
+
}
|
|
518
|
+
async function linkAccount(provider, options) {
|
|
519
|
+
if (isTauri()) {
|
|
520
|
+
const { linkAccountWithTauri: linkAccountWithTauri2 } = await Promise.resolve().then(() => (init_tauri(), tauri_exports));
|
|
521
|
+
await linkAccountWithTauri2(provider, baseUrl, scheme, options?.redirectTo, options?.profile);
|
|
522
|
+
return makeLinkUrl(provider, { redirectTo: options?.redirectTo, profile: options?.profile, redirect: "false" });
|
|
523
|
+
}
|
|
524
|
+
const linkUrl = makeLinkUrl(provider, { redirectTo: options?.redirectTo, profile: options?.profile, redirect: "false" });
|
|
525
|
+
const token = getSessionToken();
|
|
526
|
+
const fetchOptions = token ? { headers: { Authorization: `Bearer ${token}` } } : { credentials: "include" };
|
|
527
|
+
const res = await fetch(linkUrl, fetchOptions);
|
|
528
|
+
if (res.redirected)
|
|
529
|
+
return res.url;
|
|
530
|
+
try {
|
|
531
|
+
const data = await res.json();
|
|
532
|
+
if (data?.url)
|
|
533
|
+
return data.url;
|
|
534
|
+
} catch {
|
|
535
|
+
}
|
|
536
|
+
return linkUrl;
|
|
537
|
+
}
|
|
538
|
+
async function unlinkAccount(provider) {
|
|
539
|
+
const token = getSessionToken();
|
|
540
|
+
const fetchOptions = token ? { headers: { Authorization: `Bearer ${token}` } } : { credentials: "include" };
|
|
541
|
+
const res = await fetch(`${baseUrl}/unlink/${provider}`, { method: "POST", ...fetchOptions });
|
|
542
|
+
if (res.ok) {
|
|
543
|
+
await refreshSession();
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
async function signOut() {
|
|
549
|
+
const token = getSessionToken();
|
|
550
|
+
clearSessionToken();
|
|
551
|
+
const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
|
|
552
|
+
await fetch(`${baseUrl}/signout`, token ? { method: "POST", headers } : { method: "POST", credentials: "include" });
|
|
553
|
+
await refreshSession();
|
|
554
|
+
}
|
|
555
|
+
async function startTauriBridge() {
|
|
556
|
+
if (!isTauri())
|
|
557
|
+
return;
|
|
558
|
+
const { startAuthBridge: startAuthBridge2 } = await Promise.resolve().then(() => (init_tauri(), tauri_exports));
|
|
559
|
+
const cleanup = await startAuthBridge2(baseUrl, scheme, async (token) => {
|
|
560
|
+
await applySessionToken(token);
|
|
561
|
+
});
|
|
562
|
+
return cleanup;
|
|
563
|
+
}
|
|
564
|
+
async function authFetch(input, init = {}) {
|
|
565
|
+
const token = getSessionToken();
|
|
566
|
+
const headers = new Headers(init.headers);
|
|
567
|
+
if (token)
|
|
568
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
569
|
+
const res = await globalThis.fetch(input, {
|
|
570
|
+
...init,
|
|
571
|
+
headers,
|
|
572
|
+
...!token && { credentials: "include" }
|
|
573
|
+
});
|
|
574
|
+
handleRefreshedToken(res);
|
|
575
|
+
return res;
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
get session() {
|
|
579
|
+
return currentSession;
|
|
580
|
+
},
|
|
581
|
+
fetch: authFetch,
|
|
582
|
+
fetchSession,
|
|
583
|
+
refreshSession,
|
|
584
|
+
applySessionToken,
|
|
585
|
+
handleRedirectCallback,
|
|
586
|
+
onSessionChange,
|
|
587
|
+
signIn,
|
|
588
|
+
linkAccount,
|
|
589
|
+
unlinkAccount,
|
|
590
|
+
signOut,
|
|
591
|
+
startTauriBridge
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// src/client/solid2/Protected.tsx
|
|
596
|
+
import { useNavigate } from "@solidjs/router";
|
|
597
|
+
import { isServer } from "@solidjs/web";
|
|
598
|
+
import { onSettled, Show } from "solid-js";
|
|
599
|
+
function onClientReady(fn) {
|
|
600
|
+
if (isServer)
|
|
601
|
+
return;
|
|
602
|
+
onSettled(fn);
|
|
603
|
+
}
|
|
604
|
+
function Protected(page, fallbackOrRedirect) {
|
|
605
|
+
return () => {
|
|
606
|
+
const auth = useAuth();
|
|
607
|
+
const navigate = useNavigate();
|
|
608
|
+
const isRedirectMode = typeof fallbackOrRedirect === "string" || fallbackOrRedirect === void 0;
|
|
609
|
+
const redirectTo = isRedirectMode ? fallbackOrRedirect ?? "/" : void 0;
|
|
610
|
+
const Fallback = !isRedirectMode ? fallbackOrRedirect : void 0;
|
|
611
|
+
const Redirect = () => {
|
|
612
|
+
onClientReady(() => {
|
|
613
|
+
if (!isServer && redirectTo)
|
|
614
|
+
navigate(redirectTo, { replace: true });
|
|
615
|
+
});
|
|
616
|
+
return null;
|
|
617
|
+
};
|
|
618
|
+
return <Show when={!auth.isLoading()} fallback={null}>
|
|
619
|
+
<Show
|
|
620
|
+
when={auth.session().user}
|
|
621
|
+
fallback={isRedirectMode ? <Redirect /> : Fallback ? <Fallback /> : null}
|
|
622
|
+
>
|
|
623
|
+
{page(auth.session)}
|
|
624
|
+
</Show>
|
|
625
|
+
</Show>;
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// src/client/solid2/index.tsx
|
|
630
|
+
var AuthContext = createContext();
|
|
631
|
+
function onClientReady2(fn) {
|
|
632
|
+
if (isServer2)
|
|
633
|
+
return;
|
|
634
|
+
onSettled2(fn);
|
|
635
|
+
}
|
|
636
|
+
function AuthProvider(props) {
|
|
637
|
+
const scheme = untrack(() => props.scheme ?? "gau");
|
|
638
|
+
const baseUrl = untrack(() => props.baseUrl ?? "/api/auth");
|
|
639
|
+
if (!isServer2 && isTauri())
|
|
640
|
+
installSolidStartFetchBridge();
|
|
641
|
+
const client = createAuthClient({
|
|
642
|
+
baseUrl,
|
|
643
|
+
scheme
|
|
644
|
+
});
|
|
645
|
+
const hasExternalSession = () => props.session !== void 0;
|
|
646
|
+
const getExternalSession = () => {
|
|
647
|
+
const external = props.session;
|
|
648
|
+
return typeof external === "function" ? external() : external;
|
|
649
|
+
};
|
|
650
|
+
const [state, setState] = createStore({
|
|
651
|
+
mounted: false,
|
|
652
|
+
isRefreshing: false,
|
|
653
|
+
isReady: false,
|
|
654
|
+
clientOverride: null,
|
|
655
|
+
clientSession: null
|
|
656
|
+
});
|
|
657
|
+
const setResolvedSession = (next) => {
|
|
658
|
+
setState(hasExternalSession() ? { clientOverride: next } : { clientSession: next });
|
|
659
|
+
};
|
|
660
|
+
const session = createMemo(() => {
|
|
661
|
+
const override = state.clientOverride;
|
|
662
|
+
if (override !== null)
|
|
663
|
+
return override;
|
|
664
|
+
if (hasExternalSession()) {
|
|
665
|
+
const ext = getExternalSession();
|
|
666
|
+
return ext;
|
|
667
|
+
}
|
|
668
|
+
return state.clientSession ?? createEmptyClientSession();
|
|
669
|
+
});
|
|
670
|
+
const isLoading = createMemo(() => {
|
|
671
|
+
if (hasExternalSession())
|
|
672
|
+
return false;
|
|
673
|
+
return !state.mounted || !state.isReady || state.clientSession === null && state.isRefreshing;
|
|
674
|
+
});
|
|
675
|
+
const auth = createClientAuth({
|
|
676
|
+
client,
|
|
677
|
+
redirectTo: untrack(() => props.redirectTo),
|
|
678
|
+
setSession: setResolvedSession,
|
|
679
|
+
onReady: () => {
|
|
680
|
+
setState({ isReady: true });
|
|
681
|
+
},
|
|
682
|
+
onRefreshing: (refreshing) => {
|
|
683
|
+
setState({ isRefreshing: refreshing });
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
const contextValue = {
|
|
687
|
+
session,
|
|
688
|
+
isLoading,
|
|
689
|
+
...auth.controls
|
|
690
|
+
};
|
|
691
|
+
const provider = <AuthContext value={contextValue}>
|
|
692
|
+
{props.children}
|
|
693
|
+
</AuthContext>;
|
|
694
|
+
onClientReady2(() => {
|
|
695
|
+
if (!untrack(hasExternalSession))
|
|
696
|
+
setState({ mounted: true });
|
|
697
|
+
return auth.mount();
|
|
698
|
+
});
|
|
699
|
+
return provider;
|
|
700
|
+
}
|
|
701
|
+
function useAuth() {
|
|
702
|
+
return useContext(AuthContext);
|
|
703
|
+
}
|
|
704
|
+
export {
|
|
705
|
+
AuthProvider,
|
|
706
|
+
Protected,
|
|
707
|
+
useAuth
|
|
708
|
+
};
|