@supabase/gotrue-js 2.39.1 → 2.40.0

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.
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -99,10 +90,10 @@ class GoTrueClient {
99
90
  catch (e) {
100
91
  console.error('Failed to create a new BroadcastChannel, multi-tab state changes will not be available', e);
101
92
  }
102
- (_a = this.broadcastChannel) === null || _a === void 0 ? void 0 : _a.addEventListener('message', (event) => __awaiter(this, void 0, void 0, function* () {
93
+ (_a = this.broadcastChannel) === null || _a === void 0 ? void 0 : _a.addEventListener('message', async (event) => {
103
94
  this._debug('received broadcast notification from other tab or client', event);
104
- yield this._notifyAllSubscribers(event.data.event, event.data.session, false); // broadcast = false so we don't get an endless loop of messages
105
- }));
95
+ await this._notifyAllSubscribers(event.data.event, event.data.session, false); // broadcast = false so we don't get an endless loop of messages
96
+ });
106
97
  }
107
98
  this.initialize();
108
99
  }
@@ -129,53 +120,51 @@ class GoTrueClient {
129
120
  * 2. Never return a session from this method as it would be cached over
130
121
  * the whole lifetime of the client
131
122
  */
132
- _initialize() {
133
- return __awaiter(this, void 0, void 0, function* () {
134
- if (this.initializePromise) {
135
- return this.initializePromise;
136
- }
137
- try {
138
- const isPKCEFlow = (0, helpers_1.isBrowser)() ? yield this._isPKCEFlow() : false;
139
- this._debug('#_initialize()', 'begin', 'is PKCE flow', isPKCEFlow);
140
- if (isPKCEFlow || (this.detectSessionInUrl && this._isImplicitGrantFlow())) {
141
- const { data, error } = yield this._getSessionFromUrl(isPKCEFlow);
142
- if (error) {
143
- this._debug('#_initialize()', 'error detecting session from URL', error);
144
- // failed login attempt via url,
145
- // remove old session as in verifyOtp, signUp and signInWith*
146
- yield this._removeSession();
147
- return { error };
148
- }
149
- const { session, redirectType } = data;
150
- this._debug('#_initialize()', 'detected session in URL', session, 'redirect type', redirectType);
151
- yield this._saveSession(session);
152
- setTimeout(() => __awaiter(this, void 0, void 0, function* () {
153
- if (redirectType === 'recovery') {
154
- yield this._notifyAllSubscribers('PASSWORD_RECOVERY', session);
155
- }
156
- else {
157
- yield this._notifyAllSubscribers('SIGNED_IN', session);
158
- }
159
- }), 0);
160
- return { error: null };
161
- }
162
- // no login attempt via callback url try to recover session from storage
163
- yield this._recoverAndRefresh();
164
- return { error: null };
165
- }
166
- catch (error) {
167
- if ((0, errors_1.isAuthError)(error)) {
123
+ async _initialize() {
124
+ if (this.initializePromise) {
125
+ return this.initializePromise;
126
+ }
127
+ try {
128
+ const isPKCEFlow = (0, helpers_1.isBrowser)() ? await this._isPKCEFlow() : false;
129
+ this._debug('#_initialize()', 'begin', 'is PKCE flow', isPKCEFlow);
130
+ if (isPKCEFlow || (this.detectSessionInUrl && this._isImplicitGrantFlow())) {
131
+ const { data, error } = await this._getSessionFromUrl(isPKCEFlow);
132
+ if (error) {
133
+ this._debug('#_initialize()', 'error detecting session from URL', error);
134
+ // failed login attempt via url,
135
+ // remove old session as in verifyOtp, signUp and signInWith*
136
+ await this._removeSession();
168
137
  return { error };
169
138
  }
170
- return {
171
- error: new errors_1.AuthUnknownError('Unexpected error during initialization', error),
172
- };
139
+ const { session, redirectType } = data;
140
+ this._debug('#_initialize()', 'detected session in URL', session, 'redirect type', redirectType);
141
+ await this._saveSession(session);
142
+ setTimeout(async () => {
143
+ if (redirectType === 'recovery') {
144
+ await this._notifyAllSubscribers('PASSWORD_RECOVERY', session);
145
+ }
146
+ else {
147
+ await this._notifyAllSubscribers('SIGNED_IN', session);
148
+ }
149
+ }, 0);
150
+ return { error: null };
173
151
  }
174
- finally {
175
- yield this._handleVisibilityChange();
176
- this._debug('#_initialize()', 'end');
152
+ // no login attempt via callback url try to recover session from storage
153
+ await this._recoverAndRefresh();
154
+ return { error: null };
155
+ }
156
+ catch (error) {
157
+ if ((0, errors_1.isAuthError)(error)) {
158
+ return { error };
177
159
  }
178
- });
160
+ return {
161
+ error: new errors_1.AuthUnknownError('Unexpected error during initialization', error),
162
+ };
163
+ }
164
+ finally {
165
+ await this._handleVisibilityChange();
166
+ this._debug('#_initialize()', 'end');
167
+ }
179
168
  }
180
169
  /**
181
170
  * Creates a new user.
@@ -187,72 +176,70 @@ class GoTrueClient {
187
176
  * @returns A logged-in session if the server has "autoconfirm" ON
188
177
  * @returns A user if the server has "autoconfirm" OFF
189
178
  */
190
- signUp(credentials) {
179
+ async signUp(credentials) {
191
180
  var _a, _b, _c;
192
- return __awaiter(this, void 0, void 0, function* () {
193
- try {
194
- yield this._removeSession();
195
- let res;
196
- if ('email' in credentials) {
197
- const { email, password, options } = credentials;
198
- let codeChallenge = null;
199
- let codeChallengeMethod = null;
200
- if (this.flowType === 'pkce') {
201
- const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
202
- yield (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
203
- codeChallenge = yield (0, helpers_1.generatePKCEChallenge)(codeVerifier);
204
- codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
205
- }
206
- res = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/signup`, {
207
- headers: this.headers,
208
- redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
209
- body: {
210
- email,
211
- password,
212
- data: (_a = options === null || options === void 0 ? void 0 : options.data) !== null && _a !== void 0 ? _a : {},
213
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
214
- code_challenge: codeChallenge,
215
- code_challenge_method: codeChallengeMethod,
216
- },
217
- xform: fetch_1._sessionResponse,
218
- });
219
- }
220
- else if ('phone' in credentials) {
221
- const { phone, password, options } = credentials;
222
- res = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/signup`, {
223
- headers: this.headers,
224
- body: {
225
- phone,
226
- password,
227
- data: (_b = options === null || options === void 0 ? void 0 : options.data) !== null && _b !== void 0 ? _b : {},
228
- channel: (_c = options === null || options === void 0 ? void 0 : options.channel) !== null && _c !== void 0 ? _c : 'sms',
229
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
230
- },
231
- xform: fetch_1._sessionResponse,
232
- });
233
- }
234
- else {
235
- throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a password');
236
- }
237
- const { data, error } = res;
238
- if (error || !data) {
239
- return { data: { user: null, session: null }, error: error };
240
- }
241
- const session = data.session;
242
- const user = data.user;
243
- if (data.session) {
244
- yield this._saveSession(data.session);
245
- yield this._notifyAllSubscribers('SIGNED_IN', session);
246
- }
247
- return { data: { user, session }, error: null };
181
+ try {
182
+ await this._removeSession();
183
+ let res;
184
+ if ('email' in credentials) {
185
+ const { email, password, options } = credentials;
186
+ let codeChallenge = null;
187
+ let codeChallengeMethod = null;
188
+ if (this.flowType === 'pkce') {
189
+ const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
190
+ await (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
191
+ codeChallenge = await (0, helpers_1.generatePKCEChallenge)(codeVerifier);
192
+ codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
193
+ }
194
+ res = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/signup`, {
195
+ headers: this.headers,
196
+ redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
197
+ body: {
198
+ email,
199
+ password,
200
+ data: (_a = options === null || options === void 0 ? void 0 : options.data) !== null && _a !== void 0 ? _a : {},
201
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
202
+ code_challenge: codeChallenge,
203
+ code_challenge_method: codeChallengeMethod,
204
+ },
205
+ xform: fetch_1._sessionResponse,
206
+ });
248
207
  }
249
- catch (error) {
250
- if ((0, errors_1.isAuthError)(error)) {
251
- return { data: { user: null, session: null }, error };
252
- }
253
- throw error;
208
+ else if ('phone' in credentials) {
209
+ const { phone, password, options } = credentials;
210
+ res = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/signup`, {
211
+ headers: this.headers,
212
+ body: {
213
+ phone,
214
+ password,
215
+ data: (_b = options === null || options === void 0 ? void 0 : options.data) !== null && _b !== void 0 ? _b : {},
216
+ channel: (_c = options === null || options === void 0 ? void 0 : options.channel) !== null && _c !== void 0 ? _c : 'sms',
217
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
218
+ },
219
+ xform: fetch_1._sessionResponse,
220
+ });
254
221
  }
255
- });
222
+ else {
223
+ throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a password');
224
+ }
225
+ const { data, error } = res;
226
+ if (error || !data) {
227
+ return { data: { user: null, session: null }, error: error };
228
+ }
229
+ const session = data.session;
230
+ const user = data.user;
231
+ if (data.session) {
232
+ await this._saveSession(data.session);
233
+ await this._notifyAllSubscribers('SIGNED_IN', session);
234
+ }
235
+ return { data: { user, session }, error: null };
236
+ }
237
+ catch (error) {
238
+ if ((0, errors_1.isAuthError)(error)) {
239
+ return { data: { user: null, session: null }, error };
240
+ }
241
+ throw error;
242
+ }
256
243
  }
257
244
  /**
258
245
  * Log in an existing user with an email and password or phone and password.
@@ -262,146 +249,138 @@ class GoTrueClient {
262
249
  * email/phone and password combination is wrong or that the account can only
263
250
  * be accessed via social login.
264
251
  */
265
- signInWithPassword(credentials) {
266
- return __awaiter(this, void 0, void 0, function* () {
267
- try {
268
- yield this._removeSession();
269
- let res;
270
- if ('email' in credentials) {
271
- const { email, password, options } = credentials;
272
- res = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=password`, {
273
- headers: this.headers,
274
- body: {
275
- email,
276
- password,
277
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
278
- },
279
- xform: fetch_1._sessionResponse,
280
- });
281
- }
282
- else if ('phone' in credentials) {
283
- const { phone, password, options } = credentials;
284
- res = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=password`, {
285
- headers: this.headers,
286
- body: {
287
- phone,
288
- password,
289
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
290
- },
291
- xform: fetch_1._sessionResponse,
292
- });
293
- }
294
- else {
295
- throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a password');
296
- }
297
- const { data, error } = res;
298
- if (error) {
299
- return { data: { user: null, session: null }, error };
300
- }
301
- else if (!data || !data.session || !data.user) {
302
- return { data: { user: null, session: null }, error: new errors_1.AuthInvalidTokenResponseError() };
303
- }
304
- if (data.session) {
305
- yield this._saveSession(data.session);
306
- yield this._notifyAllSubscribers('SIGNED_IN', data.session);
307
- }
308
- return { data: { user: data.user, session: data.session }, error };
252
+ async signInWithPassword(credentials) {
253
+ try {
254
+ await this._removeSession();
255
+ let res;
256
+ if ('email' in credentials) {
257
+ const { email, password, options } = credentials;
258
+ res = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=password`, {
259
+ headers: this.headers,
260
+ body: {
261
+ email,
262
+ password,
263
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
264
+ },
265
+ xform: fetch_1._sessionResponse,
266
+ });
309
267
  }
310
- catch (error) {
311
- if ((0, errors_1.isAuthError)(error)) {
312
- return { data: { user: null, session: null }, error };
313
- }
314
- throw error;
268
+ else if ('phone' in credentials) {
269
+ const { phone, password, options } = credentials;
270
+ res = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=password`, {
271
+ headers: this.headers,
272
+ body: {
273
+ phone,
274
+ password,
275
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
276
+ },
277
+ xform: fetch_1._sessionResponse,
278
+ });
315
279
  }
316
- });
280
+ else {
281
+ throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a password');
282
+ }
283
+ const { data, error } = res;
284
+ if (error) {
285
+ return { data: { user: null, session: null }, error };
286
+ }
287
+ else if (!data || !data.session || !data.user) {
288
+ return { data: { user: null, session: null }, error: new errors_1.AuthInvalidTokenResponseError() };
289
+ }
290
+ if (data.session) {
291
+ await this._saveSession(data.session);
292
+ await this._notifyAllSubscribers('SIGNED_IN', data.session);
293
+ }
294
+ return { data: { user: data.user, session: data.session }, error };
295
+ }
296
+ catch (error) {
297
+ if ((0, errors_1.isAuthError)(error)) {
298
+ return { data: { user: null, session: null }, error };
299
+ }
300
+ throw error;
301
+ }
317
302
  }
318
303
  /**
319
304
  * Log in an existing user via a third-party provider.
320
305
  * This method supports the PKCE flow.
321
306
  */
322
- signInWithOAuth(credentials) {
307
+ async signInWithOAuth(credentials) {
323
308
  var _a, _b, _c, _d;
324
- return __awaiter(this, void 0, void 0, function* () {
325
- yield this._removeSession();
326
- return yield this._handleProviderSignIn(credentials.provider, {
327
- redirectTo: (_a = credentials.options) === null || _a === void 0 ? void 0 : _a.redirectTo,
328
- scopes: (_b = credentials.options) === null || _b === void 0 ? void 0 : _b.scopes,
329
- queryParams: (_c = credentials.options) === null || _c === void 0 ? void 0 : _c.queryParams,
330
- skipBrowserRedirect: (_d = credentials.options) === null || _d === void 0 ? void 0 : _d.skipBrowserRedirect,
331
- });
309
+ await this._removeSession();
310
+ return await this._handleProviderSignIn(credentials.provider, {
311
+ redirectTo: (_a = credentials.options) === null || _a === void 0 ? void 0 : _a.redirectTo,
312
+ scopes: (_b = credentials.options) === null || _b === void 0 ? void 0 : _b.scopes,
313
+ queryParams: (_c = credentials.options) === null || _c === void 0 ? void 0 : _c.queryParams,
314
+ skipBrowserRedirect: (_d = credentials.options) === null || _d === void 0 ? void 0 : _d.skipBrowserRedirect,
332
315
  });
333
316
  }
334
317
  /**
335
318
  * Log in an existing user by exchanging an Auth Code issued during the PKCE flow.
336
319
  */
337
- exchangeCodeForSession(authCode) {
338
- return __awaiter(this, void 0, void 0, function* () {
339
- const codeVerifier = yield (0, helpers_1.getItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
340
- const { data, error } = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=pkce`, {
320
+ async exchangeCodeForSession(authCode) {
321
+ const codeVerifier = await (0, helpers_1.getItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
322
+ const { data, error } = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=pkce`, {
323
+ headers: this.headers,
324
+ body: {
325
+ auth_code: authCode,
326
+ code_verifier: codeVerifier,
327
+ },
328
+ xform: fetch_1._sessionResponse,
329
+ });
330
+ await (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
331
+ if (error) {
332
+ return { data: { user: null, session: null }, error };
333
+ }
334
+ else if (!data || !data.session || !data.user) {
335
+ return { data: { user: null, session: null }, error: new errors_1.AuthInvalidTokenResponseError() };
336
+ }
337
+ if (data.session) {
338
+ await this._saveSession(data.session);
339
+ await this._notifyAllSubscribers('SIGNED_IN', data.session);
340
+ }
341
+ return { data, error };
342
+ }
343
+ /**
344
+ * Allows signing in with an OIDC ID token. The authentication provider used
345
+ * should be enabled and configured.
346
+ */
347
+ async signInWithIdToken(credentials) {
348
+ await this._removeSession();
349
+ try {
350
+ const { options, provider, token, access_token, nonce } = credentials;
351
+ const res = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=id_token`, {
341
352
  headers: this.headers,
342
353
  body: {
343
- auth_code: authCode,
344
- code_verifier: codeVerifier,
354
+ provider,
355
+ id_token: token,
356
+ access_token,
357
+ nonce,
358
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
345
359
  },
346
360
  xform: fetch_1._sessionResponse,
347
361
  });
348
- yield (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
362
+ const { data, error } = res;
349
363
  if (error) {
350
364
  return { data: { user: null, session: null }, error };
351
365
  }
352
366
  else if (!data || !data.session || !data.user) {
353
- return { data: { user: null, session: null }, error: new errors_1.AuthInvalidTokenResponseError() };
367
+ return {
368
+ data: { user: null, session: null },
369
+ error: new errors_1.AuthInvalidTokenResponseError(),
370
+ };
354
371
  }
355
372
  if (data.session) {
356
- yield this._saveSession(data.session);
357
- yield this._notifyAllSubscribers('SIGNED_IN', data.session);
373
+ await this._saveSession(data.session);
374
+ await this._notifyAllSubscribers('SIGNED_IN', data.session);
358
375
  }
359
376
  return { data, error };
360
- });
361
- }
362
- /**
363
- * Allows signing in with an OIDC ID token. The authentication provider used
364
- * should be enabled and configured.
365
- */
366
- signInWithIdToken(credentials) {
367
- return __awaiter(this, void 0, void 0, function* () {
368
- yield this._removeSession();
369
- try {
370
- const { options, provider, token, access_token, nonce } = credentials;
371
- const res = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=id_token`, {
372
- headers: this.headers,
373
- body: {
374
- provider,
375
- id_token: token,
376
- access_token,
377
- nonce,
378
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
379
- },
380
- xform: fetch_1._sessionResponse,
381
- });
382
- const { data, error } = res;
383
- if (error) {
384
- return { data: { user: null, session: null }, error };
385
- }
386
- else if (!data || !data.session || !data.user) {
387
- return {
388
- data: { user: null, session: null },
389
- error: new errors_1.AuthInvalidTokenResponseError(),
390
- };
391
- }
392
- if (data.session) {
393
- yield this._saveSession(data.session);
394
- yield this._notifyAllSubscribers('SIGNED_IN', data.session);
395
- }
396
- return { data, error };
397
- }
398
- catch (error) {
399
- if ((0, errors_1.isAuthError)(error)) {
400
- return { data: { user: null, session: null }, error };
401
- }
402
- throw error;
377
+ }
378
+ catch (error) {
379
+ if ((0, errors_1.isAuthError)(error)) {
380
+ return { data: { user: null, session: null }, error };
403
381
  }
404
- });
382
+ throw error;
383
+ }
405
384
  }
406
385
  /**
407
386
  * Log in a user using magiclink or a one-time password (OTP).
@@ -420,97 +399,93 @@ class GoTrueClient {
420
399
  * at this time.
421
400
  * This method supports PKCE when an email is passed.
422
401
  */
423
- signInWithOtp(credentials) {
402
+ async signInWithOtp(credentials) {
424
403
  var _a, _b, _c, _d, _e;
425
- return __awaiter(this, void 0, void 0, function* () {
426
- try {
427
- yield this._removeSession();
428
- if ('email' in credentials) {
429
- const { email, options } = credentials;
430
- let codeChallenge = null;
431
- let codeChallengeMethod = null;
432
- if (this.flowType === 'pkce') {
433
- const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
434
- yield (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
435
- codeChallenge = yield (0, helpers_1.generatePKCEChallenge)(codeVerifier);
436
- codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
437
- }
438
- const { error } = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/otp`, {
439
- headers: this.headers,
440
- body: {
441
- email,
442
- data: (_a = options === null || options === void 0 ? void 0 : options.data) !== null && _a !== void 0 ? _a : {},
443
- create_user: (_b = options === null || options === void 0 ? void 0 : options.shouldCreateUser) !== null && _b !== void 0 ? _b : true,
444
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
445
- code_challenge: codeChallenge,
446
- code_challenge_method: codeChallengeMethod,
447
- },
448
- redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
449
- });
450
- return { data: { user: null, session: null }, error };
451
- }
452
- if ('phone' in credentials) {
453
- const { phone, options } = credentials;
454
- const { data, error } = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/otp`, {
455
- headers: this.headers,
456
- body: {
457
- phone,
458
- data: (_c = options === null || options === void 0 ? void 0 : options.data) !== null && _c !== void 0 ? _c : {},
459
- create_user: (_d = options === null || options === void 0 ? void 0 : options.shouldCreateUser) !== null && _d !== void 0 ? _d : true,
460
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
461
- channel: (_e = options === null || options === void 0 ? void 0 : options.channel) !== null && _e !== void 0 ? _e : 'sms',
462
- },
463
- });
464
- return { data: { user: null, session: null, messageId: data === null || data === void 0 ? void 0 : data.message_id }, error };
465
- }
466
- throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number.');
404
+ try {
405
+ await this._removeSession();
406
+ if ('email' in credentials) {
407
+ const { email, options } = credentials;
408
+ let codeChallenge = null;
409
+ let codeChallengeMethod = null;
410
+ if (this.flowType === 'pkce') {
411
+ const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
412
+ await (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
413
+ codeChallenge = await (0, helpers_1.generatePKCEChallenge)(codeVerifier);
414
+ codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
415
+ }
416
+ const { error } = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/otp`, {
417
+ headers: this.headers,
418
+ body: {
419
+ email,
420
+ data: (_a = options === null || options === void 0 ? void 0 : options.data) !== null && _a !== void 0 ? _a : {},
421
+ create_user: (_b = options === null || options === void 0 ? void 0 : options.shouldCreateUser) !== null && _b !== void 0 ? _b : true,
422
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
423
+ code_challenge: codeChallenge,
424
+ code_challenge_method: codeChallengeMethod,
425
+ },
426
+ redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
427
+ });
428
+ return { data: { user: null, session: null }, error };
467
429
  }
468
- catch (error) {
469
- if ((0, errors_1.isAuthError)(error)) {
470
- return { data: { user: null, session: null }, error };
471
- }
472
- throw error;
430
+ if ('phone' in credentials) {
431
+ const { phone, options } = credentials;
432
+ const { data, error } = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/otp`, {
433
+ headers: this.headers,
434
+ body: {
435
+ phone,
436
+ data: (_c = options === null || options === void 0 ? void 0 : options.data) !== null && _c !== void 0 ? _c : {},
437
+ create_user: (_d = options === null || options === void 0 ? void 0 : options.shouldCreateUser) !== null && _d !== void 0 ? _d : true,
438
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
439
+ channel: (_e = options === null || options === void 0 ? void 0 : options.channel) !== null && _e !== void 0 ? _e : 'sms',
440
+ },
441
+ });
442
+ return { data: { user: null, session: null, messageId: data === null || data === void 0 ? void 0 : data.message_id }, error };
473
443
  }
474
- });
444
+ throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number.');
445
+ }
446
+ catch (error) {
447
+ if ((0, errors_1.isAuthError)(error)) {
448
+ return { data: { user: null, session: null }, error };
449
+ }
450
+ throw error;
451
+ }
475
452
  }
476
453
  /**
477
454
  * Log in a user given a User supplied OTP received via mobile.
478
455
  */
479
- verifyOtp(params) {
456
+ async verifyOtp(params) {
480
457
  var _a, _b;
481
- return __awaiter(this, void 0, void 0, function* () {
482
- try {
483
- if (params.type !== 'email_change' && params.type !== 'phone_change') {
484
- // we don't want to remove the authenticated session if the user is performing an email_change or phone_change verification
485
- yield this._removeSession();
486
- }
487
- const { data, error } = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/verify`, {
488
- headers: this.headers,
489
- body: Object.assign(Object.assign({}, params), { gotrue_meta_security: { captcha_token: (_a = params.options) === null || _a === void 0 ? void 0 : _a.captchaToken } }),
490
- redirectTo: (_b = params.options) === null || _b === void 0 ? void 0 : _b.redirectTo,
491
- xform: fetch_1._sessionResponse,
492
- });
493
- if (error) {
494
- throw error;
495
- }
496
- if (!data) {
497
- throw new Error('An error occurred on token verification.');
498
- }
499
- const session = data.session;
500
- const user = data.user;
501
- if (session === null || session === void 0 ? void 0 : session.access_token) {
502
- yield this._saveSession(session);
503
- yield this._notifyAllSubscribers('SIGNED_IN', session);
504
- }
505
- return { data: { user, session }, error: null };
458
+ try {
459
+ if (params.type !== 'email_change' && params.type !== 'phone_change') {
460
+ // we don't want to remove the authenticated session if the user is performing an email_change or phone_change verification
461
+ await this._removeSession();
506
462
  }
507
- catch (error) {
508
- if ((0, errors_1.isAuthError)(error)) {
509
- return { data: { user: null, session: null }, error };
510
- }
463
+ const { data, error } = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/verify`, {
464
+ headers: this.headers,
465
+ body: Object.assign(Object.assign({}, params), { gotrue_meta_security: { captcha_token: (_a = params.options) === null || _a === void 0 ? void 0 : _a.captchaToken } }),
466
+ redirectTo: (_b = params.options) === null || _b === void 0 ? void 0 : _b.redirectTo,
467
+ xform: fetch_1._sessionResponse,
468
+ });
469
+ if (error) {
511
470
  throw error;
512
471
  }
513
- });
472
+ if (!data) {
473
+ throw new Error('An error occurred on token verification.');
474
+ }
475
+ const session = data.session;
476
+ const user = data.user;
477
+ if (session === null || session === void 0 ? void 0 : session.access_token) {
478
+ await this._saveSession(session);
479
+ await this._notifyAllSubscribers('SIGNED_IN', session);
480
+ }
481
+ return { data: { user, session }, error: null };
482
+ }
483
+ catch (error) {
484
+ if ((0, errors_1.isAuthError)(error)) {
485
+ return { data: { user: null, session: null }, error };
486
+ }
487
+ throw error;
488
+ }
514
489
  }
515
490
  /**
516
491
  * Attempts a single-sign on using an enterprise Identity Provider. A
@@ -526,211 +501,201 @@ class GoTrueClient {
526
501
  * If you have built an organization-specific login page, you can use the
527
502
  * organization's SSO Identity Provider UUID directly instead.
528
503
  */
529
- signInWithSSO(params) {
504
+ async signInWithSSO(params) {
530
505
  var _a, _b, _c;
531
- return __awaiter(this, void 0, void 0, function* () {
532
- try {
533
- yield this._removeSession();
534
- return yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/sso`, {
535
- body: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, ('providerId' in params ? { provider_id: params.providerId } : null)), ('domain' in params ? { domain: params.domain } : null)), { redirect_to: (_b = (_a = params.options) === null || _a === void 0 ? void 0 : _a.redirectTo) !== null && _b !== void 0 ? _b : undefined }), (((_c = params === null || params === void 0 ? void 0 : params.options) === null || _c === void 0 ? void 0 : _c.captchaToken)
536
- ? { gotrue_meta_security: { captcha_token: params.options.captchaToken } }
537
- : null)), { skip_http_redirect: true }),
538
- headers: this.headers,
539
- xform: fetch_1._ssoResponse,
540
- });
541
- }
542
- catch (error) {
543
- if ((0, errors_1.isAuthError)(error)) {
544
- return { data: null, error };
545
- }
546
- throw error;
506
+ try {
507
+ await this._removeSession();
508
+ return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/sso`, {
509
+ body: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, ('providerId' in params ? { provider_id: params.providerId } : null)), ('domain' in params ? { domain: params.domain } : null)), { redirect_to: (_b = (_a = params.options) === null || _a === void 0 ? void 0 : _a.redirectTo) !== null && _b !== void 0 ? _b : undefined }), (((_c = params === null || params === void 0 ? void 0 : params.options) === null || _c === void 0 ? void 0 : _c.captchaToken)
510
+ ? { gotrue_meta_security: { captcha_token: params.options.captchaToken } }
511
+ : null)), { skip_http_redirect: true }),
512
+ headers: this.headers,
513
+ xform: fetch_1._ssoResponse,
514
+ });
515
+ }
516
+ catch (error) {
517
+ if ((0, errors_1.isAuthError)(error)) {
518
+ return { data: null, error };
547
519
  }
548
- });
520
+ throw error;
521
+ }
549
522
  }
550
523
  /**
551
524
  * Sends a reauthentication OTP to the user's email or phone number.
552
525
  * Requires the user to be signed-in.
553
526
  */
554
- reauthenticate() {
555
- return __awaiter(this, void 0, void 0, function* () {
556
- try {
557
- const { data: { session }, error: sessionError, } = yield this.getSession();
558
- if (sessionError)
559
- throw sessionError;
560
- if (!session)
561
- throw new errors_1.AuthSessionMissingError();
562
- const { error } = yield (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/reauthenticate`, {
563
- headers: this.headers,
564
- jwt: session.access_token,
565
- });
527
+ async reauthenticate() {
528
+ try {
529
+ const { data: { session }, error: sessionError, } = await this.getSession();
530
+ if (sessionError)
531
+ throw sessionError;
532
+ if (!session)
533
+ throw new errors_1.AuthSessionMissingError();
534
+ const { error } = await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/reauthenticate`, {
535
+ headers: this.headers,
536
+ jwt: session.access_token,
537
+ });
538
+ return { data: { user: null, session: null }, error };
539
+ }
540
+ catch (error) {
541
+ if ((0, errors_1.isAuthError)(error)) {
566
542
  return { data: { user: null, session: null }, error };
567
543
  }
568
- catch (error) {
569
- if ((0, errors_1.isAuthError)(error)) {
570
- return { data: { user: null, session: null }, error };
571
- }
572
- throw error;
573
- }
574
- });
544
+ throw error;
545
+ }
575
546
  }
576
547
  /**
577
548
  * Resends an existing signup confirmation email, email change email, SMS OTP or phone change OTP.
578
549
  */
579
- resend(credentials) {
580
- return __awaiter(this, void 0, void 0, function* () {
581
- try {
582
- yield this._removeSession();
583
- const endpoint = `${this.url}/resend`;
584
- if ('email' in credentials) {
585
- const { email, type, options } = credentials;
586
- const { error } = yield (0, fetch_1._request)(this.fetch, 'POST', endpoint, {
587
- headers: this.headers,
588
- body: {
589
- email,
590
- type,
591
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
592
- },
593
- redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
594
- });
595
- return { data: { user: null, session: null }, error };
596
- }
597
- else if ('phone' in credentials) {
598
- const { phone, type, options } = credentials;
599
- const { data, error } = yield (0, fetch_1._request)(this.fetch, 'POST', endpoint, {
600
- headers: this.headers,
601
- body: {
602
- phone,
603
- type,
604
- gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
605
- },
606
- });
607
- return { data: { user: null, session: null, messageId: data === null || data === void 0 ? void 0 : data.message_id }, error };
608
- }
609
- throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a type');
550
+ async resend(credentials) {
551
+ try {
552
+ if (credentials.type != 'email_change' && credentials.type != 'phone_change') {
553
+ await this._removeSession();
610
554
  }
611
- catch (error) {
612
- if ((0, errors_1.isAuthError)(error)) {
613
- return { data: { user: null, session: null }, error };
614
- }
615
- throw error;
555
+ const endpoint = `${this.url}/resend`;
556
+ if ('email' in credentials) {
557
+ const { email, type, options } = credentials;
558
+ const { error } = await (0, fetch_1._request)(this.fetch, 'POST', endpoint, {
559
+ headers: this.headers,
560
+ body: {
561
+ email,
562
+ type,
563
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
564
+ },
565
+ redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
566
+ });
567
+ return { data: { user: null, session: null }, error };
616
568
  }
617
- });
569
+ else if ('phone' in credentials) {
570
+ const { phone, type, options } = credentials;
571
+ const { data, error } = await (0, fetch_1._request)(this.fetch, 'POST', endpoint, {
572
+ headers: this.headers,
573
+ body: {
574
+ phone,
575
+ type,
576
+ gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken },
577
+ },
578
+ });
579
+ return { data: { user: null, session: null, messageId: data === null || data === void 0 ? void 0 : data.message_id }, error };
580
+ }
581
+ throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a type');
582
+ }
583
+ catch (error) {
584
+ if ((0, errors_1.isAuthError)(error)) {
585
+ return { data: { user: null, session: null }, error };
586
+ }
587
+ throw error;
588
+ }
618
589
  }
619
590
  /**
620
591
  * Returns the session, refreshing it if necessary.
621
592
  * The session returned can be null if the session is not detected which can happen in the event a user is not signed-in or has logged out.
622
593
  */
623
- getSession() {
624
- return __awaiter(this, void 0, void 0, function* () {
625
- // make sure we've read the session from the url if there is one
626
- // save to just await, as long we make sure _initialize() never throws
627
- yield this.initializePromise;
628
- this._debug('#getSession()', 'begin');
629
- try {
630
- let currentSession = null;
631
- if (this.persistSession) {
632
- const maybeSession = yield (0, helpers_1.getItemAsync)(this.storage, this.storageKey);
633
- this._debug('#getSession()', 'session from storage', maybeSession);
634
- if (maybeSession !== null) {
635
- if (this._isValidSession(maybeSession)) {
636
- currentSession = maybeSession;
637
- }
638
- else {
639
- this._debug('#getSession()', 'session from storage is not valid');
640
- yield this._removeSession();
641
- }
594
+ async getSession() {
595
+ // make sure we've read the session from the url if there is one
596
+ // save to just await, as long we make sure _initialize() never throws
597
+ await this.initializePromise;
598
+ this._debug('#getSession()', 'begin');
599
+ try {
600
+ let currentSession = null;
601
+ if (this.persistSession) {
602
+ const maybeSession = await (0, helpers_1.getItemAsync)(this.storage, this.storageKey);
603
+ this._debug('#getSession()', 'session from storage', maybeSession);
604
+ if (maybeSession !== null) {
605
+ if (this._isValidSession(maybeSession)) {
606
+ currentSession = maybeSession;
607
+ }
608
+ else {
609
+ this._debug('#getSession()', 'session from storage is not valid');
610
+ await this._removeSession();
642
611
  }
643
612
  }
644
- else {
645
- currentSession = this.inMemorySession;
646
- this._debug('#getSession()', 'session from memory', currentSession);
647
- }
648
- if (!currentSession) {
649
- return { data: { session: null }, error: null };
650
- }
651
- const hasExpired = currentSession.expires_at
652
- ? currentSession.expires_at <= Date.now() / 1000
653
- : false;
654
- this._debug('#getSession()', `session has${hasExpired ? '' : ' not'} expired`, 'expires_at', currentSession.expires_at);
655
- if (!hasExpired) {
656
- return { data: { session: currentSession }, error: null };
657
- }
658
- const { session, error } = yield this._callRefreshToken(currentSession.refresh_token);
659
- if (error) {
660
- return { data: { session: null }, error };
661
- }
662
- return { data: { session }, error: null };
663
613
  }
664
- finally {
665
- this._debug('#getSession()', 'end');
614
+ else {
615
+ currentSession = this.inMemorySession;
616
+ this._debug('#getSession()', 'session from memory', currentSession);
666
617
  }
667
- });
668
- }
618
+ if (!currentSession) {
619
+ return { data: { session: null }, error: null };
620
+ }
621
+ const hasExpired = currentSession.expires_at
622
+ ? currentSession.expires_at <= Date.now() / 1000
623
+ : false;
624
+ this._debug('#getSession()', `session has${hasExpired ? '' : ' not'} expired`, 'expires_at', currentSession.expires_at);
625
+ if (!hasExpired) {
626
+ return { data: { session: currentSession }, error: null };
627
+ }
628
+ const { session, error } = await this._callRefreshToken(currentSession.refresh_token);
629
+ if (error) {
630
+ return { data: { session: null }, error };
631
+ }
632
+ return { data: { session }, error: null };
633
+ }
634
+ finally {
635
+ this._debug('#getSession()', 'end');
636
+ }
637
+ }
669
638
  /**
670
639
  * Gets the current user details if there is an existing session.
671
640
  * @param jwt Takes in an optional access token jwt. If no jwt is provided, getUser() will attempt to get the jwt from the current session.
672
641
  */
673
- getUser(jwt) {
642
+ async getUser(jwt) {
674
643
  var _a, _b;
675
- return __awaiter(this, void 0, void 0, function* () {
676
- try {
677
- if (!jwt) {
678
- const { data, error } = yield this.getSession();
679
- if (error) {
680
- throw error;
681
- }
682
- // Default to Authorization header if there is no existing session
683
- jwt = (_b = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : undefined;
644
+ try {
645
+ if (!jwt) {
646
+ const { data, error } = await this.getSession();
647
+ if (error) {
648
+ throw error;
684
649
  }
685
- return yield (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/user`, {
686
- headers: this.headers,
687
- jwt: jwt,
688
- xform: fetch_1._userResponse,
689
- });
650
+ // Default to Authorization header if there is no existing session
651
+ jwt = (_b = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : undefined;
690
652
  }
691
- catch (error) {
692
- if ((0, errors_1.isAuthError)(error)) {
693
- return { data: { user: null }, error };
694
- }
695
- throw error;
653
+ return await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/user`, {
654
+ headers: this.headers,
655
+ jwt: jwt,
656
+ xform: fetch_1._userResponse,
657
+ });
658
+ }
659
+ catch (error) {
660
+ if ((0, errors_1.isAuthError)(error)) {
661
+ return { data: { user: null }, error };
696
662
  }
697
- });
663
+ throw error;
664
+ }
698
665
  }
699
666
  /**
700
667
  * Updates user data for a logged in user.
701
668
  */
702
- updateUser(attributes, options = {}) {
703
- return __awaiter(this, void 0, void 0, function* () {
704
- try {
705
- const { data: sessionData, error: sessionError } = yield this.getSession();
706
- if (sessionError) {
707
- throw sessionError;
708
- }
709
- if (!sessionData.session) {
710
- throw new errors_1.AuthSessionMissingError();
711
- }
712
- const session = sessionData.session;
713
- const { data, error: userError } = yield (0, fetch_1._request)(this.fetch, 'PUT', `${this.url}/user`, {
714
- headers: this.headers,
715
- redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
716
- body: attributes,
717
- jwt: session.access_token,
718
- xform: fetch_1._userResponse,
719
- });
720
- if (userError)
721
- throw userError;
722
- session.user = data.user;
723
- yield this._saveSession(session);
724
- yield this._notifyAllSubscribers('USER_UPDATED', session);
725
- return { data: { user: session.user }, error: null };
726
- }
727
- catch (error) {
728
- if ((0, errors_1.isAuthError)(error)) {
729
- return { data: { user: null }, error };
730
- }
731
- throw error;
669
+ async updateUser(attributes, options = {}) {
670
+ try {
671
+ const { data: sessionData, error: sessionError } = await this.getSession();
672
+ if (sessionError) {
673
+ throw sessionError;
732
674
  }
733
- });
675
+ if (!sessionData.session) {
676
+ throw new errors_1.AuthSessionMissingError();
677
+ }
678
+ const session = sessionData.session;
679
+ const { data, error: userError } = await (0, fetch_1._request)(this.fetch, 'PUT', `${this.url}/user`, {
680
+ headers: this.headers,
681
+ redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
682
+ body: attributes,
683
+ jwt: session.access_token,
684
+ xform: fetch_1._userResponse,
685
+ });
686
+ if (userError)
687
+ throw userError;
688
+ session.user = data.user;
689
+ await this._saveSession(session);
690
+ await this._notifyAllSubscribers('USER_UPDATED', session);
691
+ return { data: { user: session.user }, error: null };
692
+ }
693
+ catch (error) {
694
+ if ((0, errors_1.isAuthError)(error)) {
695
+ return { data: { user: null }, error };
696
+ }
697
+ throw error;
698
+ }
734
699
  }
735
700
  /**
736
701
  * Decodes a JWT (without performing any validation).
@@ -743,56 +708,54 @@ class GoTrueClient {
743
708
  * If the refresh token or access token in the current session is invalid, an error will be thrown.
744
709
  * @param currentSession The current session that minimally contains an access token and refresh token.
745
710
  */
746
- setSession(currentSession) {
747
- return __awaiter(this, void 0, void 0, function* () {
748
- try {
749
- if (!currentSession.access_token || !currentSession.refresh_token) {
750
- throw new errors_1.AuthSessionMissingError();
751
- }
752
- const timeNow = Date.now() / 1000;
753
- let expiresAt = timeNow;
754
- let hasExpired = true;
755
- let session = null;
756
- const payload = (0, helpers_1.decodeJWTPayload)(currentSession.access_token);
757
- if (payload.exp) {
758
- expiresAt = payload.exp;
759
- hasExpired = expiresAt <= timeNow;
760
- }
761
- if (hasExpired) {
762
- const { session: refreshedSession, error } = yield this._callRefreshToken(currentSession.refresh_token);
763
- if (error) {
764
- return { data: { user: null, session: null }, error: error };
765
- }
766
- if (!refreshedSession) {
767
- return { data: { user: null, session: null }, error: null };
768
- }
769
- session = refreshedSession;
711
+ async setSession(currentSession) {
712
+ try {
713
+ if (!currentSession.access_token || !currentSession.refresh_token) {
714
+ throw new errors_1.AuthSessionMissingError();
715
+ }
716
+ const timeNow = Date.now() / 1000;
717
+ let expiresAt = timeNow;
718
+ let hasExpired = true;
719
+ let session = null;
720
+ const payload = (0, helpers_1.decodeJWTPayload)(currentSession.access_token);
721
+ if (payload.exp) {
722
+ expiresAt = payload.exp;
723
+ hasExpired = expiresAt <= timeNow;
724
+ }
725
+ if (hasExpired) {
726
+ const { session: refreshedSession, error } = await this._callRefreshToken(currentSession.refresh_token);
727
+ if (error) {
728
+ return { data: { user: null, session: null }, error: error };
770
729
  }
771
- else {
772
- const { data, error } = yield this.getUser(currentSession.access_token);
773
- if (error) {
774
- throw error;
775
- }
776
- session = {
777
- access_token: currentSession.access_token,
778
- refresh_token: currentSession.refresh_token,
779
- user: data.user,
780
- token_type: 'bearer',
781
- expires_in: expiresAt - timeNow,
782
- expires_at: expiresAt,
783
- };
784
- yield this._saveSession(session);
785
- yield this._notifyAllSubscribers('SIGNED_IN', session);
730
+ if (!refreshedSession) {
731
+ return { data: { user: null, session: null }, error: null };
786
732
  }
787
- return { data: { user: session.user, session }, error: null };
733
+ session = refreshedSession;
788
734
  }
789
- catch (error) {
790
- if ((0, errors_1.isAuthError)(error)) {
791
- return { data: { session: null, user: null }, error };
735
+ else {
736
+ const { data, error } = await this.getUser(currentSession.access_token);
737
+ if (error) {
738
+ throw error;
792
739
  }
793
- throw error;
740
+ session = {
741
+ access_token: currentSession.access_token,
742
+ refresh_token: currentSession.refresh_token,
743
+ user: data.user,
744
+ token_type: 'bearer',
745
+ expires_in: expiresAt - timeNow,
746
+ expires_at: expiresAt,
747
+ };
748
+ await this._saveSession(session);
749
+ await this._notifyAllSubscribers('SIGNED_IN', session);
794
750
  }
795
- });
751
+ return { data: { user: session.user, session }, error: null };
752
+ }
753
+ catch (error) {
754
+ if ((0, errors_1.isAuthError)(error)) {
755
+ return { data: { session: null, user: null }, error };
756
+ }
757
+ throw error;
758
+ }
796
759
  }
797
760
  /**
798
761
  * Returns a new session, regardless of expiry status.
@@ -800,118 +763,114 @@ class GoTrueClient {
800
763
  * If the current session's refresh token is invalid, an error will be thrown.
801
764
  * @param currentSession The current session. If passed in, it must contain a refresh token.
802
765
  */
803
- refreshSession(currentSession) {
766
+ async refreshSession(currentSession) {
804
767
  var _a;
805
- return __awaiter(this, void 0, void 0, function* () {
806
- try {
807
- if (!currentSession) {
808
- const { data, error } = yield this.getSession();
809
- if (error) {
810
- throw error;
811
- }
812
- currentSession = (_a = data.session) !== null && _a !== void 0 ? _a : undefined;
813
- }
814
- if (!(currentSession === null || currentSession === void 0 ? void 0 : currentSession.refresh_token)) {
815
- throw new errors_1.AuthSessionMissingError();
816
- }
817
- const { session, error } = yield this._callRefreshToken(currentSession.refresh_token);
768
+ try {
769
+ if (!currentSession) {
770
+ const { data, error } = await this.getSession();
818
771
  if (error) {
819
- return { data: { user: null, session: null }, error: error };
820
- }
821
- if (!session) {
822
- return { data: { user: null, session: null }, error: null };
772
+ throw error;
823
773
  }
824
- return { data: { user: session.user, session }, error: null };
774
+ currentSession = (_a = data.session) !== null && _a !== void 0 ? _a : undefined;
825
775
  }
826
- catch (error) {
827
- if ((0, errors_1.isAuthError)(error)) {
828
- return { data: { user: null, session: null }, error };
829
- }
830
- throw error;
776
+ if (!(currentSession === null || currentSession === void 0 ? void 0 : currentSession.refresh_token)) {
777
+ throw new errors_1.AuthSessionMissingError();
831
778
  }
832
- });
779
+ const { session, error } = await this._callRefreshToken(currentSession.refresh_token);
780
+ if (error) {
781
+ return { data: { user: null, session: null }, error: error };
782
+ }
783
+ if (!session) {
784
+ return { data: { user: null, session: null }, error: null };
785
+ }
786
+ return { data: { user: session.user, session }, error: null };
787
+ }
788
+ catch (error) {
789
+ if ((0, errors_1.isAuthError)(error)) {
790
+ return { data: { user: null, session: null }, error };
791
+ }
792
+ throw error;
793
+ }
833
794
  }
834
795
  /**
835
796
  * Gets the session data from a URL string
836
797
  */
837
- _getSessionFromUrl(isPKCEFlow) {
838
- return __awaiter(this, void 0, void 0, function* () {
839
- try {
840
- if (!(0, helpers_1.isBrowser)())
841
- throw new errors_1.AuthImplicitGrantRedirectError('No browser detected.');
842
- if (this.flowType === 'implicit' && !this._isImplicitGrantFlow()) {
843
- throw new errors_1.AuthImplicitGrantRedirectError('Not a valid implicit grant flow url.');
844
- }
845
- else if (this.flowType == 'pkce' && !isPKCEFlow) {
846
- throw new errors_1.AuthPKCEGrantCodeExchangeError('Not a valid PKCE flow url.');
847
- }
848
- if (isPKCEFlow) {
849
- const authCode = (0, helpers_1.getParameterByName)('code');
850
- if (!authCode)
851
- throw new errors_1.AuthPKCEGrantCodeExchangeError('No code detected.');
852
- const { data, error } = yield this.exchangeCodeForSession(authCode);
853
- if (error)
854
- throw error;
855
- if (!data.session)
856
- throw new errors_1.AuthPKCEGrantCodeExchangeError('No session detected.');
857
- let url = new URL(window.location.href);
858
- url.searchParams.delete('code');
859
- window.history.replaceState(window.history.state, '', url.toString());
860
- return { data: { session: data.session, redirectType: null }, error: null };
861
- }
862
- const error_description = (0, helpers_1.getParameterByName)('error_description');
863
- if (error_description) {
864
- const error_code = (0, helpers_1.getParameterByName)('error_code');
865
- if (!error_code)
866
- throw new errors_1.AuthImplicitGrantRedirectError('No error_code detected.');
867
- const error = (0, helpers_1.getParameterByName)('error');
868
- if (!error)
869
- throw new errors_1.AuthImplicitGrantRedirectError('No error detected.');
870
- throw new errors_1.AuthImplicitGrantRedirectError(error_description, { error, code: error_code });
871
- }
872
- const provider_token = (0, helpers_1.getParameterByName)('provider_token');
873
- const provider_refresh_token = (0, helpers_1.getParameterByName)('provider_refresh_token');
874
- const access_token = (0, helpers_1.getParameterByName)('access_token');
875
- if (!access_token)
876
- throw new errors_1.AuthImplicitGrantRedirectError('No access_token detected.');
877
- const expires_in = (0, helpers_1.getParameterByName)('expires_in');
878
- if (!expires_in)
879
- throw new errors_1.AuthImplicitGrantRedirectError('No expires_in detected.');
880
- const refresh_token = (0, helpers_1.getParameterByName)('refresh_token');
881
- if (!refresh_token)
882
- throw new errors_1.AuthImplicitGrantRedirectError('No refresh_token detected.');
883
- const token_type = (0, helpers_1.getParameterByName)('token_type');
884
- if (!token_type)
885
- throw new errors_1.AuthImplicitGrantRedirectError('No token_type detected.');
886
- const timeNow = Math.round(Date.now() / 1000);
887
- const expires_at = timeNow + parseInt(expires_in);
888
- const { data, error } = yield this.getUser(access_token);
798
+ async _getSessionFromUrl(isPKCEFlow) {
799
+ try {
800
+ if (!(0, helpers_1.isBrowser)())
801
+ throw new errors_1.AuthImplicitGrantRedirectError('No browser detected.');
802
+ if (this.flowType === 'implicit' && !this._isImplicitGrantFlow()) {
803
+ throw new errors_1.AuthImplicitGrantRedirectError('Not a valid implicit grant flow url.');
804
+ }
805
+ else if (this.flowType == 'pkce' && !isPKCEFlow) {
806
+ throw new errors_1.AuthPKCEGrantCodeExchangeError('Not a valid PKCE flow url.');
807
+ }
808
+ if (isPKCEFlow) {
809
+ const authCode = (0, helpers_1.getParameterByName)('code');
810
+ if (!authCode)
811
+ throw new errors_1.AuthPKCEGrantCodeExchangeError('No code detected.');
812
+ const { data, error } = await this.exchangeCodeForSession(authCode);
889
813
  if (error)
890
814
  throw error;
891
- const user = data.user;
892
- const session = {
893
- provider_token,
894
- provider_refresh_token,
895
- access_token,
896
- expires_in: parseInt(expires_in),
897
- expires_at,
898
- refresh_token,
899
- token_type,
900
- user,
901
- };
902
- const redirectType = (0, helpers_1.getParameterByName)('type');
903
- // Remove tokens from URL
904
- window.location.hash = '';
905
- this._debug('#_getSessionFromUrl()', 'clearing window.location.hash');
906
- return { data: { session, redirectType }, error: null };
907
- }
908
- catch (error) {
909
- if ((0, errors_1.isAuthError)(error)) {
910
- return { data: { session: null, redirectType: null }, error };
911
- }
815
+ if (!data.session)
816
+ throw new errors_1.AuthPKCEGrantCodeExchangeError('No session detected.');
817
+ let url = new URL(window.location.href);
818
+ url.searchParams.delete('code');
819
+ window.history.replaceState(window.history.state, '', url.toString());
820
+ return { data: { session: data.session, redirectType: null }, error: null };
821
+ }
822
+ const error_description = (0, helpers_1.getParameterByName)('error_description');
823
+ if (error_description) {
824
+ const error_code = (0, helpers_1.getParameterByName)('error_code');
825
+ if (!error_code)
826
+ throw new errors_1.AuthImplicitGrantRedirectError('No error_code detected.');
827
+ const error = (0, helpers_1.getParameterByName)('error');
828
+ if (!error)
829
+ throw new errors_1.AuthImplicitGrantRedirectError('No error detected.');
830
+ throw new errors_1.AuthImplicitGrantRedirectError(error_description, { error, code: error_code });
831
+ }
832
+ const provider_token = (0, helpers_1.getParameterByName)('provider_token');
833
+ const provider_refresh_token = (0, helpers_1.getParameterByName)('provider_refresh_token');
834
+ const access_token = (0, helpers_1.getParameterByName)('access_token');
835
+ if (!access_token)
836
+ throw new errors_1.AuthImplicitGrantRedirectError('No access_token detected.');
837
+ const expires_in = (0, helpers_1.getParameterByName)('expires_in');
838
+ if (!expires_in)
839
+ throw new errors_1.AuthImplicitGrantRedirectError('No expires_in detected.');
840
+ const refresh_token = (0, helpers_1.getParameterByName)('refresh_token');
841
+ if (!refresh_token)
842
+ throw new errors_1.AuthImplicitGrantRedirectError('No refresh_token detected.');
843
+ const token_type = (0, helpers_1.getParameterByName)('token_type');
844
+ if (!token_type)
845
+ throw new errors_1.AuthImplicitGrantRedirectError('No token_type detected.');
846
+ const timeNow = Math.round(Date.now() / 1000);
847
+ const expires_at = timeNow + parseInt(expires_in);
848
+ const { data, error } = await this.getUser(access_token);
849
+ if (error)
912
850
  throw error;
851
+ const user = data.user;
852
+ const session = {
853
+ provider_token,
854
+ provider_refresh_token,
855
+ access_token,
856
+ expires_in: parseInt(expires_in),
857
+ expires_at,
858
+ refresh_token,
859
+ token_type,
860
+ user,
861
+ };
862
+ const redirectType = (0, helpers_1.getParameterByName)('type');
863
+ // Remove tokens from URL
864
+ window.location.hash = '';
865
+ this._debug('#_getSessionFromUrl()', 'clearing window.location.hash');
866
+ return { data: { session, redirectType }, error: null };
867
+ }
868
+ catch (error) {
869
+ if ((0, errors_1.isAuthError)(error)) {
870
+ return { data: { session: null, redirectType: null }, error };
913
871
  }
914
- });
872
+ throw error;
873
+ }
915
874
  }
916
875
  /**
917
876
  * Checks if the current URL contains parameters given by an implicit oauth grant flow (https://www.rfc-editor.org/rfc/rfc6749.html#section-4.2)
@@ -924,11 +883,9 @@ class GoTrueClient {
924
883
  /**
925
884
  * Checks if the current URL and backing storage contain parameters given by a PKCE flow
926
885
  */
927
- _isPKCEFlow() {
928
- return __awaiter(this, void 0, void 0, function* () {
929
- const currentStorageContent = yield (0, helpers_1.getItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
930
- return Boolean((0, helpers_1.getParameterByName)('code')) && Boolean(currentStorageContent);
931
- });
886
+ async _isPKCEFlow() {
887
+ const currentStorageContent = await (0, helpers_1.getItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
888
+ return Boolean((0, helpers_1.getParameterByName)('code')) && Boolean(currentStorageContent);
932
889
  }
933
890
  /**
934
891
  * Inside a browser context, `signOut()` will remove the logged in user from the browser session
@@ -939,31 +896,29 @@ class GoTrueClient {
939
896
  *
940
897
  * If using others scope, no `SIGNED_OUT` event is fired!
941
898
  */
942
- signOut({ scope } = { scope: 'global' }) {
899
+ async signOut({ scope } = { scope: 'global' }) {
943
900
  var _a;
944
- return __awaiter(this, void 0, void 0, function* () {
945
- const { data, error: sessionError } = yield this.getSession();
946
- if (sessionError) {
947
- return { error: sessionError };
948
- }
949
- const accessToken = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token;
950
- if (accessToken) {
951
- const { error } = yield this.admin.signOut(accessToken, scope);
952
- if (error) {
953
- // ignore 404s since user might not exist anymore
954
- // ignore 401s since an invalid or expired JWT should sign out the current session
955
- if (!((0, errors_1.isAuthApiError)(error) && (error.status === 404 || error.status === 401))) {
956
- return { error };
957
- }
901
+ const { data, error: sessionError } = await this.getSession();
902
+ if (sessionError) {
903
+ return { error: sessionError };
904
+ }
905
+ const accessToken = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token;
906
+ if (accessToken) {
907
+ const { error } = await this.admin.signOut(accessToken, scope);
908
+ if (error) {
909
+ // ignore 404s since user might not exist anymore
910
+ // ignore 401s since an invalid or expired JWT should sign out the current session
911
+ if (!((0, errors_1.isAuthApiError)(error) && (error.status === 404 || error.status === 401))) {
912
+ return { error };
958
913
  }
959
914
  }
960
- if (scope !== 'others') {
961
- yield this._removeSession();
962
- yield (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
963
- yield this._notifyAllSubscribers('SIGNED_OUT', null);
964
- }
965
- return { error: null };
966
- });
915
+ }
916
+ if (scope !== 'others') {
917
+ await this._removeSession();
918
+ await (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
919
+ await this._notifyAllSubscribers('SIGNED_OUT', null);
920
+ }
921
+ return { error: null };
967
922
  }
968
923
  /**
969
924
  * Receive a notification every time an auth event happens.
@@ -984,22 +939,20 @@ class GoTrueClient {
984
939
  this._emitInitialSession(id);
985
940
  return { data: { subscription } };
986
941
  }
987
- _emitInitialSession(id) {
942
+ async _emitInitialSession(id) {
988
943
  var _a, _b;
989
- return __awaiter(this, void 0, void 0, function* () {
990
- try {
991
- const { data: { session }, error, } = yield this.getSession();
992
- if (error)
993
- throw error;
994
- yield ((_a = this.stateChangeEmitters.get(id)) === null || _a === void 0 ? void 0 : _a.callback('INITIAL_SESSION', session));
995
- this._debug('INITIAL_SESSION', 'callback id', id, 'session', session);
996
- }
997
- catch (err) {
998
- yield ((_b = this.stateChangeEmitters.get(id)) === null || _b === void 0 ? void 0 : _b.callback('INITIAL_SESSION', null));
999
- this._debug('INITIAL_SESSION', 'callback id', id, 'error', err);
1000
- console.error(err);
1001
- }
1002
- });
944
+ try {
945
+ const { data: { session }, error, } = await this.getSession();
946
+ if (error)
947
+ throw error;
948
+ await ((_a = this.stateChangeEmitters.get(id)) === null || _a === void 0 ? void 0 : _a.callback('INITIAL_SESSION', session));
949
+ this._debug('INITIAL_SESSION', 'callback id', id, 'session', session);
950
+ }
951
+ catch (err) {
952
+ await ((_b = this.stateChangeEmitters.get(id)) === null || _b === void 0 ? void 0 : _b.callback('INITIAL_SESSION', null));
953
+ this._debug('INITIAL_SESSION', 'callback id', id, 'error', err);
954
+ console.error(err);
955
+ }
1003
956
  }
1004
957
  /**
1005
958
  * Sends a password reset request to an email address.
@@ -1008,72 +961,68 @@ class GoTrueClient {
1008
961
  * @param options.redirectTo The URL to send the user to after they click the password reset link.
1009
962
  * @param options.captchaToken Verification token received when the user completes the captcha on the site.
1010
963
  */
1011
- resetPasswordForEmail(email, options = {}) {
1012
- return __awaiter(this, void 0, void 0, function* () {
1013
- let codeChallenge = null;
1014
- let codeChallengeMethod = null;
1015
- if (this.flowType === 'pkce') {
1016
- const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
1017
- yield (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
1018
- codeChallenge = yield (0, helpers_1.generatePKCEChallenge)(codeVerifier);
1019
- codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
1020
- }
1021
- try {
1022
- return yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/recover`, {
1023
- body: {
1024
- email,
1025
- code_challenge: codeChallenge,
1026
- code_challenge_method: codeChallengeMethod,
1027
- gotrue_meta_security: { captcha_token: options.captchaToken },
1028
- },
1029
- headers: this.headers,
1030
- redirectTo: options.redirectTo,
1031
- });
1032
- }
1033
- catch (error) {
1034
- if ((0, errors_1.isAuthError)(error)) {
1035
- return { data: null, error };
1036
- }
1037
- throw error;
964
+ async resetPasswordForEmail(email, options = {}) {
965
+ let codeChallenge = null;
966
+ let codeChallengeMethod = null;
967
+ if (this.flowType === 'pkce') {
968
+ const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
969
+ await (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
970
+ codeChallenge = await (0, helpers_1.generatePKCEChallenge)(codeVerifier);
971
+ codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
972
+ }
973
+ try {
974
+ return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/recover`, {
975
+ body: {
976
+ email,
977
+ code_challenge: codeChallenge,
978
+ code_challenge_method: codeChallengeMethod,
979
+ gotrue_meta_security: { captcha_token: options.captchaToken },
980
+ },
981
+ headers: this.headers,
982
+ redirectTo: options.redirectTo,
983
+ });
984
+ }
985
+ catch (error) {
986
+ if ((0, errors_1.isAuthError)(error)) {
987
+ return { data: null, error };
1038
988
  }
1039
- });
989
+ throw error;
990
+ }
1040
991
  }
1041
992
  /**
1042
993
  * Generates a new JWT.
1043
994
  * @param refreshToken A valid refresh token that was returned on login.
1044
995
  */
1045
- _refreshAccessToken(refreshToken) {
1046
- return __awaiter(this, void 0, void 0, function* () {
1047
- const debugName = `#_refreshAccessToken(${refreshToken.substring(0, 5)}...)`;
1048
- this._debug(debugName, 'begin');
1049
- try {
1050
- const startedAt = Date.now();
1051
- // will attempt to refresh the token with exponential backoff
1052
- return yield (0, helpers_1.retryable)((attempt) => __awaiter(this, void 0, void 0, function* () {
1053
- yield (0, helpers_1.sleep)(attempt * 200); // 0, 200, 400, 800, ...
1054
- this._debug(debugName, 'refreshing attempt', attempt);
1055
- return yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=refresh_token`, {
1056
- body: { refresh_token: refreshToken },
1057
- headers: this.headers,
1058
- xform: fetch_1._sessionResponse,
1059
- });
1060
- }), (attempt, _, result) => result &&
1061
- result.error &&
1062
- (0, errors_1.isAuthRetryableFetchError)(result.error) &&
1063
- // retryable only if the request can be sent before the backoff overflows the tick duration
1064
- Date.now() + (attempt + 1) * 200 - startedAt < AUTO_REFRESH_TICK_DURATION);
1065
- }
1066
- catch (error) {
1067
- this._debug(debugName, 'error', error);
1068
- if ((0, errors_1.isAuthError)(error)) {
1069
- return { data: { session: null, user: null }, error };
1070
- }
1071
- throw error;
1072
- }
1073
- finally {
1074
- this._debug(debugName, 'end');
996
+ async _refreshAccessToken(refreshToken) {
997
+ const debugName = `#_refreshAccessToken(${refreshToken.substring(0, 5)}...)`;
998
+ this._debug(debugName, 'begin');
999
+ try {
1000
+ const startedAt = Date.now();
1001
+ // will attempt to refresh the token with exponential backoff
1002
+ return await (0, helpers_1.retryable)(async (attempt) => {
1003
+ await (0, helpers_1.sleep)(attempt * 200); // 0, 200, 400, 800, ...
1004
+ this._debug(debugName, 'refreshing attempt', attempt);
1005
+ return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=refresh_token`, {
1006
+ body: { refresh_token: refreshToken },
1007
+ headers: this.headers,
1008
+ xform: fetch_1._sessionResponse,
1009
+ });
1010
+ }, (attempt, _, result) => result &&
1011
+ result.error &&
1012
+ (0, errors_1.isAuthRetryableFetchError)(result.error) &&
1013
+ // retryable only if the request can be sent before the backoff overflows the tick duration
1014
+ Date.now() + (attempt + 1) * 200 - startedAt < AUTO_REFRESH_TICK_DURATION);
1015
+ }
1016
+ catch (error) {
1017
+ this._debug(debugName, 'error', error);
1018
+ if ((0, errors_1.isAuthError)(error)) {
1019
+ return { data: { session: null, user: null }, error };
1075
1020
  }
1076
- });
1021
+ throw error;
1022
+ }
1023
+ finally {
1024
+ this._debug(debugName, 'end');
1025
+ }
1077
1026
  }
1078
1027
  _isValidSession(maybeSession) {
1079
1028
  const isValidSession = typeof maybeSession === 'object' &&
@@ -1083,172 +1032,160 @@ class GoTrueClient {
1083
1032
  'expires_at' in maybeSession;
1084
1033
  return isValidSession;
1085
1034
  }
1086
- _handleProviderSignIn(provider, options) {
1087
- return __awaiter(this, void 0, void 0, function* () {
1088
- const url = yield this._getUrlForProvider(provider, {
1089
- redirectTo: options.redirectTo,
1090
- scopes: options.scopes,
1091
- queryParams: options.queryParams,
1092
- });
1093
- this._debug('#_handleProviderSignIn()', 'provider', provider, 'options', options, 'url', url);
1094
- // try to open on the browser
1095
- if ((0, helpers_1.isBrowser)() && !options.skipBrowserRedirect) {
1096
- window.location.assign(url);
1097
- }
1098
- return { data: { provider, url }, error: null };
1035
+ async _handleProviderSignIn(provider, options) {
1036
+ const url = await this._getUrlForProvider(provider, {
1037
+ redirectTo: options.redirectTo,
1038
+ scopes: options.scopes,
1039
+ queryParams: options.queryParams,
1099
1040
  });
1041
+ this._debug('#_handleProviderSignIn()', 'provider', provider, 'options', options, 'url', url);
1042
+ // try to open on the browser
1043
+ if ((0, helpers_1.isBrowser)() && !options.skipBrowserRedirect) {
1044
+ window.location.assign(url);
1045
+ }
1046
+ return { data: { provider, url }, error: null };
1100
1047
  }
1101
1048
  /**
1102
1049
  * Recovers the session from LocalStorage and refreshes
1103
1050
  * Note: this method is async to accommodate for AsyncStorage e.g. in React native.
1104
1051
  */
1105
- _recoverAndRefresh() {
1052
+ async _recoverAndRefresh() {
1106
1053
  var _a;
1107
- return __awaiter(this, void 0, void 0, function* () {
1108
- const debugName = '#_recoverAndRefresh()';
1109
- this._debug(debugName, 'begin');
1110
- try {
1111
- const currentSession = yield (0, helpers_1.getItemAsync)(this.storage, this.storageKey);
1112
- this._debug(debugName, 'session from storage', currentSession);
1113
- if (!this._isValidSession(currentSession)) {
1114
- this._debug(debugName, 'session is not valid');
1115
- if (currentSession !== null) {
1116
- yield this._removeSession();
1117
- }
1118
- return;
1054
+ const debugName = '#_recoverAndRefresh()';
1055
+ this._debug(debugName, 'begin');
1056
+ try {
1057
+ const currentSession = await (0, helpers_1.getItemAsync)(this.storage, this.storageKey);
1058
+ this._debug(debugName, 'session from storage', currentSession);
1059
+ if (!this._isValidSession(currentSession)) {
1060
+ this._debug(debugName, 'session is not valid');
1061
+ if (currentSession !== null) {
1062
+ await this._removeSession();
1119
1063
  }
1120
- const timeNow = Math.round(Date.now() / 1000);
1121
- const expiresWithMargin = ((_a = currentSession.expires_at) !== null && _a !== void 0 ? _a : Infinity) < timeNow + constants_1.EXPIRY_MARGIN;
1122
- this._debug(debugName, `session has${expiresWithMargin ? '' : ' not'} expired with margin of ${constants_1.EXPIRY_MARGIN}s`);
1123
- if (expiresWithMargin) {
1124
- if (this.autoRefreshToken && currentSession.refresh_token) {
1125
- const { error } = yield this._callRefreshToken(currentSession.refresh_token);
1126
- if (error) {
1127
- console.error(error);
1128
- if (!(0, errors_1.isAuthRetryableFetchError)(error)) {
1129
- this._debug(debugName, 'refresh failed with a non-retryable error, removing the session', error);
1130
- yield this._removeSession();
1131
- }
1064
+ return;
1065
+ }
1066
+ const timeNow = Math.round(Date.now() / 1000);
1067
+ const expiresWithMargin = ((_a = currentSession.expires_at) !== null && _a !== void 0 ? _a : Infinity) < timeNow + constants_1.EXPIRY_MARGIN;
1068
+ this._debug(debugName, `session has${expiresWithMargin ? '' : ' not'} expired with margin of ${constants_1.EXPIRY_MARGIN}s`);
1069
+ if (expiresWithMargin) {
1070
+ if (this.autoRefreshToken && currentSession.refresh_token) {
1071
+ const { error } = await this._callRefreshToken(currentSession.refresh_token);
1072
+ if (error) {
1073
+ console.error(error);
1074
+ if (!(0, errors_1.isAuthRetryableFetchError)(error)) {
1075
+ this._debug(debugName, 'refresh failed with a non-retryable error, removing the session', error);
1076
+ await this._removeSession();
1132
1077
  }
1133
1078
  }
1134
1079
  }
1135
- else {
1136
- // no need to persist currentSession again, as we just loaded it from
1137
- // local storage; persisting it again may overwrite a value saved by
1138
- // another client with access to the same local storage
1139
- yield this._notifyAllSubscribers('SIGNED_IN', currentSession);
1140
- }
1141
1080
  }
1142
- catch (err) {
1143
- this._debug(debugName, 'error', err);
1144
- console.error(err);
1145
- return;
1146
- }
1147
- finally {
1148
- this._debug(debugName, 'end');
1081
+ else {
1082
+ // no need to persist currentSession again, as we just loaded it from
1083
+ // local storage; persisting it again may overwrite a value saved by
1084
+ // another client with access to the same local storage
1085
+ await this._notifyAllSubscribers('SIGNED_IN', currentSession);
1149
1086
  }
1150
- });
1087
+ }
1088
+ catch (err) {
1089
+ this._debug(debugName, 'error', err);
1090
+ console.error(err);
1091
+ return;
1092
+ }
1093
+ finally {
1094
+ this._debug(debugName, 'end');
1095
+ }
1151
1096
  }
1152
- _callRefreshToken(refreshToken) {
1097
+ async _callRefreshToken(refreshToken) {
1153
1098
  var _a, _b;
1154
- return __awaiter(this, void 0, void 0, function* () {
1155
- if (!refreshToken) {
1099
+ if (!refreshToken) {
1100
+ throw new errors_1.AuthSessionMissingError();
1101
+ }
1102
+ // refreshing is already in progress
1103
+ if (this.refreshingDeferred) {
1104
+ return this.refreshingDeferred.promise;
1105
+ }
1106
+ const debugName = `#_callRefreshToken(${refreshToken.substring(0, 5)}...)`;
1107
+ this._debug(debugName, 'begin');
1108
+ try {
1109
+ this.refreshingDeferred = new helpers_1.Deferred();
1110
+ const { data, error } = await this._refreshAccessToken(refreshToken);
1111
+ if (error)
1112
+ throw error;
1113
+ if (!data.session)
1156
1114
  throw new errors_1.AuthSessionMissingError();
1157
- }
1158
- // refreshing is already in progress
1159
- if (this.refreshingDeferred) {
1160
- return this.refreshingDeferred.promise;
1161
- }
1162
- const debugName = `#_callRefreshToken(${refreshToken.substring(0, 5)}...)`;
1163
- this._debug(debugName, 'begin');
1164
- try {
1165
- this.refreshingDeferred = new helpers_1.Deferred();
1166
- const { data, error } = yield this._refreshAccessToken(refreshToken);
1167
- if (error)
1168
- throw error;
1169
- if (!data.session)
1170
- throw new errors_1.AuthSessionMissingError();
1171
- yield this._saveSession(data.session);
1172
- yield this._notifyAllSubscribers('TOKEN_REFRESHED', data.session);
1173
- const result = { session: data.session, error: null };
1174
- this.refreshingDeferred.resolve(result);
1115
+ await this._saveSession(data.session);
1116
+ await this._notifyAllSubscribers('TOKEN_REFRESHED', data.session);
1117
+ const result = { session: data.session, error: null };
1118
+ this.refreshingDeferred.resolve(result);
1119
+ return result;
1120
+ }
1121
+ catch (error) {
1122
+ this._debug(debugName, 'error', error);
1123
+ if ((0, errors_1.isAuthError)(error)) {
1124
+ const result = { session: null, error };
1125
+ (_a = this.refreshingDeferred) === null || _a === void 0 ? void 0 : _a.resolve(result);
1175
1126
  return result;
1176
1127
  }
1177
- catch (error) {
1178
- this._debug(debugName, 'error', error);
1179
- if ((0, errors_1.isAuthError)(error)) {
1180
- const result = { session: null, error };
1181
- (_a = this.refreshingDeferred) === null || _a === void 0 ? void 0 : _a.resolve(result);
1182
- return result;
1183
- }
1184
- (_b = this.refreshingDeferred) === null || _b === void 0 ? void 0 : _b.reject(error);
1185
- throw error;
1186
- }
1187
- finally {
1188
- this.refreshingDeferred = null;
1189
- this._debug(debugName, 'end');
1190
- }
1191
- });
1128
+ (_b = this.refreshingDeferred) === null || _b === void 0 ? void 0 : _b.reject(error);
1129
+ throw error;
1130
+ }
1131
+ finally {
1132
+ this.refreshingDeferred = null;
1133
+ this._debug(debugName, 'end');
1134
+ }
1192
1135
  }
1193
- _notifyAllSubscribers(event, session, broadcast = true) {
1194
- return __awaiter(this, void 0, void 0, function* () {
1195
- const debugName = `#_notifyAllSubscribers(${event})`;
1196
- this._debug(debugName, 'begin', session, `broadcast = ${broadcast}`);
1197
- try {
1198
- if (this.broadcastChannel && broadcast) {
1199
- this.broadcastChannel.postMessage({ event, session });
1136
+ async _notifyAllSubscribers(event, session, broadcast = true) {
1137
+ const debugName = `#_notifyAllSubscribers(${event})`;
1138
+ this._debug(debugName, 'begin', session, `broadcast = ${broadcast}`);
1139
+ try {
1140
+ if (this.broadcastChannel && broadcast) {
1141
+ this.broadcastChannel.postMessage({ event, session });
1142
+ }
1143
+ const errors = [];
1144
+ const promises = Array.from(this.stateChangeEmitters.values()).map(async (x) => {
1145
+ try {
1146
+ await x.callback(event, session);
1200
1147
  }
1201
- const errors = [];
1202
- const promises = Array.from(this.stateChangeEmitters.values()).map((x) => __awaiter(this, void 0, void 0, function* () {
1203
- try {
1204
- yield x.callback(event, session);
1205
- }
1206
- catch (e) {
1207
- errors.push(e);
1208
- }
1209
- }));
1210
- yield Promise.all(promises);
1211
- if (errors.length > 0) {
1212
- for (let i = 0; i < errors.length; i += 1) {
1213
- console.error(errors[i]);
1214
- }
1215
- throw errors[0];
1148
+ catch (e) {
1149
+ errors.push(e);
1216
1150
  }
1151
+ });
1152
+ await Promise.all(promises);
1153
+ if (errors.length > 0) {
1154
+ for (let i = 0; i < errors.length; i += 1) {
1155
+ console.error(errors[i]);
1156
+ }
1157
+ throw errors[0];
1217
1158
  }
1218
- finally {
1219
- this._debug(debugName, 'end');
1220
- }
1221
- });
1159
+ }
1160
+ finally {
1161
+ this._debug(debugName, 'end');
1162
+ }
1222
1163
  }
1223
1164
  /**
1224
1165
  * set currentSession and currentUser
1225
1166
  * process to _startAutoRefreshToken if possible
1226
1167
  */
1227
- _saveSession(session) {
1228
- return __awaiter(this, void 0, void 0, function* () {
1229
- this._debug('#_saveSession()', session);
1230
- if (!this.persistSession) {
1231
- this.inMemorySession = session;
1232
- }
1233
- if (this.persistSession && session.expires_at) {
1234
- yield this._persistSession(session);
1235
- }
1236
- });
1168
+ async _saveSession(session) {
1169
+ this._debug('#_saveSession()', session);
1170
+ if (!this.persistSession) {
1171
+ this.inMemorySession = session;
1172
+ }
1173
+ if (this.persistSession && session.expires_at) {
1174
+ await this._persistSession(session);
1175
+ }
1237
1176
  }
1238
1177
  _persistSession(currentSession) {
1239
1178
  this._debug('#_persistSession()', currentSession);
1240
1179
  return (0, helpers_1.setItemAsync)(this.storage, this.storageKey, currentSession);
1241
1180
  }
1242
- _removeSession() {
1243
- return __awaiter(this, void 0, void 0, function* () {
1244
- this._debug('#_removeSession()');
1245
- if (this.persistSession) {
1246
- yield (0, helpers_1.removeItemAsync)(this.storage, this.storageKey);
1247
- }
1248
- else {
1249
- this.inMemorySession = null;
1250
- }
1251
- });
1181
+ async _removeSession() {
1182
+ this._debug('#_removeSession()');
1183
+ if (this.persistSession) {
1184
+ await (0, helpers_1.removeItemAsync)(this.storage, this.storageKey);
1185
+ }
1186
+ else {
1187
+ this.inMemorySession = null;
1188
+ }
1252
1189
  }
1253
1190
  /**
1254
1191
  * Removes any registered visibilitychange callback.
@@ -1273,45 +1210,41 @@ class GoTrueClient {
1273
1210
  * This is the private implementation of {@link #startAutoRefresh}. Use this
1274
1211
  * within the library.
1275
1212
  */
1276
- _startAutoRefresh() {
1277
- return __awaiter(this, void 0, void 0, function* () {
1278
- yield this._stopAutoRefresh();
1279
- this._debug('#_startAutoRefresh()');
1280
- const ticker = setInterval(() => this._autoRefreshTokenTick(), AUTO_REFRESH_TICK_DURATION);
1281
- this.autoRefreshTicker = ticker;
1282
- if (ticker && typeof ticker === 'object' && typeof ticker.unref === 'function') {
1283
- // ticker is a NodeJS Timeout object that has an `unref` method
1284
- // https://nodejs.org/api/timers.html#timeoutunref
1285
- // When auto refresh is used in NodeJS (like for testing) the
1286
- // `setInterval` is preventing the process from being marked as
1287
- // finished and tests run endlessly. This can be prevented by calling
1288
- // `unref()` on the returned object.
1289
- ticker.unref();
1290
- // @ts-ignore
1291
- }
1292
- else if (typeof Deno !== 'undefined' && typeof Deno.unrefTimer === 'function') {
1293
- // similar like for NodeJS, but with the Deno API
1294
- // https://deno.land/api@latest?unstable&s=Deno.unrefTimer
1295
- // @ts-ignore
1296
- Deno.unrefTimer(ticker);
1297
- }
1298
- // run the tick immediately
1299
- yield this._autoRefreshTokenTick();
1300
- });
1213
+ async _startAutoRefresh() {
1214
+ await this._stopAutoRefresh();
1215
+ this._debug('#_startAutoRefresh()');
1216
+ const ticker = setInterval(() => this._autoRefreshTokenTick(), AUTO_REFRESH_TICK_DURATION);
1217
+ this.autoRefreshTicker = ticker;
1218
+ if (ticker && typeof ticker === 'object' && typeof ticker.unref === 'function') {
1219
+ // ticker is a NodeJS Timeout object that has an `unref` method
1220
+ // https://nodejs.org/api/timers.html#timeoutunref
1221
+ // When auto refresh is used in NodeJS (like for testing) the
1222
+ // `setInterval` is preventing the process from being marked as
1223
+ // finished and tests run endlessly. This can be prevented by calling
1224
+ // `unref()` on the returned object.
1225
+ ticker.unref();
1226
+ // @ts-ignore
1227
+ }
1228
+ else if (typeof Deno !== 'undefined' && typeof Deno.unrefTimer === 'function') {
1229
+ // similar like for NodeJS, but with the Deno API
1230
+ // https://deno.land/api@latest?unstable&s=Deno.unrefTimer
1231
+ // @ts-ignore
1232
+ Deno.unrefTimer(ticker);
1233
+ }
1234
+ // run the tick immediately
1235
+ await this._autoRefreshTokenTick();
1301
1236
  }
1302
1237
  /**
1303
1238
  * This is the private implementation of {@link #stopAutoRefresh}. Use this
1304
1239
  * within the library.
1305
1240
  */
1306
- _stopAutoRefresh() {
1307
- return __awaiter(this, void 0, void 0, function* () {
1308
- this._debug('#_stopAutoRefresh()');
1309
- const ticker = this.autoRefreshTicker;
1310
- this.autoRefreshTicker = null;
1311
- if (ticker) {
1312
- clearInterval(ticker);
1313
- }
1314
- });
1241
+ async _stopAutoRefresh() {
1242
+ this._debug('#_stopAutoRefresh()');
1243
+ const ticker = this.autoRefreshTicker;
1244
+ this.autoRefreshTicker = null;
1245
+ if (ticker) {
1246
+ clearInterval(ticker);
1247
+ }
1315
1248
  }
1316
1249
  /**
1317
1250
  * Starts an auto-refresh process in the background. The session is checked
@@ -1335,11 +1268,9 @@ class GoTrueClient {
1335
1268
  *
1336
1269
  * {@see #stopAutoRefresh}
1337
1270
  */
1338
- startAutoRefresh() {
1339
- return __awaiter(this, void 0, void 0, function* () {
1340
- this._removeVisibilityChangedCallback();
1341
- yield this._startAutoRefresh();
1342
- });
1271
+ async startAutoRefresh() {
1272
+ this._removeVisibilityChangedCallback();
1273
+ await this._startAutoRefresh();
1343
1274
  }
1344
1275
  /**
1345
1276
  * Stops an active auto refresh process running in the background (if any).
@@ -1349,94 +1280,86 @@ class GoTrueClient {
1349
1280
  *
1350
1281
  * See {@link #startAutoRefresh} for more details.
1351
1282
  */
1352
- stopAutoRefresh() {
1353
- return __awaiter(this, void 0, void 0, function* () {
1354
- this._removeVisibilityChangedCallback();
1355
- yield this._stopAutoRefresh();
1356
- });
1283
+ async stopAutoRefresh() {
1284
+ this._removeVisibilityChangedCallback();
1285
+ await this._stopAutoRefresh();
1357
1286
  }
1358
1287
  /**
1359
1288
  * Runs the auto refresh token tick.
1360
1289
  */
1361
- _autoRefreshTokenTick() {
1362
- return __awaiter(this, void 0, void 0, function* () {
1363
- this._debug('#_autoRefreshTokenTick()', 'begin');
1290
+ async _autoRefreshTokenTick() {
1291
+ this._debug('#_autoRefreshTokenTick()', 'begin');
1292
+ try {
1293
+ const now = Date.now();
1364
1294
  try {
1365
- const now = Date.now();
1366
- try {
1367
- const { data: { session }, } = yield this.getSession();
1368
- if (!session || !session.refresh_token || !session.expires_at) {
1369
- this._debug('#_autoRefreshTokenTick()', 'no session');
1370
- return;
1371
- }
1372
- // session will expire in this many ticks (or has already expired if <= 0)
1373
- const expiresInTicks = Math.floor((session.expires_at * 1000 - now) / AUTO_REFRESH_TICK_DURATION);
1374
- this._debug('#_autoRefreshTokenTick()', `access token expires in ${expiresInTicks} ticks, a tick lasts ${AUTO_REFRESH_TICK_DURATION}ms, refresh threshold is ${AUTO_REFRESH_TICK_THRESHOLD} ticks`);
1375
- if (expiresInTicks <= AUTO_REFRESH_TICK_THRESHOLD) {
1376
- yield this._callRefreshToken(session.refresh_token);
1377
- }
1295
+ const { data: { session }, } = await this.getSession();
1296
+ if (!session || !session.refresh_token || !session.expires_at) {
1297
+ this._debug('#_autoRefreshTokenTick()', 'no session');
1298
+ return;
1378
1299
  }
1379
- catch (e) {
1380
- console.error('Auto refresh tick failed with error. This is likely a transient error.', e);
1300
+ // session will expire in this many ticks (or has already expired if <= 0)
1301
+ const expiresInTicks = Math.floor((session.expires_at * 1000 - now) / AUTO_REFRESH_TICK_DURATION);
1302
+ this._debug('#_autoRefreshTokenTick()', `access token expires in ${expiresInTicks} ticks, a tick lasts ${AUTO_REFRESH_TICK_DURATION}ms, refresh threshold is ${AUTO_REFRESH_TICK_THRESHOLD} ticks`);
1303
+ if (expiresInTicks <= AUTO_REFRESH_TICK_THRESHOLD) {
1304
+ await this._callRefreshToken(session.refresh_token);
1381
1305
  }
1382
1306
  }
1383
- finally {
1384
- this._debug('#_autoRefreshTokenTick()', 'end');
1307
+ catch (e) {
1308
+ console.error('Auto refresh tick failed with error. This is likely a transient error.', e);
1385
1309
  }
1386
- });
1310
+ }
1311
+ finally {
1312
+ this._debug('#_autoRefreshTokenTick()', 'end');
1313
+ }
1387
1314
  }
1388
1315
  /**
1389
1316
  * Registers callbacks on the browser / platform, which in-turn run
1390
1317
  * algorithms when the browser window/tab are in foreground. On non-browser
1391
1318
  * platforms it assumes always foreground.
1392
1319
  */
1393
- _handleVisibilityChange() {
1394
- return __awaiter(this, void 0, void 0, function* () {
1395
- this._debug('#_handleVisibilityChange()');
1396
- if (!(0, helpers_1.isBrowser)() || !(window === null || window === void 0 ? void 0 : window.addEventListener)) {
1397
- if (this.autoRefreshToken) {
1398
- // in non-browser environments the refresh token ticker runs always
1399
- this.startAutoRefresh();
1400
- }
1401
- return false;
1402
- }
1403
- try {
1404
- this.visibilityChangedCallback = () => __awaiter(this, void 0, void 0, function* () { return yield this._onVisibilityChanged(false); });
1405
- window === null || window === void 0 ? void 0 : window.addEventListener('visibilitychange', this.visibilityChangedCallback);
1406
- // now immediately call the visbility changed callback to setup with the
1407
- // current visbility state
1408
- yield this._onVisibilityChanged(true); // initial call
1409
- }
1410
- catch (error) {
1411
- console.error('_handleVisibilityChange', error);
1412
- }
1413
- });
1320
+ async _handleVisibilityChange() {
1321
+ this._debug('#_handleVisibilityChange()');
1322
+ if (!(0, helpers_1.isBrowser)() || !(window === null || window === void 0 ? void 0 : window.addEventListener)) {
1323
+ if (this.autoRefreshToken) {
1324
+ // in non-browser environments the refresh token ticker runs always
1325
+ this.startAutoRefresh();
1326
+ }
1327
+ return false;
1328
+ }
1329
+ try {
1330
+ this.visibilityChangedCallback = async () => await this._onVisibilityChanged(false);
1331
+ window === null || window === void 0 ? void 0 : window.addEventListener('visibilitychange', this.visibilityChangedCallback);
1332
+ // now immediately call the visbility changed callback to setup with the
1333
+ // current visbility state
1334
+ await this._onVisibilityChanged(true); // initial call
1335
+ }
1336
+ catch (error) {
1337
+ console.error('_handleVisibilityChange', error);
1338
+ }
1414
1339
  }
1415
1340
  /**
1416
1341
  * Callback registered with `window.addEventListener('visibilitychange')`.
1417
1342
  */
1418
- _onVisibilityChanged(isInitial) {
1419
- return __awaiter(this, void 0, void 0, function* () {
1420
- this._debug(`#_onVisibilityChanged(${isInitial})`, 'visibilityState', document.visibilityState);
1421
- if (document.visibilityState === 'visible') {
1422
- if (!isInitial) {
1423
- // initial visibility change setup is handled in another flow under #initialize()
1424
- yield this.initializePromise;
1425
- yield this._recoverAndRefresh();
1426
- this._debug('#_onVisibilityChanged()', 'finished waiting for initialize, _recoverAndRefresh');
1427
- }
1428
- if (this.autoRefreshToken) {
1429
- // in browser environments the refresh token ticker runs only on focused tabs
1430
- // which prevents race conditions
1431
- this._startAutoRefresh();
1432
- }
1343
+ async _onVisibilityChanged(isInitial) {
1344
+ this._debug(`#_onVisibilityChanged(${isInitial})`, 'visibilityState', document.visibilityState);
1345
+ if (document.visibilityState === 'visible') {
1346
+ if (!isInitial) {
1347
+ // initial visibility change setup is handled in another flow under #initialize()
1348
+ await this.initializePromise;
1349
+ await this._recoverAndRefresh();
1350
+ this._debug('#_onVisibilityChanged()', 'finished waiting for initialize, _recoverAndRefresh');
1351
+ }
1352
+ if (this.autoRefreshToken) {
1353
+ // in browser environments the refresh token ticker runs only on focused tabs
1354
+ // which prevents race conditions
1355
+ this._startAutoRefresh();
1433
1356
  }
1434
- else if (document.visibilityState === 'hidden') {
1435
- if (this.autoRefreshToken) {
1436
- this._stopAutoRefresh();
1437
- }
1357
+ }
1358
+ else if (document.visibilityState === 'hidden') {
1359
+ if (this.autoRefreshToken) {
1360
+ this._stopAutoRefresh();
1438
1361
  }
1439
- });
1362
+ }
1440
1363
  }
1441
1364
  /**
1442
1365
  * Generates the relevant login URL for a third-party provider.
@@ -1444,213 +1367,197 @@ class GoTrueClient {
1444
1367
  * @param options.scopes A space-separated list of scopes granted to the OAuth application.
1445
1368
  * @param options.queryParams An object of key-value pairs containing query parameters granted to the OAuth application.
1446
1369
  */
1447
- _getUrlForProvider(provider, options) {
1448
- return __awaiter(this, void 0, void 0, function* () {
1449
- const urlParams = [`provider=${encodeURIComponent(provider)}`];
1450
- if (options === null || options === void 0 ? void 0 : options.redirectTo) {
1451
- urlParams.push(`redirect_to=${encodeURIComponent(options.redirectTo)}`);
1452
- }
1453
- if (options === null || options === void 0 ? void 0 : options.scopes) {
1454
- urlParams.push(`scopes=${encodeURIComponent(options.scopes)}`);
1455
- }
1456
- if (this.flowType === 'pkce') {
1457
- const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
1458
- yield (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
1459
- const codeChallenge = yield (0, helpers_1.generatePKCEChallenge)(codeVerifier);
1460
- const codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
1461
- this._debug('PKCE', 'code verifier', `${codeVerifier.substring(0, 5)}...`, 'code challenge', codeChallenge, 'method', codeChallengeMethod);
1462
- const flowParams = new URLSearchParams({
1463
- code_challenge: `${encodeURIComponent(codeChallenge)}`,
1464
- code_challenge_method: `${encodeURIComponent(codeChallengeMethod)}`,
1465
- });
1466
- urlParams.push(flowParams.toString());
1467
- }
1468
- if (options === null || options === void 0 ? void 0 : options.queryParams) {
1469
- const query = new URLSearchParams(options.queryParams);
1470
- urlParams.push(query.toString());
1471
- }
1472
- return `${this.url}/authorize?${urlParams.join('&')}`;
1473
- });
1370
+ async _getUrlForProvider(provider, options) {
1371
+ const urlParams = [`provider=${encodeURIComponent(provider)}`];
1372
+ if (options === null || options === void 0 ? void 0 : options.redirectTo) {
1373
+ urlParams.push(`redirect_to=${encodeURIComponent(options.redirectTo)}`);
1374
+ }
1375
+ if (options === null || options === void 0 ? void 0 : options.scopes) {
1376
+ urlParams.push(`scopes=${encodeURIComponent(options.scopes)}`);
1377
+ }
1378
+ if (this.flowType === 'pkce') {
1379
+ const codeVerifier = (0, helpers_1.generatePKCEVerifier)();
1380
+ await (0, helpers_1.setItemAsync)(this.storage, `${this.storageKey}-code-verifier`, codeVerifier);
1381
+ const codeChallenge = await (0, helpers_1.generatePKCEChallenge)(codeVerifier);
1382
+ const codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
1383
+ this._debug('PKCE', 'code verifier', `${codeVerifier.substring(0, 5)}...`, 'code challenge', codeChallenge, 'method', codeChallengeMethod);
1384
+ const flowParams = new URLSearchParams({
1385
+ code_challenge: `${encodeURIComponent(codeChallenge)}`,
1386
+ code_challenge_method: `${encodeURIComponent(codeChallengeMethod)}`,
1387
+ });
1388
+ urlParams.push(flowParams.toString());
1389
+ }
1390
+ if (options === null || options === void 0 ? void 0 : options.queryParams) {
1391
+ const query = new URLSearchParams(options.queryParams);
1392
+ urlParams.push(query.toString());
1393
+ }
1394
+ return `${this.url}/authorize?${urlParams.join('&')}`;
1474
1395
  }
1475
- _unenroll(params) {
1396
+ async _unenroll(params) {
1476
1397
  var _a;
1477
- return __awaiter(this, void 0, void 0, function* () {
1478
- try {
1479
- const { data: sessionData, error: sessionError } = yield this.getSession();
1480
- if (sessionError) {
1481
- return { data: null, error: sessionError };
1482
- }
1483
- return yield (0, fetch_1._request)(this.fetch, 'DELETE', `${this.url}/factors/${params.factorId}`, {
1484
- headers: this.headers,
1485
- jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1486
- });
1398
+ try {
1399
+ const { data: sessionData, error: sessionError } = await this.getSession();
1400
+ if (sessionError) {
1401
+ return { data: null, error: sessionError };
1487
1402
  }
1488
- catch (error) {
1489
- if ((0, errors_1.isAuthError)(error)) {
1490
- return { data: null, error };
1491
- }
1492
- throw error;
1403
+ return await (0, fetch_1._request)(this.fetch, 'DELETE', `${this.url}/factors/${params.factorId}`, {
1404
+ headers: this.headers,
1405
+ jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1406
+ });
1407
+ }
1408
+ catch (error) {
1409
+ if ((0, errors_1.isAuthError)(error)) {
1410
+ return { data: null, error };
1493
1411
  }
1494
- });
1412
+ throw error;
1413
+ }
1495
1414
  }
1496
1415
  /**
1497
1416
  * {@see GoTrueMFAApi#enroll}
1498
1417
  */
1499
- _enroll(params) {
1418
+ async _enroll(params) {
1500
1419
  var _a, _b;
1501
- return __awaiter(this, void 0, void 0, function* () {
1502
- try {
1503
- const { data: sessionData, error: sessionError } = yield this.getSession();
1504
- if (sessionError) {
1505
- return { data: null, error: sessionError };
1506
- }
1507
- const { data, error } = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/factors`, {
1508
- body: {
1509
- friendly_name: params.friendlyName,
1510
- factor_type: params.factorType,
1511
- issuer: params.issuer,
1512
- },
1513
- headers: this.headers,
1514
- jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1515
- });
1516
- if (error) {
1517
- return { data: null, error };
1518
- }
1519
- if ((_b = data === null || data === void 0 ? void 0 : data.totp) === null || _b === void 0 ? void 0 : _b.qr_code) {
1520
- data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}`;
1521
- }
1522
- return { data, error: null };
1420
+ try {
1421
+ const { data: sessionData, error: sessionError } = await this.getSession();
1422
+ if (sessionError) {
1423
+ return { data: null, error: sessionError };
1523
1424
  }
1524
- catch (error) {
1525
- if ((0, errors_1.isAuthError)(error)) {
1526
- return { data: null, error };
1527
- }
1528
- throw error;
1425
+ const { data, error } = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/factors`, {
1426
+ body: {
1427
+ friendly_name: params.friendlyName,
1428
+ factor_type: params.factorType,
1429
+ issuer: params.issuer,
1430
+ },
1431
+ headers: this.headers,
1432
+ jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1433
+ });
1434
+ if (error) {
1435
+ return { data: null, error };
1529
1436
  }
1530
- });
1437
+ if ((_b = data === null || data === void 0 ? void 0 : data.totp) === null || _b === void 0 ? void 0 : _b.qr_code) {
1438
+ data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}`;
1439
+ }
1440
+ return { data, error: null };
1441
+ }
1442
+ catch (error) {
1443
+ if ((0, errors_1.isAuthError)(error)) {
1444
+ return { data: null, error };
1445
+ }
1446
+ throw error;
1447
+ }
1531
1448
  }
1532
1449
  /**
1533
1450
  * {@see GoTrueMFAApi#verify}
1534
1451
  */
1535
- _verify(params) {
1452
+ async _verify(params) {
1536
1453
  var _a;
1537
- return __awaiter(this, void 0, void 0, function* () {
1538
- try {
1539
- const { data: sessionData, error: sessionError } = yield this.getSession();
1540
- if (sessionError) {
1541
- return { data: null, error: sessionError };
1542
- }
1543
- const { data, error } = yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/verify`, {
1544
- body: { code: params.code, challenge_id: params.challengeId },
1545
- headers: this.headers,
1546
- jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1547
- });
1548
- if (error) {
1549
- return { data: null, error };
1550
- }
1551
- yield this._saveSession(Object.assign({ expires_at: Math.round(Date.now() / 1000) + data.expires_in }, data));
1552
- yield this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data);
1553
- return { data, error };
1454
+ try {
1455
+ const { data: sessionData, error: sessionError } = await this.getSession();
1456
+ if (sessionError) {
1457
+ return { data: null, error: sessionError };
1554
1458
  }
1555
- catch (error) {
1556
- if ((0, errors_1.isAuthError)(error)) {
1557
- return { data: null, error };
1558
- }
1559
- throw error;
1459
+ const { data, error } = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/verify`, {
1460
+ body: { code: params.code, challenge_id: params.challengeId },
1461
+ headers: this.headers,
1462
+ jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1463
+ });
1464
+ if (error) {
1465
+ return { data: null, error };
1560
1466
  }
1561
- });
1467
+ await this._saveSession(Object.assign({ expires_at: Math.round(Date.now() / 1000) + data.expires_in }, data));
1468
+ await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data);
1469
+ return { data, error };
1470
+ }
1471
+ catch (error) {
1472
+ if ((0, errors_1.isAuthError)(error)) {
1473
+ return { data: null, error };
1474
+ }
1475
+ throw error;
1476
+ }
1562
1477
  }
1563
1478
  /**
1564
1479
  * {@see GoTrueMFAApi#challenge}
1565
1480
  */
1566
- _challenge(params) {
1481
+ async _challenge(params) {
1567
1482
  var _a;
1568
- return __awaiter(this, void 0, void 0, function* () {
1569
- try {
1570
- const { data: sessionData, error: sessionError } = yield this.getSession();
1571
- if (sessionError) {
1572
- return { data: null, error: sessionError };
1573
- }
1574
- return yield (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/challenge`, {
1575
- headers: this.headers,
1576
- jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1577
- });
1483
+ try {
1484
+ const { data: sessionData, error: sessionError } = await this.getSession();
1485
+ if (sessionError) {
1486
+ return { data: null, error: sessionError };
1578
1487
  }
1579
- catch (error) {
1580
- if ((0, errors_1.isAuthError)(error)) {
1581
- return { data: null, error };
1582
- }
1583
- throw error;
1488
+ return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/challenge`, {
1489
+ headers: this.headers,
1490
+ jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
1491
+ });
1492
+ }
1493
+ catch (error) {
1494
+ if ((0, errors_1.isAuthError)(error)) {
1495
+ return { data: null, error };
1584
1496
  }
1585
- });
1497
+ throw error;
1498
+ }
1586
1499
  }
1587
1500
  /**
1588
1501
  * {@see GoTrueMFAApi#challengeAndVerify}
1589
1502
  */
1590
- _challengeAndVerify(params) {
1591
- return __awaiter(this, void 0, void 0, function* () {
1592
- const { data: challengeData, error: challengeError } = yield this._challenge({
1593
- factorId: params.factorId,
1594
- });
1595
- if (challengeError) {
1596
- return { data: null, error: challengeError };
1597
- }
1598
- return yield this._verify({
1599
- factorId: params.factorId,
1600
- challengeId: challengeData.id,
1601
- code: params.code,
1602
- });
1503
+ async _challengeAndVerify(params) {
1504
+ const { data: challengeData, error: challengeError } = await this._challenge({
1505
+ factorId: params.factorId,
1506
+ });
1507
+ if (challengeError) {
1508
+ return { data: null, error: challengeError };
1509
+ }
1510
+ return await this._verify({
1511
+ factorId: params.factorId,
1512
+ challengeId: challengeData.id,
1513
+ code: params.code,
1603
1514
  });
1604
1515
  }
1605
1516
  /**
1606
1517
  * {@see GoTrueMFAApi#listFactors}
1607
1518
  */
1608
- _listFactors() {
1609
- return __awaiter(this, void 0, void 0, function* () {
1610
- const { data: { user }, error: userError, } = yield this.getUser();
1611
- if (userError) {
1612
- return { data: null, error: userError };
1613
- }
1614
- const factors = (user === null || user === void 0 ? void 0 : user.factors) || [];
1615
- const totp = factors.filter((factor) => factor.factor_type === 'totp' && factor.status === 'verified');
1616
- return {
1617
- data: {
1618
- all: factors,
1619
- totp,
1620
- },
1621
- error: null,
1622
- };
1623
- });
1519
+ async _listFactors() {
1520
+ const { data: { user }, error: userError, } = await this.getUser();
1521
+ if (userError) {
1522
+ return { data: null, error: userError };
1523
+ }
1524
+ const factors = (user === null || user === void 0 ? void 0 : user.factors) || [];
1525
+ const totp = factors.filter((factor) => factor.factor_type === 'totp' && factor.status === 'verified');
1526
+ return {
1527
+ data: {
1528
+ all: factors,
1529
+ totp,
1530
+ },
1531
+ error: null,
1532
+ };
1624
1533
  }
1625
1534
  /**
1626
1535
  * {@see GoTrueMFAApi#getAuthenticatorAssuranceLevel}
1627
1536
  */
1628
- _getAuthenticatorAssuranceLevel() {
1537
+ async _getAuthenticatorAssuranceLevel() {
1629
1538
  var _a, _b;
1630
- return __awaiter(this, void 0, void 0, function* () {
1631
- const { data: { session }, error: sessionError, } = yield this.getSession();
1632
- if (sessionError) {
1633
- return { data: null, error: sessionError };
1634
- }
1635
- if (!session) {
1636
- return {
1637
- data: { currentLevel: null, nextLevel: null, currentAuthenticationMethods: [] },
1638
- error: null,
1639
- };
1640
- }
1641
- const payload = this._decodeJWT(session.access_token);
1642
- let currentLevel = null;
1643
- if (payload.aal) {
1644
- currentLevel = payload.aal;
1645
- }
1646
- let nextLevel = currentLevel;
1647
- const verifiedFactors = (_b = (_a = session.user.factors) === null || _a === void 0 ? void 0 : _a.filter((factor) => factor.status === 'verified')) !== null && _b !== void 0 ? _b : [];
1648
- if (verifiedFactors.length > 0) {
1649
- nextLevel = 'aal2';
1650
- }
1651
- const currentAuthenticationMethods = payload.amr || [];
1652
- return { data: { currentLevel, nextLevel, currentAuthenticationMethods }, error: null };
1653
- });
1539
+ const { data: { session }, error: sessionError, } = await this.getSession();
1540
+ if (sessionError) {
1541
+ return { data: null, error: sessionError };
1542
+ }
1543
+ if (!session) {
1544
+ return {
1545
+ data: { currentLevel: null, nextLevel: null, currentAuthenticationMethods: [] },
1546
+ error: null,
1547
+ };
1548
+ }
1549
+ const payload = this._decodeJWT(session.access_token);
1550
+ let currentLevel = null;
1551
+ if (payload.aal) {
1552
+ currentLevel = payload.aal;
1553
+ }
1554
+ let nextLevel = currentLevel;
1555
+ const verifiedFactors = (_b = (_a = session.user.factors) === null || _a === void 0 ? void 0 : _a.filter((factor) => factor.status === 'verified')) !== null && _b !== void 0 ? _b : [];
1556
+ if (verifiedFactors.length > 0) {
1557
+ nextLevel = 'aal2';
1558
+ }
1559
+ const currentAuthenticationMethods = payload.amr || [];
1560
+ return { data: { currentLevel, nextLevel, currentAuthenticationMethods }, error: null };
1654
1561
  }
1655
1562
  }
1656
1563
  exports.default = GoTrueClient;