@account-kit/signer 4.0.0-beta.1 → 4.0.0-beta.10
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/esm/base.d.ts +42 -5
- package/dist/esm/base.js +186 -29
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +22 -4
- package/dist/esm/client/base.js +36 -2
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.d.ts +108 -7
- package/dist/esm/client/index.js +282 -14
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +31 -1
- package/dist/esm/client/types.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/metrics.d.ts +17 -0
- package/dist/esm/metrics.js +7 -0
- package/dist/esm/metrics.js.map +1 -0
- package/dist/esm/oauth.d.ts +19 -0
- package/dist/esm/oauth.js +26 -0
- package/dist/esm/oauth.js.map +1 -0
- package/dist/esm/session/manager.d.ts +3 -2
- package/dist/esm/session/manager.js +29 -15
- package/dist/esm/session/manager.js.map +1 -1
- package/dist/esm/session/types.d.ts +1 -1
- package/dist/esm/session/types.js.map +1 -1
- package/dist/esm/signer.d.ts +52 -7
- package/dist/esm/signer.js +46 -3
- package/dist/esm/signer.js.map +1 -1
- package/dist/esm/types.d.ts +8 -1
- package/dist/esm/types.js +3 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/typeAssertions.d.ts +1 -0
- package/dist/esm/utils/typeAssertions.js +4 -0
- package/dist/esm/utils/typeAssertions.js.map +1 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/base.d.ts +42 -5
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +22 -4
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +108 -7
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/client/types.d.ts +31 -1
- package/dist/types/client/types.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/metrics.d.ts +18 -0
- package/dist/types/metrics.d.ts.map +1 -0
- package/dist/types/oauth.d.ts +20 -0
- package/dist/types/oauth.d.ts.map +1 -0
- package/dist/types/session/manager.d.ts +3 -2
- package/dist/types/session/manager.d.ts.map +1 -1
- package/dist/types/session/types.d.ts +1 -1
- package/dist/types/session/types.d.ts.map +1 -1
- package/dist/types/signer.d.ts +52 -7
- package/dist/types/signer.d.ts.map +1 -1
- package/dist/types/types.d.ts +8 -1
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/typeAssertions.d.ts +2 -0
- package/dist/types/utils/typeAssertions.d.ts.map +1 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/base.ts +260 -65
- package/src/client/base.ts +49 -4
- package/src/client/index.ts +317 -20
- package/src/client/types.ts +33 -1
- package/src/index.ts +5 -1
- package/src/metrics.ts +23 -0
- package/src/oauth.ts +36 -0
- package/src/session/manager.ts +46 -19
- package/src/session/types.ts +1 -1
- package/src/signer.ts +91 -4
- package/src/types.ts +9 -1
- package/src/utils/typeAssertions.ts +3 -0
- package/src/version.ts +1 -1
package/src/session/manager.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { createStore, type Mutate, type StoreApi } from "zustand/vanilla";
|
|
9
9
|
import type { BaseSignerClient } from "../client/base";
|
|
10
10
|
import type { User } from "../client/types";
|
|
11
|
+
import { assertNever } from "../utils/typeAssertions.js";
|
|
11
12
|
import type { Session, SessionManagerEvents } from "./types";
|
|
12
13
|
|
|
13
14
|
export const DEFAULT_SESSION_MS = 15 * 60 * 1000; // 15 minutes
|
|
@@ -82,11 +83,18 @@ export class SessionManager {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
switch (existingSession.type) {
|
|
85
|
-
case "email":
|
|
86
|
+
case "email":
|
|
87
|
+
case "oauth": {
|
|
88
|
+
const connectedEventName =
|
|
89
|
+
existingSession.type === "email"
|
|
90
|
+
? "connectedEmail"
|
|
91
|
+
: "connectedOauth";
|
|
86
92
|
const result = await this.client
|
|
87
|
-
.
|
|
93
|
+
.completeAuthWithBundle({
|
|
88
94
|
bundle: existingSession.bundle,
|
|
89
95
|
orgId: existingSession.user.orgId,
|
|
96
|
+
authenticatingType: existingSession.type,
|
|
97
|
+
connectedEventName,
|
|
90
98
|
})
|
|
91
99
|
.catch((e) => {
|
|
92
100
|
console.warn("Failed to load user from session", e);
|
|
@@ -108,7 +116,10 @@ export class SessionManager {
|
|
|
108
116
|
return this.client.lookupUserWithPasskey(existingSession.user);
|
|
109
117
|
}
|
|
110
118
|
default:
|
|
111
|
-
|
|
119
|
+
assertNever(
|
|
120
|
+
existingSession,
|
|
121
|
+
`Unknown session type: ${(existingSession as any).type}`
|
|
122
|
+
);
|
|
112
123
|
}
|
|
113
124
|
};
|
|
114
125
|
|
|
@@ -168,7 +179,7 @@ export class SessionManager {
|
|
|
168
179
|
|
|
169
180
|
private setSession = (
|
|
170
181
|
session:
|
|
171
|
-
| Omit<Extract<Session, { type: "email" }>, "expirationDateMs">
|
|
182
|
+
| Omit<Extract<Session, { type: "email" | "oauth" }>, "expirationDateMs">
|
|
172
183
|
| Omit<Extract<Session, { type: "passkey" }>, "expirationDateMs">
|
|
173
184
|
) => {
|
|
174
185
|
this.store.setState({
|
|
@@ -211,21 +222,9 @@ export class SessionManager {
|
|
|
211
222
|
|
|
212
223
|
this.client.on("disconnected", () => this.clearSession());
|
|
213
224
|
|
|
214
|
-
this.client.on("connectedEmail", (user, bundle) =>
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
existingSession != null &&
|
|
218
|
-
existingSession.type === "email" &&
|
|
219
|
-
existingSession.user.userId === user.userId &&
|
|
220
|
-
// if the bundle is different, then we've refreshed the session
|
|
221
|
-
// so we need to reset the session
|
|
222
|
-
existingSession.bundle === bundle
|
|
223
|
-
) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
this.setSession({ type: "email", user, bundle });
|
|
228
|
-
});
|
|
225
|
+
this.client.on("connectedEmail", (user, bundle) =>
|
|
226
|
+
this.setSessionWithUserAndBundle({ type: "email", user, bundle })
|
|
227
|
+
);
|
|
229
228
|
|
|
230
229
|
this.client.on("connectedPasskey", (user) => {
|
|
231
230
|
const existingSession = this.getSession();
|
|
@@ -240,10 +239,38 @@ export class SessionManager {
|
|
|
240
239
|
this.setSession({ type: "passkey", user });
|
|
241
240
|
});
|
|
242
241
|
|
|
242
|
+
this.client.on("connectedOauth", (user, bundle) =>
|
|
243
|
+
this.setSessionWithUserAndBundle({ type: "oauth", user, bundle })
|
|
244
|
+
);
|
|
245
|
+
|
|
243
246
|
// sync local state if persisted state has changed from another tab
|
|
244
247
|
window.addEventListener("focus", () => {
|
|
245
248
|
this.store.persist.rehydrate();
|
|
246
249
|
this.initialize();
|
|
247
250
|
});
|
|
248
251
|
};
|
|
252
|
+
|
|
253
|
+
private setSessionWithUserAndBundle = ({
|
|
254
|
+
type,
|
|
255
|
+
user,
|
|
256
|
+
bundle,
|
|
257
|
+
}: {
|
|
258
|
+
type: "email" | "oauth";
|
|
259
|
+
user: User;
|
|
260
|
+
bundle: string;
|
|
261
|
+
}) => {
|
|
262
|
+
const existingSession = this.getSession();
|
|
263
|
+
if (
|
|
264
|
+
existingSession != null &&
|
|
265
|
+
existingSession.type === type &&
|
|
266
|
+
existingSession.user.userId === user.userId &&
|
|
267
|
+
// if the bundle is different, then we've refreshed the session
|
|
268
|
+
// so we need to reset the session
|
|
269
|
+
existingSession.bundle === bundle
|
|
270
|
+
) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
this.setSession({ type, user, bundle });
|
|
275
|
+
};
|
|
249
276
|
}
|
package/src/session/types.ts
CHANGED
package/src/signer.ts
CHANGED
|
@@ -24,8 +24,45 @@ export type AuthParams =
|
|
|
24
24
|
createNew: true;
|
|
25
25
|
username: string;
|
|
26
26
|
creationOpts?: CredentialCreationOptionOverrides;
|
|
27
|
+
}
|
|
28
|
+
| ({
|
|
29
|
+
type: "oauth";
|
|
30
|
+
scope?: string;
|
|
31
|
+
claims?: string;
|
|
32
|
+
} & OauthProviderConfig &
|
|
33
|
+
OauthRedirectConfig)
|
|
34
|
+
| {
|
|
35
|
+
type: "oauthReturn";
|
|
36
|
+
bundle: string;
|
|
37
|
+
orgId: string;
|
|
38
|
+
idToken: string;
|
|
27
39
|
};
|
|
28
40
|
|
|
41
|
+
export type OauthProviderConfig =
|
|
42
|
+
| {
|
|
43
|
+
authProviderId: "auth0";
|
|
44
|
+
isCustomProvider?: false;
|
|
45
|
+
auth0Connection?: string;
|
|
46
|
+
}
|
|
47
|
+
| {
|
|
48
|
+
authProviderId: KnownAuthProvider;
|
|
49
|
+
isCustomProvider?: false;
|
|
50
|
+
auth0Connection?: never;
|
|
51
|
+
}
|
|
52
|
+
| {
|
|
53
|
+
authProviderId: string;
|
|
54
|
+
isCustomProvider: true;
|
|
55
|
+
auth0Connection?: never;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type OauthRedirectConfig =
|
|
59
|
+
| { mode: "redirect"; redirectUrl: string }
|
|
60
|
+
| { mode: "popup"; redirectUrl?: never };
|
|
61
|
+
|
|
62
|
+
export type KnownAuthProvider = "google" | "apple" | "facebook" | "auth0";
|
|
63
|
+
|
|
64
|
+
export type OauthMode = "redirect" | "popup";
|
|
65
|
+
|
|
29
66
|
export const AlchemySignerParamsSchema = z
|
|
30
67
|
.object({
|
|
31
68
|
client: z
|
|
@@ -73,9 +110,59 @@ export class AlchemyWebSigner extends BaseAlchemySigner<AlchemySignerWebClient>
|
|
|
73
110
|
} else {
|
|
74
111
|
client = params_.client;
|
|
75
112
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
113
|
+
const { emailBundle, oauthBundle, oauthOrgId, oauthError, idToken } =
|
|
114
|
+
getAndRemoveQueryParams({
|
|
115
|
+
emailBundle: "bundle",
|
|
116
|
+
// We don't need this, but we still want to remove it from the URL.
|
|
117
|
+
emailOrgId: "orgId",
|
|
118
|
+
oauthBundle: "alchemy-bundle",
|
|
119
|
+
oauthOrgId: "alchemy-org-id",
|
|
120
|
+
oauthError: "alchemy-error",
|
|
121
|
+
idToken: "alchemy-id-token",
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const initialError =
|
|
125
|
+
oauthError != null
|
|
126
|
+
? { name: "OauthError", message: oauthError }
|
|
127
|
+
: undefined;
|
|
128
|
+
|
|
129
|
+
super({ client, sessionConfig, initialError });
|
|
130
|
+
|
|
131
|
+
if (emailBundle) {
|
|
132
|
+
this.authenticate({ type: "email", bundle: emailBundle });
|
|
133
|
+
} else if (oauthBundle && oauthOrgId && idToken) {
|
|
134
|
+
this.authenticate({
|
|
135
|
+
type: "oauthReturn",
|
|
136
|
+
bundle: oauthBundle,
|
|
137
|
+
orgId: oauthOrgId,
|
|
138
|
+
idToken,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Reads and removes the specified query params from the URL.
|
|
146
|
+
*
|
|
147
|
+
* @param {T} keys object whose values are the query parameter keys to read and
|
|
148
|
+
* remove
|
|
149
|
+
* @returns {{ [K in keyof T]: string | undefined }} object with the same keys
|
|
150
|
+
* as the input whose values are the values of the query params.
|
|
151
|
+
*/
|
|
152
|
+
function getAndRemoveQueryParams<T extends Record<string, string>>(
|
|
153
|
+
keys: T
|
|
154
|
+
): { [K in keyof T]: string | undefined } {
|
|
155
|
+
const url = new URL(window.location.href);
|
|
156
|
+
const result: Record<string, string | undefined> = {};
|
|
157
|
+
let foundQueryParam = false;
|
|
158
|
+
for (const [key, param] of Object.entries(keys)) {
|
|
159
|
+
const value = url.searchParams.get(param) ?? undefined;
|
|
160
|
+
foundQueryParam ||= value != null;
|
|
161
|
+
result[key] = value;
|
|
162
|
+
url.searchParams.delete(param);
|
|
163
|
+
}
|
|
164
|
+
if (foundQueryParam) {
|
|
165
|
+
window.history.replaceState(window.history.state, "", url.toString());
|
|
80
166
|
}
|
|
167
|
+
return result as { [K in keyof T]: string | undefined };
|
|
81
168
|
}
|
package/src/types.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type AlchemySignerEvents = {
|
|
|
4
4
|
connected(user: User): void;
|
|
5
5
|
disconnected(): void;
|
|
6
6
|
statusChanged(status: AlchemySignerStatus): void;
|
|
7
|
+
errorChanged(error: ErrorInfo | undefined): void;
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
export type AlchemySignerEvent = keyof AlchemySignerEvents;
|
|
@@ -12,6 +13,13 @@ export enum AlchemySignerStatus {
|
|
|
12
13
|
INITIALIZING = "INITIALIZING",
|
|
13
14
|
CONNECTED = "CONNECTED",
|
|
14
15
|
DISCONNECTED = "DISCONNECTED",
|
|
15
|
-
|
|
16
|
+
AUTHENTICATING_PASSKEY = "AUTHENTICATING_PASSKEY",
|
|
17
|
+
AUTHENTICATING_EMAIL = "AUTHENTICATING_EMAIL",
|
|
18
|
+
AUTHENTICATING_OAUTH = "AUTHENTICATING_OAUTH",
|
|
16
19
|
AWAITING_EMAIL_AUTH = "AWAITING_EMAIL_AUTH",
|
|
17
20
|
}
|
|
21
|
+
|
|
22
|
+
export interface ErrorInfo {
|
|
23
|
+
name: string;
|
|
24
|
+
message: string;
|
|
25
|
+
}
|
package/src/version.ts
CHANGED