@robelest/convex-auth 0.0.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 +6 -0
- package/dist/bin.cjs +27733 -0
- package/dist/client/index.d.ts +49 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +283 -0
- package/dist/client/index.js.map +1 -0
- package/dist/component/_generated/api.d.ts +36 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +295 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +121 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +4 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/index.d.ts +15 -0
- package/dist/component/index.d.ts.map +1 -0
- package/dist/component/index.js +13 -0
- package/dist/component/index.js.map +1 -0
- package/dist/component/public.d.ts +450 -0
- package/dist/component/public.d.ts.map +1 -0
- package/dist/component/public.js +528 -0
- package/dist/component/public.js.map +1 -0
- package/dist/component/schema.d.ts +107 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +26 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/providers/Anonymous.d.ts +50 -0
- package/dist/providers/Anonymous.d.ts.map +1 -0
- package/dist/providers/Anonymous.js +39 -0
- package/dist/providers/Anonymous.js.map +1 -0
- package/dist/providers/ConvexCredentials.d.ts +88 -0
- package/dist/providers/ConvexCredentials.d.ts.map +1 -0
- package/dist/providers/ConvexCredentials.js +37 -0
- package/dist/providers/ConvexCredentials.js.map +1 -0
- package/dist/providers/Email.d.ts +33 -0
- package/dist/providers/Email.d.ts.map +1 -0
- package/dist/providers/Email.js +50 -0
- package/dist/providers/Email.js.map +1 -0
- package/dist/providers/Password.d.ts +95 -0
- package/dist/providers/Password.d.ts.map +1 -0
- package/dist/providers/Password.js +174 -0
- package/dist/providers/Password.js.map +1 -0
- package/dist/providers/Phone.d.ts +22 -0
- package/dist/providers/Phone.d.ts.map +1 -0
- package/dist/providers/Phone.js +37 -0
- package/dist/providers/Phone.js.map +1 -0
- package/dist/server/convex_types.d.ts +17 -0
- package/dist/server/convex_types.d.ts.map +1 -0
- package/dist/server/convex_types.js +2 -0
- package/dist/server/convex_types.js.map +1 -0
- package/dist/server/cookies.d.ts +35 -0
- package/dist/server/cookies.d.ts.map +1 -0
- package/dist/server/cookies.js +34 -0
- package/dist/server/cookies.js.map +1 -0
- package/dist/server/implementation/db.d.ts +80 -0
- package/dist/server/implementation/db.d.ts.map +1 -0
- package/dist/server/implementation/db.js +59 -0
- package/dist/server/implementation/db.js.map +1 -0
- package/dist/server/implementation/index.d.ts +370 -0
- package/dist/server/implementation/index.d.ts.map +1 -0
- package/dist/server/implementation/index.js +521 -0
- package/dist/server/implementation/index.js.map +1 -0
- package/dist/server/implementation/mutations/createAccountFromCredentials.d.ts +33 -0
- package/dist/server/implementation/mutations/createAccountFromCredentials.d.ts.map +1 -0
- package/dist/server/implementation/mutations/createAccountFromCredentials.js +71 -0
- package/dist/server/implementation/mutations/createAccountFromCredentials.js.map +1 -0
- package/dist/server/implementation/mutations/createVerificationCode.d.ts +25 -0
- package/dist/server/implementation/mutations/createVerificationCode.d.ts.map +1 -0
- package/dist/server/implementation/mutations/createVerificationCode.js +84 -0
- package/dist/server/implementation/mutations/createVerificationCode.js.map +1 -0
- package/dist/server/implementation/mutations/index.d.ts +304 -0
- package/dist/server/implementation/mutations/index.d.ts.map +1 -0
- package/dist/server/implementation/mutations/index.js +108 -0
- package/dist/server/implementation/mutations/index.js.map +1 -0
- package/dist/server/implementation/mutations/invalidateSessions.d.ts +13 -0
- package/dist/server/implementation/mutations/invalidateSessions.d.ts.map +1 -0
- package/dist/server/implementation/mutations/invalidateSessions.js +35 -0
- package/dist/server/implementation/mutations/invalidateSessions.js.map +1 -0
- package/dist/server/implementation/mutations/modifyAccount.d.ts +23 -0
- package/dist/server/implementation/mutations/modifyAccount.d.ts.map +1 -0
- package/dist/server/implementation/mutations/modifyAccount.js +48 -0
- package/dist/server/implementation/mutations/modifyAccount.js.map +1 -0
- package/dist/server/implementation/mutations/refreshSession.d.ts +16 -0
- package/dist/server/implementation/mutations/refreshSession.d.ts.map +1 -0
- package/dist/server/implementation/mutations/refreshSession.js +116 -0
- package/dist/server/implementation/mutations/refreshSession.js.map +1 -0
- package/dist/server/implementation/mutations/retrieveAccountWithCredentials.d.ts +27 -0
- package/dist/server/implementation/mutations/retrieveAccountWithCredentials.d.ts.map +1 -0
- package/dist/server/implementation/mutations/retrieveAccountWithCredentials.js +55 -0
- package/dist/server/implementation/mutations/retrieveAccountWithCredentials.js.map +1 -0
- package/dist/server/implementation/mutations/signIn.d.ts +17 -0
- package/dist/server/implementation/mutations/signIn.d.ts.map +1 -0
- package/dist/server/implementation/mutations/signIn.js +26 -0
- package/dist/server/implementation/mutations/signIn.js.map +1 -0
- package/dist/server/implementation/mutations/signOut.d.ts +11 -0
- package/dist/server/implementation/mutations/signOut.d.ts.map +1 -0
- package/dist/server/implementation/mutations/signOut.js +24 -0
- package/dist/server/implementation/mutations/signOut.js.map +1 -0
- package/dist/server/implementation/mutations/userOAuth.d.ts +19 -0
- package/dist/server/implementation/mutations/userOAuth.d.ts.map +1 -0
- package/dist/server/implementation/mutations/userOAuth.js +84 -0
- package/dist/server/implementation/mutations/userOAuth.js.map +1 -0
- package/dist/server/implementation/mutations/verifier.d.ts +8 -0
- package/dist/server/implementation/mutations/verifier.d.ts.map +1 -0
- package/dist/server/implementation/mutations/verifier.js +19 -0
- package/dist/server/implementation/mutations/verifier.js.map +1 -0
- package/dist/server/implementation/mutations/verifierSignature.d.ts +15 -0
- package/dist/server/implementation/mutations/verifierSignature.d.ts.map +1 -0
- package/dist/server/implementation/mutations/verifierSignature.js +29 -0
- package/dist/server/implementation/mutations/verifierSignature.js.map +1 -0
- package/dist/server/implementation/mutations/verifyCodeAndSignIn.d.ts +21 -0
- package/dist/server/implementation/mutations/verifyCodeAndSignIn.d.ts.map +1 -0
- package/dist/server/implementation/mutations/verifyCodeAndSignIn.js +127 -0
- package/dist/server/implementation/mutations/verifyCodeAndSignIn.js.map +1 -0
- package/dist/server/implementation/provider.d.ts +6 -0
- package/dist/server/implementation/provider.d.ts.map +1 -0
- package/dist/server/implementation/provider.js +21 -0
- package/dist/server/implementation/provider.js.map +1 -0
- package/dist/server/implementation/rateLimit.d.ts +6 -0
- package/dist/server/implementation/rateLimit.d.ts.map +1 -0
- package/dist/server/implementation/rateLimit.js +76 -0
- package/dist/server/implementation/rateLimit.js.map +1 -0
- package/dist/server/implementation/redirects.d.ts +6 -0
- package/dist/server/implementation/redirects.d.ts.map +1 -0
- package/dist/server/implementation/redirects.js +40 -0
- package/dist/server/implementation/redirects.js.map +1 -0
- package/dist/server/implementation/refreshTokens.d.ts +40 -0
- package/dist/server/implementation/refreshTokens.d.ts.map +1 -0
- package/dist/server/implementation/refreshTokens.js +160 -0
- package/dist/server/implementation/refreshTokens.js.map +1 -0
- package/dist/server/implementation/sessions.d.ts +43 -0
- package/dist/server/implementation/sessions.d.ts.map +1 -0
- package/dist/server/implementation/sessions.js +94 -0
- package/dist/server/implementation/sessions.js.map +1 -0
- package/dist/server/implementation/signIn.d.ts +31 -0
- package/dist/server/implementation/signIn.d.ts.map +1 -0
- package/dist/server/implementation/signIn.js +148 -0
- package/dist/server/implementation/signIn.js.map +1 -0
- package/dist/server/implementation/tokens.d.ts +7 -0
- package/dist/server/implementation/tokens.d.ts.map +1 -0
- package/dist/server/implementation/tokens.js +18 -0
- package/dist/server/implementation/tokens.js.map +1 -0
- package/dist/server/implementation/types.d.ts +288 -0
- package/dist/server/implementation/types.d.ts.map +1 -0
- package/dist/server/implementation/types.js +182 -0
- package/dist/server/implementation/types.js.map +1 -0
- package/dist/server/implementation/users.d.ts +27 -0
- package/dist/server/implementation/users.d.ts.map +1 -0
- package/dist/server/implementation/users.js +181 -0
- package/dist/server/implementation/users.js.map +1 -0
- package/dist/server/implementation/utils.d.ts +17 -0
- package/dist/server/implementation/utils.d.ts.map +1 -0
- package/dist/server/implementation/utils.js +72 -0
- package/dist/server/implementation/utils.js.map +1 -0
- package/dist/server/index.d.ts +17 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +54 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/oauth/authorizationUrl.d.ts +13 -0
- package/dist/server/oauth/authorizationUrl.d.ts.map +1 -0
- package/dist/server/oauth/authorizationUrl.js +91 -0
- package/dist/server/oauth/authorizationUrl.js.map +1 -0
- package/dist/server/oauth/callback.d.ts +19 -0
- package/dist/server/oauth/callback.d.ts.map +1 -0
- package/dist/server/oauth/callback.js +173 -0
- package/dist/server/oauth/callback.js.map +1 -0
- package/dist/server/oauth/checks.d.ts +52 -0
- package/dist/server/oauth/checks.d.ts.map +1 -0
- package/dist/server/oauth/checks.js +106 -0
- package/dist/server/oauth/checks.js.map +1 -0
- package/dist/server/oauth/convexAuth.d.ts +12 -0
- package/dist/server/oauth/convexAuth.d.ts.map +1 -0
- package/dist/server/oauth/convexAuth.js +137 -0
- package/dist/server/oauth/convexAuth.js.map +1 -0
- package/dist/server/oauth/lib/utils/customFetch.d.ts +9 -0
- package/dist/server/oauth/lib/utils/customFetch.d.ts.map +1 -0
- package/dist/server/oauth/lib/utils/customFetch.js +11 -0
- package/dist/server/oauth/lib/utils/customFetch.js.map +1 -0
- package/dist/server/oauth/lib/utils/providers.d.ts +3 -0
- package/dist/server/oauth/lib/utils/providers.d.ts.map +1 -0
- package/dist/server/oauth/lib/utils/providers.js +7 -0
- package/dist/server/oauth/lib/utils/providers.js.map +1 -0
- package/dist/server/oauth/providers/oauth.d.ts +43 -0
- package/dist/server/oauth/providers/oauth.d.ts.map +1 -0
- package/dist/server/oauth/providers/oauth.js +3 -0
- package/dist/server/oauth/providers/oauth.js.map +1 -0
- package/dist/server/oauth/types.d.ts +24 -0
- package/dist/server/oauth/types.d.ts.map +1 -0
- package/dist/server/oauth/types.js +5 -0
- package/dist/server/oauth/types.js.map +1 -0
- package/dist/server/provider_utils.d.ts +76 -0
- package/dist/server/provider_utils.d.ts.map +1 -0
- package/dist/server/provider_utils.js +177 -0
- package/dist/server/provider_utils.js.map +1 -0
- package/dist/server/types.d.ts +412 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/utils.d.ts +3 -0
- package/dist/server/utils.d.ts.map +1 -0
- package/dist/server/utils.js +11 -0
- package/dist/server/utils.js.map +1 -0
- package/package.json +126 -0
- package/providers/Anonymous/package.json +6 -0
- package/providers/ConvexCredentials/package.json +6 -0
- package/providers/Email/package.json +6 -0
- package/providers/Password/package.json +6 -0
- package/providers/Phone/package.json +6 -0
- package/server/package.json +6 -0
- package/src/cli/command.ts +69 -0
- package/src/cli/generateKeys.ts +20 -0
- package/src/cli/index.ts +840 -0
- package/src/client/index.ts +415 -0
- package/src/component/_generated/api.ts +52 -0
- package/src/component/_generated/component.ts +586 -0
- package/src/component/_generated/dataModel.ts +60 -0
- package/src/component/_generated/server.ts +156 -0
- package/src/component/convex.config.ts +5 -0
- package/src/component/index.ts +40 -0
- package/src/component/public.ts +607 -0
- package/src/component/schema.ts +35 -0
- package/src/providers/Anonymous.ts +79 -0
- package/src/providers/ConvexCredentials.ts +108 -0
- package/src/providers/Email.ts +60 -0
- package/src/providers/Password.ts +253 -0
- package/src/providers/Phone.ts +46 -0
- package/src/server/convex_types.ts +55 -0
- package/src/server/cookies.ts +42 -0
- package/src/server/implementation/db.ts +125 -0
- package/src/server/implementation/index.ts +815 -0
- package/src/server/implementation/mutations/createAccountFromCredentials.ts +113 -0
- package/src/server/implementation/mutations/createVerificationCode.ts +139 -0
- package/src/server/implementation/mutations/index.ts +157 -0
- package/src/server/implementation/mutations/invalidateSessions.ts +47 -0
- package/src/server/implementation/mutations/modifyAccount.ts +65 -0
- package/src/server/implementation/mutations/refreshSession.ts +188 -0
- package/src/server/implementation/mutations/retrieveAccountWithCredentials.ts +87 -0
- package/src/server/implementation/mutations/signIn.ts +51 -0
- package/src/server/implementation/mutations/signOut.ts +38 -0
- package/src/server/implementation/mutations/userOAuth.ts +112 -0
- package/src/server/implementation/mutations/verifier.ts +29 -0
- package/src/server/implementation/mutations/verifierSignature.ts +44 -0
- package/src/server/implementation/mutations/verifyCodeAndSignIn.ts +205 -0
- package/src/server/implementation/provider.ts +38 -0
- package/src/server/implementation/rateLimit.ts +105 -0
- package/src/server/implementation/redirects.ts +58 -0
- package/src/server/implementation/refreshTokens.ts +221 -0
- package/src/server/implementation/sessions.ts +155 -0
- package/src/server/implementation/signIn.ts +253 -0
- package/src/server/implementation/tokens.ts +29 -0
- package/src/server/implementation/types.ts +220 -0
- package/src/server/implementation/users.ts +286 -0
- package/src/server/implementation/utils.ts +91 -0
- package/src/server/index.ts +74 -0
- package/src/server/oauth/NOTICE.txt +21 -0
- package/src/server/oauth/README.md +7 -0
- package/src/server/oauth/authorizationUrl.ts +113 -0
- package/src/server/oauth/callback.ts +243 -0
- package/src/server/oauth/checks.ts +136 -0
- package/src/server/oauth/convexAuth.ts +168 -0
- package/src/server/oauth/lib/utils/customFetch.ts +18 -0
- package/src/server/oauth/lib/utils/providers.ts +12 -0
- package/src/server/oauth/providers/oauth.ts +56 -0
- package/src/server/oauth/types.ts +60 -0
- package/src/server/provider_utils.ts +222 -0
- package/src/server/types.ts +470 -0
- package/src/server/utils.ts +12 -0
- package/src/test.ts +24 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { FunctionReference, OptionalRestArgs } from "convex/server";
|
|
2
|
+
import { Value } from "convex/values";
|
|
3
|
+
import type {
|
|
4
|
+
SignInAction,
|
|
5
|
+
SignOutAction,
|
|
6
|
+
} from "../server/implementation/index.js";
|
|
7
|
+
|
|
8
|
+
type AuthActionCaller = {
|
|
9
|
+
authenticatedCall<Action extends FunctionReference<"action", "public">>(
|
|
10
|
+
action: Action,
|
|
11
|
+
...args: OptionalRestArgs<Action>
|
|
12
|
+
): Promise<Action["_returnType"]>;
|
|
13
|
+
unauthenticatedCall<Action extends FunctionReference<"action", "public">>(
|
|
14
|
+
action: Action,
|
|
15
|
+
...args: OptionalRestArgs<Action>
|
|
16
|
+
): Promise<Action["_returnType"]>;
|
|
17
|
+
verbose?: boolean;
|
|
18
|
+
logger?: {
|
|
19
|
+
logVerbose?: (message: string) => void;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export interface TokenStorage {
|
|
24
|
+
getItem(key: string): string | null | undefined | Promise<string | null | undefined>;
|
|
25
|
+
setItem(key: string, value: string): void | Promise<void>;
|
|
26
|
+
removeItem(key: string): void | Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type AuthSession = {
|
|
30
|
+
token: string;
|
|
31
|
+
refreshToken: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type SignInResult = {
|
|
35
|
+
signingIn: boolean;
|
|
36
|
+
redirect?: URL;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type AuthSnapshot = {
|
|
40
|
+
isLoading: boolean;
|
|
41
|
+
isAuthenticated: boolean;
|
|
42
|
+
token: string | null;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type AuthClientOptions = {
|
|
46
|
+
transport: AuthActionCaller;
|
|
47
|
+
storage?: TokenStorage | null;
|
|
48
|
+
storageNamespace: string;
|
|
49
|
+
replaceURL?: (relativeUrl: string) => void | Promise<void>;
|
|
50
|
+
shouldHandleCode?: (() => boolean) | boolean;
|
|
51
|
+
onChange?: () => Promise<unknown>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const VERIFIER_STORAGE_KEY = "__convexAuthOAuthVerifier";
|
|
55
|
+
const JWT_STORAGE_KEY = "__convexAuthJWT";
|
|
56
|
+
const REFRESH_TOKEN_STORAGE_KEY = "__convexAuthRefreshToken";
|
|
57
|
+
|
|
58
|
+
const RETRY_BACKOFF = [500, 2000];
|
|
59
|
+
const RETRY_JITTER = 100;
|
|
60
|
+
|
|
61
|
+
export function createAuthClient(options: AuthClientOptions) {
|
|
62
|
+
const {
|
|
63
|
+
transport,
|
|
64
|
+
storage = typeof window === "undefined" ? null : window.localStorage,
|
|
65
|
+
storageNamespace,
|
|
66
|
+
replaceURL = (url: string) => {
|
|
67
|
+
if (typeof window !== "undefined") {
|
|
68
|
+
window.history.replaceState({}, "", url);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
shouldHandleCode,
|
|
72
|
+
onChange,
|
|
73
|
+
} = options;
|
|
74
|
+
|
|
75
|
+
const escapedNamespace = storageNamespace.replace(/[^a-zA-Z0-9]/g, "");
|
|
76
|
+
const key = (name: string) => `${name}_${escapedNamespace}`;
|
|
77
|
+
const subscribers = new Set<() => void>();
|
|
78
|
+
|
|
79
|
+
let token: string | null = null;
|
|
80
|
+
let isLoading = true;
|
|
81
|
+
let snapshot: AuthSnapshot = {
|
|
82
|
+
isLoading,
|
|
83
|
+
isAuthenticated: false,
|
|
84
|
+
token,
|
|
85
|
+
};
|
|
86
|
+
let handlingCodeFlow = false;
|
|
87
|
+
|
|
88
|
+
const logVerbose = (message: string) => {
|
|
89
|
+
if (transport.verbose) {
|
|
90
|
+
transport.logger?.logVerbose?.(message);
|
|
91
|
+
console.debug(`${new Date().toISOString()} ${message}`);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const notify = () => {
|
|
96
|
+
for (const cb of subscribers) cb();
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const updateSnapshot = () => {
|
|
100
|
+
const nextSnapshot: AuthSnapshot = {
|
|
101
|
+
isLoading,
|
|
102
|
+
isAuthenticated: token !== null,
|
|
103
|
+
token,
|
|
104
|
+
};
|
|
105
|
+
if (
|
|
106
|
+
snapshot.isLoading === nextSnapshot.isLoading &&
|
|
107
|
+
snapshot.isAuthenticated === nextSnapshot.isAuthenticated &&
|
|
108
|
+
snapshot.token === nextSnapshot.token
|
|
109
|
+
) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
snapshot = nextSnapshot;
|
|
113
|
+
return true;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const storageGet = async (name: string) =>
|
|
117
|
+
storage ? ((await storage.getItem(key(name))) ?? null) : null;
|
|
118
|
+
const storageSet = async (name: string, value: string) => {
|
|
119
|
+
if (storage) await storage.setItem(key(name), value);
|
|
120
|
+
};
|
|
121
|
+
const storageRemove = async (name: string) => {
|
|
122
|
+
if (storage) await storage.removeItem(key(name));
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const setToken = async (
|
|
126
|
+
args:
|
|
127
|
+
| { shouldStore: true; tokens: AuthSession | null }
|
|
128
|
+
| { shouldStore: false; tokens: { token: string } | null },
|
|
129
|
+
) => {
|
|
130
|
+
const wasAuthenticated = token !== null;
|
|
131
|
+
if (args.tokens === null) {
|
|
132
|
+
token = null;
|
|
133
|
+
if (args.shouldStore) {
|
|
134
|
+
await storageRemove(JWT_STORAGE_KEY);
|
|
135
|
+
await storageRemove(REFRESH_TOKEN_STORAGE_KEY);
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
token = args.tokens.token;
|
|
139
|
+
if (args.shouldStore && "refreshToken" in args.tokens) {
|
|
140
|
+
await storageSet(JWT_STORAGE_KEY, args.tokens.token);
|
|
141
|
+
await storageSet(REFRESH_TOKEN_STORAGE_KEY, args.tokens.refreshToken);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (wasAuthenticated !== (token !== null)) {
|
|
145
|
+
await onChange?.();
|
|
146
|
+
}
|
|
147
|
+
const hadPendingLoad = isLoading;
|
|
148
|
+
isLoading = false;
|
|
149
|
+
const changed = updateSnapshot();
|
|
150
|
+
if (hadPendingLoad || changed) {
|
|
151
|
+
notify();
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const verifyCode = async (
|
|
156
|
+
args: { code: string; verifier?: string } | { refreshToken: string },
|
|
157
|
+
) => {
|
|
158
|
+
let lastError: unknown;
|
|
159
|
+
let retry = 0;
|
|
160
|
+
while (retry < RETRY_BACKOFF.length) {
|
|
161
|
+
try {
|
|
162
|
+
return await transport.unauthenticatedCall(
|
|
163
|
+
"auth:signIn" as unknown as SignInAction,
|
|
164
|
+
"code" in args
|
|
165
|
+
? { params: { code: args.code }, verifier: args.verifier }
|
|
166
|
+
: args,
|
|
167
|
+
);
|
|
168
|
+
} catch (e) {
|
|
169
|
+
lastError = e;
|
|
170
|
+
const isNetworkError =
|
|
171
|
+
e instanceof Error && /network/i.test(e.message || "");
|
|
172
|
+
if (!isNetworkError) break;
|
|
173
|
+
const wait = RETRY_BACKOFF[retry] + RETRY_JITTER * Math.random();
|
|
174
|
+
retry++;
|
|
175
|
+
logVerbose(
|
|
176
|
+
`verifyCode network retry ${retry}/${RETRY_BACKOFF.length} in ${wait}ms`,
|
|
177
|
+
);
|
|
178
|
+
await new Promise((resolve) => setTimeout(resolve, wait));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
throw lastError;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const verifyCodeAndSetToken = async (
|
|
185
|
+
args: { code: string; verifier?: string } | { refreshToken: string },
|
|
186
|
+
) => {
|
|
187
|
+
const { tokens } = await verifyCode(args);
|
|
188
|
+
await setToken({ shouldStore: true, tokens: (tokens as AuthSession | null) ?? null });
|
|
189
|
+
return tokens !== null;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const signIn = async (
|
|
193
|
+
provider?: string,
|
|
194
|
+
args?: FormData | Record<string, Value>,
|
|
195
|
+
): Promise<SignInResult> => {
|
|
196
|
+
const params =
|
|
197
|
+
args instanceof FormData
|
|
198
|
+
? Array.from(args.entries()).reduce(
|
|
199
|
+
(acc, [k, v]) => {
|
|
200
|
+
acc[k] = v as string;
|
|
201
|
+
return acc;
|
|
202
|
+
},
|
|
203
|
+
{} as Record<string, string>,
|
|
204
|
+
)
|
|
205
|
+
: args ?? {};
|
|
206
|
+
|
|
207
|
+
const verifier = (await storageGet(VERIFIER_STORAGE_KEY)) ?? undefined;
|
|
208
|
+
await storageRemove(VERIFIER_STORAGE_KEY);
|
|
209
|
+
const result = await transport.authenticatedCall(
|
|
210
|
+
"auth:signIn" as unknown as SignInAction,
|
|
211
|
+
{ provider, params, verifier },
|
|
212
|
+
);
|
|
213
|
+
if (result.redirect !== undefined) {
|
|
214
|
+
const url = new URL(result.redirect);
|
|
215
|
+
await storageSet(VERIFIER_STORAGE_KEY, result.verifier!);
|
|
216
|
+
if (typeof window !== "undefined") {
|
|
217
|
+
window.location.href = url.toString();
|
|
218
|
+
}
|
|
219
|
+
return { signingIn: false, redirect: url };
|
|
220
|
+
}
|
|
221
|
+
if (result.tokens !== undefined) {
|
|
222
|
+
await setToken({
|
|
223
|
+
shouldStore: true,
|
|
224
|
+
tokens: (result.tokens as AuthSession | null) ?? null,
|
|
225
|
+
});
|
|
226
|
+
return { signingIn: result.tokens !== null };
|
|
227
|
+
}
|
|
228
|
+
return { signingIn: false };
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const signOut = async () => {
|
|
232
|
+
try {
|
|
233
|
+
await transport.authenticatedCall(
|
|
234
|
+
"auth:signOut" as unknown as SignOutAction,
|
|
235
|
+
);
|
|
236
|
+
} catch {
|
|
237
|
+
// Already signed out is fine.
|
|
238
|
+
}
|
|
239
|
+
await setToken({ shouldStore: true, tokens: null });
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const fetchAccessToken = async ({
|
|
243
|
+
forceRefreshToken,
|
|
244
|
+
}: {
|
|
245
|
+
forceRefreshToken: boolean;
|
|
246
|
+
}): Promise<string | null> => {
|
|
247
|
+
if (!forceRefreshToken) return token;
|
|
248
|
+
const tokenBeforeLockAcquisition = token;
|
|
249
|
+
return await browserMutex(REFRESH_TOKEN_STORAGE_KEY, async () => {
|
|
250
|
+
const tokenAfterLockAcquisition = token;
|
|
251
|
+
if (tokenAfterLockAcquisition !== tokenBeforeLockAcquisition) {
|
|
252
|
+
logVerbose(
|
|
253
|
+
`fetchAccessToken using synchronized token, is null: ${tokenAfterLockAcquisition === null}`,
|
|
254
|
+
);
|
|
255
|
+
return tokenAfterLockAcquisition;
|
|
256
|
+
}
|
|
257
|
+
const refreshToken = (await storageGet(REFRESH_TOKEN_STORAGE_KEY)) ?? null;
|
|
258
|
+
if (!refreshToken) {
|
|
259
|
+
logVerbose("fetchAccessToken found no refresh token");
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
await verifyCodeAndSetToken({ refreshToken });
|
|
263
|
+
return token;
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const handleCodeFlow = async () => {
|
|
268
|
+
if (typeof window === "undefined") return;
|
|
269
|
+
if (handlingCodeFlow) return;
|
|
270
|
+
const code = new URLSearchParams(window.location.search).get("code");
|
|
271
|
+
if (!code) return;
|
|
272
|
+
const shouldRun =
|
|
273
|
+
shouldHandleCode === undefined
|
|
274
|
+
? true
|
|
275
|
+
: typeof shouldHandleCode === "function"
|
|
276
|
+
? shouldHandleCode()
|
|
277
|
+
: shouldHandleCode;
|
|
278
|
+
if (!shouldRun) return;
|
|
279
|
+
handlingCodeFlow = true;
|
|
280
|
+
const url = new URL(window.location.href);
|
|
281
|
+
url.searchParams.delete("code");
|
|
282
|
+
try {
|
|
283
|
+
await replaceURL(url.pathname + url.search + url.hash);
|
|
284
|
+
await signIn(undefined, { code });
|
|
285
|
+
} finally {
|
|
286
|
+
handlingCodeFlow = false;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const hydrateFromStorage = async () => {
|
|
291
|
+
const storedToken = (await storageGet(JWT_STORAGE_KEY)) ?? null;
|
|
292
|
+
await setToken({
|
|
293
|
+
shouldStore: false,
|
|
294
|
+
tokens: storedToken === null ? null : { token: storedToken },
|
|
295
|
+
});
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const getSnapshot = (): AuthSnapshot => snapshot;
|
|
299
|
+
|
|
300
|
+
const subscribe = (cb: () => void) => {
|
|
301
|
+
subscribers.add(cb);
|
|
302
|
+
return () => subscribers.delete(cb);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
if (typeof window !== "undefined") {
|
|
306
|
+
const onStorage = (event: StorageEvent) => {
|
|
307
|
+
void (async () => {
|
|
308
|
+
if (event.key !== key(JWT_STORAGE_KEY)) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const value = event.newValue;
|
|
312
|
+
await setToken({
|
|
313
|
+
shouldStore: false,
|
|
314
|
+
tokens: value === null ? null : { token: value },
|
|
315
|
+
});
|
|
316
|
+
})();
|
|
317
|
+
};
|
|
318
|
+
window.addEventListener("storage", onStorage);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
signIn,
|
|
323
|
+
signOut,
|
|
324
|
+
fetchAccessToken,
|
|
325
|
+
handleCodeFlow,
|
|
326
|
+
hydrateFromStorage,
|
|
327
|
+
getSnapshot,
|
|
328
|
+
subscribe,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async function browserMutex<T>(
|
|
333
|
+
key: string,
|
|
334
|
+
callback: () => Promise<T>,
|
|
335
|
+
): Promise<T> {
|
|
336
|
+
const lockManager = (globalThis as any)?.navigator?.locks;
|
|
337
|
+
return lockManager !== undefined
|
|
338
|
+
? await lockManager.request(key, callback)
|
|
339
|
+
: await manualMutex(key, callback);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function getMutexValue(key: string): {
|
|
343
|
+
currentlyRunning: Promise<void> | null;
|
|
344
|
+
waiting: Array<() => Promise<void>>;
|
|
345
|
+
} {
|
|
346
|
+
if ((globalThis as any).__convexAuthMutexes === undefined) {
|
|
347
|
+
(globalThis as any).__convexAuthMutexes = {} as Record<
|
|
348
|
+
string,
|
|
349
|
+
{
|
|
350
|
+
currentlyRunning: Promise<void> | null;
|
|
351
|
+
waiting: Array<() => Promise<void>>;
|
|
352
|
+
}
|
|
353
|
+
>;
|
|
354
|
+
}
|
|
355
|
+
let mutex = (globalThis as any).__convexAuthMutexes[key];
|
|
356
|
+
if (mutex === undefined) {
|
|
357
|
+
(globalThis as any).__convexAuthMutexes[key] = {
|
|
358
|
+
currentlyRunning: null,
|
|
359
|
+
waiting: [],
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
mutex = (globalThis as any).__convexAuthMutexes[key];
|
|
363
|
+
return mutex;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function setMutexValue(
|
|
367
|
+
key: string,
|
|
368
|
+
value: {
|
|
369
|
+
currentlyRunning: Promise<void> | null;
|
|
370
|
+
waiting: Array<() => Promise<void>>;
|
|
371
|
+
},
|
|
372
|
+
) {
|
|
373
|
+
(globalThis as any).__convexAuthMutexes[key] = value;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async function enqueueCallbackForMutex(
|
|
377
|
+
key: string,
|
|
378
|
+
callback: () => Promise<void>,
|
|
379
|
+
) {
|
|
380
|
+
const mutex = getMutexValue(key);
|
|
381
|
+
if (mutex.currentlyRunning === null) {
|
|
382
|
+
setMutexValue(key, {
|
|
383
|
+
currentlyRunning: callback().finally(() => {
|
|
384
|
+
const nextCb = getMutexValue(key).waiting.shift();
|
|
385
|
+
getMutexValue(key).currentlyRunning = null;
|
|
386
|
+
setMutexValue(key, {
|
|
387
|
+
...getMutexValue(key),
|
|
388
|
+
currentlyRunning:
|
|
389
|
+
nextCb === undefined ? null : enqueueCallbackForMutex(key, nextCb),
|
|
390
|
+
});
|
|
391
|
+
}),
|
|
392
|
+
waiting: [],
|
|
393
|
+
});
|
|
394
|
+
} else {
|
|
395
|
+
setMutexValue(key, {
|
|
396
|
+
...mutex,
|
|
397
|
+
waiting: [...mutex.waiting, callback],
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
async function manualMutex<T>(
|
|
403
|
+
key: string,
|
|
404
|
+
callback: () => Promise<T>,
|
|
405
|
+
): Promise<T> {
|
|
406
|
+
const outerPromise = new Promise<T>((resolve, reject) => {
|
|
407
|
+
const wrappedCallback: () => Promise<void> = () => {
|
|
408
|
+
return callback()
|
|
409
|
+
.then((v) => resolve(v))
|
|
410
|
+
.catch((e) => reject(e));
|
|
411
|
+
};
|
|
412
|
+
void enqueueCallbackForMutex(key, wrappedCallback);
|
|
413
|
+
});
|
|
414
|
+
return outerPromise;
|
|
415
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Generated `api` utility.
|
|
4
|
+
*
|
|
5
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
+
*
|
|
7
|
+
* To regenerate, run `npx convex dev`.
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type * as index from "../index.js";
|
|
12
|
+
import type * as public_ from "../public.js";
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
ApiFromModules,
|
|
16
|
+
FilterApi,
|
|
17
|
+
FunctionReference,
|
|
18
|
+
} from "convex/server";
|
|
19
|
+
import { anyApi, componentsGeneric } from "convex/server";
|
|
20
|
+
|
|
21
|
+
const fullApi: ApiFromModules<{
|
|
22
|
+
index: typeof index;
|
|
23
|
+
public: typeof public_;
|
|
24
|
+
}> = anyApi as any;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A utility for referencing Convex functions in your app's public API.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* ```js
|
|
31
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const api: FilterApi<
|
|
35
|
+
typeof fullApi,
|
|
36
|
+
FunctionReference<any, "public">
|
|
37
|
+
> = anyApi as any;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A utility for referencing Convex functions in your app's internal API.
|
|
41
|
+
*
|
|
42
|
+
* Usage:
|
|
43
|
+
* ```js
|
|
44
|
+
* const myFunctionReference = internal.myModule.myFunction;
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export const internal: FilterApi<
|
|
48
|
+
typeof fullApi,
|
|
49
|
+
FunctionReference<any, "internal">
|
|
50
|
+
> = anyApi as any;
|
|
51
|
+
|
|
52
|
+
export const components = componentsGeneric() as unknown as {};
|