@rttnd/gau 0.5.0 → 0.7.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/README.md +48 -44
- package/dist/chunk-4PR5RWHE.js +1 -0
- package/dist/chunk-4PR5RWHE.js.map +1 -0
- package/dist/chunk-7SEBXKP6.js +1 -0
- package/dist/chunk-7SEBXKP6.js.map +1 -0
- package/dist/chunk-BAIUBBG4.js +1 -0
- package/dist/chunk-BAIUBBG4.js.map +1 -0
- package/dist/chunk-ZJEC3NLU.js +1 -0
- package/dist/chunk-ZJEC3NLU.js.map +1 -0
- package/dist/src/adapters/drizzle/index.d.ts.map +1 -1
- package/dist/src/adapters/drizzle/index.js +1 -1
- package/dist/src/adapters/drizzle/mysql.d.ts +0 -1
- package/dist/src/adapters/drizzle/mysql.d.ts.map +1 -1
- package/dist/src/adapters/drizzle/pg.d.ts +27 -2
- package/dist/src/adapters/drizzle/pg.d.ts.map +1 -1
- package/dist/src/adapters/drizzle/sqlite.d.ts +8 -6
- package/dist/src/adapters/drizzle/sqlite.d.ts.map +1 -1
- package/dist/src/adapters/index.js +1 -1
- package/dist/src/client/solid/Protected.d.ts +4 -0
- package/dist/src/client/solid/Protected.d.ts.map +1 -0
- package/dist/src/client/solid/index.d.ts +3 -3
- package/dist/src/client/solid/index.d.ts.map +1 -1
- package/dist/src/client/solid/index.jsx +277 -125
- package/dist/src/client/svelte/Protected/index.svelte +32 -0
- 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.d.ts +25 -0
- package/dist/src/client/vanilla/index.d.ts.map +1 -0
- package/dist/src/client/vanilla/index.js +1 -0
- package/dist/src/client/vanilla/index.js.map +1 -0
- package/dist/src/core/cookies.d.ts +1 -1
- package/dist/src/core/cookies.d.ts.map +1 -1
- package/dist/src/core/createAuth.d.ts.map +1 -1
- package/dist/src/core/handler.d.ts.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/handlers/login.d.ts.map +1 -1
- package/dist/src/core/handlers/utils.d.ts.map +1 -1
- package/dist/src/core/index.d.ts +2 -2
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/jwt/index.js +1 -1
- package/dist/src/oauth/index.d.ts +2 -0
- 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 +3 -0
- package/dist/src/oauth/providers/discord.d.ts.map +1 -0
- package/dist/src/oauth/providers/facebook.d.ts +3 -0
- package/dist/src/oauth/providers/facebook.d.ts.map +1 -0
- package/dist/src/oauth/providers/microsoft.d.ts +0 -1
- package/dist/src/oauth/providers/microsoft.d.ts.map +1 -1
- package/dist/src/runtimes/index.js +1 -1
- package/dist/src/runtimes/tauri/index.d.ts +4 -2
- 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.js +1 -1
- package/dist/src/sveltekit/index.js +1 -1
- package/package.json +42 -14
- package/dist/chunk-3NKNADKP.js +0 -1
- package/dist/chunk-3NKNADKP.js.map +0 -1
- package/dist/chunk-GV4FQQFM.js +0 -1
- package/dist/chunk-GV4FQQFM.js.map +0 -1
- package/dist/chunk-Z35ZTMGZ.js +0 -1
- package/dist/chunk-Z35ZTMGZ.js.map +0 -1
- package/dist/src/client/svelte/index.svelte.d.ts +0 -22
- package/dist/src/client/svelte/index.svelte.d.ts.map +0 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Accessor, JSXElement, VoidComponent } from 'solid-js';
|
|
2
|
+
import type { GauSession, ProviderIds } from '../../core';
|
|
3
|
+
export declare function Protected<const TAuth = unknown>(page: (session: Accessor<GauSession<ProviderIds<TAuth>>>) => JSXElement, fallbackOrRedirect?: (() => JSXElement) | string): VoidComponent;
|
|
4
|
+
//# sourceMappingURL=Protected.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Protected.d.ts","sourceRoot":"","sources":["../../../../src/client/solid/Protected.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAMzD,wBAAgB,SAAS,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,EAC7C,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,UAAU,EACvE,kBAAkB,CAAC,EAAE,CAAC,MAAM,UAAU,CAAC,GAAG,MAAM,GAC/C,aAAa,CA0Bf"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Accessor,
|
|
1
|
+
import type { Accessor, ParentProps } from 'solid-js';
|
|
2
2
|
import type { GauSession, ProfileName, ProviderIds } from '../../core';
|
|
3
3
|
interface AuthContextValue<TAuth = unknown> {
|
|
4
4
|
session: Accessor<GauSession<ProviderIds<TAuth>>>;
|
|
@@ -12,6 +12,7 @@ interface AuthContextValue<TAuth = unknown> {
|
|
|
12
12
|
}) => Promise<void>;
|
|
13
13
|
unlinkAccount: (provider: ProviderIds<TAuth>) => Promise<void>;
|
|
14
14
|
signOut: () => Promise<void>;
|
|
15
|
+
refresh: () => Promise<void>;
|
|
15
16
|
}
|
|
16
17
|
export declare function AuthProvider<const TAuth = unknown>(props: ParentProps & {
|
|
17
18
|
auth?: TAuth;
|
|
@@ -20,6 +21,5 @@ export declare function AuthProvider<const TAuth = unknown>(props: ParentProps &
|
|
|
20
21
|
redirectTo?: string;
|
|
21
22
|
}): import("solid-js").JSX.Element;
|
|
22
23
|
export declare function useAuth<const TAuth = unknown>(): AuthContextValue<TAuth>;
|
|
23
|
-
export
|
|
24
|
-
export {};
|
|
24
|
+
export { Protected } from './Protected';
|
|
25
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/solid/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/solid/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAOtE,UAAU,gBAAgB,CAAC,KAAK,GAAG,OAAO;IACxC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACjD,MAAM,EAAE,CAAC,CAAC,SAAS,WAAW,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxI,WAAW,EAAE,CAAC,CAAC,SAAS,WAAW,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7I,aAAa,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAID,wBAAgB,YAAY,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG;IAAE,IAAI,CAAC,EAAE,KAAK,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,kCAgGhJ;AAED,wBAAgB,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,KAAK,gBAAgB,CAAC,KAAK,CAAC,CAKxE;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -1,32 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
// src/jwt/jwt.ts
|
|
10
|
-
import {
|
|
11
|
-
createJWTSignatureMessage,
|
|
12
|
-
encodeJWT,
|
|
13
|
-
JWSRegisteredHeaders,
|
|
14
|
-
JWTRegisteredClaims,
|
|
15
|
-
parseJWT
|
|
16
|
-
} from "@oslojs/jwt";
|
|
17
|
-
|
|
18
|
-
// src/oauth/utils.ts
|
|
19
|
-
import { generateCodeVerifier, generateState } from "arctic";
|
|
20
|
-
|
|
21
|
-
// src/core/index.ts
|
|
22
|
-
var NULL_SESSION = {
|
|
23
|
-
user: null,
|
|
24
|
-
session: null,
|
|
25
|
-
accounts: null
|
|
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 });
|
|
26
9
|
};
|
|
27
|
-
|
|
28
|
-
// src/runtimes/tauri/index.ts
|
|
29
|
-
import { BROWSER as BROWSER2 } from "esm-env";
|
|
30
10
|
|
|
31
11
|
// src/client/token.ts
|
|
32
12
|
import { BROWSER } from "esm-env";
|
|
@@ -53,8 +33,23 @@ function clearSessionToken() {
|
|
|
53
33
|
} catch {
|
|
54
34
|
}
|
|
55
35
|
}
|
|
36
|
+
var init_token = __esm({
|
|
37
|
+
"src/client/token.ts"() {
|
|
38
|
+
"use strict";
|
|
39
|
+
}
|
|
40
|
+
});
|
|
56
41
|
|
|
57
42
|
// src/runtimes/tauri/index.ts
|
|
43
|
+
var tauri_exports = {};
|
|
44
|
+
__export(tauri_exports, {
|
|
45
|
+
handleTauriDeepLink: () => handleTauriDeepLink,
|
|
46
|
+
isTauri: () => isTauri,
|
|
47
|
+
linkAccountWithTauri: () => linkAccountWithTauri,
|
|
48
|
+
setupTauriListener: () => setupTauriListener,
|
|
49
|
+
signInWithTauri: () => signInWithTauri,
|
|
50
|
+
startAuthBridge: () => startAuthBridge
|
|
51
|
+
});
|
|
52
|
+
import { BROWSER as BROWSER2 } from "esm-env";
|
|
58
53
|
function isTauri() {
|
|
59
54
|
return BROWSER2 && "__TAURI_INTERNALS__" in globalThis;
|
|
60
55
|
}
|
|
@@ -62,7 +57,7 @@ async function signInWithTauri(provider, baseUrl, scheme = "gau", redirectOverri
|
|
|
62
57
|
if (!isTauri())
|
|
63
58
|
return;
|
|
64
59
|
const { platform } = await import("@tauri-apps/plugin-os");
|
|
65
|
-
const {
|
|
60
|
+
const { openUrl } = await import("@tauri-apps/plugin-opener");
|
|
66
61
|
const currentPlatform = platform();
|
|
67
62
|
let redirectTo;
|
|
68
63
|
if (redirectOverride)
|
|
@@ -74,9 +69,9 @@ async function signInWithTauri(provider, baseUrl, scheme = "gau", redirectOverri
|
|
|
74
69
|
const params = new URLSearchParams();
|
|
75
70
|
params.set("redirectTo", redirectTo);
|
|
76
71
|
if (profile)
|
|
77
|
-
params.set("profile", profile);
|
|
72
|
+
params.set("profile", String(profile));
|
|
78
73
|
const authUrl = `${baseUrl}/${provider}?${params.toString()}`;
|
|
79
|
-
await
|
|
74
|
+
await openUrl(authUrl);
|
|
80
75
|
}
|
|
81
76
|
async function setupTauriListener(handler) {
|
|
82
77
|
if (!isTauri())
|
|
@@ -104,7 +99,7 @@ async function linkAccountWithTauri(provider, baseUrl, scheme = "gau", redirectO
|
|
|
104
99
|
if (!isTauri())
|
|
105
100
|
return;
|
|
106
101
|
const { platform } = await import("@tauri-apps/plugin-os");
|
|
107
|
-
const {
|
|
102
|
+
const { openUrl } = await import("@tauri-apps/plugin-opener");
|
|
108
103
|
const currentPlatform = platform();
|
|
109
104
|
let redirectTo;
|
|
110
105
|
if (redirectOverride)
|
|
@@ -122,9 +117,217 @@ async function linkAccountWithTauri(provider, baseUrl, scheme = "gau", redirectO
|
|
|
122
117
|
params.set("redirectTo", redirectTo);
|
|
123
118
|
params.set("token", token);
|
|
124
119
|
if (profile)
|
|
125
|
-
params.set("profile", profile);
|
|
120
|
+
params.set("profile", String(profile));
|
|
126
121
|
const linkUrl = `${baseUrl}/link/${provider}?${params.toString()}`;
|
|
127
|
-
await
|
|
122
|
+
await openUrl(linkUrl);
|
|
123
|
+
}
|
|
124
|
+
async function startAuthBridge(baseUrl, scheme, onToken) {
|
|
125
|
+
if (!isTauri())
|
|
126
|
+
return;
|
|
127
|
+
const unlisten = await setupTauriListener(async (url) => {
|
|
128
|
+
handleTauriDeepLink(url, baseUrl, scheme, onToken);
|
|
129
|
+
});
|
|
130
|
+
return unlisten;
|
|
131
|
+
}
|
|
132
|
+
var init_tauri = __esm({
|
|
133
|
+
"src/runtimes/tauri/index.ts"() {
|
|
134
|
+
"use strict";
|
|
135
|
+
init_token();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// src/client/solid/index.tsx
|
|
140
|
+
import { createContext, createResource, onCleanup, onMount as onMount2, untrack, useContext } from "solid-js";
|
|
141
|
+
import { isServer as isServer2 } from "solid-js/web";
|
|
142
|
+
|
|
143
|
+
// src/core/cookies.ts
|
|
144
|
+
import { parse, serialize } from "cookie";
|
|
145
|
+
var CSRF_MAX_AGE = 60 * 10;
|
|
146
|
+
|
|
147
|
+
// src/jwt/jwt.ts
|
|
148
|
+
import {
|
|
149
|
+
createJWTSignatureMessage,
|
|
150
|
+
encodeJWT,
|
|
151
|
+
JWSRegisteredHeaders,
|
|
152
|
+
JWTRegisteredClaims,
|
|
153
|
+
parseJWT
|
|
154
|
+
} from "@oslojs/jwt";
|
|
155
|
+
|
|
156
|
+
// src/oauth/utils.ts
|
|
157
|
+
import { generateCodeVerifier, generateState } from "arctic";
|
|
158
|
+
|
|
159
|
+
// src/core/index.ts
|
|
160
|
+
var NULL_SESSION = {
|
|
161
|
+
user: null,
|
|
162
|
+
session: null,
|
|
163
|
+
accounts: null
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// src/client/solid/index.tsx
|
|
167
|
+
init_tauri();
|
|
168
|
+
|
|
169
|
+
// src/client/vanilla/index.ts
|
|
170
|
+
init_token();
|
|
171
|
+
function buildQuery(params) {
|
|
172
|
+
const q = new URLSearchParams();
|
|
173
|
+
for (const [k, v] of Object.entries(params)) {
|
|
174
|
+
if (v != null && v !== "")
|
|
175
|
+
q.set(k, String(v));
|
|
176
|
+
}
|
|
177
|
+
const s = q.toString();
|
|
178
|
+
return s ? `?${s}` : "";
|
|
179
|
+
}
|
|
180
|
+
function createAuthClient({ baseUrl }) {
|
|
181
|
+
let currentSession = { user: null, session: null, accounts: null, providers: [] };
|
|
182
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
183
|
+
const notify = () => {
|
|
184
|
+
for (const l of listeners)
|
|
185
|
+
l(currentSession);
|
|
186
|
+
};
|
|
187
|
+
async function fetchSession() {
|
|
188
|
+
const token = getSessionToken();
|
|
189
|
+
const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
|
|
190
|
+
const res = await fetch(`${baseUrl}/session`, token ? { headers } : { credentials: "include" });
|
|
191
|
+
const contentType = res.headers.get("content-type");
|
|
192
|
+
if (contentType?.includes("application/json"))
|
|
193
|
+
return await res.json();
|
|
194
|
+
return { user: null, session: null, accounts: null, providers: [] };
|
|
195
|
+
}
|
|
196
|
+
async function refreshSession() {
|
|
197
|
+
const next = await fetchSession();
|
|
198
|
+
currentSession = next;
|
|
199
|
+
notify();
|
|
200
|
+
return next;
|
|
201
|
+
}
|
|
202
|
+
async function applySessionToken(token) {
|
|
203
|
+
try {
|
|
204
|
+
storeSessionToken(token);
|
|
205
|
+
} finally {
|
|
206
|
+
await refreshSession();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function onSessionChange(listener) {
|
|
210
|
+
listeners.add(listener);
|
|
211
|
+
return () => listeners.delete(listener);
|
|
212
|
+
}
|
|
213
|
+
async function handleRedirectCallback(replaceUrl) {
|
|
214
|
+
if (typeof window === "undefined")
|
|
215
|
+
return false;
|
|
216
|
+
if (window.location.hash === "#_=_") {
|
|
217
|
+
const cleanUrl2 = window.location.pathname + window.location.search;
|
|
218
|
+
if (replaceUrl)
|
|
219
|
+
replaceUrl(cleanUrl2);
|
|
220
|
+
else
|
|
221
|
+
window.history.replaceState(null, "", cleanUrl2);
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
const hash = window.location.hash?.substring(1) ?? "";
|
|
225
|
+
if (!hash)
|
|
226
|
+
return false;
|
|
227
|
+
const params = new URLSearchParams(hash);
|
|
228
|
+
const token = params.get("token");
|
|
229
|
+
if (!token)
|
|
230
|
+
return false;
|
|
231
|
+
await applySessionToken(token);
|
|
232
|
+
const cleanUrl = window.location.pathname + window.location.search;
|
|
233
|
+
if (replaceUrl)
|
|
234
|
+
replaceUrl(cleanUrl);
|
|
235
|
+
else
|
|
236
|
+
window.history.replaceState(null, "", cleanUrl);
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
function makeProviderUrl(provider, params) {
|
|
240
|
+
const q = buildQuery({
|
|
241
|
+
redirectTo: params?.redirectTo,
|
|
242
|
+
profile: params?.profile != null ? String(params.profile) : void 0
|
|
243
|
+
});
|
|
244
|
+
return `${baseUrl}/${provider}${q}`;
|
|
245
|
+
}
|
|
246
|
+
function makeLinkUrl(provider, params) {
|
|
247
|
+
const q = buildQuery({
|
|
248
|
+
redirectTo: params.redirectTo,
|
|
249
|
+
profile: params.profile != null ? String(params.profile) : void 0,
|
|
250
|
+
redirect: params.redirect
|
|
251
|
+
});
|
|
252
|
+
return `${baseUrl}/link/${provider}${q}`;
|
|
253
|
+
}
|
|
254
|
+
async function signIn(provider, options) {
|
|
255
|
+
const url = makeProviderUrl(provider, options);
|
|
256
|
+
return url;
|
|
257
|
+
}
|
|
258
|
+
async function linkAccount(provider, options) {
|
|
259
|
+
const linkUrl = makeLinkUrl(provider, { redirectTo: options?.redirectTo, profile: options?.profile, redirect: "false" });
|
|
260
|
+
const token = getSessionToken();
|
|
261
|
+
const fetchOptions = token ? { headers: { Authorization: `Bearer ${token}` } } : { credentials: "include" };
|
|
262
|
+
const res = await fetch(linkUrl, fetchOptions);
|
|
263
|
+
if (res.redirected)
|
|
264
|
+
return res.url;
|
|
265
|
+
try {
|
|
266
|
+
const data = await res.json();
|
|
267
|
+
if (data?.url)
|
|
268
|
+
return data.url;
|
|
269
|
+
} catch {
|
|
270
|
+
}
|
|
271
|
+
return linkUrl;
|
|
272
|
+
}
|
|
273
|
+
async function unlinkAccount(provider) {
|
|
274
|
+
const token = getSessionToken();
|
|
275
|
+
const fetchOptions = token ? { headers: { Authorization: `Bearer ${token}` } } : { credentials: "include" };
|
|
276
|
+
const res = await fetch(`${baseUrl}/unlink/${provider}`, { method: "POST", ...fetchOptions });
|
|
277
|
+
if (res.ok) {
|
|
278
|
+
await refreshSession();
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
async function signOut() {
|
|
284
|
+
clearSessionToken();
|
|
285
|
+
const token = getSessionToken();
|
|
286
|
+
const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
|
|
287
|
+
await fetch(`${baseUrl}/signout`, token ? { method: "POST", headers } : { method: "POST", credentials: "include" });
|
|
288
|
+
await refreshSession();
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
get session() {
|
|
292
|
+
return currentSession;
|
|
293
|
+
},
|
|
294
|
+
fetchSession,
|
|
295
|
+
refreshSession,
|
|
296
|
+
applySessionToken,
|
|
297
|
+
handleRedirectCallback,
|
|
298
|
+
onSessionChange,
|
|
299
|
+
signIn,
|
|
300
|
+
linkAccount,
|
|
301
|
+
unlinkAccount,
|
|
302
|
+
signOut
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/client/solid/Protected.tsx
|
|
307
|
+
import { useNavigate } from "@solidjs/router";
|
|
308
|
+
import { onMount, Show } from "solid-js";
|
|
309
|
+
import { isServer } from "solid-js/web";
|
|
310
|
+
function Protected(page, fallbackOrRedirect) {
|
|
311
|
+
return () => {
|
|
312
|
+
const auth = useAuth();
|
|
313
|
+
const navigate = useNavigate();
|
|
314
|
+
const isRedirectMode = typeof fallbackOrRedirect === "string" || fallbackOrRedirect === void 0;
|
|
315
|
+
const redirectTo = isRedirectMode ? fallbackOrRedirect ?? "/" : void 0;
|
|
316
|
+
const Fallback = !isRedirectMode ? fallbackOrRedirect : void 0;
|
|
317
|
+
const Redirect = () => {
|
|
318
|
+
onMount(() => {
|
|
319
|
+
if (!isServer && redirectTo)
|
|
320
|
+
navigate(redirectTo, { replace: true });
|
|
321
|
+
});
|
|
322
|
+
return null;
|
|
323
|
+
};
|
|
324
|
+
return <Show
|
|
325
|
+
when={auth.session().user}
|
|
326
|
+
fallback={isRedirectMode ? <Redirect /> : Fallback ? <Fallback /> : null}
|
|
327
|
+
>
|
|
328
|
+
{page(auth.session)}
|
|
329
|
+
</Show>;
|
|
330
|
+
};
|
|
128
331
|
}
|
|
129
332
|
|
|
130
333
|
// src/client/solid/index.tsx
|
|
@@ -132,16 +335,13 @@ var AuthContext = createContext();
|
|
|
132
335
|
function AuthProvider(props) {
|
|
133
336
|
const scheme = untrack(() => props.scheme ?? "gau");
|
|
134
337
|
const baseUrl = untrack(() => props.baseUrl ?? "/api/auth");
|
|
338
|
+
const client = createAuthClient({
|
|
339
|
+
baseUrl
|
|
340
|
+
});
|
|
135
341
|
const fetchSession = async () => {
|
|
136
|
-
if (
|
|
342
|
+
if (isServer2)
|
|
137
343
|
return { ...NULL_SESSION, providers: [] };
|
|
138
|
-
|
|
139
|
-
const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
|
|
140
|
-
const res = await fetch(`${baseUrl}/session`, token ? { headers } : { credentials: "include" });
|
|
141
|
-
const contentType = res.headers.get("content-type");
|
|
142
|
-
if (contentType?.includes("application/json"))
|
|
143
|
-
return res.json();
|
|
144
|
-
return { ...NULL_SESSION, providers: [] };
|
|
344
|
+
return client.refreshSession();
|
|
145
345
|
};
|
|
146
346
|
const [session, { refetch }] = createResource(
|
|
147
347
|
fetchSession,
|
|
@@ -149,96 +349,69 @@ function AuthProvider(props) {
|
|
|
149
349
|
);
|
|
150
350
|
async function signIn(provider, { redirectTo, profile } = {}) {
|
|
151
351
|
let finalRedirectTo = redirectTo ?? props.redirectTo;
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (finalRedirectTo)
|
|
159
|
-
params.set("redirectTo", finalRedirectTo);
|
|
160
|
-
if (profile)
|
|
161
|
-
params.set("profile", String(profile));
|
|
162
|
-
const q = params.toString();
|
|
163
|
-
const authUrl = `${baseUrl}/${provider}${q ? `?${q}` : ""}`;
|
|
164
|
-
window.location.href = authUrl;
|
|
352
|
+
if (!finalRedirectTo && !isServer2)
|
|
353
|
+
finalRedirectTo = window.location.origin;
|
|
354
|
+
if (!isServer2 && isTauri()) {
|
|
355
|
+
const { signInWithTauri: signInWithTauri2 } = await Promise.resolve().then(() => (init_tauri(), tauri_exports));
|
|
356
|
+
await signInWithTauri2(provider, baseUrl, scheme, finalRedirectTo, profile);
|
|
357
|
+
return;
|
|
165
358
|
}
|
|
359
|
+
const url = await client.signIn(provider, { redirectTo: finalRedirectTo, profile });
|
|
360
|
+
if (!isServer2)
|
|
361
|
+
window.location.href = url;
|
|
166
362
|
}
|
|
167
363
|
async function linkAccount(provider, { redirectTo, profile } = {}) {
|
|
168
|
-
if (isTauri()) {
|
|
169
|
-
await
|
|
364
|
+
if (!isServer2 && isTauri()) {
|
|
365
|
+
const { linkAccountWithTauri: linkAccountWithTauri2 } = await Promise.resolve().then(() => (init_tauri(), tauri_exports));
|
|
366
|
+
await linkAccountWithTauri2(provider, baseUrl, scheme, redirectTo, profile);
|
|
170
367
|
return;
|
|
171
368
|
}
|
|
172
369
|
let finalRedirectTo = redirectTo ?? props.redirectTo;
|
|
173
|
-
if (!finalRedirectTo && !
|
|
370
|
+
if (!finalRedirectTo && !isServer2)
|
|
174
371
|
finalRedirectTo = window.location.href;
|
|
175
|
-
const
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
if (profile)
|
|
179
|
-
params.set("profile", String(profile));
|
|
180
|
-
params.set("redirect", "false");
|
|
181
|
-
const linkUrl = `${baseUrl}/link/${provider}?${params.toString()}`;
|
|
182
|
-
const token = getSessionToken();
|
|
183
|
-
const fetchOptions = token ? { headers: { Authorization: `Bearer ${token}` } } : { credentials: "include" };
|
|
184
|
-
const res = await fetch(linkUrl, fetchOptions);
|
|
185
|
-
if (res.redirected) {
|
|
186
|
-
window.location.href = res.url;
|
|
187
|
-
} else {
|
|
188
|
-
const data = await res.json();
|
|
189
|
-
if (data.url)
|
|
190
|
-
window.location.href = data.url;
|
|
191
|
-
}
|
|
372
|
+
const url = await client.linkAccount(provider, { redirectTo: finalRedirectTo, profile });
|
|
373
|
+
if (!isServer2)
|
|
374
|
+
window.location.href = url;
|
|
192
375
|
}
|
|
193
376
|
async function unlinkAccount(provider) {
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
const res = await fetch(`${baseUrl}/unlink/${provider}`, {
|
|
197
|
-
method: "POST",
|
|
198
|
-
...fetchOptions
|
|
199
|
-
});
|
|
200
|
-
if (res.ok)
|
|
377
|
+
const ok = await client.unlinkAccount(provider);
|
|
378
|
+
if (ok)
|
|
201
379
|
refetch();
|
|
202
380
|
else
|
|
203
|
-
console.error("Failed to unlink account"
|
|
381
|
+
console.error("Failed to unlink account");
|
|
204
382
|
}
|
|
205
383
|
const signOut = async () => {
|
|
206
|
-
|
|
207
|
-
const token = getSessionToken();
|
|
208
|
-
const headers = token ? { Authorization: `Bearer ${token}` } : void 0;
|
|
209
|
-
await fetch(`${baseUrl}/signout`, token ? { method: "POST", headers } : { method: "POST", credentials: "include" });
|
|
384
|
+
await client.signOut();
|
|
210
385
|
refetch();
|
|
211
386
|
};
|
|
212
|
-
|
|
387
|
+
onMount2(() => {
|
|
213
388
|
if (!isTauri()) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
refetch();
|
|
220
|
-
window.history.replaceState(null, "", window.location.pathname + window.location.search);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if (!isTauri())
|
|
389
|
+
void (async () => {
|
|
390
|
+
const handled = await client.handleRedirectCallback();
|
|
391
|
+
if (handled)
|
|
392
|
+
refetch();
|
|
393
|
+
})();
|
|
224
394
|
return;
|
|
395
|
+
}
|
|
225
396
|
let disposed = false;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
397
|
+
void (async () => {
|
|
398
|
+
const { startAuthBridge: startAuthBridge2 } = await Promise.resolve().then(() => (init_tauri(), tauri_exports));
|
|
399
|
+
const unlisten = await startAuthBridge2(baseUrl, scheme, async (token) => {
|
|
400
|
+
await client.applySessionToken(token);
|
|
229
401
|
refetch();
|
|
230
402
|
});
|
|
231
|
-
}).then((unlisten) => {
|
|
232
403
|
if (disposed)
|
|
233
404
|
unlisten?.();
|
|
234
405
|
else if (unlisten)
|
|
235
406
|
onCleanup(() => unlisten());
|
|
236
|
-
});
|
|
407
|
+
})();
|
|
237
408
|
onCleanup(() => {
|
|
238
409
|
disposed = true;
|
|
239
410
|
});
|
|
240
411
|
});
|
|
241
|
-
return <AuthContext.Provider value={{ session, signIn, linkAccount, unlinkAccount, signOut
|
|
412
|
+
return <AuthContext.Provider value={{ session, signIn, linkAccount, unlinkAccount, signOut, refresh: async () => {
|
|
413
|
+
await refetch();
|
|
414
|
+
} }}>
|
|
242
415
|
{props.children}
|
|
243
416
|
</AuthContext.Provider>;
|
|
244
417
|
}
|
|
@@ -248,27 +421,6 @@ function useAuth() {
|
|
|
248
421
|
throw new Error("useAuth must be used within an AuthProvider");
|
|
249
422
|
return context;
|
|
250
423
|
}
|
|
251
|
-
function Protected(page, fallbackOrRedirect) {
|
|
252
|
-
return () => {
|
|
253
|
-
const auth = useAuth();
|
|
254
|
-
const isRedirectMode = typeof fallbackOrRedirect === "string" || fallbackOrRedirect === void 0;
|
|
255
|
-
const redirectTo = isRedirectMode ? fallbackOrRedirect ?? "/" : void 0;
|
|
256
|
-
const Fallback = !isRedirectMode ? fallbackOrRedirect : void 0;
|
|
257
|
-
const Redirect = () => {
|
|
258
|
-
onMount(() => {
|
|
259
|
-
if (!isServer && redirectTo)
|
|
260
|
-
window.location.replace(redirectTo);
|
|
261
|
-
});
|
|
262
|
-
return null;
|
|
263
|
-
};
|
|
264
|
-
return <Show
|
|
265
|
-
when={auth.session().user}
|
|
266
|
-
fallback={isRedirectMode ? <Redirect /> : Fallback ? <Fallback /> : null}
|
|
267
|
-
>
|
|
268
|
-
{page(auth.session)}
|
|
269
|
-
</Show>;
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
424
|
export {
|
|
273
425
|
AuthProvider,
|
|
274
426
|
Protected,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang='ts'>
|
|
2
|
+
import type { Snippet } from 'svelte'
|
|
3
|
+
// @ts-expect-error svelte-kit
|
|
4
|
+
import { goto } from '$app/navigation'
|
|
5
|
+
import { BROWSER } from 'esm-env'
|
|
6
|
+
import { useAuth } from '../index.svelte'
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
redirectTo?: string
|
|
10
|
+
fallback?: Snippet
|
|
11
|
+
children: Snippet
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { redirectTo = '/', fallback, children }: Props = $props()
|
|
15
|
+
|
|
16
|
+
const auth = useAuth()
|
|
17
|
+
|
|
18
|
+
$effect(() => {
|
|
19
|
+
if (BROWSER && !auth.isLoading && !auth.session?.user)
|
|
20
|
+
goto(redirectTo)
|
|
21
|
+
})
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
{#if auth.isLoading}
|
|
25
|
+
{#if fallback}
|
|
26
|
+
{@render fallback()}
|
|
27
|
+
{/if}
|
|
28
|
+
{:else if auth.session?.user}
|
|
29
|
+
{@render children()}
|
|
30
|
+
{:else if fallback}
|
|
31
|
+
{@render fallback()}
|
|
32
|
+
{/if}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
var n=Object.defineProperty,t=Object.getOwnPropertyNames,e=(n,e)=>function(){return n&&(e=(0,n[t(n)[0]])(n=0)),e};import{BROWSER as i}from"esm-env";function r(){return i?localStorage.getItem("gau-token"):null}var o=e({"src/client/token.ts"(){}}),a={};((t,e)=>{for(var i in e)n(t,i,{get:e[i],enumerable:!0})})(a,{handleTauriDeepLink:()=>f,isTauri:()=>c,linkAccountWithTauri:()=>d,setupTauriListener:()=>l,signInWithTauri:()=>u,startAuthBridge:()=>w});import{BROWSER as s}from"esm-env";function c(){return s&&"__TAURI_INTERNALS__"in globalThis}async function u(n,t,e="gau",i,r){if(!c())return;const{platform:o}=await import("@tauri-apps/plugin-os"),{openUrl:a}=await import("@tauri-apps/plugin-opener"),s=o();let u;u=i||("android"===s||"ios"===s?new URL(t).origin:`${e}://oauth/callback`);const l=new URLSearchParams;l.set("redirectTo",u),r&&l.set("profile",String(r));const f=`${t}/${n}?${l.toString()}`;await a(f)}async function l(n){if(!c())return;const{listen:t}=await import("@tauri-apps/api/event");try{return await t("deep-link",async t=>{await n(t.payload)})}catch(n){console.error(n)}}function f(n,t,e,i){const r=new URL(n);if(r.protocol!==`${e}:`&&r.origin!==new URL(t).origin)return;const o=new URLSearchParams(r.hash.substring(1)).get("token");o&&i(o)}async function d(n,t,e="gau",i,o){if(!c())return;const{platform:a}=await import("@tauri-apps/plugin-os"),{openUrl:s}=await import("@tauri-apps/plugin-opener"),u=a();let l;l=i||("android"===u||"ios"===u?new URL(t).origin:`${e}://oauth/callback`);const f=r();if(!f)return void console.error("No session token found, cannot link account.");const d=new URLSearchParams;d.set("redirectTo",l),d.set("token",f),o&&d.set("profile",String(o));const w=`${t}/link/${n}?${d.toString()}`;await s(w)}async function w(n,t,e){if(!c())return;return await l(async i=>{f(i,n,t,e)})}var p=e({"src/runtimes/tauri/index.ts"(){o()}});import{replaceState as h}from"$app/navigation";import{BROWSER as g}from"esm-env";import{getContext as m,onMount as y,setContext as k}from"svelte";import{parse as S,serialize as v}from"cookie";import{createJWTSignatureMessage as T,encodeJWT as A,JWSRegisteredHeaders as R,JWTRegisteredClaims as b,parseJWT as U}from"@oslojs/jwt";import{generateCodeVerifier as P,generateState as L}from"arctic";var O={user:null,session:null,accounts:null};function _(n){const t=new URLSearchParams;for(const[e,i]of Object.entries(n))null!=i&&""!==i&&t.set(e,String(i));const e=t.toString();return e?`?${e}`:""}function I({baseUrl:n}){let t={user:null,session:null,accounts:null,providers:[]};const e=new Set;async function o(){const t=r(),e=t?{Authorization:`Bearer ${t}`}:void 0,i=await fetch(`${n}/session`,t?{headers:e}:{credentials:"include"}),o=i.headers.get("content-type");return o?.includes("application/json")?await i.json():{user:null,session:null,accounts:null,providers:[]}}async function a(){const n=await o();return t=n,(()=>{for(const n of e)n(t)})(),n}async function s(n){try{!function(n){if(i)try{localStorage.setItem("gau-token",n),document.cookie=`__gau-session-token=${n}; path=/; max-age=31536000; samesite=lax; secure`}catch{}}(n)}finally{await a()}}return{get session(){return t},fetchSession:o,refreshSession:a,applySessionToken:s,handleRedirectCallback:async function(n){if("undefined"==typeof window)return!1;if("#_=_"===window.location.hash){const t=window.location.pathname+window.location.search;return n?n(t):window.history.replaceState(null,"",t),!1}const t=window.location.hash?.substring(1)??"";if(!t)return!1;const e=new URLSearchParams(t).get("token");if(!e)return!1;await s(e);const i=window.location.pathname+window.location.search;return n?n(i):window.history.replaceState(null,"",i),!0},onSessionChange:function(n){return e.add(n),()=>e.delete(n)},signIn:async function(t,e){return function(t,e){const i=_({redirectTo:e?.redirectTo,profile:null!=e?.profile?String(e.profile):void 0});return`${n}/${t}${i}`}(t,e)},linkAccount:async function(t,e){const i=function(t,e){const i=_({redirectTo:e.redirectTo,profile:null!=e.profile?String(e.profile):void 0,redirect:e.redirect});return`${n}/link/${t}${i}`}(t,{redirectTo:e?.redirectTo,profile:e?.profile,redirect:"false"}),o=r(),a=o?{headers:{Authorization:`Bearer ${o}`}}:{credentials:"include"},s=await fetch(i,a);if(s.redirected)return s.url;try{const n=await s.json();if(n?.url)return n.url}catch{}return i},unlinkAccount:async function(t){const e=r(),i=e?{headers:{Authorization:`Bearer ${e}`}}:{credentials:"include"};return!!(await fetch(`${n}/unlink/${t}`,{method:"POST",...i})).ok&&(await a(),!0)},signOut:async function(){!function(){if(i)try{localStorage.removeItem("gau-token"),document.cookie="__gau-session-token=; path=/; max-age=0"}catch{}}();const t=r(),e=t?{Authorization:`Bearer ${t}`}:void 0;await fetch(`${n}/signout`,t?{method:"POST",headers:e}:{method:"POST",credentials:"include"}),await a()}}}p(),o();var j=Symbol("gau-auth");function B({baseUrl:n="/api/auth",scheme:t="gau",redirectTo:e}={}){const i=I({baseUrl:n}),r=async()=>g?i.refreshSession():{...O,providers:[]};let o=$state({...O,providers:[]}),s=$state(!0);y(()=>{if(!g)return;let e;(async()=>{await i.handleRedirectCallback(async n=>async function(n){try{h(n,{})}catch{g&&window.history.replaceState(null,"",n)}}(n))||(o=await r()),s=!1})();let u=!1;return c()?((async()=>{const{startAuthBridge:s}=await Promise.resolve().then(()=>(p(),a)),c=await s(n,t,async n=>{await i.applySessionToken(n),o=await r()});u?c?.():e=c})(),()=>{u=!0,e?.()}):void 0});k(j,{get session(){return o},get isLoading(){return s},signIn:async function(r,{redirectTo:o,profile:s}={}){let u=o??e;if(!u&&g&&(u=window.location.origin),c()){const{signInWithTauri:e}=await Promise.resolve().then(()=>(p(),a));return void await e(r,n,t,u,s)}const l=await i.signIn(r,{redirectTo:u,profile:s});g&&(window.location.href=l)},linkAccount:async function(r,{redirectTo:o,profile:s}={}){if(c()){const{linkAccountWithTauri:e}=await Promise.resolve().then(()=>(p(),a));return void await e(r,n,t,o,s)}let u=o??e;!u&&g&&(u=window.location.href);const l=await i.linkAccount(r,{redirectTo:u,profile:s});g&&(window.location.href=l)},unlinkAccount:async function(n){await i.unlinkAccount(n)?o=await r():console.error("Failed to unlink account")},signOut:async function(){await i.signOut(),o=await r()},refresh:async()=>{o=await r()}})}function W(){const n=m(j);if(!n)throw new Error("useAuth must be used within an AuthProvider");return n}export{B as createSvelteAuth,W as useAuth};//# sourceMappingURL=index.svelte.js.map
|